Message ID | 1509929689-2935-1-git-send-email-wanpeng.li@hotmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 06/11/2017 01:54, Wanpeng Li wrote: > From: Wanpeng Li <wanpeng.li@hotmail.com> > > Pedro reported: > During tests that we conducted on KVM, we noticed that executing a "PUSH %ES" > instruction under KVM produces different results on both memory and the SP > register depending on whether EPT support is enabled. With EPT the SP is > reduced by 4 bytes (and the written value is 0-padded) but without EPT support > it is only reduced by 2 bytes. The difference can be observed when the CS.DB > field is 1 (32-bit) but not when it's 0 (16-bit). > > The internal segment descriptor cache exist even in real/vm8096 mode. The CS.D > also should be respected instead of just default operand/address-size/66H > prefix/67H prefix during instruction decoding. This patch fixes it by also > adjusting operand/address-size according to CS.D. > > Reported-by: Pedro Fonseca <pfonseca@cs.washington.edu> > Tested-by: Pedro Fonseca <pfonseca@cs.washington.edu> > Cc: Paolo Bonzini <pbonzini@redhat.com> > Cc: Radim Krčmář <rkrcmar@redhat.com> > Cc: Nadav Amit <nadav.amit@gmail.com> > Cc: Pedro Fonseca <pfonseca@cs.washington.edu> > Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com> > --- > v4 -> v5: > * cleanup patch subject/description > v3 -> v4: > * def_ad_bytes must be changed to 4 > * separate X86EMUL_MODE_PROT16 altogether from the others > v2 -> v3: > * cleanup the codes > v1 -> v2: > * respect cs.d for real/vm8096, other modes have already > been considered in init_emulate_ctxt(). > > arch/x86/kvm/emulate.c | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c > index 8079d14..b4a87de 100644 > --- a/arch/x86/kvm/emulate.c > +++ b/arch/x86/kvm/emulate.c > @@ -5000,6 +5000,8 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) > bool op_prefix = false; > bool has_seg_override = false; > struct opcode opcode; > + u16 dummy; > + struct desc_struct desc; > > ctxt->memop.type = OP_NONE; > ctxt->memopp = NULL; > @@ -5018,6 +5020,11 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) > switch (mode) { > case X86EMUL_MODE_REAL: > case X86EMUL_MODE_VM86: > + def_op_bytes = def_ad_bytes = 2; > + ctxt->ops->get_segment(ctxt, &dummy, &desc, NULL, VCPU_SREG_CS); > + if (desc.d) > + def_op_bytes = def_ad_bytes = 4; > + break; > case X86EMUL_MODE_PROT16: > def_op_bytes = def_ad_bytes = 2; > break; > Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Applied all three, thanks.
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 8079d14..b4a87de 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -5000,6 +5000,8 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) bool op_prefix = false; bool has_seg_override = false; struct opcode opcode; + u16 dummy; + struct desc_struct desc; ctxt->memop.type = OP_NONE; ctxt->memopp = NULL; @@ -5018,6 +5020,11 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) switch (mode) { case X86EMUL_MODE_REAL: case X86EMUL_MODE_VM86: + def_op_bytes = def_ad_bytes = 2; + ctxt->ops->get_segment(ctxt, &dummy, &desc, NULL, VCPU_SREG_CS); + if (desc.d) + def_op_bytes = def_ad_bytes = 4; + break; case X86EMUL_MODE_PROT16: def_op_bytes = def_ad_bytes = 2; break;