debuggers.hg

changeset 20673:c61953922215

Add RDTSCP instruction support for HVM VMX guest.

RDTSCP is introduced in Nehalem processor on Intel platform. Like
RDTSC, RDTSCP will return the TSC value, besides, it will return the
low 32bit of TSC_AUX MSR. Currently Linux kernel will write (node_id
<< 12 | process_id) into that MSR, so that when guest execs RDTSCP, it
will also get processor information. - This instruction is supported
for HVM only when the hardware has this capability (indicated by
cpuid).

Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Dec 14 07:46:57 2009 +0000 (2009-12-14)
parents 2d072636c4f8
children 3d505c9f1b73
files xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/cpufeature.h xen/include/asm-x86/hvm/vmx/vmcs.h xen/include/asm-x86/hvm/vmx/vmx.h xen/include/asm-x86/msr-index.h xen/include/public/arch-x86/hvm/save.h
line diff
     1.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c	Mon Dec 14 07:45:04 2009 +0000
     1.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c	Mon Dec 14 07:46:57 2009 +0000
     1.3 @@ -594,6 +594,11 @@ static int construct_vmcs(struct vcpu *v
     1.4          __vmwrite(PLE_WINDOW, ple_window);
     1.5      }
     1.6  
     1.7 +#ifdef __x86_64__
     1.8 +    if ( cpu_has_rdtscp )
     1.9 +        v->arch.hvm_vmx.secondary_exec_control |= SECONDARY_EXEC_ENABLE_RDTSCP;
    1.10 +#endif
    1.11 +
    1.12      if ( cpu_has_vmx_secondary_exec_control )
    1.13          __vmwrite(SECONDARY_VM_EXEC_CONTROL,
    1.14                    v->arch.hvm_vmx.secondary_exec_control);
     2.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Mon Dec 14 07:45:04 2009 +0000
     2.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Mon Dec 14 07:46:57 2009 +0000
     2.3 @@ -136,18 +136,31 @@ static void vmx_vcpu_destroy(struct vcpu
     2.4  
     2.5  static DEFINE_PER_CPU(struct vmx_msr_state, host_msr_state);
     2.6  
     2.7 -static u32 msr_index[VMX_MSR_COUNT] =
     2.8 +static u32 msr_index[] =
     2.9  {
    2.10      MSR_LSTAR, MSR_STAR, MSR_SYSCALL_MASK
    2.11  };
    2.12  
    2.13 +#define MSR_INDEX_SIZE (ARRAY_SIZE(msr_index))
    2.14 +
    2.15  static void vmx_save_host_msrs(void)
    2.16  {
    2.17      struct vmx_msr_state *host_msr_state = &this_cpu(host_msr_state);
    2.18      int i;
    2.19  
    2.20 -    for ( i = 0; i < VMX_MSR_COUNT; i++ )
    2.21 +    /*
    2.22 +     * If new MSR is needed to add into msr_index[] and VMX_INDEX_MSR_*** enum,
    2.23 +     * please note that elements in msr_index[] and VMX_INDEX_MSR_*** enum
    2.24 +     * are not the same. Currently we only save three MSRs(MSR_LSTAR, MSR_STAR,
    2.25 +     * and MSR_SYSCALL_MASK into host state. 
    2.26 +     */
    2.27 +    BUILD_BUG_ON(MSR_INDEX_SIZE != VMX_INDEX_MSR_TSC_AUX ||
    2.28 +                 VMX_INDEX_MSR_TSC_AUX != VMX_MSR_COUNT - 1);
    2.29 +    for ( i = 0; i < MSR_INDEX_SIZE; i++ )
    2.30          rdmsrl(msr_index[i], host_msr_state->msrs[i]);
    2.31 +
    2.32 +    if ( cpu_has_rdtscp )
    2.33 +        rdmsrl(MSR_TSC_AUX, host_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]);
    2.34  }
    2.35  
    2.36  #define WRITE_MSR(address)                                              \
    2.37 @@ -198,6 +211,21 @@ static enum handler_return long_mode_do_
    2.38          msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK];
    2.39          break;
    2.40  
    2.41 +    case MSR_TSC_AUX:
    2.42 +        if ( cpu_has_rdtscp ) 
    2.43 +        {
    2.44 +            msr_content = guest_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX];
    2.45 +            break;
    2.46 +        }
    2.47 +        else
    2.48 +        {
    2.49 +            HVM_DBG_LOG(DBG_LEVEL_0, "Reading from nonexistence msr 0x%x\n",
    2.50 +                        ecx);
    2.51 +            vmx_inject_hw_exception(TRAP_gp_fault, 0);
    2.52 +            return HNDL_exception_raised;
    2.53 +        }
    2.54 +            
    2.55 +
    2.56      default:
    2.57          return HNDL_unhandled;
    2.58      }
    2.59 @@ -259,6 +287,20 @@ static enum handler_return long_mode_do_
    2.60      case MSR_SYSCALL_MASK:
    2.61          WRITE_MSR(SYSCALL_MASK);
    2.62  
    2.63 +    case MSR_TSC_AUX:
    2.64 +        if ( cpu_has_rdtscp )
    2.65 +        {
    2.66 +            struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state;
    2.67 +            guest_state->msrs[VMX_INDEX_MSR_TSC_AUX] = msr_content;
    2.68 +            wrmsrl(MSR_TSC_AUX, msr_content);
    2.69 +        }
    2.70 +        else
    2.71 +        {
    2.72 +            HVM_DBG_LOG(DBG_LEVEL_0, "Writing to nonexistence msr 0x%x\n", ecx);
    2.73 +            vmx_inject_hw_exception(TRAP_gp_fault, 0);
    2.74 +            return HNDL_exception_raised;
    2.75 +        }
    2.76 +
    2.77      default:
    2.78          return HNDL_unhandled;
    2.79      }
    2.80 @@ -289,15 +331,21 @@ static void vmx_restore_host_msrs(void)
    2.81          wrmsrl(msr_index[i], host_msr_state->msrs[i]);
    2.82          clear_bit(i, &host_msr_state->flags);
    2.83      }
    2.84 +
    2.85 +    if ( cpu_has_rdtscp )
    2.86 +        wrmsrl(MSR_TSC_AUX, host_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]);
    2.87  }
    2.88  
    2.89  static void vmx_save_guest_msrs(struct vcpu *v)
    2.90  {
    2.91 +    struct vmx_msr_state *guest_msr_state = &v->arch.hvm_vmx.msr_state;
    2.92      /*
    2.93       * We cannot cache SHADOW_GS_BASE while the VCPU runs, as it can
    2.94       * be updated at any time via SWAPGS, which we cannot trap.
    2.95       */
    2.96      rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.shadow_gs);
    2.97 +    if ( cpu_has_rdtscp )
    2.98 +        rdmsrl(MSR_TSC_AUX, guest_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]);
    2.99  }
   2.100  
   2.101  static void vmx_restore_guest_msrs(struct vcpu *v)
   2.102 @@ -333,6 +381,9 @@ static void vmx_restore_guest_msrs(struc
   2.103          write_efer((read_efer() & ~EFER_SCE) |
   2.104                     (v->arch.hvm_vcpu.guest_efer & EFER_SCE));
   2.105      }
   2.106 +
   2.107 +    if ( cpu_has_rdtscp )
   2.108 +        wrmsrl(MSR_TSC_AUX, guest_msr_state->msrs[VMX_INDEX_MSR_TSC_AUX]);
   2.109  }
   2.110  
   2.111  #else  /* __i386__ */
   2.112 @@ -574,6 +625,8 @@ static void vmx_save_cpu_state(struct vc
   2.113      data->msr_lstar        = guest_state->msrs[VMX_INDEX_MSR_LSTAR];
   2.114      data->msr_star         = guest_state->msrs[VMX_INDEX_MSR_STAR];
   2.115      data->msr_syscall_mask = guest_state->msrs[VMX_INDEX_MSR_SYSCALL_MASK];
   2.116 +    if ( cpu_has_rdtscp )
   2.117 +        data->msr_tsc_aux = guest_state->msrs[VMX_INDEX_MSR_TSC_AUX];
   2.118  #endif
   2.119  
   2.120      data->tsc = hvm_get_guest_tsc(v);
   2.121 @@ -592,6 +645,8 @@ static void vmx_load_cpu_state(struct vc
   2.122  
   2.123      v->arch.hvm_vmx.cstar     = data->msr_cstar;
   2.124      v->arch.hvm_vmx.shadow_gs = data->shadow_gs;
   2.125 +    if ( cpu_has_rdtscp )
   2.126 +        guest_state->msrs[VMX_INDEX_MSR_TSC_AUX] = data->msr_tsc_aux;
   2.127  #endif
   2.128  
   2.129      hvm_set_guest_tsc(v, data->tsc);
   2.130 @@ -1507,6 +1562,14 @@ static void vmx_cpuid_intercept(
   2.131                  *edx |= bitmaskof(X86_FEATURE_SYSCALL);
   2.132              else
   2.133                  *edx &= ~(bitmaskof(X86_FEATURE_SYSCALL));
   2.134 +
   2.135 +#ifdef __x86_64__
   2.136 +            if ( cpu_has_rdtscp )
   2.137 +                *edx |= bitmaskof(X86_FEATURE_RDTSCP);
   2.138 +            else
   2.139 +                *edx &= ~(bitmaskof(X86_FEATURE_RDTSCP));
   2.140 +#endif
   2.141 +
   2.142              break;
   2.143      }
   2.144  
   2.145 @@ -2495,6 +2558,15 @@ asmlinkage void vmx_vmexit_handler(struc
   2.146          __update_guest_eip(inst_len);
   2.147          hvm_rdtsc_intercept(regs);
   2.148          break;
   2.149 +    case EXIT_REASON_RDTSCP:
   2.150 +    {
   2.151 +        struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state;
   2.152 +        inst_len = __get_instruction_length();
   2.153 +        __update_guest_eip(inst_len);
   2.154 +        hvm_rdtsc_intercept(regs);
   2.155 +        regs->ecx = (uint32_t)(guest_state->msrs[VMX_INDEX_MSR_TSC_AUX]);
   2.156 +        break;
   2.157 +    }
   2.158      case EXIT_REASON_VMCALL:
   2.159      {
   2.160          int rc;
     3.1 --- a/xen/include/asm-x86/cpufeature.h	Mon Dec 14 07:45:04 2009 +0000
     3.2 +++ b/xen/include/asm-x86/cpufeature.h	Mon Dec 14 07:46:57 2009 +0000
     3.3 @@ -196,6 +196,8 @@
     3.4  
     3.5  #define cpu_has_arch_perfmon    boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
     3.6  
     3.7 +#define cpu_has_rdtscp          boot_cpu_has(X86_FEATURE_RDTSCP)
     3.8 +
     3.9  #endif /* __ASM_I386_CPUFEATURE_H */
    3.10  
    3.11  /* 
     4.1 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h	Mon Dec 14 07:45:04 2009 +0000
     4.2 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h	Mon Dec 14 07:46:57 2009 +0000
     4.3 @@ -44,6 +44,7 @@ enum {
     4.4      VMX_INDEX_MSR_LSTAR = 0,
     4.5      VMX_INDEX_MSR_STAR,
     4.6      VMX_INDEX_MSR_SYSCALL_MASK,
     4.7 +    VMX_INDEX_MSR_TSC_AUX,
     4.8  
     4.9      VMX_MSR_COUNT
    4.10  };
    4.11 @@ -166,6 +167,7 @@ extern u32 vmx_vmentry_control;
    4.12  
    4.13  #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
    4.14  #define SECONDARY_EXEC_ENABLE_EPT               0x00000002
    4.15 +#define SECONDARY_EXEC_ENABLE_RDTSCP            0x00000008
    4.16  #define SECONDARY_EXEC_ENABLE_VPID              0x00000020
    4.17  #define SECONDARY_EXEC_WBINVD_EXITING           0x00000040
    4.18  #define SECONDARY_EXEC_UNRESTRICTED_GUEST       0x00000080
     5.1 --- a/xen/include/asm-x86/hvm/vmx/vmx.h	Mon Dec 14 07:45:04 2009 +0000
     5.2 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h	Mon Dec 14 07:46:57 2009 +0000
     5.3 @@ -110,6 +110,7 @@ void vmx_update_debug_state(struct vcpu 
     5.4  #define EXIT_REASON_APIC_ACCESS         44
     5.5  #define EXIT_REASON_EPT_VIOLATION       48
     5.6  #define EXIT_REASON_EPT_MISCONFIG       49
     5.7 +#define EXIT_REASON_RDTSCP              51
     5.8  #define EXIT_REASON_WBINVD              54
     5.9  #define EXIT_REASON_XSETBV              55
    5.10  
     6.1 --- a/xen/include/asm-x86/msr-index.h	Mon Dec 14 07:45:04 2009 +0000
     6.2 +++ b/xen/include/asm-x86/msr-index.h	Mon Dec 14 07:46:57 2009 +0000
     6.3 @@ -12,6 +12,7 @@
     6.4  #define MSR_FS_BASE		0xc0000100 /* 64bit FS base */
     6.5  #define MSR_GS_BASE		0xc0000101 /* 64bit GS base */
     6.6  #define MSR_SHADOW_GS_BASE	0xc0000102 /* SwapGS GS shadow */
     6.7 +#define MSR_TSC_AUX		0xc0000103 /* Auxiliary TSC */
     6.8  
     6.9  /* EFER bits: */
    6.10  #define _EFER_SCE		0  /* SYSCALL/SYSRET */
     7.1 --- a/xen/include/public/arch-x86/hvm/save.h	Mon Dec 14 07:45:04 2009 +0000
     7.2 +++ b/xen/include/public/arch-x86/hvm/save.h	Mon Dec 14 07:46:57 2009 +0000
     7.3 @@ -137,6 +137,7 @@ struct hvm_hw_cpu {
     7.4      uint64_t msr_cstar;
     7.5      uint64_t msr_syscall_mask;
     7.6      uint64_t msr_efer;
     7.7 +    uint64_t msr_tsc_aux;
     7.8  
     7.9      /* guest's idea of what rdtsc() would return */
    7.10      uint64_t tsc;