]> xenbits.xensource.com Git - xen.git/commitdiff
VPMU: Enable vpmu for svm
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 13 May 2010 07:56:10 +0000 (08:56 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 13 May 2010 07:56:10 +0000 (08:56 +0100)
Signed-off-by: Wei Wang <wei.wang2@amd.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vpmu.c
xen/include/asm-x86/hvm/svm/svm.h

index 1f527a8222b2b358e9608acdb8d4bfda13e23f0e..4231079d131201e18b4e5249f0fa0a74787aa481 100644 (file)
@@ -639,6 +639,7 @@ static void svm_ctxt_switch_from(struct vcpu *v)
     svm_fpu_leave(v);
 
     svm_save_dr(v);
+    vpmu_save(v);
 
     svm_sync_vmcb(v);
     svm_vmload(root_vmcb[cpu]);
@@ -679,6 +680,7 @@ static void svm_ctxt_switch_to(struct vcpu *v)
 
     svm_vmsave(root_vmcb[cpu]);
     svm_vmload(v->arch.hvm_svm.vmcb);
+    vpmu_load(v);
 
     if ( cpu_has_rdtscp )
         wrmsrl(MSR_TSC_AUX, hvm_msr_tsc_aux(v));
@@ -742,12 +744,15 @@ static int svm_vcpu_initialise(struct vcpu *v)
         return rc;
     }
 
+    vpmu_initialise(v);
     return 0;
 }
 
 static void svm_vcpu_destroy(struct vcpu *v)
 {
     svm_destroy_vmcb(v);
+    vpmu_destroy(v);
+    passive_domain_destroy(v);
 }
 
 static void svm_inject_exception(
@@ -810,7 +815,7 @@ static int svm_event_pending(struct vcpu *v)
 
 static int svm_do_pmu_interrupt(struct cpu_user_regs *regs)
 {
-    return 0;
+    return vpmu_do_interrupt(regs);
 }
 
 static int svm_cpu_prepare(unsigned int cpu)
@@ -1071,6 +1076,17 @@ static int svm_msr_read_intercept(struct cpu_user_regs *regs)
         msr_content = vmcb->lastinttoip;
         break;
 
+    case MSR_K7_PERFCTR0:
+    case MSR_K7_PERFCTR1:
+    case MSR_K7_PERFCTR2:
+    case MSR_K7_PERFCTR3:
+    case MSR_K7_EVNTSEL0:
+    case MSR_K7_EVNTSEL1:
+    case MSR_K7_EVNTSEL2:
+    case MSR_K7_EVNTSEL3:
+        vpmu_do_rdmsr(regs);
+        goto done;
+
     default:
 
         if ( rdmsr_viridian_regs(ecx, &msr_content) ||
@@ -1089,6 +1105,7 @@ static int svm_msr_read_intercept(struct cpu_user_regs *regs)
     regs->eax = (uint32_t)msr_content;
     regs->edx = (uint32_t)(msr_content >> 32);
 
+done:
     HVMTRACE_3D (MSR_READ, ecx, regs->eax, regs->edx);
     HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx",
                 ecx, (unsigned long)regs->eax, (unsigned long)regs->edx);
@@ -1153,6 +1170,17 @@ static int svm_msr_write_intercept(struct cpu_user_regs *regs)
         vmcb->lastinttoip = msr_content;
         break;
 
+    case MSR_K7_PERFCTR0:
+    case MSR_K7_PERFCTR1:
+    case MSR_K7_PERFCTR2:
+    case MSR_K7_PERFCTR3:
+    case MSR_K7_EVNTSEL0:
+    case MSR_K7_EVNTSEL1:
+    case MSR_K7_EVNTSEL2:
+    case MSR_K7_EVNTSEL3:
+        vpmu_do_wrmsr(regs);
+        goto done;
+
     default:
         if ( wrmsr_viridian_regs(ecx, msr_content) )
             break;
@@ -1169,7 +1197,7 @@ static int svm_msr_write_intercept(struct cpu_user_regs *regs)
         }
         break;
     }
-
+done:
     return X86EMUL_OKAY;
 
  gpf:
index ac2129106fc7d36f24a93906dd351df26c2d2711..48c34790a058f93d84f6dc89192fbd088789b516 100644 (file)
@@ -30,6 +30,8 @@
 #include <public/sched.h>
 #include <public/hvm/save.h>
 #include <asm/hvm/vpmu.h>
+#include <asm/hvm/svm/svm.h>
+#include <asm/hvm/svm/vmcb.h>
 
 static int __read_mostly opt_vpmu_enabled;
 boolean_param("vpmu", opt_vpmu_enabled);
@@ -78,9 +80,14 @@ void vpmu_load(struct vcpu *v)
 }
 
 extern struct arch_vpmu_ops core2_vpmu_ops;
+extern struct arch_vpmu_ops amd_vpmu_ops;
+
 void vpmu_initialise(struct vcpu *v)
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
+    __u8 vendor = current_cpu_data.x86_vendor;
+    __u8 family = current_cpu_data.x86;
+    __u8 cpu_model = current_cpu_data.x86_model;
 
     if ( !opt_vpmu_enabled )
         return;
@@ -88,17 +95,45 @@ void vpmu_initialise(struct vcpu *v)
     if ( vpmu->flags & VPMU_CONTEXT_ALLOCATED )
         vpmu_destroy(v);
 
-    if ( current_cpu_data.x86 == 6 )
+    switch ( vendor )
     {
-        switch ( current_cpu_data.x86_model )
+        case X86_VENDOR_AMD:
         {
-        case 15:
-        case 23:
-        case 26:
-        case 29:
-            vpmu->arch_vpmu_ops = &core2_vpmu_ops;
-            break;
+            switch ( family )
+            {
+            case 0x10:
+                vpmu->arch_vpmu_ops = &amd_vpmu_ops;
+                break;
+            default:
+                printk("VMPU: Initialization failed. "
+                       "AMD processor family %d has not "
+                       "been supported\n", family);
+                return;
+            }
         }
+        break;
+
+        case X86_VENDOR_INTEL:
+        {
+            if ( family == 6 )
+            {
+                switch ( cpu_model )
+                {
+                case 15:
+                case 23:
+                case 26:
+                case 29:
+                    vpmu->arch_vpmu_ops = &core2_vpmu_ops;
+                    break;
+                }
+            }
+        }
+        break;
+
+        default:
+            printk("VMPU: Initialization failed. "
+                   "Unknown CPU vendor %d\n", vendor);
+            return;
     }
 
     if ( vpmu->arch_vpmu_ops != NULL )
index 9020aabffa176bf7d918ad0ecadfb4331e4ad55a..9a3743cc3002249e7112c5db322a70f81fb81de4 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/processor.h>
 #include <asm/hvm/svm/vmcb.h>
 #include <asm/i387.h>
+#include <asm/hvm/vpmu.h>
 
 void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb);