diff options
author | Nadav Amit <namit@cs.technion.ac.il> | 2014-05-25 16:05:21 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-05-27 04:22:56 -0400 |
commit | 9b88ae99d2fe11e359b3b3992aff953e28b0b43a (patch) | |
tree | 11e43ca7db20ad0583755642b384939101938914 /arch | |
parent | fc57ac2c9ca8109ea97fcc594f4be436944230cc (diff) |
KVM: x86: MOV CR/DR emulation should ignore mod
MOV CR/DR instructions ignore the mod field (in the ModR/M byte). As the SDM
states: "The 2 bits in the mod field are ignored". Accordingly, the second
operand of these instructions is always a general purpose register.
The current emulator implementation does not do so. If the mod bits do not
equal 3, it expects the second operand to be in memory.
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/emulate.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 2fa7ab069817..e4e833d3d7d7 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -161,6 +161,7 @@ | |||
161 | #define Fastop ((u64)1 << 44) /* Use opcode::u.fastop */ | 161 | #define Fastop ((u64)1 << 44) /* Use opcode::u.fastop */ |
162 | #define NoWrite ((u64)1 << 45) /* No writeback */ | 162 | #define NoWrite ((u64)1 << 45) /* No writeback */ |
163 | #define SrcWrite ((u64)1 << 46) /* Write back src operand */ | 163 | #define SrcWrite ((u64)1 << 46) /* Write back src operand */ |
164 | #define NoMod ((u64)1 << 47) /* Mod field is ignored */ | ||
164 | 165 | ||
165 | #define DstXacc (DstAccLo | SrcAccHi | SrcWrite) | 166 | #define DstXacc (DstAccLo | SrcAccHi | SrcWrite) |
166 | 167 | ||
@@ -1077,7 +1078,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt, | |||
1077 | ctxt->modrm_rm |= (ctxt->modrm & 0x07); | 1078 | ctxt->modrm_rm |= (ctxt->modrm & 0x07); |
1078 | ctxt->modrm_seg = VCPU_SREG_DS; | 1079 | ctxt->modrm_seg = VCPU_SREG_DS; |
1079 | 1080 | ||
1080 | if (ctxt->modrm_mod == 3) { | 1081 | if (ctxt->modrm_mod == 3 || (ctxt->d & NoMod)) { |
1081 | op->type = OP_REG; | 1082 | op->type = OP_REG; |
1082 | op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes; | 1083 | op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes; |
1083 | op->addr.reg = decode_register(ctxt, ctxt->modrm_rm, | 1084 | op->addr.reg = decode_register(ctxt, ctxt->modrm_rm, |
@@ -3877,10 +3878,12 @@ static const struct opcode twobyte_table[256] = { | |||
3877 | N, N, N, N, N, N, N, N, | 3878 | N, N, N, N, N, N, N, N, |
3878 | D(ImplicitOps | ModRM), N, N, N, N, N, N, D(ImplicitOps | ModRM), | 3879 | D(ImplicitOps | ModRM), N, N, N, N, N, N, D(ImplicitOps | ModRM), |
3879 | /* 0x20 - 0x2F */ | 3880 | /* 0x20 - 0x2F */ |
3880 | DIP(ModRM | DstMem | Priv | Op3264, cr_read, check_cr_read), | 3881 | DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_read), |
3881 | DIP(ModRM | DstMem | Priv | Op3264, dr_read, check_dr_read), | 3882 | DIP(ModRM | DstMem | Priv | Op3264 | NoMod, dr_read, check_dr_read), |
3882 | IIP(ModRM | SrcMem | Priv | Op3264, em_cr_write, cr_write, check_cr_write), | 3883 | IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_cr_write, cr_write, |
3883 | IIP(ModRM | SrcMem | Priv | Op3264, em_dr_write, dr_write, check_dr_write), | 3884 | check_cr_write), |
3885 | IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_dr_write, dr_write, | ||
3886 | check_dr_write), | ||
3884 | N, N, N, N, | 3887 | N, N, N, N, |
3885 | GP(ModRM | DstReg | SrcMem | Mov | Sse, &pfx_0f_28_0f_29), | 3888 | GP(ModRM | DstReg | SrcMem | Mov | Sse, &pfx_0f_28_0f_29), |
3886 | GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_28_0f_29), | 3889 | GP(ModRM | DstMem | SrcReg | Mov | Sse, &pfx_0f_28_0f_29), |