aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2012-06-10 10:15:39 -0400
committerAvi Kivity <avi@redhat.com>2012-07-09 07:19:02 -0400
commita6e3407bb1570ac5d8d7fc471bca07d531d1dde7 (patch)
treec0bb9742c418f8633256b90f4eac43387638d838 /arch/x86/kvm
parentcbd27ee783f1e56d56415e8c5f2492ccedd565c4 (diff)
KVM: Fix SS default ESP/EBP based addressing
We correctly default to SS when BP is used as a base in 16-bit address mode, but we don't do that for 32-bit mode. Fix by adjusting the default to SS when either ESP or EBP is used as the base register. Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/emulate.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 33ccd757cb11..7552c0ac6e76 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -974,6 +974,12 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
974 op->orig_val = op->val; 974 op->orig_val = op->val;
975} 975}
976 976
977static void adjust_modrm_seg(struct x86_emulate_ctxt *ctxt, int base_reg)
978{
979 if (base_reg == VCPU_REGS_RSP || base_reg == VCPU_REGS_RBP)
980 ctxt->modrm_seg = VCPU_SREG_SS;
981}
982
977static int decode_modrm(struct x86_emulate_ctxt *ctxt, 983static int decode_modrm(struct x86_emulate_ctxt *ctxt,
978 struct operand *op) 984 struct operand *op)
979{ 985{
@@ -1077,15 +1083,20 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
1077 1083
1078 if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0) 1084 if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)
1079 modrm_ea += insn_fetch(s32, ctxt); 1085 modrm_ea += insn_fetch(s32, ctxt);
1080 else 1086 else {
1081 modrm_ea += ctxt->regs[base_reg]; 1087 modrm_ea += ctxt->regs[base_reg];
1088 adjust_modrm_seg(ctxt, base_reg);
1089 }
1082 if (index_reg != 4) 1090 if (index_reg != 4)
1083 modrm_ea += ctxt->regs[index_reg] << scale; 1091 modrm_ea += ctxt->regs[index_reg] << scale;
1084 } else if ((ctxt->modrm_rm & 7) == 5 && ctxt->modrm_mod == 0) { 1092 } else if ((ctxt->modrm_rm & 7) == 5 && ctxt->modrm_mod == 0) {
1085 if (ctxt->mode == X86EMUL_MODE_PROT64) 1093 if (ctxt->mode == X86EMUL_MODE_PROT64)
1086 ctxt->rip_relative = 1; 1094 ctxt->rip_relative = 1;
1087 } else 1095 } else {
1088 modrm_ea += ctxt->regs[ctxt->modrm_rm]; 1096 base_reg = ctxt->modrm_rm;
1097 modrm_ea += ctxt->regs[base_reg];
1098 adjust_modrm_seg(ctxt, base_reg);
1099 }
1089 switch (ctxt->modrm_mod) { 1100 switch (ctxt->modrm_mod) {
1090 case 0: 1101 case 0:
1091 if (ctxt->modrm_rm == 5) 1102 if (ctxt->modrm_rm == 5)