ia64/xen-unstable

changeset 12579:84c0f49de1b1

[PATCH] svm: fix RIP-relative addressing in invlpg emulation

RIP-relative addressing as relative to the beginning of the next (or,
in other word, the end of the current) instruction.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author kfraser@localhost.localdomain
date Mon Nov 27 10:06:41 2006 +0000 (2006-11-27)
parents b0a86eda868a
children f3ee62b7fb52
files xen/arch/x86/hvm/svm/emulate.c xen/arch/x86/hvm/svm/svm.c xen/include/asm-x86/hvm/svm/emulate.h
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/emulate.c	Mon Nov 27 10:05:23 2006 +0000
     1.2 +++ b/xen/arch/x86/hvm/svm/emulate.c	Mon Nov 27 10:06:41 2006 +0000
     1.3 @@ -145,8 +145,8 @@ static inline u64 hv_is_canonical(u64 ad
     1.4  
     1.5  
     1.6  unsigned long get_effective_addr_modrm64(struct vmcb_struct *vmcb, 
     1.7 -        struct cpu_user_regs *regs, const u8 prefix, const u8 *operand, 
     1.8 -        u8 *size)
     1.9 +        struct cpu_user_regs *regs, const u8 prefix, int inst_len,
    1.10 +        const u8 *operand, u8 *size)
    1.11  {
    1.12      unsigned long effective_addr = (unsigned long) -1;
    1.13      u8 length, modrm_mod, modrm_rm;
    1.14 @@ -191,17 +191,8 @@ unsigned long get_effective_addr_modrm64
    1.15              *size = 1;
    1.16              break;
    1.17          }
    1.18 -
    1.19 -        CHECK_LENGTH64(*size + (u8)sizeof(u32));
    1.20 -
    1.21 -        memcpy (&disp, operand + 1, sizeof (u32));
    1.22 -        *size += sizeof (u32);
    1.23 -        if (vmcb->cs.attributes.fields.l) // 64-bit mode
    1.24 -            return vmcb->rip + disp;
    1.25 -        else
    1.26 -            return disp;
    1.27 -
    1.28  #if __x86_64__
    1.29 +        /* FALLTHRU */
    1.30      case 0xD:
    1.31          if (0 < modrm_mod)
    1.32          {
    1.33 @@ -209,19 +200,20 @@ unsigned long get_effective_addr_modrm64
    1.34              effective_addr = regs->r13;
    1.35              break;
    1.36          }
    1.37 +#endif
    1.38  
    1.39          CHECK_LENGTH64(*size + (u8)sizeof(u32));
    1.40  
    1.41          memcpy (&disp, operand + 1, sizeof (u32));
    1.42          *size += sizeof (u32);
    1.43  
    1.44 +#if __x86_64__
    1.45          /* 64-bit mode */
    1.46 -        if (vmcb->cs.attributes.fields.l)
    1.47 -            return vmcb->rip + disp;
    1.48 -        else
    1.49 -            return disp;
    1.50 +        if (vmcb->cs.attributes.fields.l && (vmcb->efer & EFER_LMA))
    1.51 +            return vmcb->rip + inst_len + *size + disp;
    1.52 +#endif
    1.53 +        return disp;
    1.54  
    1.55 -#endif
    1.56      default:
    1.57          effective_addr = DECODE_GPR_VALUE(vmcb, regs, modrm_rm);
    1.58  
     2.1 --- a/xen/arch/x86/hvm/svm/svm.c	Mon Nov 27 10:05:23 2006 +0000
     2.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Mon Nov 27 10:06:41 2006 +0000
     2.3 @@ -2053,10 +2053,10 @@ void svm_handle_invlpg(const short invlp
     2.4  
     2.5          /* 
     2.6           * Decode memory operand of the instruction including ModRM, SIB, and
     2.7 -         * displacement to get effecticve address and length in bytes.  Assume
     2.8 +         * displacement to get effective address and length in bytes.  Assume
     2.9           * the system in either 32- or 64-bit mode.
    2.10           */
    2.11 -        g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix, 
    2.12 +        g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix, inst_len,
    2.13                                               &opcode[inst_len], &length);
    2.14  
    2.15          inst_len += length;
     3.1 --- a/xen/include/asm-x86/hvm/svm/emulate.h	Mon Nov 27 10:05:23 2006 +0000
     3.2 +++ b/xen/include/asm-x86/hvm/svm/emulate.h	Mon Nov 27 10:06:41 2006 +0000
     3.3 @@ -77,8 +77,8 @@ enum instruction_index {
     3.4  
     3.5  
     3.6  extern unsigned long get_effective_addr_modrm64(struct vmcb_struct *vmcb, 
     3.7 -        struct cpu_user_regs *regs, const u8 prefix, const u8 *operand, 
     3.8 -        u8 *size);
     3.9 +        struct cpu_user_regs *regs, const u8 prefix, int inst_len,
    3.10 +        const u8 *operand, u8 *size);
    3.11  extern unsigned long get_effective_addr_sib(struct vmcb_struct *vmcb, 
    3.12          struct cpu_user_regs *regs, const u8 prefix, const u8 *operand, 
    3.13          u8 *size);