[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Add Xenoprof passive domain support
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |