arch/x86/kernel/traps.c

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

File Facts

System
Linux kernel
Corpus path
arch/x86/kernel/traps.c
Extension
.c
Size
46168 bytes
Lines
1678
Domain
Architecture Layer
Bucket
arch/x86
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 (v == INSN_LOCK) {
			lock = true;
			continue;
		}

		if ((v & 0xf0) == 0x40) {
			rex = v;
			continue;
		}

		break;
	}

	switch (v) {
	case 0x70 ... 0x7f: /* Jcc.d8 */
		addr += 1; /* d8 */
		*len = addr - start;
		WARN_ON_ONCE(!lock);
		return BUG_LOCK;

	case 0xd6:
		*len = addr - start;
		return BUG_UDB;

	case OPCODE_ESCAPE:
		break;

	default:
		return BUG_NONE;
	}

	v = *(u8 *)(addr++);
	if (v == SECOND_BYTE_OPCODE_UD2) {
		*len = addr - start;
		return BUG_UD2;
	}

	if (v != SECOND_BYTE_OPCODE_UD1)
		return BUG_NONE;

	*imm = 0;
	v = *(u8 *)(addr++);		/* ModRM */

	if (X86_MODRM_MOD(v) != 3 && X86_MODRM_RM(v) == 4)
		addr++;			/* SIB */

	reg = X86_MODRM_REG(v) + 8*!!X86_REX_R(rex);
	rm  = X86_MODRM_RM(v)  + 8*!!X86_REX_B(rex);

	/* Decode immediate, if present */
	switch (X86_MODRM_MOD(v)) {
	case 0: if (X86_MODRM_RM(v) == 5)
			addr += 4;	/* RIP + disp32 */

		if (rm == 0)		/* (%eax) */
			type = BUG_UD1_UBSAN;

		if (rm == 2) {		/* (%edx) */
			*imm = reg;
			type = BUG_UD1_WARN;
		}
		break;

	case 1: *imm = *(s8 *)addr;
		addr += 1;
		if (rm == 0)		/* (%eax) */
			type = BUG_UD1_UBSAN;
		break;

	case 2: *imm = *(s32 *)addr;
		addr += 4;
		if (rm == 0)		/* (%eax) */
			type = BUG_UD1_UBSAN;
		break;

	case 3: break;
	}

	/* record instruction length */
	*len = addr - start;

	return type;
}

static inline unsigned long pt_regs_val(struct pt_regs *regs, int nr)
{
	int offset = pt_regs_offset(regs, nr);
	if (WARN_ON_ONCE(offset < -0))
		return 0;
	return *((unsigned long *)((void *)regs + offset));

Annotation

Implementation Notes