ia64/xen-unstable

changeset 16365:fc8be8f3707b

x86, hvm: Better handling of INVD/WBINVD on VMX and SVM.
Also better handling of MONITOR/MWAIT on VMX.
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Fri Nov 09 12:05:27 2007 +0000 (2007-11-09)
parents 1dcb24e6c4e4
children 837f83225153
files xen/arch/x86/hvm/svm/emulate.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/svm/vmcb.c xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/svm/emulate.h xen/include/asm-x86/hvm/svm/vmcb.h xen/include/asm-x86/perfc_defn.h
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/emulate.c	Thu Nov 08 18:15:36 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/svm/emulate.c	Fri Nov 09 12:05:27 2007 +0000
     1.3 @@ -344,6 +344,7 @@ unsigned long svm_rip2pointer(struct vcp
     1.4   * Special case: Last byte, if zero, doesn't need to match. 
     1.5   */
     1.6  MAKE_INSTR(INVD,   2, 0x0f, 0x08);
     1.7 +MAKE_INSTR(WBINVD, 2, 0x0f, 0x09);
     1.8  MAKE_INSTR(CPUID,  2, 0x0f, 0xa2);
     1.9  MAKE_INSTR(RDMSR,  2, 0x0f, 0x32);
    1.10  MAKE_INSTR(WRMSR,  2, 0x0f, 0x30);
    1.11 @@ -378,6 +379,7 @@ MAKE_INSTR(INT3,   1, 0xcc);
    1.12  static const u8 *opc_bytes[INSTR_MAX_COUNT] = 
    1.13  {
    1.14      [INSTR_INVD]   = OPCODE_INVD,
    1.15 +    [INSTR_WBINVD] = OPCODE_WBINVD,
    1.16      [INSTR_CPUID]  = OPCODE_CPUID,
    1.17      [INSTR_RDMSR]  = OPCODE_RDMSR,
    1.18      [INSTR_WRMSR]  = OPCODE_WRMSR,
     2.1 --- a/xen/arch/x86/hvm/svm/svm.c	Thu Nov 08 18:15:36 2007 +0000
     2.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Fri Nov 09 12:05:27 2007 +0000
     2.3 @@ -1942,24 +1942,24 @@ static void svm_vmexit_do_hlt(struct vmc
     2.4      hvm_hlt(regs->eflags);
     2.5  }
     2.6  
     2.7 -static void svm_vmexit_do_invd(struct cpu_user_regs *regs)
     2.8 +static void svm_vmexit_do_invalidate_cache(struct cpu_user_regs *regs)
     2.9  {
    2.10 +    enum instruction_index list[] = { INSTR_INVD, INSTR_WBINVD };
    2.11 +    struct vcpu *curr = current;
    2.12 +    struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
    2.13      int inst_len;
    2.14 -    
    2.15 -    /* Invalidate the cache - we can't really do that safely - maybe we should 
    2.16 -     * WBINVD, but I think it's just fine to completely ignore it - we should 
    2.17 -     * have cache-snooping that solves it anyways. -- Mats P. 
    2.18 -     */
    2.19  
    2.20 -    /* Tell the user that we did this - just in case someone runs some really 
    2.21 -     * weird operating system and wants to know why it's not working...
    2.22 -     */
    2.23 -    gdprintk(XENLOG_WARNING, "INVD instruction intercepted - ignored\n");
    2.24 -    
    2.25 -    inst_len = __get_instruction_length(current, INSTR_INVD, NULL);
    2.26 +    if ( !list_empty(&(domain_hvm_iommu(curr->domain)->pdev_list)) )
    2.27 +    {
    2.28 +        vmcb->general2_intercepts &= ~GENERAL2_INTERCEPT_WBINVD;
    2.29 +        wbinvd();
    2.30 +    }
    2.31 +
    2.32 +    inst_len = __get_instruction_length_from_list(
    2.33 +        curr, list, ARRAY_SIZE(list), NULL, NULL);
    2.34      __update_guest_eip(regs, inst_len);
    2.35 -}    
    2.36 -        
    2.37 +}
    2.38 +
    2.39  void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
    2.40  {
    2.41      struct vcpu *v = current;
    2.42 @@ -2205,7 +2205,8 @@ asmlinkage void svm_vmexit_handler(struc
    2.43          break;
    2.44  
    2.45      case VMEXIT_INVD:
    2.46 -        svm_vmexit_do_invd(regs);
    2.47 +    case VMEXIT_WBINVD:
    2.48 +        svm_vmexit_do_invalidate_cache(regs);
    2.49          break;
    2.50  
    2.51      case VMEXIT_TASK_SWITCH: {
     3.1 --- a/xen/arch/x86/hvm/svm/vmcb.c	Thu Nov 08 18:15:36 2007 +0000
     3.2 +++ b/xen/arch/x86/hvm/svm/vmcb.c	Fri Nov 09 12:05:27 2007 +0000
     3.3 @@ -127,7 +127,8 @@ static int construct_vmcb(struct vcpu *v
     3.4          GENERAL2_INTERCEPT_VMRUN       | GENERAL2_INTERCEPT_VMMCALL     |
     3.5          GENERAL2_INTERCEPT_VMLOAD      | GENERAL2_INTERCEPT_VMSAVE      |
     3.6          GENERAL2_INTERCEPT_STGI        | GENERAL2_INTERCEPT_CLGI        |
     3.7 -        GENERAL2_INTERCEPT_SKINIT      | GENERAL2_INTERCEPT_RDTSCP;
     3.8 +        GENERAL2_INTERCEPT_SKINIT      | GENERAL2_INTERCEPT_RDTSCP      |
     3.9 +        GENERAL2_INTERCEPT_WBINVD;
    3.10  
    3.11      /* Intercept all debug-register writes. */
    3.12      vmcb->dr_intercepts = ~0u;
     4.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c	Thu Nov 08 18:15:36 2007 +0000
     4.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c	Fri Nov 09 12:05:27 2007 +0000
     4.3 @@ -84,6 +84,7 @@ static void vmx_init_vmcs_config(void)
     4.4  
     4.5      min = (CPU_BASED_HLT_EXITING |
     4.6             CPU_BASED_INVLPG_EXITING |
     4.7 +           CPU_BASED_MONITOR_EXITING |
     4.8             CPU_BASED_MWAIT_EXITING |
     4.9             CPU_BASED_MOV_DR_EXITING |
    4.10             CPU_BASED_ACTIVATE_IO_BITMAP |
     5.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Thu Nov 08 18:15:36 2007 +0000
     5.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Fri Nov 09 12:05:27 2007 +0000
     5.3 @@ -2881,10 +2881,9 @@ asmlinkage void vmx_vmexit_handler(struc
     5.4          if ( vmx_do_msr_write(regs) )
     5.5              __update_guest_eip(inst_len);
     5.6          break;
     5.7 +
     5.8      case EXIT_REASON_MWAIT_INSTRUCTION:
     5.9      case EXIT_REASON_MONITOR_INSTRUCTION:
    5.10 -    case EXIT_REASON_PAUSE_INSTRUCTION:
    5.11 -        goto exit_and_crash;
    5.12      case EXIT_REASON_VMCLEAR:
    5.13      case EXIT_REASON_VMLAUNCH:
    5.14      case EXIT_REASON_VMPTRLD:
    5.15 @@ -2894,8 +2893,6 @@ asmlinkage void vmx_vmexit_handler(struc
    5.16      case EXIT_REASON_VMWRITE:
    5.17      case EXIT_REASON_VMXOFF:
    5.18      case EXIT_REASON_VMXON:
    5.19 -        /* Report invalid opcode exception when a VMX guest tries to execute
    5.20 -            any of the VMX instructions */
    5.21          vmx_inject_hw_exception(v, TRAP_invalid_op, VMX_DELIVER_NO_ERROR_CODE);
    5.22          break;
    5.23  
    5.24 @@ -2911,6 +2908,15 @@ asmlinkage void vmx_vmexit_handler(struc
    5.25          break;
    5.26      }
    5.27  
    5.28 +    case EXIT_REASON_INVD:
    5.29 +    {
    5.30 +        inst_len = __get_instruction_length(); /* Safe: INVD */
    5.31 +        __update_guest_eip(inst_len);
    5.32 +        if ( !list_empty(&(domain_hvm_iommu(v->domain)->pdev_list)) )
    5.33 +            wbinvd();
    5.34 +        break;
    5.35 +    }
    5.36 +
    5.37      default:
    5.38      exit_and_crash:
    5.39          gdprintk(XENLOG_ERR, "Bad vmexit (reason %x)\n", exit_reason);
     6.1 --- a/xen/include/asm-x86/hvm/svm/emulate.h	Thu Nov 08 18:15:36 2007 +0000
     6.2 +++ b/xen/include/asm-x86/hvm/svm/emulate.h	Fri Nov 09 12:05:27 2007 +0000
     6.3 @@ -43,6 +43,7 @@ typedef enum OPERATING_MODE_ {
     6.4  /* Enumerate some standard instructions that we support */
     6.5  enum instruction_index {
     6.6      INSTR_INVD,
     6.7 +    INSTR_WBINVD,
     6.8      INSTR_CPUID,
     6.9      INSTR_RDMSR,
    6.10      INSTR_WRMSR,
     7.1 --- a/xen/include/asm-x86/hvm/svm/vmcb.h	Thu Nov 08 18:15:36 2007 +0000
     7.2 +++ b/xen/include/asm-x86/hvm/svm/vmcb.h	Fri Nov 09 12:05:27 2007 +0000
     7.3 @@ -72,7 +72,11 @@ enum GenericIntercept2bits
     7.4      GENERAL2_INTERCEPT_CLGI    = 1 << 5,
     7.5      GENERAL2_INTERCEPT_SKINIT  = 1 << 6,
     7.6      GENERAL2_INTERCEPT_RDTSCP  = 1 << 7,
     7.7 -    GENERAL2_INTERCEPT_ICEBP   = 1 << 8
     7.8 +    GENERAL2_INTERCEPT_ICEBP   = 1 << 8,
     7.9 +    GENERAL2_INTERCEPT_WBINVD  = 1 << 9,
    7.10 +    GENERAL2_INTERCEPT_MONITOR = 1 << 10,
    7.11 +    GENERAL2_INTERCEPT_MWAIT   = 1 << 11,
    7.12 +    GENERAL2_INTERCEPT_MWAIT_CONDITIONAL = 1 << 12
    7.13  };
    7.14  
    7.15  
    7.16 @@ -291,6 +295,10 @@ enum VMEXIT_EXITCODE
    7.17      VMEXIT_SKINIT           = 134,
    7.18      VMEXIT_RDTSCP           = 135,
    7.19      VMEXIT_ICEBP            = 136,
    7.20 +    VMEXIT_WBINVD           = 137,
    7.21 +    VMEXIT_MONITOR          = 138,
    7.22 +    VMEXIT_MWAIT            = 139,
    7.23 +    VMEXIT_MWAIT_CONDITIONAL= 140,
    7.24      VMEXIT_NPF              = 1024, /* nested paging fault */
    7.25      VMEXIT_INVALID          =  -1
    7.26  };
     8.1 --- a/xen/include/asm-x86/perfc_defn.h	Thu Nov 08 18:15:36 2007 +0000
     8.2 +++ b/xen/include/asm-x86/perfc_defn.h	Fri Nov 09 12:05:27 2007 +0000
     8.3 @@ -9,8 +9,8 @@ PERFCOUNTER_ARRAY(exceptions,           
     8.4  PERFCOUNTER_ARRAY(vmexits,              "vmexits", VMX_PERF_EXIT_REASON_SIZE)
     8.5  PERFCOUNTER_ARRAY(cause_vector,         "cause vector", VMX_PERF_VECTOR_SIZE)
     8.6  
     8.7 -#define VMEXIT_NPF_PERFC 137
     8.8 -#define SVM_PERF_EXIT_REASON_SIZE (1+137)
     8.9 +#define VMEXIT_NPF_PERFC 141
    8.10 +#define SVM_PERF_EXIT_REASON_SIZE (1+141)
    8.11  PERFCOUNTER_ARRAY(svmexits,             "SVMexits", SVM_PERF_EXIT_REASON_SIZE)
    8.12  
    8.13  PERFCOUNTER(seg_fixups,             "segmentation fixups")