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 <ehrhardt@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx>
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 <hollisb@xxxxxxxxxx>
*/
@@ -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 <ehrhardt@xxxxxxxxxxxxxxxxxx>
+ */
+#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 <jimix@xxxxxxxxxxxxxx>
+ * Christian Ehrhardt <ehrhardt@xxxxxxxxxxxxxxxxxx>
*/
#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, MSR_RI@l
mtmsrd r0
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|