[XEN][POWERPC][PATCH 2/3] Guest Perfmon implementation - H_PERFMON papr
call, perfmon exception handler
->attachment
--
Grüsse / regards,
Christian Ehrhardt
IBM Linux Technology Center, Open Virtualization
+49 7031/16-3385
Ehrhardt@xxxxxxxxxxxxxxxxxxx
Ehrhardt@xxxxxxxxxx
IBM Deutschland Entwicklung GmbH
Vorsitzender des Aufsichtsrats: Johann Weihen
Geschäftsführung: Herbert Kircher
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294
# HG changeset patch
# User Christian Ehrhardt <ehrhardt@xxxxxxxxxxxxxxxxxx>
# Date 1178509111 -7200
# Node ID 16a5031473951e5a69680db92924e3fc327e8f67
# Parent c3dc8f02bf0ebb4ce277096a8fd966f59cf7e7fe
[XEN][POWERPC][PATCH 2/3] Guest Perfmon implementation - H_PERFMON papr call,
perfmon exception handler
This is the first step of enabling oprofile performance monitoring on the
xenppc platform. It allows users to work with oprofile in Diom0 and DomU guests
as known from non virtualized ppc-linux.
This patch:
- implements the H_PERFMON papr call in xen
- implements a xen handler for the performance monitor exception
- contains a minor indent fix
- adds CONFIG_PPC64 to config.h to keep leveraged linux code more similar
Signed-off-by: Christian Ehrhardt <ehrhardt@xxxxxxxxxxxxxxxxxx>
diff -r c3dc8f02bf0e -r 16a503147395 xen/arch/powerpc/exceptions.h
--- a/xen/arch/powerpc/exceptions.h Mon May 07 05:34:23 2007 +0200
+++ b/xen/arch/powerpc/exceptions.h Mon May 07 05:38:31 2007 +0200
@@ -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 c3dc8f02bf0e -r 16a503147395 xen/arch/powerpc/papr/Makefile
--- a/xen/arch/powerpc/papr/Makefile Mon May 07 05:34:23 2007 +0200
+++ b/xen/arch/powerpc/papr/Makefile Mon May 07 05:38:31 2007 +0200
@@ -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 c3dc8f02bf0e -r 16a503147395 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 Mon May 07 05:38:31 2007 +0200
@@ -0,0 +1,155 @@
+/*
+ * 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 (C) 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),
+#ifdef CONFIG_PPC64
+ (0x8000000-0x0),
+ (0x8000000-0x0),
+ (0x8000000-0x0)};
+#else
+ (0x8000000-0x0)};
+#endif
+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();
+ }
+ /*
+ ** Else = 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 c3dc8f02bf0e -r 16a503147395 xen/include/asm-powerpc/papr.h
--- a/xen/include/asm-powerpc/papr.h Mon May 07 05:34:23 2007 +0200
+++ b/xen/include/asm-powerpc/papr.h Mon May 07 05:38:31 2007 +0200
@@ -66,6 +66,7 @@
#define H_IPOLL 0x0070 /* Crit Yes int */
#define H_XIRR 0x0074 /* Crit Yes int */
#define H_MIGRATE_PCI_TCE 0x0078 /* Norm Yes-if LRDR migrate */
+#define H_PERFMON 0x007c /* Norm Yes-if PMU perfmon */
#define H_CEDE 0x00e0 /* Crit Yes splpar */
#define H_CONFER 0x00e4
#define H_PROD 0x00e8
diff -r c3dc8f02bf0e -r 16a503147395 xen/include/asm-powerpc/powerpc64/config.h
--- a/xen/include/asm-powerpc/powerpc64/config.h Mon May 07 05:34:23
2007 +0200
+++ b/xen/include/asm-powerpc/powerpc64/config.h Mon May 07 05:38:31
2007 +0200
@@ -21,6 +21,8 @@
#ifndef __PPC_64_CONFIG_H__
#define __PPC_64_CONFIG_H__
+#define CONFIG_PPC64
+
#define CONFIG_L1_CACHE_SHIFT 7
/* 288 bytes below the stack pointer must be preserved by interrupt handlers */
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|