[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Fix the emulation of instructions in vm86 mode. It fetches
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID 38765166ad7a788dfac3ffde9a50b4964039cac2 # Parent e5d29225a8d12aa3855339cbbef81dbb75dcaa78 [XEN] Fix the emulation of instructions in vm86 mode. It fetches them using cs and eip instead of only eip. This makes it at least possible to use the i945GM vesa bios from the running system. Signed-off-by: Bastian Blank <waldi@xxxxxxxxxx> --- xen/arch/x86/traps.c | 28 +++++++++++++++------------- 1 files changed, 15 insertions(+), 13 deletions(-) diff -r e5d29225a8d1 -r 38765166ad7a xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Tue Sep 19 11:08:11 2006 +0100 +++ b/xen/arch/x86/traps.c Tue Sep 19 11:13:10 2006 +0100 @@ -1028,9 +1028,11 @@ static inline unsigned char inb_user( (admin_io_okay(_p, 4, _d, _r) ? outl(_v, _p) : ((void)0)) /* Instruction fetch with error handling. */ -#define insn_fetch(_type, _size, _ptr) \ -({ unsigned long _rc, _x; \ - if ( (_rc = copy_from_user(&_x, (_type *)eip, sizeof(_type))) != 0 ) \ +#define insn_fetch(_type, _size, cs, eip) \ +({ unsigned long _rc, _x, _ptr = eip; \ + if ( vm86_mode(regs) ) \ + _ptr += cs << 4; \ + if ( (_rc = copy_from_user(&_x, (_type *)_ptr, sizeof(_type))) != 0 ) \ { \ propagate_page_fault(eip + sizeof(_type) - _rc, 0); \ return EXCRET_fault_fixed; \ @@ -1040,7 +1042,7 @@ static int emulate_privileged_op(struct static int emulate_privileged_op(struct cpu_user_regs *regs) { struct vcpu *v = current; - unsigned long *reg, eip = regs->eip, res; + unsigned long *reg, eip = regs->eip, cs = regs->cs, res; u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0; unsigned int port, i, op_bytes = 4, data, rc; u32 l, h; @@ -1048,7 +1050,7 @@ static int emulate_privileged_op(struct /* Legacy prefixes. */ for ( i = 0; i < 8; i++ ) { - switch ( opcode = insn_fetch(u8, 1, eip) ) + switch ( opcode = insn_fetch(u8, 1, cs, eip) ) { case 0x66: /* operand-size override */ op_bytes ^= 6; /* switch between 2/4 bytes */ @@ -1080,7 +1082,7 @@ static int emulate_privileged_op(struct modrm_rm = (opcode & 1) << 3; /* REX.B */ /* REX.W and REX.X do not need to be decoded. */ - opcode = insn_fetch(u8, 1, eip); + opcode = insn_fetch(u8, 1, cs, eip); } #endif @@ -1162,7 +1164,7 @@ static int emulate_privileged_op(struct case 0xe4: /* IN imm8,%al */ op_bytes = 1; case 0xe5: /* IN imm8,%eax */ - port = insn_fetch(u8, 1, eip); + port = insn_fetch(u8, 1, cs, eip); exec_in: if ( !guest_io_okay(port, op_bytes, v, regs) ) goto fail; @@ -1191,7 +1193,7 @@ static int emulate_privileged_op(struct case 0xe6: /* OUT %al,imm8 */ op_bytes = 1; case 0xe7: /* OUT %eax,imm8 */ - port = insn_fetch(u8, 1, eip); + port = insn_fetch(u8, 1, cs, eip); exec_out: if ( !guest_io_okay(port, op_bytes, v, regs) ) goto fail; @@ -1240,7 +1242,7 @@ static int emulate_privileged_op(struct goto fail; /* Privileged (ring 0) instructions. */ - opcode = insn_fetch(u8, 1, eip); + opcode = insn_fetch(u8, 1, cs, eip); switch ( opcode ) { case 0x06: /* CLTS */ @@ -1258,7 +1260,7 @@ static int emulate_privileged_op(struct break; case 0x20: /* MOV CR?,<reg> */ - opcode = insn_fetch(u8, 1, eip); + opcode = insn_fetch(u8, 1, cs, eip); modrm_reg |= (opcode >> 3) & 7; modrm_rm |= (opcode >> 0) & 7; reg = decode_register(modrm_rm, regs, 0); @@ -1292,7 +1294,7 @@ static int emulate_privileged_op(struct break; case 0x21: /* MOV DR?,<reg> */ - opcode = insn_fetch(u8, 1, eip); + opcode = insn_fetch(u8, 1, cs, eip); modrm_reg |= (opcode >> 3) & 7; modrm_rm |= (opcode >> 0) & 7; reg = decode_register(modrm_rm, regs, 0); @@ -1302,7 +1304,7 @@ static int emulate_privileged_op(struct break; case 0x22: /* MOV <reg>,CR? */ - opcode = insn_fetch(u8, 1, eip); + opcode = insn_fetch(u8, 1, cs, eip); modrm_reg |= (opcode >> 3) & 7; modrm_rm |= (opcode >> 0) & 7; reg = decode_register(modrm_rm, regs, 0); @@ -1342,7 +1344,7 @@ static int emulate_privileged_op(struct break; case 0x23: /* MOV <reg>,DR? */ - opcode = insn_fetch(u8, 1, eip); + opcode = insn_fetch(u8, 1, cs, eip); modrm_reg |= (opcode >> 3) & 7; modrm_rm |= (opcode >> 0) & 7; reg = decode_register(modrm_rm, regs, 0); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |