ia64/xen-unstable

changeset 18648:6bf61b830153

NextRIPS support for forthcoming AMD processors

Future versions of AMD processors will support a feature called
NextRIPS or Next RIP Save. This feature causes the processor
to store the next sequential RIP of a guest in the VMCB on
most instruction interrupts. The hypervisor can use this
information to determine how much memory to read to determine
the intercepted instruction, modestly improving performance.
The following patch implements support for this feature.

Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Oct 16 18:45:48 2008 +0100 (2008-10-16)
parents dc61548aa479
children 50aaffd8f87c
files xen/arch/x86/hvm/svm/emulate.c xen/include/asm-x86/hvm/svm/vmcb.h
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/emulate.c	Thu Oct 16 18:36:43 2008 +0100
     1.2 +++ b/xen/arch/x86/hvm/svm/emulate.c	Thu Oct 16 18:45:48 2008 +0100
     1.3 @@ -61,6 +61,33 @@ static unsigned long svm_rip2pointer(str
     1.4      return p;
     1.5  }
     1.6  
     1.7 +static unsigned long svm_nextrip_insn_length(struct vcpu *v)
     1.8 +{
     1.9 +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
    1.10 +
    1.11 +    if ( !cpu_has_svm_nrips || (vmcb->nextrip <= vmcb->rip) )
    1.12 +        return 0;
    1.13 +
    1.14 +    switch ( vmcb->exitcode )
    1.15 +    {
    1.16 +    case VMEXIT_CR0_READ... VMEXIT_DR15_WRITE:
    1.17 +        /* faults due to instruction intercepts */
    1.18 +        /* (exitcodes 84-95) are reserved */
    1.19 +    case VMEXIT_IDTR_READ ... VMEXIT_TR_WRITE:
    1.20 +    case VMEXIT_RDTSC ... VMEXIT_SWINT:
    1.21 +    case VMEXIT_INVD ... VMEXIT_INVLPGA:
    1.22 +    case VMEXIT_VMRUN ...  VMEXIT_MWAIT_CONDITIONAL:
    1.23 +    case VMEXIT_IOIO:
    1.24 +        /* ...and the rest of the #VMEXITs */
    1.25 +    case VMEXIT_CR0_SEL_WRITE:
    1.26 +    case VMEXIT_MSR:
    1.27 +    case VMEXIT_EXCEPTION_BP:
    1.28 +        return vmcb->nextrip - vmcb->rip;
    1.29 +    }
    1.30 +  
    1.31 +    return 0;
    1.32 +}
    1.33 +
    1.34  /* First byte: Length. Following bytes: Opcode bytes. */
    1.35  #define MAKE_INSTR(nm, ...) static const u8 OPCODE_##nm[] = { __VA_ARGS__ }
    1.36  MAKE_INSTR(INVD,   2, 0x0f, 0x08);
    1.37 @@ -118,6 +145,9 @@ int __get_instruction_length_from_list(s
    1.38      unsigned long fetch_addr;
    1.39      unsigned int fetch_len;
    1.40  
    1.41 +    if ( (inst_len = svm_nextrip_insn_length(v)) != 0 )
    1.42 +        return inst_len;
    1.43 +
    1.44      /* Fetch up to the next page break; we'll fetch from the next page
    1.45       * later if we have to. */
    1.46      fetch_addr = svm_rip2pointer(v);
     2.1 --- a/xen/include/asm-x86/hvm/svm/vmcb.h	Thu Oct 16 18:36:43 2008 +0100
     2.2 +++ b/xen/include/asm-x86/hvm/svm/vmcb.h	Thu Oct 16 18:45:48 2008 +0100
     2.3 @@ -393,7 +393,9 @@ struct vmcb_struct {
     2.4      eventinj_t  eventinj;       /* offset 0xA8 */
     2.5      u64 h_cr3;                  /* offset 0xB0 */
     2.6      lbrctrl_t lbr_control;      /* offset 0xB8 */
     2.7 -    u64 res09[104];             /* offset 0xC0 pad to save area */
     2.8 +    u64 res09;                  /* offset 0xC0 */
     2.9 +    u64 nextrip;                /* offset 0xC8 */
    2.10 +    u64 res10a[102];            /* offset 0xD0 pad to save area */
    2.11  
    2.12      svm_segment_register_t es;      /* offset 1024 */
    2.13      svm_segment_register_t cs;