77 lines
3.1 KiB
Diff
77 lines
3.1 KiB
Diff
Index: 2007-01-31/xen/arch/x86/traps.c
|
|
===================================================================
|
|
--- 2007-01-31.orig/xen/arch/x86/traps.c 2007-01-31 09:41:46.000000000 +0100
|
|
+++ 2007-01-31/xen/arch/x86/traps.c 2007-01-31 09:41:54.000000000 +0100
|
|
@@ -1196,7 +1196,7 @@ static int emulate_privileged_op(struct
|
|
{
|
|
struct vcpu *v = current;
|
|
unsigned long *reg, eip = regs->eip, res;
|
|
- u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0, rex = 0;
|
|
+ u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0, lock = 0, rex = 0;
|
|
enum { lm_seg_none, lm_seg_fs, lm_seg_gs } lm_ovr = lm_seg_none;
|
|
unsigned int port, i, data_sel, ar, data, rc;
|
|
unsigned int op_bytes, op_default, ad_bytes, ad_default;
|
|
@@ -1261,6 +1261,7 @@ static int emulate_privileged_op(struct
|
|
data_sel = regs->ss;
|
|
continue;
|
|
case 0xf0: /* LOCK */
|
|
+ lock = 1;
|
|
continue;
|
|
case 0xf2: /* REPNE/REPNZ */
|
|
case 0xf3: /* REP/REPE/REPZ */
|
|
@@ -1287,6 +1288,9 @@ static int emulate_privileged_op(struct
|
|
if ( opcode == 0x0f )
|
|
goto twobyte_opcode;
|
|
|
|
+ if ( lock )
|
|
+ goto fail;
|
|
+
|
|
/* Input/Output String instructions. */
|
|
if ( (opcode >= 0x6c) && (opcode <= 0x6f) )
|
|
{
|
|
@@ -1550,6 +1554,8 @@ static int emulate_privileged_op(struct
|
|
|
|
/* Privileged (ring 0) instructions. */
|
|
opcode = insn_fetch(u8, code_base, eip, code_limit);
|
|
+ if ( lock && (opcode & ~3) != 0x20 )
|
|
+ goto fail;
|
|
switch ( opcode )
|
|
{
|
|
case 0x06: /* CLTS */
|
|
@@ -1568,7 +1574,7 @@ static int emulate_privileged_op(struct
|
|
|
|
case 0x20: /* MOV CR?,<reg> */
|
|
opcode = insn_fetch(u8, code_base, eip, code_limit);
|
|
- modrm_reg |= (opcode >> 3) & 7;
|
|
+ modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
|
|
modrm_rm |= (opcode >> 0) & 7;
|
|
reg = decode_register(modrm_rm, regs, 0);
|
|
switch ( modrm_reg )
|
|
@@ -1608,7 +1614,7 @@ static int emulate_privileged_op(struct
|
|
|
|
case 0x21: /* MOV DR?,<reg> */
|
|
opcode = insn_fetch(u8, code_base, eip, code_limit);
|
|
- modrm_reg |= (opcode >> 3) & 7;
|
|
+ modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
|
|
modrm_rm |= (opcode >> 0) & 7;
|
|
reg = decode_register(modrm_rm, regs, 0);
|
|
if ( (res = do_get_debugreg(modrm_reg)) > (unsigned long)-256 )
|
|
@@ -1618,7 +1624,7 @@ static int emulate_privileged_op(struct
|
|
|
|
case 0x22: /* MOV <reg>,CR? */
|
|
opcode = insn_fetch(u8, code_base, eip, code_limit);
|
|
- modrm_reg |= (opcode >> 3) & 7;
|
|
+ modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
|
|
modrm_rm |= (opcode >> 0) & 7;
|
|
reg = decode_register(modrm_rm, regs, 0);
|
|
switch ( modrm_reg )
|
|
@@ -1666,7 +1672,7 @@ static int emulate_privileged_op(struct
|
|
|
|
case 0x23: /* MOV <reg>,DR? */
|
|
opcode = insn_fetch(u8, code_base, eip, code_limit);
|
|
- modrm_reg |= (opcode >> 3) & 7;
|
|
+ modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
|
|
modrm_rm |= (opcode >> 0) & 7;
|
|
reg = decode_register(modrm_rm, regs, 0);
|
|
if ( do_set_debugreg(modrm_reg, *reg) != 0 )
|