Changeset 3867217d3155 : 
http://xenbits.xensource.com/ext/ppc/xen-unstable.hg?cmd=changeset;node=3867217d3155

        [POWERPC][XEN] Enable in-guest performance monitoring.
        - Lazily save and restore the performance monitor counters when 
switching
          domains.
        - Control with the H_PERFMON PAPR hypercall.
        - Ignore guest perfmon exceptions that land in Xen.
        Signed-off-by: Christian Ehrhardt <[EMAIL PROTECTED]>
        Signed-off-by: Hollis Blanchard <[EMAIL PROTECTED]>

diffstat:

11 files changed, 490 insertions(+), 8 deletions(-)
xen/arch/powerpc/exceptions.h           |    3 
xen/arch/powerpc/of_handler/papr.S      |    2 
xen/arch/powerpc/papr/Makefile          |    1 
xen/arch/powerpc/papr/h_perfmon.c       |  158 +++++++++++++++++++++++++++++++
xen/arch/powerpc/powerpc64/domain.c     |   46 ++++++++-
xen/arch/powerpc/powerpc64/exceptions.S |   25 ++++
xen/include/asm-powerpc/domain.h        |   21 +++-
xen/include/asm-powerpc/papr.h          |    1 
xen/include/asm-powerpc/processor.h     |  138 ++++++++++++++++++++++++++-
xen/include/asm-powerpc/reg_defs.h      |   27 +++++
xen/include/asm-powerpc/xenoprof.h      |   76 ++++++++++++++

diffs (truncated from 697 to 300 lines):

diff -r a69843c46641 -r 3867217d3155 xen/arch/powerpc/exceptions.h
--- a/xen/arch/powerpc/exceptions.h     Fri Jul 13 15:23:24 2007 -0500
+++ b/xen/arch/powerpc/exceptions.h     Fri Jul 13 17:28:15 2007 -0500
@@ -13,7 +13,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * Copyright (C) IBM Corp. 2005
+ * Copyright IBM Corp. 2005, 2007
  *
  * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
  */
