# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 23591d2c46aa666a9d50cf36baf73aa0b95aa11b
# Parent b12cd185d579a0fb3b74b73e44add5524304d8cc
Add Xenoprof passive domain support
Signed-off-by: Yang Xiaowei <xiaowei.yang@xxxxxxxxx>
Signed-off-by: Jose Renato Santos <jsantos@xxxxxxxxxx>
---
linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c | 134 +++++++
patches/linux-2.6.16.13/xenoprof-generic.patch | 81 ++--
xen/arch/x86/oprofile/nmi_int.c | 2
xen/arch/x86/oprofile/xenoprof.c | 358 +++++++++++++--------
xen/include/public/xenoprof.h | 9
xen/include/xen/xenoprof.h | 1
6 files changed, 404 insertions(+), 181 deletions(-)
diff -r b12cd185d579 -r 23591d2c46aa
linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c
--- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Jun 27
11:17:14 2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Jun 27
11:23:06 2006 +0100
@@ -28,6 +28,7 @@
#include <xen/interface/xen.h>
#include <xen/interface/xenoprof.h>
+#include <../../../drivers/oprofile/cpu_buffer.h>
static int xenoprof_start(void);
static void xenoprof_stop(void);
@@ -50,6 +51,11 @@ 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)
@@ -102,16 +108,14 @@ static void __exit exit_driverfs(void)
#endif /* CONFIG_PM */
unsigned long long oprofile_samples = 0;
-
-static irqreturn_t
-xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+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;
- struct xenoprof_buf * buf;
- int cpu;
-
- cpu = smp_processor_id();
- buf = xenoprof_buf[cpu];
head = buf->event_head;
tail = buf->event_tail;
@@ -122,7 +126,10 @@ xenoprof_ovf_interrupt(int irq, void * d
oprofile_add_pc(buf->event_log[tail].eip,
buf->event_log[tail].mode,
buf->event_log[tail].event);
- oprofile_samples++;
+ if (!is_passive)
+ oprofile_samples++;
+ else
+ p_oprofile_samples++;
tail++;
}
tail = 0;
@@ -131,11 +138,47 @@ xenoprof_ovf_interrupt(int irq, void * d
oprofile_add_pc(buf->event_log[tail].eip,
buf->event_log[tail].mode,
buf->event_log[tail].event);
- oprofile_samples++;
+ if (!is_passive)
+ oprofile_samples++;
+ else
+ p_oprofile_samples++;
tail++;
}
buf->event_tail = tail;
+}
+
+static void xenoprof_handle_passive(void)
+{
+ int i, j;
+
+ for (i = 0; i < pdomains; i++)
+ 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;
+ oprofile_add_pc(IGNORED_PC, CPU_MODE_PASSIVE_START,
passive_domains[i].domain_id);
+ xenoprof_add_pc(buf, 1);
+ oprofile_add_pc(IGNORED_PC, CPU_MODE_PASSIVE_STOP,
passive_domains[i].domain_id);
+ }
+}
+
+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();
+ clear_bit(0, &flag);
+ }
return IRQ_HANDLED;
}
@@ -312,6 +355,63 @@ out:
return ret;
}
+static int xenoprof_set_passive(int * p_domains,
+ unsigned int pdoms)
+{
+ int ret;
+ int i, j;
+ int vm_size;
+ int npages;
+ struct xenoprof_buf *buf;
+ 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)
+ return ret;
+
+ npages = (passive_domains[i].bufsize * passive_domains[i].nbuf
- 1) / PAGE_SIZE + 1;
+ vm_size = npages * PAGE_SIZE;
+
+ p_shared_buffer[i] = (char
*)vm_map_xen_pages(passive_domains[i].buf_maddr,
+ vm_size, prot);
+ if (!p_shared_buffer[i]) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ 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 op_counter_config counter_config[OP_MAX_COUNTER];
@@ -346,6 +446,7 @@ struct oprofile_operations xenoprof_ops
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,
@@ -420,6 +521,8 @@ int __init oprofile_arch_init(struct opr
void __exit oprofile_arch_exit(void)
{
+ int i;
+
if (using_xenoprof)
exit_driverfs();
@@ -427,6 +530,13 @@ void __exit oprofile_arch_exit(void)
vunmap(shared_buffer);
shared_buffer = NULL;
}
- if (is_primary)
+ 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 b12cd185d579 -r 23591d2c46aa
patches/linux-2.6.16.13/xenoprof-generic.patch
--- a/patches/linux-2.6.16.13/xenoprof-generic.patch Tue Jun 27 11:17:14
2006 +0100
+++ b/patches/linux-2.6.16.13/xenoprof-generic.patch Tue Jun 27 11:23:06
2006 +0100
@@ -1,6 +1,6 @@ diff -pruN ../pristine-linux-2.6.16.13/d
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c
./drivers/oprofile/buffer_sync.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c 2006-05-02
22:38:44.000000000 +0100
-+++ ./drivers/oprofile/buffer_sync.c 2006-05-04 17:41:51.000000000 +0100
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c
./drivers/oprofile/buffer_sync.c
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c 2006-05-03
05:38:44.000000000 +0800
++++ ./drivers/oprofile/buffer_sync.c 2006-06-27 12:14:53.000000000 +0800
@@ -6,6 +6,10 @@
*
* @author John Levon <levon@xxxxxxxxxxxxxxxxx>
@@ -12,7 +12,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d
* This is the core of the buffer management. Each
* CPU buffer is processed and entered into the
* global event buffer. Such processing is necessary
-@@ -275,15 +279,24 @@ static void add_cpu_switch(int i)
+@@ -275,15 +279,30 @@ static void add_cpu_switch(int i)
last_cookie = INVALID_COOKIE;
}
@@ -33,7 +33,13 @@ diff -pruN ../pristine-linux-2.6.16.13/d
+ break;
+ case CPU_MODE_XEN:
+ add_event_entry(XEN_ENTER_SWITCH_CODE);
-+ break;
++ break;
++ case CPU_MODE_PASSIVE_START:
++ add_event_entry(PASSIVE_START_CODE);
++ break;
++ case CPU_MODE_PASSIVE_STOP:
++ add_event_entry(PASSIVE_STOP_CODE);
++ break;
+ default:
+ break;
+ }
@@ -43,7 +49,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d
static void
add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
{
-@@ -348,9 +361,9 @@ static int add_us_sample(struct mm_struc
+@@ -348,9 +367,9 @@ static int add_us_sample(struct mm_struc
* for later lookup from userspace.
*/
static int
@@ -55,7 +61,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d
add_sample_entry(s->eip, s->event);
return 1;
} else if (mm) {
-@@ -496,7 +509,7 @@ void sync_buffer(int cpu)
+@@ -496,10 +515,11 @@ void sync_buffer(int cpu)
struct mm_struct *mm = NULL;
struct task_struct * new;
unsigned long cookie = 0;
@@ -64,34 +70,62 @@ diff -pruN ../pristine-linux-2.6.16.13/d
unsigned int i;
sync_buffer_state state = sb_buffer_start;
unsigned long available;
-@@ -513,12 +526,12 @@ void sync_buffer(int cpu)
++ int domain_switch = NO_DOMAIN_SWITCH;
+
+ down(&buffer_sem);
+
+@@ -513,12 +533,19 @@ void sync_buffer(int cpu)
struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
if (is_code(s->eip)) {
- if (s->event <= CPU_IS_KERNEL) {
-+ if (s->event <= CPU_MODE_XEN) {
++ if (s->event < CPU_TRACE_BEGIN) {
/* kernel/userspace switch */
- in_kernel = s->event;
+ cpu_mode = s->event;
if (state == sb_buffer_start)
state = sb_sample_start;
- add_kernel_ctx_switch(s->event);
-+ add_cpu_mode_switch(s->event);
++
++ if (s->event == CPU_MODE_PASSIVE_START)
++ domain_switch =
DOMAIN_SWITCH_START_EVENT1;
++ else if (s->event == CPU_MODE_PASSIVE_STOP)
++ domain_switch =
DOMAIN_SWITCH_STOP_EVENT1;
++
++ if (domain_switch != DOMAIN_SWITCH_START_EVENT2)
++ add_cpu_mode_switch(s->event);
} else if (s->event == CPU_TRACE_BEGIN) {
state = sb_bt_start;
add_trace_begin();
-@@ -536,7 +549,7 @@ void sync_buffer(int cpu)
+@@ -535,11 +562,20 @@ void sync_buffer(int cpu)
+ add_user_ctx_switch(new, cookie);
}
} else {
- if (state >= sb_bt_start &&
+- if (state >= sb_bt_start &&
- !add_sample(mm, s, in_kernel)) {
-+ !add_sample(mm, s, cpu_mode)) {
- if (state == sb_bt_start) {
- state = sb_bt_ignore;
-
atomic_inc(&oprofile_stats.bt_lost_no_mapping);
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c
./drivers/oprofile/cpu_buffer.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c 2006-05-02
22:38:44.000000000 +0100
-+++ ./drivers/oprofile/cpu_buffer.c 2006-05-04 17:41:51.000000000 +0100
+- if (state == sb_bt_start) {
+- state = sb_bt_ignore;
+-
atomic_inc(&oprofile_stats.bt_lost_no_mapping);
++ if (domain_switch == DOMAIN_SWITCH_START_EVENT1) {
++ add_event_entry(s->event);
++ domain_switch = DOMAIN_SWITCH_START_EVENT2;
++ } else if (domain_switch == DOMAIN_SWITCH_START_EVENT1)
{
++ add_sample_entry(s->eip, s->event);
++ } else if (domain_switch == DOMAIN_SWITCH_STOP_EVENT1) {
++ domain_switch = NO_DOMAIN_SWITCH;
++ } else {
++ if (state >= sb_bt_start &&
++ !add_sample(mm, s, cpu_mode)) {
++ if (state == sb_bt_start) {
++ state = sb_bt_ignore;
++
atomic_inc(&oprofile_stats.bt_lost_no_mapping);
++ }
+ }
+ }
+ }
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c
./drivers/oprofile/cpu_buffer.c
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c 2006-05-03
05:38:44.000000000 +0800
++++ ./drivers/oprofile/cpu_buffer.c 2006-06-19 22:43:53.000000000 +0800
@@ -6,6 +6,10 @@
*
* @author John Levon <levon@xxxxxxxxxxxxxxxxx>
@@ -139,13 +173,12 @@ diff -pruN ../pristine-linux-2.6.16.13/d
{
struct task_struct * task;
-@@ -181,16 +185,16 @@ static int log_sample(struct oprofile_cp
+@@ -181,16 +185,14 @@ static int log_sample(struct oprofile_cp
return 0;
}
- is_kernel = !!is_kernel;
-+ WARN_ON(cpu_mode > CPU_MODE_XEN);
-
+-
task = current;
/* notice a switch from user->kernel or vice versa */
@@ -161,9 +194,9 @@ diff -pruN ../pristine-linux-2.6.16.13/d
/* notice a task switch */
if (cpu_buf->last_task != task) {
cpu_buf->last_task = task;
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h
./drivers/oprofile/cpu_buffer.h
---- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h 2006-05-02
22:38:44.000000000 +0100
-+++ ./drivers/oprofile/cpu_buffer.h 2006-05-04 17:41:51.000000000 +0100
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h
./drivers/oprofile/cpu_buffer.h
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.h 2006-05-03
05:38:44.000000000 +0800
++++ ./drivers/oprofile/cpu_buffer.h 2006-06-27 10:38:08.000000000 +0800
@@ -36,7 +36,7 @@ struct oprofile_cpu_buffer {
volatile unsigned long tail_pos;
unsigned long buffer_size;
@@ -173,22 +206,26 @@ diff -pruN ../pristine-linux-2.6.16.13/d
int tracing;
struct op_sample * buffer;
unsigned long sample_received;
-@@ -51,7 +51,9 @@ extern struct oprofile_cpu_buffer cpu_bu
+@@ -51,7 +51,13 @@ extern struct oprofile_cpu_buffer cpu_bu
void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
/* transient events for the CPU buffer -> event buffer */
-#define CPU_IS_KERNEL 1
-#define CPU_TRACE_BEGIN 2
-+#define CPU_MODE_USER 0
-+#define CPU_MODE_KERNEL 1
-+#define CPU_MODE_XEN 2
-+#define CPU_TRACE_BEGIN 3
++#define CPU_MODE_USER 0
++#define CPU_MODE_KERNEL 1
++#define CPU_MODE_XEN 2
++#define CPU_MODE_PASSIVE_START 3
++#define CPU_MODE_PASSIVE_STOP 4
++#define CPU_TRACE_BEGIN 5
++
++#define IGNORED_PC 0
#endif /* OPROFILE_CPU_BUFFER_H */
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h
./drivers/oprofile/event_buffer.h
---- ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h
2006-05-02 22:38:44.000000000 +0100
-+++ ./drivers/oprofile/event_buffer.h 2006-05-04 17:41:51.000000000 +0100
-@@ -29,11 +29,12 @@ void wake_up_buffer_waiter(void);
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h
./drivers/oprofile/event_buffer.h
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/event_buffer.h
2006-05-03 05:38:44.000000000 +0800
++++ ./drivers/oprofile/event_buffer.h 2006-06-19 22:43:53.000000000 +0800
+@@ -29,11 +29,14 @@ void wake_up_buffer_waiter(void);
#define CPU_SWITCH_CODE 2
#define COOKIE_SWITCH_CODE 3
#define KERNEL_ENTER_SWITCH_CODE 4
@@ -199,12 +236,14 @@ diff -pruN ../pristine-linux-2.6.16.13/d
#define TRACE_BEGIN_CODE 8
#define TRACE_END_CODE 9
+#define XEN_ENTER_SWITCH_CODE 10
++#define PASSIVE_START_CODE 11
++#define PASSIVE_STOP_CODE 12
#define INVALID_COOKIE ~0UL
#define NO_COOKIE 0UL
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c
./drivers/oprofile/oprof.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c 2006-05-02
22:38:44.000000000 +0100
-+++ ./drivers/oprofile/oprof.c 2006-05-04 17:41:51.000000000 +0100
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c
./drivers/oprofile/oprof.c
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c 2006-05-03
05:38:44.000000000 +0800
++++ ./drivers/oprofile/oprof.c 2006-06-19 23:45:17.000000000 +0800
@@ -5,6 +5,10 @@
* @remark Read the file COPYING
*
@@ -225,7 +264,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d
struct oprofile_operations oprofile_ops;
unsigned long oprofile_started;
-@@ -33,6 +37,19 @@ static DECLARE_MUTEX(start_sem);
+@@ -33,6 +37,32 @@ static DECLARE_MUTEX(start_sem);
*/
static int timer = 0;
@@ -242,23 +281,37 @@ diff -pruN ../pristine-linux-2.6.16.13/d
+ return err;
+}
+
++int oprofile_set_passive(int passive_domains[], unsigned int pdomains)
++{
++ int err;
++
++ if (!oprofile_ops.set_passive)
++ return -EINVAL;
++
++ down(&start_sem);
++ err = oprofile_ops.set_passive(passive_domains, pdomains);
++ up(&start_sem);
++ return err;
++}
++
int oprofile_setup(void)
{
int err;
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h
./drivers/oprofile/oprof.h
---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h 2006-05-02
22:38:44.000000000 +0100
-+++ ./drivers/oprofile/oprof.h 2006-05-04 17:41:51.000000000 +0100
-@@ -35,5 +35,7 @@ void oprofile_create_files(struct super_
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h
./drivers/oprofile/oprof.h
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.h 2006-05-03
05:38:44.000000000 +0800
++++ ./drivers/oprofile/oprof.h 2006-06-19 23:42:36.000000000 +0800
+@@ -35,5 +35,8 @@ void oprofile_create_files(struct super_
void oprofile_timer_init(struct oprofile_operations * ops);
int oprofile_set_backtrace(unsigned long depth);
+
+int oprofile_set_active(int active_domains[], unsigned int adomains);
++int oprofile_set_passive(int passive_domains[], unsigned int pdomains);
#endif /* OPROF_H */
-diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c
./drivers/oprofile/oprofile_files.c
---- ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c
2006-05-02 22:38:44.000000000 +0100
-+++ ./drivers/oprofile/oprofile_files.c 2006-05-04 17:41:51.000000000
+0100
+diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c
./drivers/oprofile/oprofile_files.c
+--- ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c
2006-05-03 05:38:44.000000000 +0800
++++ ./drivers/oprofile/oprofile_files.c 2006-06-19 23:29:07.000000000
+0800
@@ -5,15 +5,21 @@
* @remark Read the file COPYING
*
@@ -282,7 +335,7 @@ diff -pruN ../pristine-linux-2.6.16.13/d
unsigned long fs_buffer_size = 131072;
unsigned long fs_cpu_buffer_size = 8192;
unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */
-@@ -117,11 +123,108 @@ static ssize_t dump_write(struct file *
+@@ -117,11 +123,202 @@ static ssize_t dump_write(struct file *
static struct file_operations dump_fops = {
.write = dump_write,
};
@@ -384,17 +437,110 @@ diff -pruN ../pristine-linux-2.6.16.13/d
+ .write = adomain_write,
+};
+
++static unsigned int pdomains = 0;
++static int passive_domains[MAX_OPROF_DOMAINS];
++static DEFINE_MUTEX(pdom_mutex);
++
++static ssize_t pdomain_write(struct file * file, char const __user * buf,
++ size_t count, loff_t * offset)
++{
++ char *tmpbuf;
++ char *startp, *endp;
++ int i;
++ unsigned long val;
++ ssize_t retval = count;
++
++ if (*offset)
++ return -EINVAL;
++ if (count > TMPBUFSIZE - 1)
++ return -EINVAL;
++
++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++ return -ENOMEM;
++
++ if (copy_from_user(tmpbuf, buf, count)) {
++ kfree(tmpbuf);
++ return -EFAULT;
++ }
++ tmpbuf[count] = 0;
++
++ mutex_lock(&pdom_mutex);
++
++ startp = tmpbuf;
++ /* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */
++ for (i = 0; i <= MAX_OPROF_DOMAINS; i++) {
++ val = simple_strtoul(startp, &endp, 0);
++ if (endp == startp)
++ break;
++ while (ispunct(*endp) || isspace(*endp))
++ endp++;
++ passive_domains[i] = val;
++ if (passive_domains[i] != val)
++ /* Overflow, force error below */
++ i = MAX_OPROF_DOMAINS + 1;
++ startp = endp;
++ }
++ /* Force error on trailing junk */
++ pdomains = *startp ? MAX_OPROF_DOMAINS + 1 : i;
++
++ kfree(tmpbuf);
++
++ if (pdomains > MAX_OPROF_DOMAINS
++ || oprofile_set_passive(passive_domains, pdomains)) {
++ pdomains = 0;
++ retval = -EINVAL;
++ }
++
++ mutex_unlock(&pdom_mutex);
++ return retval;
++}
++
++static ssize_t pdomain_read(struct file * file, char __user * buf,
++ size_t count, loff_t * offset)
++{
++ char * tmpbuf;
++ size_t len;
++ int i;
++ ssize_t retval;
++
++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++ return -ENOMEM;
++
++ mutex_lock(&pdom_mutex);
++
++ len = 0;
++ for (i = 0; i < pdomains; i++)
++ len += snprintf(tmpbuf + len,
++ len < TMPBUFSIZE ? TMPBUFSIZE - len : 0,
++ "%u ", passive_domains[i]);
++ WARN_ON(len > TMPBUFSIZE);
++ if (len != 0 && len <= TMPBUFSIZE)
++ tmpbuf[len-1] = '\n';
++
++ mutex_unlock(&pdom_mutex);
++
++ retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len);
++
++ kfree(tmpbuf);
++ return retval;
++}
++
++static struct file_operations passive_domain_ops = {
++ .read = pdomain_read,
++ .write = pdomain_write,
++};
++
void oprofile_create_files(struct super_block * sb, struct dentry * root)
{
oprofilefs_create_file(sb, root, "enable", &enable_fops);
oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
+ oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops);
++ oprofilefs_create_file(sb, root, "passive_domains",
&passive_domain_ops);
oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size);
oprofilefs_create_ulong(sb, root, "buffer_watershed",
&fs_buffer_watershed);
-diff -pruN ../pristine-linux-2.6.16.13/include/linux/oprofile.h
./include/linux/oprofile.h
---- ../pristine-linux-2.6.16.13/include/linux/oprofile.h 2006-05-02
22:38:44.000000000 +0100
-+++ ./include/linux/oprofile.h 2006-05-04 17:41:51.000000000 +0100
+--- ../pristine-linux-2.6.16.13/include/linux/oprofile.h 2006-05-03
05:38:44.000000000 +0800
++++ ./include/linux/oprofile.h 2006-06-19 23:52:00.000000000 +0800
@@ -16,6 +16,8 @@
#include <linux/types.h>
#include <linux/spinlock.h>
@@ -404,12 +550,15 @@ diff -pruN ../pristine-linux-2.6.16.13/i
struct super_block;
struct dentry;
-@@ -27,6 +29,8 @@ struct oprofile_operations {
+@@ -27,6 +29,11 @@ struct oprofile_operations {
/* create any necessary configuration files in the oprofile fs.
* Optional. */
int (*create_files)(struct super_block * sb, struct dentry * root);
+ /* setup active domains with Xen */
+ int (*set_active)(int *active_domains, unsigned int adomains);
++ /* setup passive domains with Xen */
++ int (*set_passive)(int *passive_domains, unsigned int pdomains);
++
/* Do any necessary interrupt setup. Optional. */
int (*setup)(void);
/* Do any necessary interrupt shutdown. Optional. */
diff -r b12cd185d579 -r 23591d2c46aa xen/arch/x86/oprofile/nmi_int.c
--- a/xen/arch/x86/oprofile/nmi_int.c Tue Jun 27 11:17:14 2006 +0100
+++ b/xen/arch/x86/oprofile/nmi_int.c Tue Jun 27 11:23:06 2006 +0100
@@ -269,7 +269,7 @@ static int __init p4_init(char * cpu_typ
{
__u8 cpu_model = current_cpu_data.x86_model;
- if (cpu_model > 4)
+ if ((cpu_model > 6) || (cpu_model == 5))
return 0;
#ifndef CONFIG_SMP
diff -r b12cd185d579 -r 23591d2c46aa xen/arch/x86/oprofile/xenoprof.c
--- a/xen/arch/x86/oprofile/xenoprof.c Tue Jun 27 11:17:14 2006 +0100
+++ b/xen/arch/x86/oprofile/xenoprof.c Tue Jun 27 11:23:06 2006 +0100
@@ -13,9 +13,13 @@
/* Limit amount of pages used for shared buffer (per domain) */
#define MAX_OPROF_SHARED_PAGES 32
-domid_t active_domains[MAX_OPROF_DOMAINS];
+struct domain *active_domains[MAX_OPROF_DOMAINS];
int active_ready[MAX_OPROF_DOMAINS];
unsigned int adomains;
+
+struct domain *passive_domains[MAX_OPROF_DOMAINS];
+unsigned int pdomains;
+
unsigned int activated;
struct domain *primary_profiler;
int xenoprof_state = XENOPROF_IDLE;
@@ -25,6 +29,7 @@ u64 corrupted_buffer_samples;
u64 corrupted_buffer_samples;
u64 lost_samples;
u64 active_samples;
+u64 passive_samples;
u64 idle_samples;
u64 others_samples;
@@ -44,9 +49,15 @@ int is_active(struct domain *d)
return ((x != NULL) && (x->domain_type == XENOPROF_DOMAIN_ACTIVE));
}
+int is_passive(struct domain *d)
+{
+ struct xenoprof *x = d->xenoprof;
+ return ((x != NULL) && (x->domain_type == XENOPROF_DOMAIN_PASSIVE));
+}
+
int is_profiled(struct domain *d)
{
- return is_active(d);
+ return (is_active(d) || is_passive(d));
}
static void xenoprof_reset_stat(void)
@@ -56,6 +67,7 @@ static void xenoprof_reset_stat(void)
corrupted_buffer_samples = 0;
lost_samples = 0;
active_samples = 0;
+ passive_samples = 0;
idle_samples = 0;
others_samples = 0;
}
@@ -83,13 +95,122 @@ static void xenoprof_reset_buf(struct do
}
}
+char *alloc_xenoprof_buf(struct domain *d, int npages)
+{
+ char *rawbuf;
+ int i, order;
+
+ /* allocate pages to store sample buffer shared with domain */
+ order = get_order_from_pages(npages);
+ rawbuf = alloc_xenheap_pages(order);
+ if ( rawbuf == NULL )
+ {
+ printk("alloc_xenoprof_buf(): memory allocation failed\n");
+ return 0;
+ }
+
+ /* Share pages so that kernel can map it */
+ for ( i = 0; i < npages; i++ )
+ share_xen_page_with_guest(
+ virt_to_page(rawbuf + i * PAGE_SIZE),
+ d, XENSHARE_writable);
+
+ return rawbuf;
+}
+
+int alloc_xenoprof_struct(struct domain *d, int max_samples, int is_passive)
+{
+ struct vcpu *v;
+ int nvcpu, npages, bufsize, max_bufsize;
+ int i;
+
+ d->xenoprof = xmalloc(struct xenoprof);
+
+ if ( d->xenoprof == NULL )
+ {
+ printk ("alloc_xenoprof_struct(): memory "
+ "allocation (xmalloc) failed\n");
+ return -ENOMEM;
+ }
+
+ memset(d->xenoprof, 0, sizeof(*d->xenoprof));
+
+ nvcpu = 0;
+ for_each_vcpu ( d, v )
+ nvcpu++;
+
+ /* reduce buffer size if necessary to limit pages allocated */
+ bufsize = sizeof(struct xenoprof_buf) +
+ (max_samples - 1) * sizeof(struct event_log);
+ max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu;
+ if ( bufsize > max_bufsize )
+ {
+ bufsize = max_bufsize;
+ max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) /
+ sizeof(struct event_log) ) + 1;
+ }
+
+ npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1;
+
+ d->xenoprof->rawbuf = alloc_xenoprof_buf(is_passive ? dom0 : d, npages);
+
+ if ( d->xenoprof->rawbuf == NULL )
+ {
+ xfree(d->xenoprof);
+ d->xenoprof = NULL;
+ return -ENOMEM;
+ }
+
+ d->xenoprof->npages = npages;
+ d->xenoprof->nbuf = nvcpu;
+ d->xenoprof->bufsize = bufsize;
+ d->xenoprof->domain_ready = 0;
+ d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED;
+
+ /* Update buffer pointers for active vcpus */
+ i = 0;
+ for_each_vcpu ( d, v )
+ {
+ d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples;
+ d->xenoprof->vcpu[v->vcpu_id].buffer =
+ (struct xenoprof_buf *)&d->xenoprof->rawbuf[i * bufsize];
+ d->xenoprof->vcpu[v->vcpu_id].buffer->event_size = max_samples;
+ d->xenoprof->vcpu[v->vcpu_id].buffer->vcpu_id = v->vcpu_id;
+
+ i++;
+ /* in the unlikely case that the number of active vcpus changes */
+ if ( i >= nvcpu )
+ break;
+ }
+
+ return 0;
+}
+
+void free_xenoprof_pages(struct domain *d)
+{
+ struct xenoprof *x;
+ int order;
+
+ x = d->xenoprof;
+ if ( x == NULL )
+ return;
+
+ if ( x->rawbuf != NULL )
+ {
+ order = get_order_from_pages(x->npages);
+ free_xenheap_pages(x->rawbuf, order);
+ }
+
+ xfree(x);
+ d->xenoprof = NULL;
+}
+
int active_index(struct domain *d)
{
int i;
- domid_t id = d->domain_id;
for ( i = 0; i < adomains; i++ )
- if ( active_domains[i] == id )
+ if ( active_domains[i] == d )
return i;
return -1;
@@ -132,47 +253,116 @@ int reset_active(struct domain *d)
x->domain_ready = 0;
x->domain_type = XENOPROF_DOMAIN_IGNORED;
active_ready[ind] = 0;
+ active_domains[ind] = NULL;
activated--;
+ put_domain(d);
+
if ( activated <= 0 )
adomains = 0;
return 0;
}
-int reset_active_list(void)
+void reset_passive(struct domain *d)
+{
+ struct xenoprof *x;
+
+ if (d==0)
+ return;
+
+ x = d->xenoprof;
+ if ( x == NULL )
+ return;
+
+ x->domain_type = XENOPROF_DOMAIN_IGNORED;
+
+ return;
+}
+
+void reset_active_list(void)
{
int i;
- struct domain *d;
for ( i = 0; i < adomains; i++ )
{
if ( active_ready[i] )
{
- d = find_domain_by_id(active_domains[i]);
- if ( d != NULL )
- {
- reset_active(d);
- put_domain(d);
- }
+ reset_active(active_domains[i]);
}
}
adomains = 0;
activated = 0;
-
- return 0;
+}
+
+void reset_passive_list(void)
+{
+ int i;
+
+ for ( i = 0; i < pdomains; i++ )
+ {
+ reset_passive(passive_domains[i]);
+ put_domain(passive_domains[i]);
+ passive_domains[i] = NULL;
+ }
+
+ pdomains = 0;
}
int add_active_list (domid_t domid)
{
+ struct domain *d;
+
if ( adomains >= MAX_OPROF_DOMAINS )
return -E2BIG;
- active_domains[adomains] = domid;
+ d = find_domain_by_id(domid);
+ if ( d == NULL )
+ return -EINVAL;
+
+ active_domains[adomains] = d;
active_ready[adomains] = 0;
adomains++;
return 0;
+}
+
+int add_passive_list(XEN_GUEST_HANDLE(void) arg)
+{
+ struct xenoprof_passive passive;
+ struct domain *d;
+ int ret = 0;
+
+ if ( pdomains >= MAX_OPROF_DOMAINS )
+ return -E2BIG;
+
+ if ( copy_from_guest(&passive, arg, 1) )
+ return -EFAULT;
+
+ d = find_domain_by_id(passive.domain_id);
+ if ( d == NULL )
+ return -EINVAL;
+
+ if ( (d->xenoprof == NULL) &&
+ ((ret = alloc_xenoprof_struct(d, passive.max_samples, 1)) < 0) ) {
+ put_domain(d);
+ return -ENOMEM;
+ }
+
+ d->xenoprof->domain_type = XENOPROF_DOMAIN_PASSIVE;
+ passive.nbuf = d->xenoprof->nbuf;
+ passive.bufsize = d->xenoprof->bufsize;
+ passive.buf_maddr = __pa(d->xenoprof->rawbuf);
+
+ if ( copy_to_guest(arg, &passive, 1) ) {
+ put_domain(d);
+ return -EFAULT;
+ }
+
+ passive_domains[pdomains] = d;
+ pdomains++;
+
+ return ret;
}
void xenoprof_log_event(
@@ -231,7 +421,10 @@ void xenoprof_log_event(
if ( head >= size )
head = 0;
buf->event_head = head;
- active_samples++;
+ if ( is_active(vcpu->domain) )
+ active_samples++;
+ else
+ passive_samples++;
if ( mode == 0 )
buf->user_samples++;
else if ( mode == 1 )
@@ -241,114 +434,6 @@ void xenoprof_log_event(
}
}
-char *alloc_xenoprof_buf(struct domain *d, int npages)
-{
- char *rawbuf;
- int i, order;
-
- /* allocate pages to store sample buffer shared with domain */
- order = get_order_from_pages(npages);
- rawbuf = alloc_xenheap_pages(order);
- if ( rawbuf == NULL )
- {
- printk("alloc_xenoprof_buf(): memory allocation failed\n");
- return 0;
- }
-
- /* Share pages so that kernel can map it */
- for ( i = 0; i < npages; i++ )
- share_xen_page_with_guest(
- virt_to_page(rawbuf + i * PAGE_SIZE),
- d, XENSHARE_writable);
-
- return rawbuf;
-}
-
-int alloc_xenoprof_struct(struct domain *d, int max_samples)
-{
- struct vcpu *v;
- int nvcpu, npages, bufsize, max_bufsize;
- int i;
-
- d->xenoprof = xmalloc(struct xenoprof);
-
- if ( d->xenoprof == NULL )
- {
- printk ("alloc_xenoprof_struct(): memory "
- "allocation (xmalloc) failed\n");
- return -ENOMEM;
- }
-
- memset(d->xenoprof, 0, sizeof(*d->xenoprof));
-
- nvcpu = 0;
- for_each_vcpu ( d, v )
- nvcpu++;
-
- /* reduce buffer size if necessary to limit pages allocated */
- bufsize = sizeof(struct xenoprof_buf) +
- (max_samples - 1) * sizeof(struct event_log);
- max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu;
- if ( bufsize > max_bufsize )
- {
- bufsize = max_bufsize;
- max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) /
- sizeof(struct event_log) ) + 1;
- }
-
- npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1;
- d->xenoprof->rawbuf = alloc_xenoprof_buf(d, npages);
- if ( d->xenoprof->rawbuf == NULL )
- {
- xfree(d->xenoprof);
- d->xenoprof = NULL;
- return -ENOMEM;
- }
-
- d->xenoprof->npages = npages;
- d->xenoprof->nbuf = nvcpu;
- d->xenoprof->bufsize = bufsize;
- d->xenoprof->domain_ready = 0;
- d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED;
-
- /* Update buffer pointers for active vcpus */
- i = 0;
- for_each_vcpu ( d, v )
- {
- d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples;
- d->xenoprof->vcpu[v->vcpu_id].buffer =
- (struct xenoprof_buf *)&d->xenoprof->rawbuf[i * bufsize];
- d->xenoprof->vcpu[v->vcpu_id].buffer->event_size = max_samples;
- d->xenoprof->vcpu[v->vcpu_id].buffer->vcpu_id = v->vcpu_id;
-
- i++;
- /* in the unlikely case that the number of active vcpus changes */
- if ( i >= nvcpu )
- break;
- }
-
- return 0;
-}
-
-void free_xenoprof_pages(struct domain *d)
-{
- struct xenoprof *x;
- int order;
-
- x = d->xenoprof;
- if ( x == NULL )
- return;
-
- if ( x->rawbuf != NULL )
- {
- order = get_order_from_pages(x->npages);
- free_xenheap_pages(x->rawbuf, order);
- }
-
- xfree(x);
- d->xenoprof = NULL;
-}
-
int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
{
struct xenoprof_init xenoprof_init;
@@ -373,7 +458,7 @@ int xenoprof_op_init(XEN_GUEST_HANDLE(vo
* is called. Memory is then kept until domain is destroyed.
*/
if ( (d->xenoprof == NULL) &&
- ((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples)) < 0) )
+ ((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples, 0)) < 0) )
goto err;
xenoprof_reset_buf(d);
@@ -429,7 +514,14 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
case XENOPROF_reset_active_list:
{
- ret = reset_active_list();
+ reset_active_list();
+ ret = 0;
+ break;
+ }
+ case XENOPROF_reset_passive_list:
+ {
+ reset_passive_list();
+ ret = 0;
break;
}
case XENOPROF_set_active:
@@ -440,6 +532,13 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
if ( copy_from_guest(&domid, arg, 1) )
return -EFAULT;
ret = add_active_list(domid);
+ break;
+ }
+ case XENOPROF_set_passive:
+ {
+ if ( xenoprof_state != XENOPROF_IDLE )
+ return -EPERM;
+ ret = add_passive_list(arg);
break;
}
case XENOPROF_reserve_counters:
@@ -484,14 +583,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
break;
case XENOPROF_enable_virq:
+ {
+ int i;
if ( current->domain == primary_profiler )
{
nmi_enable_virq();
xenoprof_reset_stat();
+ for ( i = 0; i < pdomains; i++ ) {
+ xenoprof_reset_buf(passive_domains[i]);
+ }
}
xenoprof_reset_buf(current->domain);
ret = set_active(current->domain);
break;
+ }
case XENOPROF_start:
ret = -EPERM;
@@ -525,6 +630,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
xenoprof_state = XENOPROF_IDLE;
nmi_release_counters();
nmi_disable_virq();
+ reset_passive_list();
ret = 0;
}
break;
diff -r b12cd185d579 -r 23591d2c46aa xen/include/public/xenoprof.h
--- a/xen/include/public/xenoprof.h Tue Jun 27 11:17:14 2006 +0100
+++ b/xen/include/public/xenoprof.h Tue Jun 27 11:23:06 2006 +0100
@@ -80,6 +80,15 @@ typedef struct xenoprof_counter xenoprof
typedef struct xenoprof_counter xenoprof_counter_t;
DEFINE_XEN_GUEST_HANDLE(xenoprof_counter_t);
+typedef struct xenoprof_passive {
+ uint16_t domain_id;
+ int32_t max_samples;
+ int32_t nbuf;
+ int32_t bufsize;
+ uint64_t buf_maddr;
+} xenoprof_passive_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t);
+
#endif /* __XEN_PUBLIC_XENOPROF_H__ */
diff -r b12cd185d579 -r 23591d2c46aa xen/include/xen/xenoprof.h
--- a/xen/include/xen/xenoprof.h Tue Jun 27 11:17:14 2006 +0100
+++ b/xen/include/xen/xenoprof.h Tue Jun 27 11:23:06 2006 +0100
@@ -14,6 +14,7 @@
#define XENOPROF_DOMAIN_IGNORED 0
#define XENOPROF_DOMAIN_ACTIVE 1
+#define XENOPROF_DOMAIN_PASSIVE 2
#define XENOPROF_IDLE 0
#define XENOPROF_COUNTERS_RESERVED 1
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|