arch/x86/mm/pf_in.c

Source file repositories/reference/linux-study-clean/arch/x86/mm/pf_in.c

File Facts

System
Linux kernel
Corpus path
arch/x86/mm/pf_in.c
Extension
.c
Size
10068 bytes
Lines
517
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

struct prefix_bits {
	unsigned shorted:1;
	unsigned enlarged:1;
	unsigned rexr:1;
	unsigned rex:1;
};

static int skip_prefix(unsigned char *addr, struct prefix_bits *prf)
{
	int i;
	unsigned char *p = addr;
	prf->shorted = 0;
	prf->enlarged = 0;
	prf->rexr = 0;
	prf->rex = 0;

restart:
	for (i = 0; i < ARRAY_SIZE(prefix_codes); i++) {
		if (*p == prefix_codes[i]) {
			if (*p == 0x66)
				prf->shorted = 1;
#ifdef __amd64__
			if ((*p & 0xf8) == 0x48)
				prf->enlarged = 1;
			if ((*p & 0xf4) == 0x44)
				prf->rexr = 1;
			if ((*p & 0xf0) == 0x40)
				prf->rex = 1;
#endif
			p++;
			goto restart;
		}
	}

	return (p - addr);
}

static int get_opcode(unsigned char *addr, unsigned int *opcode)
{
	int len;

	if (*addr == 0x0F) {
		/* 0x0F is extension instruction */
		*opcode = *(unsigned short *)addr;
		len = 2;
	} else {
		*opcode = *addr;
		len = 1;
	}

	return len;
}

#define CHECK_OP_TYPE(opcode, array, type) \
	for (i = 0; i < ARRAY_SIZE(array); i++) { \
		if (array[i] == opcode) { \
			rv = type; \
			goto exit; \
		} \
	}

enum reason_type get_ins_type(unsigned long ins_addr)
{
	unsigned int opcode;
	unsigned char *p;
	struct prefix_bits prf;
	int i;
	enum reason_type rv = OTHERS;

	p = (unsigned char *)ins_addr;
	p += skip_prefix(p, &prf);
	p += get_opcode(p, &opcode);

	CHECK_OP_TYPE(opcode, reg_rop, REG_READ);
	CHECK_OP_TYPE(opcode, reg_wop, REG_WRITE);
	CHECK_OP_TYPE(opcode, imm_wop, IMM_WRITE);

exit:
	return rv;
}
#undef CHECK_OP_TYPE

static unsigned int get_ins_reg_width(unsigned long ins_addr)
{
	unsigned int opcode;
	unsigned char *p;
	struct prefix_bits prf;
	int i;

	p = (unsigned char *)ins_addr;

Annotation

Implementation Notes