@@ -39,6 +39,7 @@ extern  multiboot_info_t *boot_of_init(u
 
 extern void do_timer(struct cpu_user_regs *regs);
 extern void do_dec(struct cpu_user_regs *regs);
+extern void do_perfmon(struct cpu_user_regs *regs);
 extern void program_exception(
     struct cpu_user_regs *regs, unsigned long cookie);
 
diff -r a69843c46641 -r 3867217d3155 xen/arch/powerpc/of_handler/papr.S
--- a/xen/arch/powerpc/of_handler/papr.S        Fri Jul 13 15:23:24 2007 -0500
+++ b/xen/arch/powerpc/of_handler/papr.S        Fri Jul 13 17:28:15 2007 -0500
@@ -67,7 +67,7 @@ PAPR(5, 1,papr_pci_config_read, H_PCI_CO
 PAPR(5, 1,papr_pci_config_read, H_PCI_CONFIG_READ)
 PAPR(5, 0,papr_pci_config_write, H_PCI_CONFIG_WRITE)
 
-       PAPR(5, 1,papr_grant_logical, H_GRANT_LOGICAL)
+PAPR(5, 1,papr_grant_logical, H_GRANT_LOGICAL)
 PAPR(1, 1,papr_accept_logical, H_ACCEPT_LOGICAL)
 PAPR(0, 2,papr_rescind_logical, H_RESCIND_LOGICAL)
 PAPR(3, 0,papr_register_vterm, H_REGISTER_VTERM)
diff -r a69843c46641 -r 3867217d3155 xen/arch/powerpc/papr/Makefile
--- a/xen/arch/powerpc/papr/Makefile    Fri Jul 13 15:23:24 2007 -0500
+++ b/xen/arch/powerpc/papr/Makefile    Fri Jul 13 17:28:15 2007 -0500
@@ -8,3 +8,4 @@ obj-y += vtce.o
 obj-y += vtce.o
 obj-$(papr_vterm) += vterm.o
 obj-y += xlate.o
+obj-y += h_perfmon.o
diff -r a69843c46641 -r 3867217d3155 xen/arch/powerpc/papr/h_perfmon.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/papr/h_perfmon.c Fri Jul 13 17:28:15 2007 -0500
@@ -0,0 +1,158 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Christian Ehrhardt <[EMAIL PROTECTED]>
+ */
+#undef DEBUG
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <xen/init.h>
+#include <xen/domain.h>
+#include <public/xen.h>
+#include <asm/current.h>
+#include <asm/msr.h>
+#include <asm/papr.h>
+#include <asm/hcalls.h>
+#include <asm/xenoprof.h>
+
+#define H_PERFMON_ENABLE (1UL << 63)
+#define H_PERFMON_THRESHOLDGRANULARITY (1UL << 62)
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/* FIXME workaround - these are just the default values, need the values set to
+ * linux via sysfs up-to-date. */
+int pmc_reset_val[NUM_PMCS] = { (0x8000000-0x0),
+                                (0x8000000-0x100000),
+                                (0x8000000-0x0),
+                                (0x8000000-0x0),
+                                (0x8000000-0x0),
+                                (0x8000000-0x0),
+                                (0x8000000-0x0),
+                                (0x8000000-0x0)};
+int perf_count_active_vcpu;
+perf_sprs_t perf_clear_sprs;
+static DEFINE_SPINLOCK(perf_pmu_lock);
+
+static inline int has_pmu(void) { return 1; }
+
+void do_perfmon(struct cpu_user_regs *regs)
+{
+    ulong mmcra = mfmmcra();
+    ulong mmcr0 = mfmmcr0();
+    int pmc,i;
+    
+    if ((mmcra & MMCRA_SAMPHV) && !(mmcra & MMCRA_SAMPPR)) {
+        /* TODO Hypervisor sample - support to sample xen, 
+         * pass the sample to the primary sampling domain via an event channel.
+         */
+        printk("do_perfmon - called with sample of xen space\n");
+        print_perf_status();
+        BUG();
+    } 
+
+    /* Dom sample postponed into xen space
+     * Currently just ignored (decreases accuracy) 
+     * TODO pass the Dom samples to the appropriate domain via an event channel
+     * TODO get access to the real pmc_reset_val currently used by the domain
+     * to reset counter safe and valid
+     */
+
+    for (i = 0; i < NUM_PMCS; ++i) {
+        pmc = ctr_read(i);
+        if (pmc < 0) {
+            DBG("postponed perfmon exception - PMC%d < 0 - reset to default "
+                "'0x%0x'\n", i, pmc_reset_val[i]);
+            ctr_write(i,pmc_reset_val[i]);
+        }
+    }
+
+    mmcr0 |= MMCR0_PMAE;
+    mmcr0 &= ~MMCR0_FC;
+    mtmmcr0(mmcr0);
+}
+
+static void h_perfmon(struct cpu_user_regs *regs)
+{
+    ulong mode_set   = regs->gprs[4];
+    ulong mode_reset = regs->gprs[5];
+    struct vcpu *v = get_current();
+    struct domain *d = v->domain;
+
+    if (!has_pmu()) {
+        regs->gprs[3] = H_Function;
+        return;
+    }
+
+    /* only bits 0&1 are supported by H_PERFMON */
+    if (((mode_set | mode_reset) & ~(H_PERFMON_ENABLE |
+            H_PERFMON_THRESHOLDGRANULARITY)) != 0) {
+        regs->gprs[3] = H_Parameter;
+        return;
+    }
+    /* enable or disable it, not both */
+    if ((mode_set & mode_reset) != 0) {
+        regs->gprs[3] = H_Resource;
+        return;
+    }
+
+    spin_lock(&perf_pmu_lock);
+    if (mode_set & H_PERFMON_ENABLE) {
+        if (v->arch.pmu_enabled) {
+            DBG("H_PERFMON call on already enabled PMU for domain '%d' on "
+                "vcpu '%d'\n", d->domain_id, v->vcpu_id);
+            goto success;
+        }
+
+        if (!perf_count_active_vcpu) {
+           save_pmc_sprs(&perf_clear_sprs);
+#ifdef DEBUG
+           DBG("H_PERFMON Saved initial clear performance special purpose "
+               "registers\n");
+           print_perf_status();
+#endif
+        }
+        v->arch.pmu_enabled = 1;
+        perf_count_active_vcpu++;
+        printk("H_PERFMON call enabled PMU for domain '%d' on vcpu '%d'\n",
+                d->domain_id, v->vcpu_id);
+    } else if (mode_reset & H_PERFMON_ENABLE) {
+        if (!v->arch.pmu_enabled) {
+            DBG("H_PERFMON call on already disabled PMU for domain '%d' on "
+                "vcpu '%d'\n", d->domain_id, v->vcpu_id);
+            goto success;
+        }
+        v->arch.pmu_enabled = 0;
+        perf_count_active_vcpu--;
+        printk("H_PERFMON call disabled PMU for domain '%d' on vcpu '%d'\n",
+                d->domain_id, v->vcpu_id);
+    } else {
+        regs->gprs[3] = H_Parameter;
+    }
+
+success:
+    regs->gprs[3] = H_Success;
+    spin_unlock(&perf_pmu_lock);
+}
+
+__init_papr_hcall(H_PERFMON, h_perfmon);
diff -r a69843c46641 -r 3867217d3155 xen/arch/powerpc/powerpc64/domain.c
--- a/xen/arch/powerpc/powerpc64/domain.c       Fri Jul 13 15:23:24 2007 -0500
+++ b/xen/arch/powerpc/powerpc64/domain.c       Fri Jul 13 17:28:15 2007 -0500
@@ -13,16 +13,48 @@
  * along with this program; if not, write to the Free Software
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * Copyright (C) IBM Corp. 2005
+ * Copyright IBM Corp. 2005, 2007
  *
  * Authors: Jimi Xenidis <[EMAIL PROTECTED]>
+ *          Christian Ehrhardt <[EMAIL PROTECTED]>
  */
 
 #include <xen/config.h>
 #include <xen/lib.h>
 #include <xen/sched.h>
 #include <xen/mm.h>
+#include <xen/domain.h>
 #include <asm/current.h>
+
+void save_pmc_sprs(perf_sprs_t *p_sprs)
+{
+    p_sprs->mmcr0 = mfmmcr0();
+    p_sprs->mmcr1 = mfmmcr1();
+    p_sprs->mmcra = mfmmcra();
+    p_sprs->pmc[0] = mfpmc1();
+    p_sprs->pmc[1] = mfpmc2();
+    p_sprs->pmc[2] = mfpmc3();
+    p_sprs->pmc[3] = mfpmc4();
+    p_sprs->pmc[4] = mfpmc5();
+    p_sprs->pmc[5] = mfpmc6();
+    p_sprs->pmc[6] = mfpmc7();
+    p_sprs->pmc[7] = mfpmc8();
+}
+
+void load_pmc_sprs(perf_sprs_t *p_sprs)
+{
+    mtpmc1(p_sprs->pmc[0]);
+    mtpmc2(p_sprs->pmc[1]);
+    mtpmc3(p_sprs->pmc[2]);
+    mtpmc4(p_sprs->pmc[3]);
+    mtpmc5(p_sprs->pmc[4]);
+    mtpmc6(p_sprs->pmc[5]);
+    mtpmc7(p_sprs->pmc[6]);
+    mtpmc8(p_sprs->pmc[7]);
+    mtmmcra(p_sprs->mmcra);
+    mtmmcr1(p_sprs->mmcr1);
+    mtmmcr0(p_sprs->mmcr0);
+}
 
 void save_sprs(struct vcpu *v)
 {
@@ -35,6 +67,11 @@ void save_sprs(struct vcpu *v)
 
     v->arch.dar = mfdar();
     v->arch.dsisr = mfdsisr();
+
+    if (v->arch.pmu_enabled) {
+        save_pmc_sprs(&(v->arch.perf_sprs));
+        v->arch.perf_sprs_stored = 1;
+    }
 
     save_cpu_sprs(v);
 }
@@ -49,6 +86,13 @@ void load_sprs(struct vcpu *v)
     mtsprg3(v->arch.sprg[3]);
     mtdar(v->arch.dar);
     mtdsisr(v->arch.dsisr);
+
+    if (v->arch.pmu_enabled) {
+        if (v->arch.perf_sprs_stored)
+            load_pmc_sprs(&(v->arch.perf_sprs));
+        else
+            load_pmc_sprs(&perf_clear_sprs);
+    }
 
     load_cpu_sprs(v);
 
diff -r a69843c46641 -r 3867217d3155 xen/arch/powerpc/powerpc64/exceptions.S
--- a/xen/arch/powerpc/powerpc64/exceptions.S   Fri Jul 13 15:23:24 2007 -0500
+++ b/xen/arch/powerpc/powerpc64/exceptions.S   Fri Jul 13 17:28:15 2007 -0500
@@ -105,6 +105,12 @@ 1:
     nop
 .endm
 
+.macro PMU_SAVE_STATE scratch
+    mfspr \scratch,SPRN_MMCR0             /* ensure MMCR0[FCH] is 1 */
+    ori \scratch,\scratch,MMCR0_FCH
+    mtspr SPRN_MMCR0, \scratch
+.endm
+
 .macro EXCEPTION_HEAD parea continue
     /* make room for cpu_user_regs */
     subi r1, r1, STACK_VOLATILE_AREA + UREGS_sizeof
@@ -156,7 +162,7 @@ 1:
     ori r0, r0, [EMAIL PROTECTED]
     mtmsrd r0

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@lists.xensource.com
http://lists.xensource.com/xen-ppc-devel

Reply via email to