mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
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:
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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. */
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||