#! /bin/sh /usr/share/dpatch/dpatch-run ## vm86-support.dpatch by Bastian Blank ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: No description. @DPATCH@ diff -urNad xen-unstable~/xen/arch/x86/traps.c xen-unstable/xen/arch/x86/traps.c --- xen-unstable~/xen/arch/x86/traps.c 2006-08-30 18:36:52.000000000 +0200 +++ xen-unstable/xen/arch/x86/traps.c 2006-09-07 01:27:22.000000000 +0200 @@ -1015,9 +1015,11 @@ (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; \ @@ -1027,7 +1029,7 @@ 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; @@ -1035,7 +1037,7 @@ /* 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 */ @@ -1067,7 +1069,7 @@ 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 @@ -1149,7 +1151,7 @@ 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; @@ -1178,7 +1180,7 @@ 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; @@ -1227,7 +1229,7 @@ goto fail; /* Privileged (ring 0) instructions. */ - opcode = insn_fetch(u8, 1, eip); + opcode = insn_fetch(u8, 1, cs, eip); switch ( opcode ) { case 0x06: /* CLTS */ @@ -1245,7 +1247,7 @@ break; case 0x20: /* MOV 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); @@ -1279,7 +1281,7 @@ break; case 0x21: /* MOV 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); @@ -1289,7 +1291,7 @@ break; case 0x22: /* MOV ,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); @@ -1329,7 +1331,7 @@ break; case 0x23: /* MOV ,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);