]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
x86/AMD: Load context when attempting to read VPMU MSRs
authorBoris Ostrovsky <boris.ostrovsky@oracle.com>
Mon, 15 Apr 2013 09:24:52 +0000 (11:24 +0200)
committerJan Beulich <jbeulich@suse.com>
Mon, 15 Apr 2013 09:24:52 +0000 (11:24 +0200)
Load context (and mark it as LOADED) on any MSR access. This will allow
us to always read the most up-to-date value of an MSR: guest may write
into an MSR without enabling it (thus not marking the context as RUNNING)
and then be migrated. Without first loading the context reading this MSR
from HW will not match the pervious write since registers will not be
loaded into HW in amd_vpmu_load().

In addition, we should be saving the context when it is LOADED, not
RUNNING --- otherwise we need to save it any time it becomes non-RUNNING,
which may be a frequent occurrence.

Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Reviewed-by: Dietmar Hahn <dietmar.hahn@ts.fujitsu.com>
xen/arch/x86/hvm/svm/vpmu.c

index 1e54497c431d26ffaf43e8c2825fc97451786161..4be56524dbdff34bd0a7caa9e1c6b5a7bc5b0644 100644 (file)
@@ -225,6 +225,8 @@ static void amd_vpmu_restore(struct vcpu *v)
 
     context_restore(v);
     apic_write(APIC_LVTPC, ctxt->hw_lapic_lvtpc);
+
+    vpmu_set(vpmu, VPMU_CONTEXT_LOADED);
 }
 
 static inline void context_save(struct vcpu *v)
@@ -246,7 +248,7 @@ static void amd_vpmu_save(struct vcpu *v)
     struct amd_vpmu_context *ctx = vpmu->context;
 
     if ( !(vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) &&
-           vpmu_is_set(vpmu, VPMU_RUNNING)) )
+           vpmu_is_set(vpmu, VPMU_CONTEXT_LOADED)) )
         return;
 
     context_save(v);
@@ -256,6 +258,7 @@ static void amd_vpmu_save(struct vcpu *v)
 
     ctx->hw_lapic_lvtpc = apic_read(APIC_LVTPC);
     apic_write(APIC_LVTPC,  ctx->hw_lapic_lvtpc | APIC_LVT_MASKED);
+    vpmu_reset(vpmu, VPMU_CONTEXT_LOADED);
 }
 
 static void context_update(unsigned int msr, u64 msr_content)
@@ -318,6 +321,12 @@ static int amd_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content)
         release_pmu_ownship(PMU_OWNER_HVM);
     }
 
+    if ( !vpmu_is_set(vpmu, VPMU_CONTEXT_LOADED) )
+    {
+        context_restore(v);
+        vpmu_set(vpmu, VPMU_CONTEXT_LOADED);
+    }
+
     /* Update vpmu context immediately */
     context_update(msr, msr_content);
 
@@ -328,7 +337,17 @@ static int amd_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content)
 
 static int amd_vpmu_do_rdmsr(unsigned int msr, uint64_t *msr_content)
 {
+    struct vcpu *v = current;
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+
+    if ( !vpmu_is_set(vpmu, VPMU_CONTEXT_LOADED) )
+    {
+        context_restore(v);
+        vpmu_set(vpmu, VPMU_CONTEXT_LOADED);
+    }
+
     rdmsrl(msr, *msr_content);
+
     return 1;
 }