Commit a6e3407b authored by Avi Kivity's avatar Avi Kivity
Browse files

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: default avatarAvi Kivity <avi@redhat.com>
parent cbd27ee7
Loading
Loading
Loading
Loading
+14 −3
Original line number Original line Diff line number Diff line
@@ -974,6 +974,12 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
	op->orig_val = op->val;
	op->orig_val = op->val;
}
}


static void adjust_modrm_seg(struct x86_emulate_ctxt *ctxt, int base_reg)
{
	if (base_reg == VCPU_REGS_RSP || base_reg == VCPU_REGS_RBP)
		ctxt->modrm_seg = VCPU_SREG_SS;
}

static int decode_modrm(struct x86_emulate_ctxt *ctxt,
static int decode_modrm(struct x86_emulate_ctxt *ctxt,
			struct operand *op)
			struct operand *op)
{
{
@@ -1077,15 +1083,20 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,


			if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)
			if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)
				modrm_ea += insn_fetch(s32, ctxt);
				modrm_ea += insn_fetch(s32, ctxt);
			else
			else {
				modrm_ea += ctxt->regs[base_reg];
				modrm_ea += ctxt->regs[base_reg];
				adjust_modrm_seg(ctxt, base_reg);
			}
			if (index_reg != 4)
			if (index_reg != 4)
				modrm_ea += ctxt->regs[index_reg] << scale;
				modrm_ea += ctxt->regs[index_reg] << scale;
		} else if ((ctxt->modrm_rm & 7) == 5 && ctxt->modrm_mod == 0) {
		} else if ((ctxt->modrm_rm & 7) == 5 && ctxt->modrm_mod == 0) {
			if (ctxt->mode == X86EMUL_MODE_PROT64)
			if (ctxt->mode == X86EMUL_MODE_PROT64)
				ctxt->rip_relative = 1;
				ctxt->rip_relative = 1;
		} else
		} else {
			modrm_ea += ctxt->regs[ctxt->modrm_rm];
			base_reg = ctxt->modrm_rm;
			modrm_ea += ctxt->regs[base_reg];
			adjust_modrm_seg(ctxt, base_reg);
		}
		switch (ctxt->modrm_mod) {
		switch (ctxt->modrm_mod) {
		case 0:
		case 0:
			if (ctxt->modrm_rm == 5)
			if (ctxt->modrm_rm == 5)