# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 2f15fce777588becf3fa9fa6d44c70dbf4591a4a
# Parent da5c5fc8908fd966772eed40b1c1ab63793dbc1e
[XENOPROFILE] Split linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c into
linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c
without code changes except slight adjustment to compile.
Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
---
linux-2.6-xen-sparse/arch/i386/oprofile/Makefile | 5
linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c | 549 ---------
linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile | 5
linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c | 559 ++++++++++
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h | 31
linux-2.6-xen-sparse/include/xen/xenoprof.h | 30
6 files changed, 636 insertions(+), 543 deletions(-)
diff -r da5c5fc8908f -r 2f15fce77758
linux-2.6-xen-sparse/arch/i386/oprofile/Makefile
--- a/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile Wed Nov 22 09:48:42
2006 +0000
+++ b/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile Wed Nov 22 09:49:55
2006 +0000
@@ -7,7 +7,10 @@ DRIVER_OBJS = $(addprefix ../../../drive
timer_int.o )
ifdef CONFIG_XEN
-oprofile-y := $(DRIVER_OBJS) xenoprof.o
+XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \
+ xenoprofile.o)
+oprofile-y := $(DRIVER_OBJS) \
+ $(XENOPROF_COMMON_OBJS) xenoprof.o
else
oprofile-y := $(DRIVER_OBJS) init.o backtrace.o
oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \
diff -r da5c5fc8908f -r 2f15fce77758
linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c
--- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Wed Nov 22
09:48:42 2006 +0000
+++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Wed Nov 22
09:49:55 2006 +0000
@@ -9,481 +9,21 @@
* Modified by Aravind Menon and Jose Renato Santos for Xen
* These modifications are:
* Copyright (C) 2005 Hewlett-Packard Co.
+ *
+ * x86-specific part
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
*/
-#include <linux/init.h>
-#include <linux/notifier.h>
-#include <linux/smp.h>
#include <linux/oprofile.h>
-#include <linux/sysdev.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/vmalloc.h>
-#include <asm/nmi.h>
-#include <asm/msr.h>
-#include <asm/apic.h>
-#include <asm/pgtable.h>
-#include <xen/evtchn.h>
+
+#include <xen/xenoprof.h>
#include "op_counter.h"
-#include <xen/driver_util.h>
-#include <xen/interface/xen.h>
-#include <xen/interface/xenoprof.h>
-#include <../../../drivers/oprofile/cpu_buffer.h>
-#include <../../../drivers/oprofile/event_buffer.h>
-
-#define MAX_XENOPROF_SAMPLES 16
-
-static int xenoprof_start(void);
-static void xenoprof_stop(void);
-
-static int xenoprof_enabled = 0;
-static unsigned int num_events = 0;
-static int is_primary = 0;
-static int active_defined;
-
-/* sample buffers shared with Xen */
-xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS];
-/* Shared buffer area */
-char * shared_buffer = NULL;
-/* Number of buffers in shared area (one per VCPU) */
-int nbuf;
-/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
-int ovf_irq[NR_CPUS];
-/* cpu model type string - copied from Xen memory space on XENOPROF_init
command */
-char cpu_type[XENOPROF_CPU_TYPE_SIZE];
-
-/* Passive sample buffers shared with Xen */
-xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS];
-/* Passive shared buffer area */
-char *p_shared_buffer[MAX_OPROF_DOMAINS];
-
-#ifdef CONFIG_PM
-
-static int xenoprof_suspend(struct sys_device * dev, pm_message_t state)
-{
- if (xenoprof_enabled == 1)
- xenoprof_stop();
- return 0;
-}
-
-
-static int xenoprof_resume(struct sys_device * dev)
-{
- if (xenoprof_enabled == 1)
- xenoprof_start();
- return 0;
-}
-
-
-static struct sysdev_class oprofile_sysclass = {
- set_kset_name("oprofile"),
- .resume = xenoprof_resume,
- .suspend = xenoprof_suspend
-};
-
-
-static struct sys_device device_oprofile = {
- .id = 0,
- .cls = &oprofile_sysclass,
-};
-
-
-static int __init init_driverfs(void)
-{
- int error;
- if (!(error = sysdev_class_register(&oprofile_sysclass)))
- error = sysdev_register(&device_oprofile);
- return error;
-}
-
-
-static void __exit exit_driverfs(void)
-{
- sysdev_unregister(&device_oprofile);
- sysdev_class_unregister(&oprofile_sysclass);
-}
-
-#else
-#define init_driverfs() do { } while (0)
-#define exit_driverfs() do { } while (0)
-#endif /* CONFIG_PM */
-
-unsigned long long oprofile_samples = 0;
-unsigned long long p_oprofile_samples = 0;
-
-unsigned int pdomains;
-struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
-
-static void xenoprof_add_pc(xenoprof_buf_t *buf, int is_passive)
-{
- int head, tail, size;
-
- head = buf->event_head;
- tail = buf->event_tail;
- size = buf->event_size;
-
- if (tail > head) {
- while (tail < size) {
- oprofile_add_pc(buf->event_log[tail].eip,
- buf->event_log[tail].mode,
- buf->event_log[tail].event);
- if (!is_passive)
- oprofile_samples++;
- else
- p_oprofile_samples++;
- tail++;
- }
- tail = 0;
- }
- while (tail < head) {
- oprofile_add_pc(buf->event_log[tail].eip,
- buf->event_log[tail].mode,
- buf->event_log[tail].event);
- if (!is_passive)
- oprofile_samples++;
- else
- p_oprofile_samples++;
- tail++;
- }
-
- buf->event_tail = tail;
-}
-
-static void xenoprof_handle_passive(void)
-{
- int i, j;
- int flag_domain, flag_switch = 0;
-
- for (i = 0; i < pdomains; i++) {
- flag_domain = 0;
- for (j = 0; j < passive_domains[i].nbuf; j++) {
- xenoprof_buf_t *buf = p_xenoprof_buf[i][j];
- if (buf->event_head == buf->event_tail)
- continue;
- if (!flag_domain) {
- if
(!oprofile_add_domain_switch(passive_domains[i].
- domain_id))
- goto done;
- flag_domain = 1;
- }
- xenoprof_add_pc(buf, 1);
- flag_switch = 1;
- }
- }
-done:
- if (flag_switch)
- oprofile_add_domain_switch(COORDINATOR_DOMAIN);
-}
-
-static irqreturn_t
-xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
-{
- struct xenoprof_buf * buf;
- int cpu;
- static unsigned long flag;
-
- cpu = smp_processor_id();
- buf = xenoprof_buf[cpu];
-
- xenoprof_add_pc(buf, 0);
-
- if (is_primary && !test_and_set_bit(0, &flag)) {
- xenoprof_handle_passive();
- smp_mb__before_clear_bit();
- clear_bit(0, &flag);
- }
-
- return IRQ_HANDLED;
-}
-
-
-static void unbind_virq(void)
-{
- int i;
-
- for_each_cpu(i) {
- if (ovf_irq[i] >= 0) {
- unbind_from_irqhandler(ovf_irq[i], NULL);
- ovf_irq[i] = -1;
- }
- }
-}
-
-
-static int bind_virq(void)
-{
- int i, result;
-
- for_each_cpu(i) {
- result = bind_virq_to_irqhandler(VIRQ_XENOPROF,
- i,
- xenoprof_ovf_interrupt,
- SA_INTERRUPT,
- "xenoprof",
- NULL);
-
- if (result < 0) {
- unbind_virq();
- return result;
- }
-
- ovf_irq[i] = result;
- }
-
- return 0;
-}
-
-
-static int map_xenoprof_buffer(int max_samples)
-{
- struct xenoprof_get_buffer get_buffer;
- struct xenoprof_buf *buf;
- int npages, ret, i;
- struct vm_struct *area;
-
- if ( shared_buffer )
- return 0;
-
- get_buffer.max_samples = max_samples;
-
- if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, &get_buffer)) )
- return ret;
-
- nbuf = get_buffer.nbuf;
- npages = (get_buffer.bufsize * nbuf - 1) / PAGE_SIZE + 1;
-
- area = alloc_vm_area(npages * PAGE_SIZE);
- if (area == NULL)
- return -ENOMEM;
-
- if ( (ret = direct_kernel_remap_pfn_range(
- (unsigned long)area->addr,
- get_buffer.buf_maddr >> PAGE_SHIFT,
- npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE), DOMID_SELF))
) {
- vunmap(area->addr);
- return ret;
- }
-
- shared_buffer = area->addr;
- for (i=0; i< nbuf; i++) {
- buf = (struct xenoprof_buf*)
- &shared_buffer[i * get_buffer.bufsize];
- BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
- xenoprof_buf[buf->vcpu_id] = buf;
- }
-
- return 0;
-}
-
-
-static int xenoprof_setup(void)
-{
- int ret;
- int i;
-
- if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) )
- return ret;
-
- if ( (ret = bind_virq()) )
- return ret;
-
- if (is_primary) {
- struct xenoprof_counter counter;
-
- /* Define dom0 as an active domain if not done yet */
- if (!active_defined) {
- domid_t domid;
- ret =
HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
- if (ret)
- goto err;
- domid = 0;
- ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active,
&domid);
- if (ret)
- goto err;
- active_defined = 1;
- }
-
- ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL);
- if (ret)
- goto err;
- for (i=0; i<num_events; i++) {
- counter.ind = i;
- counter.count = (uint64_t)counter_config[i].count;
- counter.enabled = (uint32_t)counter_config[i].enabled;
- counter.event = (uint32_t)counter_config[i].event;
- counter.kernel = (uint32_t)counter_config[i].kernel;
- counter.user = (uint32_t)counter_config[i].user;
- counter.unit_mask =
(uint64_t)counter_config[i].unit_mask;
- HYPERVISOR_xenoprof_op(XENOPROF_counter,
- &counter);
- }
- ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL);
-
- if (ret)
- goto err;
- }
-
- ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq, NULL);
- if (ret)
- goto err;
-
- xenoprof_enabled = 1;
- return 0;
- err:
- unbind_virq();
- return ret;
-}
-
-
-static void xenoprof_shutdown(void)
-{
- xenoprof_enabled = 0;
-
- HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL);
-
- if (is_primary) {
- HYPERVISOR_xenoprof_op(XENOPROF_release_counters, NULL);
- active_defined = 0;
- }
-
- unbind_virq();
-
-}
-
-
-static int xenoprof_start(void)
-{
- int ret = 0;
-
- if (is_primary)
- ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL);
-
- return ret;
-}
-
-
-static void xenoprof_stop(void)
-{
- if (is_primary)
- HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL);
-}
-
-
-static int xenoprof_set_active(int * active_domains,
- unsigned int adomains)
-{
- int ret = 0;
- int i;
- int set_dom0 = 0;
- domid_t domid;
-
- if (!is_primary)
- return 0;
-
- if (adomains > MAX_OPROF_DOMAINS)
- return -E2BIG;
-
- ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
- if (ret)
- return ret;
-
- for (i=0; i<adomains; i++) {
- domid = active_domains[i];
- if (domid != active_domains[i]) {
- ret = -EINVAL;
- goto out;
- }
- ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
- if (ret)
- goto out;
- if (active_domains[i] == 0)
- set_dom0 = 1;
- }
- /* dom0 must always be active but may not be in the list */
- if (!set_dom0) {
- domid = 0;
- ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
- }
-
-out:
- if (ret)
- HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
- active_defined = !ret;
- return ret;
-}
-
-static int xenoprof_set_passive(int * p_domains,
- unsigned int pdoms)
-{
- int ret;
- int i, j;
- int npages;
- struct xenoprof_buf *buf;
- struct vm_struct *area;
- pgprot_t prot = __pgprot(_KERNPG_TABLE);
-
- if (!is_primary)
- return 0;
-
- if (pdoms > MAX_OPROF_DOMAINS)
- return -E2BIG;
-
- ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL);
- if (ret)
- return ret;
-
- for (i = 0; i < pdoms; i++) {
- passive_domains[i].domain_id = p_domains[i];
- passive_domains[i].max_samples = 2048;
- ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive,
- &passive_domains[i]);
- if (ret)
- goto out;
-
- npages = (passive_domains[i].bufsize * passive_domains[i].nbuf
- 1) / PAGE_SIZE + 1;
-
- area = alloc_vm_area(npages * PAGE_SIZE);
- if (area == NULL) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = direct_kernel_remap_pfn_range(
- (unsigned long)area->addr,
- passive_domains[i].buf_maddr >> PAGE_SHIFT,
- npages * PAGE_SIZE, prot, DOMID_SELF);
- if (ret) {
- vunmap(area->addr);
- goto out;
- }
-
- p_shared_buffer[i] = area->addr;
-
- for (j = 0; j < passive_domains[i].nbuf; j++) {
- buf = (struct xenoprof_buf *)
- &p_shared_buffer[i][j *
passive_domains[i].bufsize];
- BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
- p_xenoprof_buf[i][buf->vcpu_id] = buf;
- }
-
- }
-
- pdomains = pdoms;
- return 0;
-
-out:
- for (j = 0; j < i; j++) {
- vunmap(p_shared_buffer[j]);
- p_shared_buffer[j] = NULL;
- }
-
- return ret;
-}
-
+unsigned int num_events = 0;
struct op_counter_config counter_config[OP_MAX_COUNTER];
-static int xenoprof_create_files(struct super_block * sb, struct dentry * root)
+int xenoprof_create_files(struct super_block * sb, struct dentry * root)
{
unsigned int i;
@@ -509,76 +49,3 @@ static int xenoprof_create_files(struct
return 0;
}
-
-
-struct oprofile_operations xenoprof_ops = {
- .create_files = xenoprof_create_files,
- .set_active = xenoprof_set_active,
- .set_passive = xenoprof_set_passive,
- .setup = xenoprof_setup,
- .shutdown = xenoprof_shutdown,
- .start = xenoprof_start,
- .stop = xenoprof_stop
-};
-
-
-/* in order to get driverfs right */
-static int using_xenoprof;
-
-int __init oprofile_arch_init(struct oprofile_operations * ops)
-{
- struct xenoprof_init init;
- int ret, i;
-
- ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init);
-
- if (!ret) {
- num_events = init.num_events;
- is_primary = init.is_primary;
-
- /* just in case - make sure we do not overflow event list
- (i.e. counter_config list) */
- if (num_events > OP_MAX_COUNTER)
- num_events = OP_MAX_COUNTER;
-
- /* cpu_type is detected by Xen */
- cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
- strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
- xenoprof_ops.cpu_type = cpu_type;
-
- init_driverfs();
- using_xenoprof = 1;
- *ops = xenoprof_ops;
-
- for (i=0; i<NR_CPUS; i++)
- ovf_irq[i] = -1;
-
- active_defined = 0;
- }
- printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, "
- "is_primary %d\n", ret, num_events, is_primary);
- return ret;
-}
-
-
-void __exit oprofile_arch_exit(void)
-{
- int i;
-
- if (using_xenoprof)
- exit_driverfs();
-
- if (shared_buffer) {
- vunmap(shared_buffer);
- shared_buffer = NULL;
- }
- if (is_primary) {
- for (i = 0; i < pdomains; i++)
- if (p_shared_buffer[i]) {
- vunmap(p_shared_buffer[i]);
- p_shared_buffer[i] = NULL;
- }
- HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL);
- }
-
-}
diff -r da5c5fc8908f -r 2f15fce77758
linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile
--- a/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile Wed Nov 22
09:48:42 2006 +0000
+++ b/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile Wed Nov 22
09:49:55 2006 +0000
@@ -12,6 +12,8 @@ DRIVER_OBJS = $(addprefix ../../../drive
timer_int.o )
ifdef CONFIG_XEN
+XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \
+ xenoprofile.o)
OPROFILE-y := xenoprof.o
else
OPROFILE-y := init.o backtrace.o
@@ -19,4 +21,5 @@ OPROFILE-$(CONFIG_X86_LOCAL_APIC) += nmi
op_model_ppro.o
OPROFILE-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o
endif
-oprofile-y = $(DRIVER_OBJS) $(addprefix ../../i386/oprofile/, $(OPROFILE-y))
+oprofile-y = $(DRIVER_OBJS) $(XENOPROF_COMMON_OBJS) \
+ $(addprefix ../../i386/oprofile/, $(OPROFILE-y))
diff -r da5c5fc8908f -r 2f15fce77758
linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c Wed Nov 22
09:49:55 2006 +0000
@@ -0,0 +1,559 @@
+/**
+ * @file xenoprof.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@xxxxxxxxxxxxxxxxx>
+ *
+ * Modified by Aravind Menon and Jose Renato Santos for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ *
+ * Separated out arch-generic part
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ */
+
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/smp.h>
+#include <linux/oprofile.h>
+#include <linux/sysdev.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <asm/nmi.h>
+#include <asm/msr.h>
+#include <asm/apic.h>
+#include <asm/pgtable.h>
+#include <xen/evtchn.h>
+#include <xen/xenoprof.h>
+#include "../../../arch/i386/oprofile/op_counter.h"
+
+#include <xen/driver_util.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/xenoprof.h>
+#include "../../../drivers/oprofile/cpu_buffer.h"
+#include "../../../drivers/oprofile/event_buffer.h"
+
+#define MAX_XENOPROF_SAMPLES 16
+
+static int xenoprof_start(void);
+static void xenoprof_stop(void);
+
+static int xenoprof_enabled = 0;
+extern unsigned int num_events;
+static int is_primary = 0;
+static int active_defined;
+
+/* sample buffers shared with Xen */
+xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS];
+/* Shared buffer area */
+char * shared_buffer = NULL;
+/* Number of buffers in shared area (one per VCPU) */
+int nbuf;
+/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
+int ovf_irq[NR_CPUS];
+/* cpu model type string - copied from Xen memory space on XENOPROF_init
command */
+char cpu_type[XENOPROF_CPU_TYPE_SIZE];
+
+/* Passive sample buffers shared with Xen */
+xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS];
+/* Passive shared buffer area */
+char *p_shared_buffer[MAX_OPROF_DOMAINS];
+
+#ifdef CONFIG_PM
+
+static int xenoprof_suspend(struct sys_device * dev, pm_message_t state)
+{
+ if (xenoprof_enabled == 1)
+ xenoprof_stop();
+ return 0;
+}
+
+
+static int xenoprof_resume(struct sys_device * dev)
+{
+ if (xenoprof_enabled == 1)
+ xenoprof_start();
+ return 0;
+}
+
+
+static struct sysdev_class oprofile_sysclass = {
+ set_kset_name("oprofile"),
+ .resume = xenoprof_resume,
+ .suspend = xenoprof_suspend
+};
+
+
+static struct sys_device device_oprofile = {
+ .id = 0,
+ .cls = &oprofile_sysclass,
+};
+
+
+static int __init init_driverfs(void)
+{
+ int error;
+ if (!(error = sysdev_class_register(&oprofile_sysclass)))
+ error = sysdev_register(&device_oprofile);
+ return error;
+}
+
+
+static void __exit exit_driverfs(void)
+{
+ sysdev_unregister(&device_oprofile);
+ sysdev_class_unregister(&oprofile_sysclass);
+}
+
+#else
+#define init_driverfs() do { } while (0)
+#define exit_driverfs() do { } while (0)
+#endif /* CONFIG_PM */
+
+unsigned long long oprofile_samples = 0;
+unsigned long long p_oprofile_samples = 0;
+
+unsigned int pdomains;
+struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
+
+static void xenoprof_add_pc(xenoprof_buf_t *buf, int is_passive)
+{
+ int head, tail, size;
+
+ head = buf->event_head;
+ tail = buf->event_tail;
+ size = buf->event_size;
+
+ if (tail > head) {
+ while (tail < size) {
+ oprofile_add_pc(buf->event_log[tail].eip,
+ buf->event_log[tail].mode,
+ buf->event_log[tail].event);
+ if (!is_passive)
+ oprofile_samples++;
+ else
+ p_oprofile_samples++;
+ tail++;
+ }
+ tail = 0;
+ }
+ while (tail < head) {
+ oprofile_add_pc(buf->event_log[tail].eip,
+ buf->event_log[tail].mode,
+ buf->event_log[tail].event);
+ if (!is_passive)
+ oprofile_samples++;
+ else
+ p_oprofile_samples++;
+ tail++;
+ }
+
+ buf->event_tail = tail;
+}
+
+static void xenoprof_handle_passive(void)
+{
+ int i, j;
+ int flag_domain, flag_switch = 0;
+
+ for (i = 0; i < pdomains; i++) {
+ flag_domain = 0;
+ for (j = 0; j < passive_domains[i].nbuf; j++) {
+ xenoprof_buf_t *buf = p_xenoprof_buf[i][j];
+ if (buf->event_head == buf->event_tail)
+ continue;
+ if (!flag_domain) {
+ if
(!oprofile_add_domain_switch(passive_domains[i].
+ domain_id))
+ goto done;
+ flag_domain = 1;
+ }
+ xenoprof_add_pc(buf, 1);
+ flag_switch = 1;
+ }
+ }
+done:
+ if (flag_switch)
+ oprofile_add_domain_switch(COORDINATOR_DOMAIN);
+}
+
+static irqreturn_t
+xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct xenoprof_buf * buf;
+ int cpu;
+ static unsigned long flag;
+
+ cpu = smp_processor_id();
+ buf = xenoprof_buf[cpu];
+
+ xenoprof_add_pc(buf, 0);
+
+ if (is_primary && !test_and_set_bit(0, &flag)) {
+ xenoprof_handle_passive();
+ smp_mb__before_clear_bit();
+ clear_bit(0, &flag);
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+static void unbind_virq(void)
+{
+ int i;
+
+ for_each_cpu(i) {
+ if (ovf_irq[i] >= 0) {
+ unbind_from_irqhandler(ovf_irq[i], NULL);
+ ovf_irq[i] = -1;
+ }
+ }
+}
+
+
+static int bind_virq(void)
+{
+ int i, result;
+
+ for_each_cpu(i) {
+ result = bind_virq_to_irqhandler(VIRQ_XENOPROF,
+ i,
+ xenoprof_ovf_interrupt,
+ SA_INTERRUPT,
+ "xenoprof",
+ NULL);
+
+ if (result < 0) {
+ unbind_virq();
+ return result;
+ }
+
+ ovf_irq[i] = result;
+ }
+
+ return 0;
+}
+
+
+static int map_xenoprof_buffer(int max_samples)
+{
+ struct xenoprof_get_buffer get_buffer;
+ struct xenoprof_buf *buf;
+ int npages, ret, i;
+ struct vm_struct *area;
+
+ if ( shared_buffer )
+ return 0;
+
+ get_buffer.max_samples = max_samples;
+
+ if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, &get_buffer)) )
+ return ret;
+
+ nbuf = get_buffer.nbuf;
+ npages = (get_buffer.bufsize * nbuf - 1) / PAGE_SIZE + 1;
+
+ area = alloc_vm_area(npages * PAGE_SIZE);
+ if (area == NULL)
+ return -ENOMEM;
+
+ if ( (ret = direct_kernel_remap_pfn_range(
+ (unsigned long)area->addr,
+ get_buffer.buf_maddr >> PAGE_SHIFT,
+ npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE), DOMID_SELF))
) {
+ vunmap(area->addr);
+ return ret;
+ }
+
+ shared_buffer = area->addr;
+ for (i=0; i< nbuf; i++) {
+ buf = (struct xenoprof_buf*)
+ &shared_buffer[i * get_buffer.bufsize];
+ BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
+ xenoprof_buf[buf->vcpu_id] = buf;
+ }
+
+ return 0;
+}
+
+
+static int xenoprof_setup(void)
+{
+ int ret;
+ int i;
+
+ if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) )
+ return ret;
+
+ if ( (ret = bind_virq()) )
+ return ret;
+
+ if (is_primary) {
+ struct xenoprof_counter counter;
+
+ /* Define dom0 as an active domain if not done yet */
+ if (!active_defined) {
+ domid_t domid;
+ ret =
HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
+ if (ret)
+ goto err;
+ domid = 0;
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active,
&domid);
+ if (ret)
+ goto err;
+ active_defined = 1;
+ }
+
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL);
+ if (ret)
+ goto err;
+ for (i=0; i<num_events; i++) {
+ counter.ind = i;
+ counter.count = (uint64_t)counter_config[i].count;
+ counter.enabled = (uint32_t)counter_config[i].enabled;
+ counter.event = (uint32_t)counter_config[i].event;
+ counter.kernel = (uint32_t)counter_config[i].kernel;
+ counter.user = (uint32_t)counter_config[i].user;
+ counter.unit_mask =
(uint64_t)counter_config[i].unit_mask;
+ HYPERVISOR_xenoprof_op(XENOPROF_counter,
+ &counter);
+ }
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL);
+
+ if (ret)
+ goto err;
+ }
+
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq, NULL);
+ if (ret)
+ goto err;
+
+ xenoprof_enabled = 1;
+ return 0;
+ err:
+ unbind_virq();
+ return ret;
+}
+
+
+static void xenoprof_shutdown(void)
+{
+ xenoprof_enabled = 0;
+
+ HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL);
+
+ if (is_primary) {
+ HYPERVISOR_xenoprof_op(XENOPROF_release_counters, NULL);
+ active_defined = 0;
+ }
+
+ unbind_virq();
+
+}
+
+
+static int xenoprof_start(void)
+{
+ int ret = 0;
+
+ if (is_primary)
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL);
+
+ return ret;
+}
+
+
+static void xenoprof_stop(void)
+{
+ if (is_primary)
+ HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL);
+}
+
+
+static int xenoprof_set_active(int * active_domains,
+ unsigned int adomains)
+{
+ int ret = 0;
+ int i;
+ int set_dom0 = 0;
+ domid_t domid;
+
+ if (!is_primary)
+ return 0;
+
+ if (adomains > MAX_OPROF_DOMAINS)
+ return -E2BIG;
+
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
+ if (ret)
+ return ret;
+
+ for (i=0; i<adomains; i++) {
+ domid = active_domains[i];
+ if (domid != active_domains[i]) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
+ if (ret)
+ goto out;
+ if (active_domains[i] == 0)
+ set_dom0 = 1;
+ }
+ /* dom0 must always be active but may not be in the list */
+ if (!set_dom0) {
+ domid = 0;
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
+ }
+
+out:
+ if (ret)
+ HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
+ active_defined = !ret;
+ return ret;
+}
+
+static int xenoprof_set_passive(int * p_domains,
+ unsigned int pdoms)
+{
+ int ret;
+ int i, j;
+ int npages;
+ struct xenoprof_buf *buf;
+ struct vm_struct *area;
+ pgprot_t prot = __pgprot(_KERNPG_TABLE);
+
+ if (!is_primary)
+ return 0;
+
+ if (pdoms > MAX_OPROF_DOMAINS)
+ return -E2BIG;
+
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < pdoms; i++) {
+ passive_domains[i].domain_id = p_domains[i];
+ passive_domains[i].max_samples = 2048;
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive,
+ &passive_domains[i]);
+ if (ret)
+ goto out;
+
+ npages = (passive_domains[i].bufsize * passive_domains[i].nbuf
- 1) / PAGE_SIZE + 1;
+
+ area = alloc_vm_area(npages * PAGE_SIZE);
+ if (area == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = direct_kernel_remap_pfn_range(
+ (unsigned long)area->addr,
+ passive_domains[i].buf_maddr >> PAGE_SHIFT,
+ npages * PAGE_SIZE, prot, DOMID_SELF);
+ if (ret) {
+ vunmap(area->addr);
+ goto out;
+ }
+
+ p_shared_buffer[i] = area->addr;
+
+ for (j = 0; j < passive_domains[i].nbuf; j++) {
+ buf = (struct xenoprof_buf *)
+ &p_shared_buffer[i][j *
passive_domains[i].bufsize];
+ BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
+ p_xenoprof_buf[i][buf->vcpu_id] = buf;
+ }
+
+ }
+
+ pdomains = pdoms;
+ return 0;
+
+out:
+ for (j = 0; j < i; j++) {
+ vunmap(p_shared_buffer[j]);
+ p_shared_buffer[j] = NULL;
+ }
+
+ return ret;
+}
+
+struct oprofile_operations xenoprof_ops = {
+ .create_files = xenoprof_create_files,
+ .set_active = xenoprof_set_active,
+ .set_passive = xenoprof_set_passive,
+ .setup = xenoprof_setup,
+ .shutdown = xenoprof_shutdown,
+ .start = xenoprof_start,
+ .stop = xenoprof_stop
+};
+
+
+/* in order to get driverfs right */
+static int using_xenoprof;
+
+int __init oprofile_arch_init(struct oprofile_operations * ops)
+{
+ struct xenoprof_init init;
+ int ret, i;
+
+ ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init);
+
+ if (!ret) {
+ num_events = init.num_events;
+ is_primary = init.is_primary;
+
+ /* just in case - make sure we do not overflow event list
+ (i.e. counter_config list) */
+ if (num_events > OP_MAX_COUNTER)
+ num_events = OP_MAX_COUNTER;
+
+ /* cpu_type is detected by Xen */
+ cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
+ strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
+ xenoprof_ops.cpu_type = cpu_type;
+
+ init_driverfs();
+ using_xenoprof = 1;
+ *ops = xenoprof_ops;
+
+ for (i=0; i<NR_CPUS; i++)
+ ovf_irq[i] = -1;
+
+ active_defined = 0;
+ }
+ printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, "
+ "is_primary %d\n", ret, num_events, is_primary);
+ return ret;
+}
+
+
+void __exit oprofile_arch_exit(void)
+{
+ int i;
+
+ if (using_xenoprof)
+ exit_driverfs();
+
+ if (shared_buffer) {
+ vunmap(shared_buffer);
+ shared_buffer = NULL;
+ }
+ if (is_primary) {
+ for (i = 0; i < pdomains; i++)
+ if (p_shared_buffer[i]) {
+ vunmap(p_shared_buffer[i]);
+ p_shared_buffer[i] = NULL;
+ }
+ HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL);
+ }
+
+}
diff -r da5c5fc8908f -r 2f15fce77758
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h Wed Nov
22 09:49:55 2006 +0000
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * asm-i386/mach-xen/asm/xenoprof.h
+ *
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __ASM_XENOPROF_H__
+#define __ASM_XENOPROF_H__
+#ifdef CONFIG_OPROFILE
+
+struct super_block;
+struct dentry;
+int xenoprof_create_files(struct super_block * sb, struct dentry * root);
+
+#endif /* CONFIG_OPROFILE */
+#endif /* __ASM_XENOPROF_H__ */
diff -r da5c5fc8908f -r 2f15fce77758 linux-2.6-xen-sparse/include/xen/xenoprof.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/include/xen/xenoprof.h Wed Nov 22 09:49:55
2006 +0000
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * xen/xenoprof.h
+ *
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __XEN_XENOPROF_H__
+#define __XEN_XENOPROF_H__
+#ifdef CONFIG_OPROFILE
+
+#include <asm/xenoprof.h>
+
+#endif /* CONFIG_OPROFILE */
+#endif /* __XEN_XENOPROF_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|