⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vm86.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	addr = operand(prefix, regs, modrm);	if (prefix & DATA32) {		data = read32(addr);		push32(regs, data);	} else {		data = read16(addr);		push16(regs, data);	}	TRACE((regs, (regs->eip - n) + 1, "push *0x%x", addr));}enum { OPC_INVALID, OPC_EMULATED };#define rdmsr(msr,val1,val2)				\	__asm__ __volatile__(				\		"rdmsr"					\		: "=a" (val1), "=d" (val2)		\		: "c" (msr))#define wrmsr(msr,val1,val2)				\	__asm__ __volatile__(				\		"wrmsr"					\		: /* no outputs */			\		: "c" (msr), "a" (val1), "d" (val2))/* * Emulate a single instruction, including all its prefixes. We only implement * a small subset of the opcodes, and not all opcodes are implemented for each * of the four modes we can operate in. */static intopcode(struct regs *regs){	unsigned eip = regs->eip;	unsigned opc, modrm, disp;	unsigned prefix = 0;	if (mode == VM86_PROTECTED_TO_REAL &&		oldctx.cs_arbytes.fields.default_ops_size) {		prefix |= DATA32;		prefix |= ADDR32;	}	for (;;) {		switch ((opc = fetch8(regs))) {		case 0x00: /* addr32 add r8, r/m8 */		case 0x01: /* addr32 add r16, r/m16 */		case 0x03: /* addr32 add r/m16, r16 */			if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)				goto invalid;			if ((prefix & ADDR32) == 0)				goto invalid;			if (!add(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;					case 0x07: /* pop %es */			regs->ves = (prefix & DATA32) ?				pop32(regs) : pop16(regs);			TRACE((regs, regs->eip - eip, "pop %%es"));			if (mode == VM86_REAL_TO_PROTECTED) {				saved_rm_regs.ves = 0;				oldctx.es_sel = regs->ves;			}			return OPC_EMULATED;		case 0x0F: /* two byte opcode */			if (mode == VM86_PROTECTED)				goto invalid;			switch ((opc = fetch8(regs))) {			case 0x01:				switch (((modrm = fetch8(regs)) >> 3) & 7) {				case 0: /* sgdt */				case 1: /* sidt */					goto invalid;				case 2: /* lgdt */					if (!lgdt(regs, prefix, modrm))						goto invalid;					return OPC_EMULATED;				case 3: /* lidt */					if (!lidt(regs, prefix, modrm))						goto invalid;					return OPC_EMULATED;				case 4: /* smsw */					goto invalid;				case 5:					goto invalid;				case 6: /* lmsw */					if (!lmsw(regs, prefix, modrm))						goto invalid;					return OPC_EMULATED;				case 7: /* invlpg */					goto invalid;				}				break;			case 0x06: /* clts */				oldctx.cr0 &= ~CR0_TS;				return OPC_EMULATED;			case 0x09: /* wbinvd */				return OPC_EMULATED;			case 0x20: /* mov Rd, Cd (1h) */			case 0x22:				if (!movcr(regs, prefix, opc))					goto invalid;				return OPC_EMULATED;			case 0x30: /* WRMSR */				wrmsr(regs->ecx, regs->eax, regs->edx);				return OPC_EMULATED;			case 0x32: /* RDMSR */				rdmsr(regs->ecx, regs->eax, regs->edx);				return OPC_EMULATED;			default:				goto invalid;			}			goto invalid;		case 0x1F: /* pop %ds */			regs->vds = (prefix & DATA32) ?				pop32(regs) : pop16(regs);			TRACE((regs, regs->eip - eip, "pop %%ds"));			if (mode == VM86_REAL_TO_PROTECTED) {				saved_rm_regs.vds = 0;				oldctx.ds_sel = regs->vds;			}			return OPC_EMULATED;		case 0x26:			TRACE((regs, regs->eip - eip, "%%es:"));			prefix |= SEG_ES;			continue;		case 0x2E:			TRACE((regs, regs->eip - eip, "%%cs:"));			prefix |= SEG_CS;			continue;		case 0x36:			TRACE((regs, regs->eip - eip, "%%ss:"));			prefix |= SEG_SS;			continue;		case 0x39: /* addr32 cmp r16, r/m16 */		case 0x3B: /* addr32 cmp r/m16, r16 */			if (mode == VM86_PROTECTED_TO_REAL || !(prefix & ADDR32))				goto invalid;			if (!cmp(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0x3E:			TRACE((regs, regs->eip - eip, "%%ds:"));			prefix |= SEG_DS;			continue;		case 0x64:			TRACE((regs, regs->eip - eip, "%%fs:"));			prefix |= SEG_FS;			continue;		case 0x65:			TRACE((regs, regs->eip - eip, "%%gs:"));			prefix |= SEG_GS;			continue;		case 0x66:			if (mode == VM86_PROTECTED_TO_REAL &&				oldctx.cs_arbytes.fields.default_ops_size) {				TRACE((regs, regs->eip - eip, "data16"));				prefix &= ~DATA32;			} else {				TRACE((regs, regs->eip - eip, "data32"));				prefix |= DATA32;			}			continue;		case 0x67:			if (mode == VM86_PROTECTED_TO_REAL &&				oldctx.cs_arbytes.fields.default_ops_size) {				TRACE((regs, regs->eip - eip, "addr16"));				prefix &= ~ADDR32;			} else {				TRACE((regs, regs->eip - eip, "addr32"));				prefix |= ADDR32;			}			continue;		case 0x88: /* addr32 mov r8, r/m8 */		case 0x8A: /* addr32 mov r/m8, r8 */			if (mode == VM86_PROTECTED_TO_REAL || !(prefix & ADDR32))				goto invalid;			if (!movr(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0x89: /* mov r16, r/m16 */		case 0x8B: /* mov r/m16, r16 */			if (mode != VM86_PROTECTED_TO_REAL && !(prefix & ADDR32))				goto invalid;			if (!movr(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0x8E: /* mov r16, sreg */			if (!mov_to_seg(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0x8F: /* addr32 pop r/m16 */			if (!(prefix & ADDR32))				goto invalid;			if (!pop(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0x90: /* nop */			TRACE((regs, regs->eip - eip, "nop"));			return OPC_EMULATED;		case 0x9C: /* pushf */			TRACE((regs, regs->eip - eip, "pushf"));			if (prefix & DATA32)				push32(regs, regs->eflags & ~EFLAGS_VM);			else				push16(regs, regs->eflags & ~EFLAGS_VM);			return OPC_EMULATED;		case 0x9D: /* popf */			TRACE((regs, regs->eip - eip, "popf"));			if (prefix & DATA32)				regs->eflags = pop32(regs);			else				regs->eflags = (regs->eflags & 0xFFFF0000L) |								pop16(regs);			regs->eflags |= EFLAGS_VM;			return OPC_EMULATED;		case 0xA1: /* mov ax, r/m16 */		{			int addr, data;			int seg = segment(prefix, regs, regs->vds);			int offset = prefix & ADDR32 ? fetch32(regs) : fetch16(regs);			if (prefix & DATA32) {				addr = address(regs, seg, offset);				data = read32(addr);				setreg32(regs, 0, data);			} else {				addr = address(regs, seg, offset);				data = read16(addr);				setreg16(regs, 0, data);			}			TRACE((regs, regs->eip - eip, "mov *0x%x, %%ax", addr));			return OPC_EMULATED;		}		case 0xA4: /* movsb */		case 0xA5: /* movsw */			if ((prefix & ADDR32) == 0)				goto invalid;			if (!movs(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0xAD: /* lodsw */			if ((prefix & ADDR32) == 0)				goto invalid;			if (!lods(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;					case 0xBB: /* mov bx, imm16 */		{			int data;			if (prefix & DATA32) {				data = fetch32(regs);				setreg32(regs, 3, data);			} else {				data = fetch16(regs);				setreg16(regs, 3, data);			}			TRACE((regs, regs->eip - eip, "mov $0x%x, %%bx", data));			return OPC_EMULATED;		}		case 0xC6: /* addr32 movb $imm, r/m8 */			if (!(prefix & ADDR32))				goto invalid;			if (!movr(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0xCB: /* retl */			if (mode == VM86_REAL_TO_PROTECTED ||				mode == VM86_PROTECTED_TO_REAL) {				retl(regs, prefix);				return OPC_INVALID;			}			goto invalid;		case 0xCD: /* int $n */			TRACE((regs, regs->eip - eip, "int"));			interrupt(regs, fetch8(regs));			return OPC_EMULATED;		case 0xCF: /* iret */			if (prefix & DATA32) {				TRACE((regs, regs->eip - eip, "data32 iretd"));				regs->eip = pop32(regs);				regs->cs = pop32(regs);				regs->eflags = pop32(regs);			} else {				TRACE((regs, regs->eip - eip, "iret"));				regs->eip = pop16(regs);				regs->cs = pop16(regs);				regs->eflags = (regs->eflags & 0xFFFF0000L) |								pop16(regs);			}			return OPC_EMULATED;		case 0xE4: /* inb al, port */			if (!inbyte(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0xE6: /* outb port, al */			if (!outbyte(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0xEA: /* jmpl */			if (mode == VM86_REAL_TO_PROTECTED ||				mode == VM86_PROTECTED_TO_REAL) {				jmpl(regs, prefix);				return OPC_INVALID;			}			goto invalid;		case 0xFF:		{			unsigned modrm = fetch8(regs);			switch((modrm >> 3) & 7) {			case 5: /* jmpl (indirect) */				if (mode == VM86_REAL_TO_PROTECTED ||					mode == VM86_PROTECTED_TO_REAL) {					jmpl_indirect(regs, prefix, modrm);					return OPC_INVALID;				}				goto invalid;			case 6: /* push r/m16 */				pushrm(regs, prefix, modrm);				return OPC_EMULATED;			default:				goto invalid;			}		}		case 0xEB: /* short jump */			if (mode == VM86_REAL_TO_PROTECTED ||				mode == VM86_PROTECTED_TO_REAL) {				disp = (char) fetch8(regs);				TRACE((regs, 2, "jmp 0x%x", regs->eip + disp));				regs->eip += disp;				return OPC_EMULATED;			}			goto invalid;		case 0xEC: /* inb al, (%dx) */			if (!inbyte(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0xEE: /* outb (%dx), al */			if (!outbyte(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0xF0: /* lock */			TRACE((regs, regs->eip - eip, "lock"));			continue;		case 0xF4: /* hlt */			TRACE((regs, regs->eip - eip, "hlt"));			/* Do something power-saving here! */			return OPC_EMULATED;		case 0xF3: /* rep/repe/repz */			TRACE((regs, regs->eip - eip, "rep"));			prefix |= REP;			continue;		case 0xF6: /* addr32 testb $imm, r/m8 */			if (!(prefix & ADDR32))				goto invalid;			if (!test(regs, prefix, opc))				goto invalid;			return OPC_EMULATED;		case 0xFA: /* cli */			TRACE((regs, regs->eip - eip, "cli"));			regs->eflags &= ~EFLAGS_IF;			return OPC_EMULATED;		case 0xFB: /* sti */			TRACE((regs, regs->eip - eip, "sti"));			regs->eflags |= EFLAGS_IF;			return OPC_EMULATED;		default:			goto invalid;		}	}invalid:	regs->eip = eip;	TRACE((regs, regs->eip - eip, "opc 0x%x", opc));	return OPC_INVALID;}voidemulate(struct regs *regs){	unsigned flteip;	int nemul = 0;	unsigned ip;	/* emulate as many instructions as possible */	while (opcode(regs) != OPC_INVALID)		nemul++;	/* detect the case where we are not making progress */	if (nemul == 0 && prev_eip == regs->eip) {		flteip = address(regs, MASK16(regs->cs), regs->eip);		printf("Undecoded sequence: \n");		for (ip=flteip; ip < flteip+16; ip++)			printf("0x%02x ", read8(ip));		printf("\n");		panic("Unknown opcode at %04x:%04x=0x%x",			MASK16(regs->cs), regs->eip, flteip);	} else		prev_eip = regs->eip;}voidtrap(int trapno, int errno, struct regs *regs){	/* emulate device interrupts */	if (trapno >= NR_EXCEPTION_HANDLER) {		int irq = trapno - NR_EXCEPTION_HANDLER;		if (irq < 8) 			interrupt(regs, irq + 8);		else			interrupt(regs, 0x70 + (irq - 8));		return;	}	switch (trapno) {	case 1: /* Debug */		if (regs->eflags & EFLAGS_VM) {			/* emulate any 8086 instructions  */			if (mode == VM86_REAL)				return;			if (mode != VM86_REAL_TO_PROTECTED)				panic("not in real-to-protected mode");			emulate(regs);			return;		}		goto invalid;	case 13: /* GPF */		if (regs->eflags & EFLAGS_VM) {			/* emulate any 8086 instructions  */			if (mode == VM86_PROTECTED)				panic("unexpected protected mode");			emulate(regs);			return;		}		goto invalid;	default:	invalid:		printf("Trap (0x%x) while in %s mode\n",			trapno, regs->eflags & EFLAGS_VM ? "real" : "protected");		if (trapno == 14)			printf("Page fault address 0x%x\n", get_cr2());		dump_regs(regs);		halt();	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -