WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] vmx: Enable Core 2 Duo Performance Counte

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] vmx: Enable Core 2 Duo Performance Counters in HVM guest
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 30 Jan 2008 06:30:07 -0800
Delivery-date: Wed, 30 Jan 2008 07:29:01 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1201687167 0
# Node ID 6ea3db7ae24df1afd8e13e13c8c55ada95dd8d13
# Parent  47b7ec3b4055d59a09a1af26a29e8ef90e0d8d9c
vmx: Enable Core 2 Duo Performance Counters in HVM guest
Signed-off-by: Haitao Shan <haitao.shan@xxxxxxxxx>
---
 xen/arch/x86/apic.c                            |   13 
 xen/arch/x86/hvm/svm/svm.c                     |    8 
 xen/arch/x86/hvm/vmx/Makefile                  |    2 
 xen/arch/x86/hvm/vmx/vmx.c                     |   26 +
 xen/arch/x86/hvm/vmx/vpmu.c                    |  119 ++++++
 xen/arch/x86/hvm/vmx/vpmu_core2.c              |  469 +++++++++++++++++++++++++
 xen/arch/x86/i8259.c                           |    1 
 xen/arch/x86/oprofile/op_model_ppro.c          |    8 
 xen/common/xenoprof.c                          |   41 ++
 xen/include/asm-x86/hvm/hvm.h                  |    6 
 xen/include/asm-x86/hvm/vlapic.h               |    6 
 xen/include/asm-x86/hvm/vmx/vmcs.h             |    4 
 xen/include/asm-x86/hvm/vmx/vpmu.h             |   83 ++++
 xen/include/asm-x86/hvm/vmx/vpmu_core2.h       |   68 +++
 xen/include/asm-x86/irq.h                      |    1 
 xen/include/asm-x86/mach-default/irq_vectors.h |    3 
 xen/include/xen/xenoprof.h                     |    6 
 17 files changed, 861 insertions(+), 3 deletions(-)

diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/arch/x86/apic.c       Wed Jan 30 09:59:27 2008 +0000
@@ -93,6 +93,9 @@ void __init apic_intr_init(void)
     /* IPI vectors for APIC spurious and error interrupts */
     set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
     set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+
+    /* Performance Counters Interrupt */
+    set_intr_gate(PMU_APIC_VECTOR, pmu_apic_interrupt);
 
     /* thermal monitor LVT interrupt */
 #ifdef CONFIG_X86_MCE_P4THERMAL
@@ -1227,6 +1230,16 @@ fastcall void smp_error_interrupt(struct
 }
 
 /*
+ * This interrupt handles performance counters interrupt
+ */
+
+fastcall void smp_pmu_apic_interrupt(struct cpu_user_regs *regs)
+{
+    ack_APIC_irq();
+    hvm_do_pmu_interrupt(regs);
+}
+
+/*
  * This initializes the IO-APIC and APIC hardware if this is
  * a UP kernel.
  */
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c        Wed Jan 30 09:59:27 2008 +0000
@@ -860,6 +860,11 @@ static int svm_event_pending(struct vcpu
     return vmcb->eventinj.fields.v;
 }
 
+static int svm_do_pmu_interrupt(struct cpu_user_regs *regs)
+{
+    return 0;
+}
+
 static struct hvm_function_table svm_function_table = {
     .name                 = "SVM",
     .cpu_down             = svm_cpu_down,
@@ -882,7 +887,8 @@ static struct hvm_function_table svm_fun
     .set_tsc_offset       = svm_set_tsc_offset,
     .inject_exception     = svm_inject_exception,
     .init_hypercall_page  = svm_init_hypercall_page,
-    .event_pending        = svm_event_pending
+    .event_pending        = svm_event_pending,
+    .do_pmu_interrupt     = svm_do_pmu_interrupt
 };
 
 int start_svm(struct cpuinfo_x86 *c)
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/arch/x86/hvm/vmx/Makefile
--- a/xen/arch/x86/hvm/vmx/Makefile     Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/Makefile     Wed Jan 30 09:59:27 2008 +0000
@@ -9,3 +9,5 @@ endif
 endif
 obj-y += vmcs.o
 obj-y += vmx.o
+obj-y += vpmu.o
+obj-y += vpmu_core2.o
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Wed Jan 30 09:59:27 2008 +0000
@@ -90,6 +90,8 @@ static int vmx_vcpu_initialise(struct vc
         return rc;
     }
 
+    vpmu_initialise(v);
+
     vmx_install_vlapic_mapping(v);
 
 #ifndef VMXASSIST
@@ -104,6 +106,7 @@ static void vmx_vcpu_destroy(struct vcpu
 static void vmx_vcpu_destroy(struct vcpu *v)
 {
     vmx_destroy_vmcs(v);
+    vpmu_destroy(v);
 }
 
 #ifdef __x86_64__
@@ -742,6 +745,7 @@ static void vmx_ctxt_switch_from(struct 
     vmx_save_guest_msrs(v);
     vmx_restore_host_msrs();
     vmx_save_dr(v);
+    vpmu_save(v);
 }
 
 static void vmx_ctxt_switch_to(struct vcpu *v)
@@ -752,6 +756,7 @@ static void vmx_ctxt_switch_to(struct vc
 
     vmx_restore_guest_msrs(v);
     vmx_restore_dr(v);
+    vpmu_load(v);
 }
 
 static unsigned long vmx_get_segment_base(struct vcpu *v, enum x86_segment seg)
@@ -1117,6 +1122,11 @@ static int vmx_event_pending(struct vcpu
 {
     ASSERT(v == current);
     return (__vmread(VM_ENTRY_INTR_INFO) & INTR_INFO_VALID_MASK);
+}
+
+static int vmx_do_pmu_interrupt(struct cpu_user_regs *regs)
+{
+    return vpmu_do_interrupt(regs);
 }
 
 static struct hvm_function_table vmx_function_table = {
@@ -1141,6 +1151,7 @@ static struct hvm_function_table vmx_fun
     .inject_exception     = vmx_inject_exception,
     .init_hypercall_page  = vmx_init_hypercall_page,
     .event_pending        = vmx_event_pending,
+    .do_pmu_interrupt     = vmx_do_pmu_interrupt,
     .cpu_up               = vmx_cpu_up,
     .cpu_down             = vmx_cpu_down,
 };
@@ -1300,7 +1311,6 @@ void vmx_cpuid_intercept(
 
     case 0x00000006:
     case 0x00000009:
-    case 0x0000000A:
         *eax = *ebx = *ecx = *edx = 0;
         break;
 
@@ -2376,7 +2386,15 @@ static int vmx_do_msr_read(struct cpu_us
         /* No point in letting the guest see real MCEs */
         msr_content = 0;
         break;
+    case MSR_IA32_MISC_ENABLE:
+        rdmsrl(MSR_IA32_MISC_ENABLE, msr_content);
+        /* Debug Trace Store is not supported. */
+        msr_content |= MSR_IA32_MISC_ENABLE_BTS_UNAVAIL |
+                       MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL;
+        break;
     default:
+        if ( vpmu_do_rdmsr(regs) )
+            goto done;
         switch ( long_mode_do_msr_read(regs) )
         {
             case HNDL_unhandled:
@@ -2583,6 +2601,8 @@ static int vmx_do_msr_write(struct cpu_u
     case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_PROCBASED_CTLS2:
         goto gp_fault;
     default:
+        if ( vpmu_do_wrmsr(regs) )
+            return 1;
         switch ( long_mode_do_msr_write(regs) )
         {
             case HNDL_unhandled:
@@ -2632,6 +2652,7 @@ static void vmx_do_extint(struct cpu_use
     fastcall void smp_call_function_interrupt(void);
     fastcall void smp_spurious_interrupt(struct cpu_user_regs *regs);
     fastcall void smp_error_interrupt(struct cpu_user_regs *regs);
+    fastcall void smp_pmu_apic_interrupt(struct cpu_user_regs *regs);
 #ifdef CONFIG_X86_MCE_P4THERMAL
     fastcall void smp_thermal_interrupt(struct cpu_user_regs *regs);
 #endif
@@ -2661,6 +2682,9 @@ static void vmx_do_extint(struct cpu_use
         break;
     case ERROR_APIC_VECTOR:
         smp_error_interrupt(regs);
+        break;
+    case PMU_APIC_VECTOR:
+        smp_pmu_apic_interrupt(regs);
         break;
 #ifdef CONFIG_X86_MCE_P4THERMAL
     case THERMAL_APIC_VECTOR:
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/arch/x86/hvm/vmx/vpmu.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/hvm/vmx/vpmu.c       Wed Jan 30 09:59:27 2008 +0000
@@ -0,0 +1,119 @@
+/*
+ * vpmu.c: PMU virtualization for HVM domain.
+ *
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Haitao Shan <haitao.shan@xxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/sched.h>
+#include <asm/regs.h>
+#include <asm/types.h>
+#include <asm/msr.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/vmx/vmx.h>
+#include <asm/hvm/vmx/vmcs.h>
+#include <public/sched.h>
+#include <public/hvm/save.h>
+#include <asm/hvm/vmx/vpmu.h>
+
+int inline vpmu_do_wrmsr(struct cpu_user_regs *regs)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(current);
+
+    if ( vpmu->arch_vpmu_ops )
+        return vpmu->arch_vpmu_ops->do_wrmsr(regs);
+    return 0;
+}
+
+int inline vpmu_do_rdmsr(struct cpu_user_regs *regs)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(current);
+
+    if ( vpmu->arch_vpmu_ops )
+        return vpmu->arch_vpmu_ops->do_rdmsr(regs);
+    return 0;
+}
+
+int inline vpmu_do_interrupt(struct cpu_user_regs *regs)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(current);
+
+    if ( vpmu->arch_vpmu_ops )
+        return vpmu->arch_vpmu_ops->do_interrupt(regs);
+    return 0;
+}
+
+void vpmu_save(struct vcpu *v)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+
+    if ( vpmu->arch_vpmu_ops )
+        vpmu->arch_vpmu_ops->arch_vpmu_save(v);
+}
+
+void vpmu_load(struct vcpu *v)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+
+    if ( vpmu->arch_vpmu_ops )
+        vpmu->arch_vpmu_ops->arch_vpmu_load(v);
+}
+
+extern struct arch_vpmu_ops core2_vpmu_ops;
+void inline vpmu_initialise(struct vcpu *v)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+
+    /* If it is not a fresh initialization, release all resources
+     * before initialise again.
+     */
+    if ( vpmu->flags & VPMU_CONTEXT_ALLOCATED )
+        vpmu_destroy(v);
+
+    if ( current_cpu_data.x86 == 6 )
+    {
+        switch ( current_cpu_data.x86_model )
+        {
+        case 15:
+        case 23:
+            vpmu->arch_vpmu_ops = &core2_vpmu_ops;
+            dprintk(XENLOG_INFO,
+                   "Core 2 duo CPU detected for guest PMU usage.\n");
+            break;
+        }
+    }
+
+    if ( !vpmu->arch_vpmu_ops )
+    {
+        dprintk(XENLOG_WARNING, "Unsupport CPU model for guest PMU usage.\n");
+        return;
+    }
+
+    vpmu->flags = 0;
+    vpmu->context = NULL;
+    vpmu->arch_vpmu_ops->arch_vpmu_initialise(v);
+}
+
+void inline vpmu_destroy(struct vcpu *v)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+
+    if ( vpmu->arch_vpmu_ops )
+        vpmu->arch_vpmu_ops->arch_vpmu_destroy(v);
+}
+
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/arch/x86/hvm/vmx/vpmu_core2.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c Wed Jan 30 09:59:27 2008 +0000
@@ -0,0 +1,469 @@
+/*
+ * vpmu_core2.c: CORE 2 specific PMU virtualization for HVM domain.
+ *
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Haitao Shan <haitao.shan@xxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/sched.h>
+#include <asm/system.h>
+#include <asm/regs.h>
+#include <asm/types.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/vlapic.h>
+#include <asm/hvm/vmx/vmx.h>
+#include <asm/hvm/vmx/vmcs.h>
+#include <public/sched.h>
+#include <public/hvm/save.h>
+#include <asm/hvm/vmx/vpmu.h>
+#include <asm/hvm/vmx/vpmu_core2.h>
+
+static int arch_pmc_cnt = 0;
+
+static int core2_get_pmc_count(void)
+{
+    u32 eax, ebx, ecx, edx;
+
+    if ( arch_pmc_cnt )
+        return arch_pmc_cnt;
+
+    cpuid(0xa, &eax, &ebx, &ecx, &edx);
+    return arch_pmc_cnt = (eax & 0xff00) >> 8;
+}
+
+static int is_core2_vpmu_msr(u32 msr_index, int *type, int *index)
+{
+    int i;
+
+    for ( i=0; i < core2_counters.num; i++ )
+        if ( core2_counters.msr[i] == msr_index )
+        {
+            *type = MSR_TYPE_COUNTER;
+            *index = i;
+            return 1;
+        }
+    for ( i=0; i < core2_ctrls.num; i++ )
+        if ( core2_ctrls.msr[i] == msr_index )
+        {
+            *type = MSR_TYPE_CTRL;
+            *index = i;
+            return 1;
+        }
+
+    if ( msr_index == MSR_CORE_PERF_GLOBAL_CTRL ||
+         msr_index == MSR_CORE_PERF_GLOBAL_STATUS ||
+         msr_index == MSR_CORE_PERF_GLOBAL_OVF_CTRL )
+    {
+        *type = MSR_TYPE_GLOBAL;
+        return 1;
+    }
+
+    if ( msr_index >= MSR_IA32_PERFCTR0 &&
+         msr_index < MSR_IA32_PERFCTR0 + core2_get_pmc_count() )
+    {
+        *type = MSR_TYPE_ARCH_COUNTER;
+        *index = msr_index - MSR_IA32_PERFCTR0;
+        return 1;
+    }
+    if ( msr_index >= MSR_P6_EVNTSEL0 &&
+         msr_index < MSR_P6_EVNTSEL0 + core2_get_pmc_count() )
+    {
+        *type = MSR_TYPE_ARCH_CTRL;
+        *index = msr_index - MSR_P6_EVNTSEL0;
+        return 1;
+    }
+    return 0;
+}
+
+static void core2_vpmu_set_msr_bitmap(char *msr_bitmap)
+{
+    int i;
+
+    /* Allow Read/Write PMU Counters MSR Directly. */
+    for ( i=0; i < core2_counters.num; i++ )
+    {
+        clear_bit(msraddr_to_bitpos(core2_counters.msr[i]), msr_bitmap);
+        clear_bit(msraddr_to_bitpos(core2_counters.msr[i]), msr_bitmap + 
0x800);
+    }
+    for ( i=0; i < core2_get_pmc_count(); i++ )
+    {
+        clear_bit(msraddr_to_bitpos(MSR_IA32_PERFCTR0+i), msr_bitmap);
+        clear_bit(msraddr_to_bitpos(MSR_IA32_PERFCTR0+i), msr_bitmap + 0x800);
+    }
+    /* Allow Read PMU Non-global Controls Directly. */
+    for ( i=0; i < core2_ctrls.num; i++ )
+        clear_bit(msraddr_to_bitpos(core2_ctrls.msr[i]), msr_bitmap);
+    for ( i=0; i < core2_get_pmc_count(); i++ )
+        clear_bit(msraddr_to_bitpos(MSR_P6_EVNTSEL0+i), msr_bitmap);
+}
+
+static void core2_vpmu_unset_msr_bitmap(char *msr_bitmap)
+{
+    int i;
+
+    /* Undo all the changes to msr bitmap. */
+    for ( i=0; i < core2_counters.num; i++ )
+    {
+        set_bit(msraddr_to_bitpos(core2_counters.msr[i]), msr_bitmap);
+        set_bit(msraddr_to_bitpos(core2_counters.msr[i]), msr_bitmap + 0x800);
+    }
+    for ( i=0; i < core2_get_pmc_count(); i++ )
+    {
+        set_bit(msraddr_to_bitpos(MSR_IA32_PERFCTR0+i), msr_bitmap);
+        set_bit(msraddr_to_bitpos(MSR_IA32_PERFCTR0+i), msr_bitmap + 0x800);
+    }
+    for ( i=0; i < core2_ctrls.num; i++ )
+        set_bit(msraddr_to_bitpos(core2_ctrls.msr[i]), msr_bitmap);
+    for ( i=0; i < core2_get_pmc_count(); i++ )
+        set_bit(msraddr_to_bitpos(MSR_P6_EVNTSEL0+i), msr_bitmap);
+}
+
+static inline void __core2_vpmu_save(struct vcpu *v)
+{
+    int i;
+    struct core2_vpmu_context *core2_vpmu_cxt = vcpu_vpmu(v)->context;
+
+    for ( i=0; i < core2_counters.num; i++ )
+        rdmsrl(core2_counters.msr[i], core2_vpmu_cxt->counters[i]);
+    for ( i=0; i < core2_get_pmc_count(); i++ )
+        rdmsrl(MSR_IA32_PERFCTR0+i, core2_vpmu_cxt->arch_msr_pair[i].counter);
+    core2_vpmu_cxt->hw_lapic_lvtpc = apic_read(APIC_LVTPC);
+    apic_write(APIC_LVTPC, LVTPC_HVM_PMU | APIC_LVT_MASKED);
+}
+
+static void core2_vpmu_save(struct vcpu *v)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+
+    if ( !((vpmu->flags & VPMU_CONTEXT_ALLOCATED) &&
+           (vpmu->flags & VPMU_CONTEXT_LOADED)) )
+        return;
+
+    __core2_vpmu_save(v);
+
+    /* Unset PMU MSR bitmap to trap lazy load. */
+    if ( !(vpmu->flags & VPMU_RUNNING) && cpu_has_vmx_msr_bitmap )
+        core2_vpmu_unset_msr_bitmap(v->arch.hvm_vmx.msr_bitmap);
+
+    vpmu->flags &= ~VPMU_CONTEXT_LOADED;
+    return;
+}
+
+static inline void __core2_vpmu_load(struct vcpu *v)
+{
+    int i;
+    struct core2_vpmu_context *core2_vpmu_cxt = vcpu_vpmu(v)->context;
+
+    for ( i=0; i < core2_counters.num; i++ )
+        wrmsrl(core2_counters.msr[i], core2_vpmu_cxt->counters[i]);
+    for ( i=0; i < core2_get_pmc_count(); i++ )
+        wrmsrl(MSR_IA32_PERFCTR0+i, core2_vpmu_cxt->arch_msr_pair[i].counter);
+
+    for ( i=0; i < core2_ctrls.num; i++ )
+        wrmsrl(core2_ctrls.msr[i], core2_vpmu_cxt->ctrls[i]);
+    for ( i=0; i < core2_get_pmc_count(); i++ )
+        wrmsrl(MSR_P6_EVNTSEL0+i, core2_vpmu_cxt->arch_msr_pair[i].control);
+
+    apic_write_around(APIC_LVTPC, core2_vpmu_cxt->hw_lapic_lvtpc);
+}
+
+static void core2_vpmu_load(struct vcpu *v)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+
+    /* Only when PMU is counting, we load PMU context immediately. */
+    if ( !((vpmu->flags & VPMU_CONTEXT_ALLOCATED) &&
+           (vpmu->flags & VPMU_RUNNING)) )
+        return;
+    __core2_vpmu_load(v);
+    vpmu->flags |= VPMU_CONTEXT_LOADED;
+}
+
+static int core2_vpmu_alloc_resource(struct vcpu *v)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+    struct core2_vpmu_context *core2_vpmu_cxt;
+    struct core2_pmu_enable *pmu_enable;
+
+    if ( !acquire_pmu_ownership(PMU_OWNER_HVM) )
+        return 0;
+
+    wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
+    if ( vmx_add_host_load_msr(v, MSR_CORE_PERF_GLOBAL_CTRL) )
+        return 0;
+
+    if ( vmx_add_guest_msr(v, MSR_CORE_PERF_GLOBAL_CTRL) )
+        return 0;
+    vmx_write_guest_msr(v, MSR_CORE_PERF_GLOBAL_CTRL, -1ULL);
+
+    pmu_enable = xmalloc_bytes(sizeof(struct core2_pmu_enable) +
+                 (core2_get_pmc_count()-1)*sizeof(char));
+    if ( !pmu_enable )
+        goto out1;
+    memset(pmu_enable, 0, sizeof(struct core2_pmu_enable) +
+                 (core2_get_pmc_count()-1)*sizeof(char));
+
+    core2_vpmu_cxt = xmalloc_bytes(sizeof(struct core2_vpmu_context) +
+                    (core2_get_pmc_count()-1)*sizeof(struct arch_msr_pair));
+    if ( !core2_vpmu_cxt )
+        goto out2;
+    memset(core2_vpmu_cxt, 0, sizeof(struct core2_vpmu_context) +
+                    (core2_get_pmc_count()-1)*sizeof(struct arch_msr_pair));
+    core2_vpmu_cxt->pmu_enable = pmu_enable;
+    vpmu->context = (void *)core2_vpmu_cxt;
+
+    return 1;
+ out2:
+    xfree(pmu_enable);
+ out1:
+    dprintk(XENLOG_WARNING, "Insufficient memory for PMU, PMU feature is \
+            unavailable on domain %d vcpu %d.\n",
+            v->vcpu_id, v->domain->domain_id);
+    return 0;
+}
+
+static void core2_vpmu_save_msr_context(struct vcpu *v, int type,
+                                       int index, u64 msr_data)
+{
+    struct core2_vpmu_context *core2_vpmu_cxt = vcpu_vpmu(v)->context;
+
+    switch ( type )
+    {
+    case MSR_TYPE_CTRL:
+        core2_vpmu_cxt->ctrls[index] = msr_data;
+        break;
+    case MSR_TYPE_ARCH_CTRL:
+        core2_vpmu_cxt->arch_msr_pair[index].control = msr_data;
+        break;
+    }
+}
+
+static int core2_vpmu_msr_common_check(u32 msr_index, int *type, int *index)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(current);
+
+    if ( !is_core2_vpmu_msr(msr_index, type, index) )
+        return 0;
+
+    if ( unlikely(!(vpmu->flags & VPMU_CONTEXT_ALLOCATED)) &&
+         !core2_vpmu_alloc_resource(current) )
+        return 0;
+    vpmu->flags |= VPMU_CONTEXT_ALLOCATED;
+
+    /* Do the lazy load staff. */
+    if ( !(vpmu->flags & VPMU_CONTEXT_LOADED) )
+    {
+        __core2_vpmu_load(current);
+        vpmu->flags |= VPMU_CONTEXT_LOADED;
+        if ( cpu_has_vmx_msr_bitmap )
+            core2_vpmu_set_msr_bitmap(current->arch.hvm_vmx.msr_bitmap);
+    }
+    return 1;
+}
+
+static int core2_vpmu_do_wrmsr(struct cpu_user_regs *regs)
+{
+    u32 ecx = regs->ecx;
+    u64 msr_content, global_ctrl, non_global_ctrl;
+    char pmu_enable = 0;
+    int i, tmp;
+    int type = -1, index = -1;
+    struct vcpu *v = current;
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+    struct core2_vpmu_context *core2_vpmu_cxt = NULL;
+
+    if ( !core2_vpmu_msr_common_check(ecx, &type, &index) )
+        return 0;
+
+    msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
+    core2_vpmu_cxt = vpmu->context;
+    switch ( ecx )
+    {
+    case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+        core2_vpmu_cxt->global_ovf_status &= ~msr_content;
+        return 1;
+    case MSR_CORE_PERF_GLOBAL_STATUS:
+        dprintk(XENLOG_INFO, "Can not write readonly MSR: \
+                            MSR_PERF_GLOBAL_STATUS(0x38E)!\n");
+        vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
+        return 1;
+    case MSR_IA32_PEBS_ENABLE:
+        if ( msr_content & 1 )
+            dprintk(XENLOG_WARNING, "Guest is trying to enable PEBS, \
+                    which is not supported.\n");
+        return 1;
+    case MSR_IA32_DS_AREA:
+        dprintk(XENLOG_WARNING, "Guest setting of DTS is ignored.\n");
+        return 1;
+    case MSR_CORE_PERF_GLOBAL_CTRL:
+        global_ctrl = msr_content;
+        for ( i = 0; i < core2_get_pmc_count(); i++ )
+        {
+            rdmsrl(MSR_P6_EVNTSEL0+i, non_global_ctrl);
+            core2_vpmu_cxt->pmu_enable->arch_pmc_enable[i] =
+                    global_ctrl & (non_global_ctrl >> 22) & 1;
+            global_ctrl >>= 1;
+        }
+
+        rdmsrl(MSR_CORE_PERF_FIXED_CTR_CTRL, non_global_ctrl);
+        global_ctrl = msr_content >> 32;
+        for ( i = 0; i < 3; i++ )
+        {
+            core2_vpmu_cxt->pmu_enable->fixed_ctr_enable[i] =
+                (global_ctrl & 1) & ((non_global_ctrl & 0x3)? 1: 0);
+            non_global_ctrl >>= 4;
+            global_ctrl >>= 1;
+        }
+        break;
+    case MSR_CORE_PERF_FIXED_CTR_CTRL:
+        non_global_ctrl = msr_content;
+        vmx_read_guest_msr(v, MSR_CORE_PERF_GLOBAL_CTRL, &global_ctrl);
+        global_ctrl >>= 32;
+        for ( i = 0; i < 3; i++ )
+        {
+            core2_vpmu_cxt->pmu_enable->fixed_ctr_enable[i] =
+                (global_ctrl & 1) & ((non_global_ctrl & 0x3)? 1: 0);
+            non_global_ctrl >>= 4;
+            global_ctrl >>= 1;
+        }
+        break;
+    default:
+        tmp = ecx - MSR_P6_EVNTSEL0;
+        vmx_read_guest_msr(v, MSR_CORE_PERF_GLOBAL_CTRL, &global_ctrl);
+        if ( tmp >= 0 && tmp < core2_get_pmc_count() )
+            core2_vpmu_cxt->pmu_enable->arch_pmc_enable[tmp] =
+                (global_ctrl >> tmp) & (msr_content >> 22) & 1;
+    }
+
+    for ( i = 0; i < 3; i++ )
+        pmu_enable |= core2_vpmu_cxt->pmu_enable->fixed_ctr_enable[i];
+    for ( i = 0; i < core2_get_pmc_count(); i++ )
+        pmu_enable |= core2_vpmu_cxt->pmu_enable->arch_pmc_enable[i];
+    if ( pmu_enable )
+        vpmu->flags |= VPMU_RUNNING;
+    else
+        vpmu->flags &= ~VPMU_RUNNING;
+
+    /* Setup LVTPC in local apic */
+    if ( vpmu->flags & VPMU_RUNNING &&
+         is_vlapic_lvtpc_enabled(vcpu_vlapic(v)) )
+        apic_write_around(APIC_LVTPC, LVTPC_HVM_PMU);
+    else
+        apic_write_around(APIC_LVTPC, LVTPC_HVM_PMU | APIC_LVT_MASKED);
+
+    core2_vpmu_save_msr_context(v, type, index, msr_content);
+    if ( type != MSR_TYPE_GLOBAL )
+        wrmsrl(ecx, msr_content);
+    else
+        vmx_write_guest_msr(v, MSR_CORE_PERF_GLOBAL_CTRL, msr_content);
+
+    return 1;
+}
+
+static int core2_vpmu_do_rdmsr(struct cpu_user_regs *regs)
+{
+    u64 msr_content = 0;
+    int type = -1, index = -1;
+    struct vcpu *v = current;
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+    struct core2_vpmu_context *core2_vpmu_cxt = NULL;
+
+    if ( !core2_vpmu_msr_common_check(regs->ecx, &type, &index) )
+        return 0;
+
+    core2_vpmu_cxt = vpmu->context;
+    switch ( regs->ecx )
+    {
+    case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+        break;
+    case MSR_CORE_PERF_GLOBAL_STATUS:
+        msr_content = core2_vpmu_cxt->global_ovf_status;
+        break;
+    case MSR_CORE_PERF_GLOBAL_CTRL:
+        vmx_read_guest_msr(v, MSR_CORE_PERF_GLOBAL_CTRL, &msr_content);
+        break;
+    default:
+        rdmsrl(regs->ecx, msr_content);
+    }
+
+    regs->eax = msr_content & 0xFFFFFFFF;
+    regs->edx = msr_content >> 32;
+    return 1;
+}
+
+static int core2_vpmu_do_interrupt(struct cpu_user_regs *regs)
+{
+    struct vcpu *v = current;
+    u64 msr_content;
+    u32 vlapic_lvtpc;
+    unsigned char int_vec;
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+    struct core2_vpmu_context *core2_vpmu_cxt = vpmu->context;
+    struct vlapic *vlapic = vcpu_vlapic(v);
+
+    rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, msr_content);
+    if ( !msr_content )
+        return 0;
+    core2_vpmu_cxt->global_ovf_status |= msr_content;
+    wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, 0xC000000700000003);
+
+    apic_write_around(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
+
+    if ( !is_vlapic_lvtpc_enabled(vlapic) )
+        return 1;
+
+    vlapic_lvtpc = vlapic_get_reg(vlapic, APIC_LVTPC);
+    int_vec = vlapic_lvtpc & APIC_VECTOR_MASK;
+    vlapic_set_reg(vlapic, APIC_LVTPC, vlapic_lvtpc | APIC_LVT_MASKED);
+    if ( GET_APIC_DELIVERY_MODE(vlapic_lvtpc) == APIC_MODE_FIXED )
+        vlapic_set_irq(vcpu_vlapic(v), int_vec, 0);
+    else
+        test_and_set_bool(v->nmi_pending);
+    return 1;
+}
+
+static void core2_vpmu_initialise(struct vcpu *v)
+{
+}
+
+static void core2_vpmu_destroy(struct vcpu *v)
+{
+    struct vpmu_struct *vpmu = vcpu_vpmu(v);
+    struct core2_vpmu_context *core2_vpmu_cxt = vpmu->context;
+
+    if ( !vpmu->flags & VPMU_CONTEXT_ALLOCATED )
+        return;
+    xfree(core2_vpmu_cxt->pmu_enable);
+    xfree(vpmu->context);
+    if ( cpu_has_vmx_msr_bitmap )
+        core2_vpmu_unset_msr_bitmap(v->arch.hvm_vmx.msr_bitmap);
+    release_pmu_ownship(PMU_OWNER_HVM);
+}
+
+struct arch_vpmu_ops core2_vpmu_ops = {
+    .do_wrmsr = core2_vpmu_do_wrmsr,
+    .do_rdmsr = core2_vpmu_do_rdmsr,
+    .do_interrupt = core2_vpmu_do_interrupt,
+    .arch_vpmu_initialise = core2_vpmu_initialise,
+    .arch_vpmu_destroy = core2_vpmu_destroy,
+    .arch_vpmu_save = core2_vpmu_save,
+    .arch_vpmu_load = core2_vpmu_load
+};
+
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/arch/x86/i8259.c
--- a/xen/arch/x86/i8259.c      Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/arch/x86/i8259.c      Wed Jan 30 09:59:27 2008 +0000
@@ -72,6 +72,7 @@ BUILD_SMP_INTERRUPT(apic_timer_interrupt
 BUILD_SMP_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
 BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
 BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
+BUILD_SMP_INTERRUPT(pmu_apic_interrupt,PMU_APIC_VECTOR)
 BUILD_SMP_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR)
 
 #define IRQ(x,y) \
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/arch/x86/oprofile/op_model_ppro.c
--- a/xen/arch/x86/oprofile/op_model_ppro.c     Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/arch/x86/oprofile/op_model_ppro.c     Wed Jan 30 09:59:27 2008 +0000
@@ -41,6 +41,7 @@
 #define CTRL_SET_EVENT(val, e) (val |= e)
 
 static unsigned long reset_value[NUM_COUNTERS];
+int ppro_has_global_ctrl = 0;
  
 static void ppro_fill_in_addresses(struct op_msrs * const msrs)
 {
@@ -134,6 +135,11 @@ static void ppro_start(struct op_msrs co
                        CTRL_WRITE(low, high, msrs, i);
                }
        }
+    /* Global Control MSR is enabled by default when system power on.
+     * However, this may not hold true when xenoprof starts to run.
+     */
+    if ( ppro_has_global_ctrl )
+        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, (1<<NUM_COUNTERS) - 1);
 }
 
 
@@ -149,6 +155,8 @@ static void ppro_stop(struct op_msrs con
                CTRL_SET_INACTIVE(low);
                CTRL_WRITE(low, high, msrs, i);
        }
+    if ( ppro_has_global_ctrl )
+        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
 }
 
 
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/common/xenoprof.c
--- a/xen/common/xenoprof.c     Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/common/xenoprof.c     Wed Jan 30 09:59:27 2008 +0000
@@ -23,6 +23,10 @@
 /* Lock protecting the following global state */
 static DEFINE_SPINLOCK(xenoprof_lock);
 
+static DEFINE_SPINLOCK(pmu_owner_lock);
+int pmu_owner = 0;
+int pmu_hvm_refcount = 0;
+
 static struct domain *active_domains[MAX_OPROF_DOMAINS];
 static int active_ready[MAX_OPROF_DOMAINS];
 static unsigned int adomains;
@@ -43,6 +47,37 @@ static u64 passive_samples;
 static u64 passive_samples;
 static u64 idle_samples;
 static u64 others_samples;
+
+int acquire_pmu_ownership(int pmu_ownship)
+{
+    spin_lock(&pmu_owner_lock);
+    if ( pmu_owner == PMU_OWNER_NONE )
+    {
+        pmu_owner = pmu_ownship;
+        goto out;
+    }
+
+    if ( pmu_owner == pmu_ownship )
+        goto out;
+
+    spin_unlock(&pmu_owner_lock);
+    return 0;
+ out:
+    if ( pmu_owner == PMU_OWNER_HVM )
+        pmu_hvm_refcount++;
+    spin_unlock(&pmu_owner_lock);
+    return 1;
+}
+
+void release_pmu_ownship(int pmu_ownship)
+{
+    spin_lock(&pmu_owner_lock);
+    if ( pmu_ownship == PMU_OWNER_HVM )
+        pmu_hvm_refcount--;
+    if ( !pmu_hvm_refcount )
+        pmu_owner = PMU_OWNER_NONE;
+    spin_unlock(&pmu_owner_lock);
+}
 
 int is_active(struct domain *d)
 {
@@ -649,6 +684,11 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
         break;
 
     case XENOPROF_get_buffer:
+        if ( !acquire_pmu_ownership(PMU_OWNER_XENOPROF) )
+        {
+            ret = -EBUSY;
+            break;
+        }
         ret = xenoprof_op_get_buffer(arg);
         break;
 
@@ -786,6 +826,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
             break;
         x = current->domain->xenoprof;
         unshare_xenoprof_page_with_guest(x);
+        release_pmu_ownship(PMU_OWNER_XENOPROF);
         break;
     }
 
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/include/asm-x86/hvm/hvm.h     Wed Jan 30 09:59:27 2008 +0000
@@ -119,6 +119,7 @@ struct hvm_function_table {
     void (*init_hypercall_page)(struct domain *d, void *hypercall_page);
 
     int  (*event_pending)(struct vcpu *v);
+    int  (*do_pmu_interrupt)(struct cpu_user_regs *regs);
 
     int  (*cpu_up)(void);
     void (*cpu_down)(void);
@@ -233,6 +234,11 @@ static inline int hvm_event_pending(stru
 static inline int hvm_event_pending(struct vcpu *v)
 {
     return hvm_funcs.event_pending(v);
+}
+
+static inline int hvm_do_pmu_interrupt(struct cpu_user_regs *regs)
+{
+    return hvm_funcs.do_pmu_interrupt(regs);
 }
 
 /* These reserved bits in lower 32 remain 0 after any load of CR0 */
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h  Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/include/asm-x86/hvm/vlapic.h  Wed Jan 30 09:59:27 2008 +0000
@@ -71,6 +71,12 @@ static inline void vlapic_set_reg(
     *((uint32_t *)(&vlapic->regs->data[reg])) = val;
 }
 
+static inline int is_vlapic_lvtpc_enabled(struct vlapic *vlapic)
+{
+    return vlapic_enabled(vlapic) &&
+           !(vlapic_get_reg(vlapic, APIC_LVTPC) & APIC_LVT_MASKED);
+}
+
 int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig);
 
 int vlapic_has_pending_irq(struct vcpu *v);
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h        Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h        Wed Jan 30 09:59:27 2008 +0000
@@ -22,6 +22,7 @@
 #include <asm/config.h>
 #include <asm/hvm/io.h>
 #include <asm/hvm/vmx/cpu.h>
+#include <asm/hvm/vmx/vpmu.h>
 
 #ifdef VMXASSIST
 #include <public/hvm/vmx_assist.h>
@@ -75,6 +76,9 @@ struct arch_vmx_struct {
 
     /* Cache of cpu execution control. */
     u32                  exec_control;
+
+    /* PMU */
+    struct vpmu_struct   vpmu;
 
 #ifdef __x86_64__
     struct vmx_msr_state msr_state;
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/include/asm-x86/hvm/vmx/vpmu.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vpmu.h        Wed Jan 30 09:59:27 2008 +0000
@@ -0,0 +1,83 @@
+/*
+ * vpmu.h: PMU virtualization for HVM domain.
+ *
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Haitao Shan <haitao.shan@xxxxxxxxx>
+ */
+
+#ifndef __ASM_X86_HVM_VPMU_H_
+#define __ASM_X86_HVM_VPMU_H_
+
+#define msraddr_to_bitpos(x) (((x)&0xffff) + ((x)>>31)*0x2000)
+#define vcpu_vpmu(vcpu)   (&(vcpu)->arch.hvm_vcpu.u.vmx.vpmu)
+#define vpmu_vcpu(vpmu)   (container_of((vpmu), struct vcpu, \
+                                          arch.hvm_vcpu.u.vmx.vpmu))
+#define vpmu_domain(vpmu) (vpmu_vcpu(vpmu)->domain)
+
+#define MSR_TYPE_COUNTER            0
+#define MSR_TYPE_CTRL               1
+#define MSR_TYPE_GLOBAL             2
+#define MSR_TYPE_ARCH_COUNTER       3
+#define MSR_TYPE_ARCH_CTRL          4
+
+#define LVTPC_HVM_PMU            0xf8
+
+struct pmumsr {
+    unsigned int num;
+    u32 *msr;
+};
+
+struct msr_load_store_entry {
+    u32 msr_index;
+    u32 msr_reserved;
+    u64 msr_data;
+};
+
+/* Arch specific operations shared by all vpmus */
+struct arch_vpmu_ops {
+    int (*do_wrmsr)(struct cpu_user_regs *regs);
+    int (*do_rdmsr)(struct cpu_user_regs *regs);
+    int (*do_interrupt)(struct cpu_user_regs *regs);
+    void (*arch_vpmu_initialise)(struct vcpu *v);
+    void (*arch_vpmu_destroy)(struct vcpu *v);
+    void (*arch_vpmu_save)(struct vcpu *v);
+    void (*arch_vpmu_load)(struct vcpu *v);
+};
+
+struct vpmu_struct {
+    u32 flags;
+    void *context;
+    struct arch_vpmu_ops *arch_vpmu_ops;
+};
+
+#define VPMU_CONTEXT_ALLOCATED              0x1
+#define VPMU_CONTEXT_LOADED                 0x2
+#define VPMU_RUNNING                        0x4
+
+int inline vpmu_do_wrmsr(struct cpu_user_regs *regs);
+int inline vpmu_do_rdmsr(struct cpu_user_regs *regs);
+int inline vpmu_do_interrupt(struct cpu_user_regs *regs);
+void inline vpmu_initialise(struct vcpu *v);
+void inline vpmu_destroy(struct vcpu *v);
+void inline vpmu_save(struct vcpu *v);
+void inline vpmu_load(struct vcpu *v);
+
+extern int acquire_pmu_ownership(int pmu_ownership);
+extern void release_pmu_ownership(int pmu_ownership);
+
+#endif /* __ASM_X86_HVM_VPMU_H_*/
+
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/include/asm-x86/hvm/vmx/vpmu_core2.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vpmu_core2.h  Wed Jan 30 09:59:27 2008 +0000
@@ -0,0 +1,68 @@
+
+/*
+ * vpmu_core2.h: CORE 2 specific PMU virtualization for HVM domain.
+ *
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Haitao Shan <haitao.shan@xxxxxxxxx>
+ */
+
+#ifndef __ASM_X86_HVM_VPMU_CORE_H_
+#define __ASM_X86_HVM_VPMU_CORE_H_
+
+/* Core 2 Non-architectual Performance Counter MSRs. */
+u32 core2_counters_msr[] =   {
+    MSR_CORE_PERF_FIXED_CTR0,
+    MSR_CORE_PERF_FIXED_CTR1,
+    MSR_CORE_PERF_FIXED_CTR2};
+
+/* Core 2 Non-architectual Performance Control MSRs. */
+u32 core2_ctrls_msr[] = {
+    MSR_CORE_PERF_FIXED_CTR_CTRL,
+    MSR_IA32_PEBS_ENABLE,
+    MSR_IA32_DS_AREA};
+
+struct pmumsr core2_counters = {
+    3,
+    core2_counters_msr
+};
+
+struct pmumsr core2_ctrls = {
+    3,
+    core2_ctrls_msr
+};
+
+struct arch_msr_pair {
+    u64 counter;
+    u64 control;
+};
+
+struct core2_pmu_enable {
+    char fixed_ctr_enable[3];
+    char arch_pmc_enable[1];
+};
+
+struct core2_vpmu_context {
+    struct core2_pmu_enable *pmu_enable;
+    u64 counters[3];
+    u64 ctrls[3];
+    u64 global_ovf_status;
+    u32 hw_lapic_lvtpc;
+    struct arch_msr_pair arch_msr_pair[1];
+};
+
+#endif /* __ASM_X86_HVM_VPMU_CORE_H_ */
+
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/include/asm-x86/irq.h
--- a/xen/include/asm-x86/irq.h Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/include/asm-x86/irq.h Wed Jan 30 09:59:27 2008 +0000
@@ -28,6 +28,7 @@ fastcall void call_function_interrupt(vo
 fastcall void call_function_interrupt(void);
 fastcall void apic_timer_interrupt(void);
 fastcall void error_interrupt(void);
+fastcall void pmu_apic_interrupt(void);
 fastcall void spurious_interrupt(void);
 fastcall void thermal_interrupt(void);
 
diff -r 47b7ec3b4055 -r 6ea3db7ae24d 
xen/include/asm-x86/mach-default/irq_vectors.h
--- a/xen/include/asm-x86/mach-default/irq_vectors.h    Wed Jan 30 09:38:10 
2008 +0000
+++ b/xen/include/asm-x86/mach-default/irq_vectors.h    Wed Jan 30 09:59:27 
2008 +0000
@@ -9,13 +9,14 @@
 #define CALL_FUNCTION_VECTOR   0xfb
 #define THERMAL_APIC_VECTOR    0xfa
 #define LOCAL_TIMER_VECTOR     0xf9
+#define PMU_APIC_VECTOR        0xf8
 
 /*
  * High-priority dynamically-allocated vectors. For interrupts that
  * must be higher priority than any guest-bound interrupt.
  */
 #define FIRST_HIPRIORITY_VECTOR        0xf0
-#define LAST_HIPRIORITY_VECTOR  0xf8
+#define LAST_HIPRIORITY_VECTOR  0xf7
 
 /* Legacy PIC uses vectors 0xe0-0xef. */
 #define FIRST_LEGACY_VECTOR    0xe0
diff -r 47b7ec3b4055 -r 6ea3db7ae24d xen/include/xen/xenoprof.h
--- a/xen/include/xen/xenoprof.h        Wed Jan 30 09:38:10 2008 +0000
+++ b/xen/include/xen/xenoprof.h        Wed Jan 30 09:59:27 2008 +0000
@@ -69,4 +69,10 @@ int xenoprof_add_trace(struct domain *d,
 int xenoprof_add_trace(struct domain *d, struct vcpu *v, 
                        unsigned long eip, int mode);
 
+#define PMU_OWNER_NONE          0
+#define PMU_OWNER_XENOPROF      1
+#define PMU_OWNER_HVM           2
+int acquire_pmu_ownship(int pmu_ownership);
+void release_pmu_ownship(int pmu_ownership);
+
 #endif  /* __XEN__XENOPROF_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] vmx: Enable Core 2 Duo Performance Counters in HVM guest, Xen patchbot-unstable <=