hvm: handle PVRDTSCP mode
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 17 Dec 2009 06:22:02 +0000 (06:22 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 17 Dec 2009 06:22:02 +0000 (06:22 +0000)
Signed-off-by: Dan Magenheimer <dan.magenheimer@oracle.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/svm/vmcb.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/hvm.h

index 2f6242b59cea7fa092561c2b4cc6f22d2873a6a0..eb010013b439c95616aa5595246db49a4f0b25c4 100644 (file)
@@ -478,7 +478,7 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
         /* Architecture-specific vmcs/vmcb bits */
         hvm_funcs.save_cpu_ctxt(v, &ctxt);
 
-        ctxt.msr_tsc_aux = v->arch.hvm_vcpu.msr_tsc_aux;
+        ctxt.msr_tsc_aux = hvm_msr_tsc_aux(v);
 
         hvm_get_segment_register(v, x86_seg_idtr, &seg);
         ctxt.idtr_limit = seg.limit;
@@ -1898,6 +1898,11 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
             }
         }
         break;
+    case 0x80000001:
+        /* Don't expose RDTSCP feature when in PVRDTSCP mode. */
+        if ( v->domain->arch.tsc_mode == TSC_MODE_PVRDTSCP )
+            *edx &= ~bitmaskof(X86_FEATURE_RDTSCP);
+        break;
     }
 }
 
@@ -1934,7 +1939,7 @@ int hvm_msr_read_intercept(struct cpu_user_regs *regs)
         break;
 
     case MSR_TSC_AUX:
-        msr_content = v->arch.hvm_vcpu.msr_tsc_aux;
+        msr_content = hvm_msr_tsc_aux(v);
         break;
 
     case MSR_IA32_APICBASE:
@@ -2031,7 +2036,8 @@ int hvm_msr_write_intercept(struct cpu_user_regs *regs)
 
     case MSR_TSC_AUX:
         v->arch.hvm_vcpu.msr_tsc_aux = (uint32_t)msr_content;
-        if ( cpu_has_rdtscp )
+        if ( cpu_has_rdtscp
+             && (v->domain->arch.tsc_mode != TSC_MODE_PVRDTSCP) )
             wrmsrl(MSR_TSC_AUX, (uint32_t)msr_content);
         break;
 
index c297b0b509c9e353becc61391fff682b22a1a84d..4cb4d01c5a9ed01ea393ab4e2a61b16cbd546ff3 100644 (file)
@@ -674,6 +674,9 @@ static void svm_ctxt_switch_to(struct vcpu *v)
 
     svm_vmsave(root_vmcb[cpu]);
     svm_vmload(v->arch.hvm_svm.vmcb);
+
+    if ( cpu_has_rdtscp )
+        wrmsrl(MSR_TSC_AUX, hvm_msr_tsc_aux(v));
 }
 
 static void svm_do_resume(struct vcpu *v) 
@@ -1457,11 +1460,13 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
         hvm_triple_fault();
         break;
 
+    case VMEXIT_RDTSCP:
+        regs->ecx = hvm_msr_tsc_aux(v);
+        /* fall through */
     case VMEXIT_RDTSC:
         svm_vmexit_do_rdtsc(regs);
         break;
 
-    case VMEXIT_RDTSCP:
     case VMEXIT_MONITOR:
     case VMEXIT_MWAIT:
     case VMEXIT_VMRUN:
index 9218028221f29720dad2498cc2994abc38041863..95979627aacd4f0f2931a85810e454c9b7cc0881 100644 (file)
@@ -126,9 +126,8 @@ static int construct_vmcb(struct vcpu *v)
         GENERAL2_INTERCEPT_VMRUN       | GENERAL2_INTERCEPT_VMMCALL     |
         GENERAL2_INTERCEPT_VMLOAD      | GENERAL2_INTERCEPT_VMSAVE      |
         GENERAL2_INTERCEPT_STGI        | GENERAL2_INTERCEPT_CLGI        |
-        GENERAL2_INTERCEPT_SKINIT      | GENERAL2_INTERCEPT_RDTSCP      |
-        GENERAL2_INTERCEPT_WBINVD      | GENERAL2_INTERCEPT_MONITOR     |
-        GENERAL2_INTERCEPT_MWAIT;
+        GENERAL2_INTERCEPT_SKINIT      | GENERAL2_INTERCEPT_MWAIT       |
+        GENERAL2_INTERCEPT_WBINVD      | GENERAL2_INTERCEPT_MONITOR;
 
     /* Intercept all debug-register writes. */
     vmcb->dr_intercepts = ~0u;
@@ -165,7 +164,10 @@ static int construct_vmcb(struct vcpu *v)
     /* TSC. */
     vmcb->tsc_offset = 0;
     if ( v->domain->arch.vtsc )
+    {
         vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;
+        vmcb->general2_intercepts |= GENERAL2_INTERCEPT_RDTSCP;
+    }
 
     /* Guest EFER. */
     v->arch.hvm_vcpu.guest_efer = 0;
index b75bd584af7d64d780149129a2f604bd35604ebb..4c7d63d94e222a39221892731b895c51b5b9329d 100644 (file)
@@ -337,7 +337,7 @@ static void vmx_restore_guest_msrs(struct vcpu *v)
     }
 
     if ( cpu_has_rdtscp )
-        wrmsrl(MSR_TSC_AUX, v->arch.hvm_vcpu.msr_tsc_aux);
+        wrmsrl(MSR_TSC_AUX, hvm_msr_tsc_aux(v));
 }
 
 #else  /* __i386__ */
@@ -2495,7 +2495,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
         vmx_invlpg_intercept(exit_qualification);
         break;
     case EXIT_REASON_RDTSCP:
-        regs->ecx = v->arch.hvm_vcpu.msr_tsc_aux;
+        regs->ecx = hvm_msr_tsc_aux(v);
         /* fall through */
     case EXIT_REASON_RDTSC:
         inst_len = __get_instruction_length();
index 8643f92926400a452d0d6202838daddccd2f2c85..1697c8b31bcf600de387b5098a2108ad0f8ad152 100644 (file)
@@ -333,4 +333,10 @@ int hvm_debug_op(struct vcpu *v, int32_t op);
 
 bool_t hvm_hap_nested_page_fault(unsigned long gfn);
 
+#define hvm_msr_tsc_aux(v) ({                                               \
+    struct domain *__d = (v)->domain;                                       \
+    (__d->arch.tsc_mode == TSC_MODE_PVRDTSCP)                               \
+        ? (u32)__d->arch.incarnation : (u32)(v)->arch.hvm_vcpu.msr_tsc_aux; \
+})
+
 #endif /* __ASM_X86_HVM_HVM_H__ */