arch/xtensa/kernel/traps.c

Source file repositories/reference/linux-study-clean/arch/xtensa/kernel/traps.c

File Facts

System
Linux kernel
Corpus path
arch/xtensa/kernel/traps.c
Extension
.c
Size
16985 bytes
Lines
652
Domain
Architecture Layer
Bucket
arch/xtensa
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (int_at_level & int_level_mask[level]) {
				int_at_level &= int_level_mask[level];
				if (int_at_level & unhandled)
					int_at_level &= unhandled;
				else
					unhandled |= int_level_mask[level];
				break;
			}
		}

		if (level == 0)
			break;

		/* clear lowest pending irq in the unhandled mask */
		unhandled ^= (int_at_level & -int_at_level);
		do_IRQ(__ffs(int_at_level), regs);
	}

	irq_exit();
	set_irq_regs(old_regs);
}

static bool check_div0(struct pt_regs *regs)
{
	static const u8 pattern[] = {'D', 'I', 'V', '0'};
	const u8 *p;
	u8 buf[5];

	if (user_mode(regs)) {
		if (copy_from_user(buf, (void __user *)regs->pc + 2, 5))
			return false;
		p = buf;
	} else {
		p = (const u8 *)regs->pc + 2;
	}

	return memcmp(p, pattern, sizeof(pattern)) == 0 ||
		memcmp(p + 1, pattern, sizeof(pattern)) == 0;
}

/*
 * Illegal instruction. Fatal if in kernel space.
 */

static void do_illegal_instruction(struct pt_regs *regs)
{
#ifdef CONFIG_USER_ABI_CALL0_PROBE
	/*
	 * When call0 application encounters an illegal instruction fast
	 * exception handler will attempt to set PS.WOE and retry failing
	 * instruction.
	 * If we get here we know that that instruction is also illegal
	 * with PS.WOE set, so it's not related to the windowed option
	 * hence PS.WOE may be cleared.
	 */
	if (regs->pc == current_thread_info()->ps_woe_fix_addr)
		regs->ps &= ~PS_WOE_MASK;
#endif
	if (check_div0(regs)) {
		do_div0(regs);
		return;
	}

	__die_if_kernel("Illegal instruction in kernel", regs, SIGKILL);

	/* If in user mode, send SIGILL signal to current process. */

	pr_info_ratelimited("Illegal Instruction in '%s' (pid = %d, pc = %#010lx)\n",
			    current->comm, task_pid_nr(current), regs->pc);
	force_sig(SIGILL);
}

static void do_div0(struct pt_regs *regs)
{
	__die_if_kernel("Unhandled division by 0 in kernel", regs, SIGKILL);
	force_sig_fault(SIGFPE, FPE_INTDIV, (void __user *)regs->pc);
}

#ifdef CONFIG_XTENSA_LOAD_STORE
static void do_load_store(struct pt_regs *regs)
{
	__die_if_kernel("Unhandled load/store exception in kernel",
			regs, SIGKILL);

	pr_info_ratelimited("Load/store error to %08lx in '%s' (pid = %d, pc = %#010lx)\n",
			    regs->excvaddr, current->comm,
			    task_pid_nr(current), regs->pc);
	force_sig_fault(SIGBUS, BUS_ADRERR, (void *)regs->excvaddr);
}
#endif

Annotation

Implementation Notes