diff options
| author | Avi Kivity <avi@qumranet.com> | 2008-05-05 07:58:26 -0400 |
|---|---|---|
| committer | Avi Kivity <avi@qumranet.com> | 2008-05-18 07:34:14 -0400 |
| commit | 107d6d2efa9eb8c48d050936d8019230ac6b24cd (patch) | |
| tree | fc1d94a18e3f909e31c900ac698811831ed0abb2 | |
| parent | f26a3988917913b3d11b2bd741601a2c64ab9204 (diff) | |
KVM: x86 emulator: fix writes to registers with modrm encodings
A register destination encoded with a mod=3 encoding left dst.ptr NULL.
Normally we don't trap writes to registers, but in the case of smsw, we do.
Fix by pointing dst.ptr at the destination register.
Signed-off-by: Avi Kivity <avi@qumranet.com>
| -rw-r--r-- | arch/x86/kvm/x86_emulate.c | 7 | ||||
| -rw-r--r-- | include/asm-x86/kvm_x86_emulate.h | 1 |
2 files changed, 6 insertions, 2 deletions
diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index f2a696d6a243..8a96320ab071 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c | |||
| @@ -677,8 +677,9 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt, | |||
| 677 | c->use_modrm_ea = 1; | 677 | c->use_modrm_ea = 1; |
| 678 | 678 | ||
| 679 | if (c->modrm_mod == 3) { | 679 | if (c->modrm_mod == 3) { |
| 680 | c->modrm_val = *(unsigned long *) | 680 | c->modrm_ptr = decode_register(c->modrm_rm, |
| 681 | decode_register(c->modrm_rm, c->regs, c->d & ByteOp); | 681 | c->regs, c->d & ByteOp); |
| 682 | c->modrm_val = *(unsigned long *)c->modrm_ptr; | ||
| 682 | return rc; | 683 | return rc; |
| 683 | } | 684 | } |
| 684 | 685 | ||
| @@ -1005,6 +1006,7 @@ done_prefixes: | |||
| 1005 | if ((c->d & ModRM) && c->modrm_mod == 3) { | 1006 | if ((c->d & ModRM) && c->modrm_mod == 3) { |
| 1006 | c->src.type = OP_REG; | 1007 | c->src.type = OP_REG; |
| 1007 | c->src.val = c->modrm_val; | 1008 | c->src.val = c->modrm_val; |
| 1009 | c->src.ptr = c->modrm_ptr; | ||
| 1008 | break; | 1010 | break; |
| 1009 | } | 1011 | } |
| 1010 | c->src.type = OP_MEM; | 1012 | c->src.type = OP_MEM; |
| @@ -1049,6 +1051,7 @@ done_prefixes: | |||
| 1049 | if ((c->d & ModRM) && c->modrm_mod == 3) { | 1051 | if ((c->d & ModRM) && c->modrm_mod == 3) { |
| 1050 | c->dst.type = OP_REG; | 1052 | c->dst.type = OP_REG; |
| 1051 | c->dst.val = c->dst.orig_val = c->modrm_val; | 1053 | c->dst.val = c->dst.orig_val = c->modrm_val; |
| 1054 | c->dst.ptr = c->modrm_ptr; | ||
| 1052 | break; | 1055 | break; |
| 1053 | } | 1056 | } |
| 1054 | c->dst.type = OP_MEM; | 1057 | c->dst.type = OP_MEM; |
diff --git a/include/asm-x86/kvm_x86_emulate.h b/include/asm-x86/kvm_x86_emulate.h index d6337f941c98..b877bbd2d3a7 100644 --- a/include/asm-x86/kvm_x86_emulate.h +++ b/include/asm-x86/kvm_x86_emulate.h | |||
| @@ -135,6 +135,7 @@ struct decode_cache { | |||
| 135 | u8 modrm_rm; | 135 | u8 modrm_rm; |
| 136 | u8 use_modrm_ea; | 136 | u8 use_modrm_ea; |
| 137 | unsigned long modrm_ea; | 137 | unsigned long modrm_ea; |
| 138 | void *modrm_ptr; | ||
| 138 | unsigned long modrm_val; | 139 | unsigned long modrm_val; |
| 139 | struct fetch_cache fetch; | 140 | struct fetch_cache fetch; |
| 140 | }; | 141 | }; |
