| From 05c83ec9b73c8124555b706f6af777b10adf0862 Mon Sep 17 00:00:00 2001 |
| From: Nadav Amit <namit@cs.technion.ac.il> |
| Date: Thu, 18 Sep 2014 22:39:37 +0300 |
| Subject: KVM: x86: Fix wrong masking on relative jump/call |
| |
| From: Nadav Amit <namit@cs.technion.ac.il> |
| |
| commit 05c83ec9b73c8124555b706f6af777b10adf0862 upstream. |
| |
| Relative jumps and calls do the masking according to the operand size, and not |
| according to the address size as the KVM emulator does today. |
| |
| This patch fixes KVM behavior. |
| |
| Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/kvm/emulate.c | 27 ++++++++++++++++++++++----- |
| 1 file changed, 22 insertions(+), 5 deletions(-) |
| |
| --- a/arch/x86/kvm/emulate.c |
| +++ b/arch/x86/kvm/emulate.c |
| @@ -504,11 +504,6 @@ static void rsp_increment(struct x86_emu |
| masked_increment(reg_rmw(ctxt, VCPU_REGS_RSP), stack_mask(ctxt), inc); |
| } |
| |
| -static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) |
| -{ |
| - register_address_increment(ctxt, &ctxt->_eip, rel); |
| -} |
| - |
| static u32 desc_limit_scaled(struct desc_struct *desc) |
| { |
| u32 limit = get_desc_limit(desc); |
| @@ -568,6 +563,28 @@ static int emulate_nm(struct x86_emulate |
| return emulate_exception(ctxt, NM_VECTOR, 0, false); |
| } |
| |
| +static inline void assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst) |
| +{ |
| + switch (ctxt->op_bytes) { |
| + case 2: |
| + ctxt->_eip = (u16)dst; |
| + break; |
| + case 4: |
| + ctxt->_eip = (u32)dst; |
| + break; |
| + case 8: |
| + ctxt->_eip = dst; |
| + break; |
| + default: |
| + WARN(1, "unsupported eip assignment size\n"); |
| + } |
| +} |
| + |
| +static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) |
| +{ |
| + assign_eip_near(ctxt, ctxt->_eip + rel); |
| +} |
| + |
| static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg) |
| { |
| u16 selector; |