Add Xenoprof passive domain support

Signed-off-by: Yang Xiaowei <xiaowei.yang@intel.com>
Signed-off-by: Jose Renato Santos <jsantos@hpl.hp.com>
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2006-06-27 11:23:06 +01:00
1 parent 78d2beff2c
commit b9a9bc6e86
6 files changed
+561 -186

No files matched your search

@@ -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;
unsigned long long p_oprofile_samples = 0;
static irqreturn_t
xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
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 * dev_id, struct pt_regs * regs)
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 * dev_id, struct pt_regs * regs)
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 @@ static int xenoprof_create_files(struct super_block * sb, struct dentry * root)
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 oprofile_operations * ops)
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);
}
}
+199 -50
View File
@@ -1,6 +1,6 @@
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@movementarian.org>
@@ -12,7 +12,7 @@ diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c ./drivers/
* 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/drivers/oprofile/buffer_sync.c ./drivers/
+ 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/drivers/oprofile/buffer_sync.c ./drivers/
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/drivers/oprofile/buffer_sync.c ./drivers/
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/drivers/oprofile/buffer_sync.c ./drivers/
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@movementarian.org>
@@ -139,13 +173,12 @@ diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c ./drivers/o
{
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/drivers/oprofile/cpu_buffer.c ./drivers/o
/* 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/drivers/oprofile/cpu_buffer.h ./drivers/o
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/drivers/oprofile/event_buffer.h ./drivers
#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/drivers/oprofile/oprof.c ./drivers/oprofi
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;
@@ -241,24 +280,38 @@ diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprof.c ./drivers/oprofi
+ up(&start_sem);
+ 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/drivers/oprofile/oprofile_files.c ./drive
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,
};
@@ -383,18 +436,111 @@ diff -pruN ../pristine-linux-2.6.16.13/drivers/oprofile/oprofile_files.c ./drive
+ .read = adomain_read,
+ .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/include/linux/oprofile.h ./include/linux/
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. */
+1 -1
View File
@@ -269,7 +269,7 @@ static int __init p4_init(char * cpu_type)
{
__u8 cpu_model = current_cpu_data.x86_model;
if (cpu_model > 4)
if ((cpu_model > 6) || (cpu_model == 5))
return 0;
#ifndef CONFIG_SMP
+231 -125
View File
@@ -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 invalid_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 domain *d)
}
}
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,49 +253,118 @@ 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(
struct vcpu *vcpu, unsigned long eip, int mode, int 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(void) arg)
* 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_HANDLE(void) arg)
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:
@@ -442,6 +534,13 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
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:
if ( xenoprof_state != XENOPROF_IDLE )
return -EPERM;
@@ -484,14 +583,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
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_HANDLE(void) arg)
xenoprof_state = XENOPROF_IDLE;
nmi_release_counters();
nmi_disable_virq();
reset_passive_list();
ret = 0;
}
break;
+9
View File
@@ -80,6 +80,15 @@ struct xenoprof_counter {
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__ */
+1
View File
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.