Add new operation XENOPROF_get_buffer in xenoprof hypercall. Also

remove buffer related arguments from XENOPROF_init operation. This
is the first step to allow dynamic mapping/unmapping of xenoprof
buffers to
enable profiling a domain in passive mode and then switch to active
mode (or vice-versa). Currently a domain can only be profiled in a
single mode. Also passive domains cannot have oprofile builtin the
kernel or passive profiling will fail.

Signed-off-by: Jose Renato Santos <jsantos@hpl.hp.com>
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2006-09-13 14:05:33 +01:00
1 parent 80f2588d2b
commit d4b644873d
3 files changed
+101 -72

No files matched your search

@@ -32,6 +32,8 @@
#include <../../../drivers/oprofile/cpu_buffer.h>
#include <../../../drivers/oprofile/event_buffer.h>
#define MAX_XENOPROF_SAMPLES 16
static int xenoprof_start(void);
static void xenoprof_stop(void);
@@ -43,7 +45,7 @@ static int active_defined;
/* sample buffers shared with Xen */
xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS];
/* Shared buffer area */
char * shared_buffer;
char * shared_buffer = NULL;
/* Number of buffers in shared area (one per VCPU) */
int nbuf;
/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
@@ -233,13 +235,57 @@ static int bind_virq(void)
}
static int map_xenoprof_buffer(int max_samples)
{
struct xenoprof_get_buffer get_buffer;
struct xenoprof_buf *buf;
int npages, ret, i;
struct vm_struct *area;
if ( shared_buffer )
return 0;
get_buffer.max_samples = max_samples;
if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, &get_buffer)) )
return ret;
nbuf = get_buffer.nbuf;
npages = (get_buffer.bufsize * nbuf - 1) / PAGE_SIZE + 1;
area = alloc_vm_area(npages * PAGE_SIZE);
if (area == NULL)
return -ENOMEM;
if ( (ret = direct_kernel_remap_pfn_range(
(unsigned long)area->addr,
get_buffer.buf_maddr >> PAGE_SHIFT,
npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE), DOMID_SELF)) ) {
vunmap(area->addr);
return ret;
}
shared_buffer = area->addr;
for (i=0; i< nbuf; i++) {
buf = (struct xenoprof_buf*)
&shared_buffer[i * get_buffer.bufsize];
BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
xenoprof_buf[buf->vcpu_id] = buf;
}
return 0;
}
static int xenoprof_setup(void)
{
int ret;
int i;
ret = bind_virq();
if (ret)
if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) )
return ret;
if ( (ret = bind_virq()) )
return ret;
if (is_primary) {
@@ -482,51 +528,19 @@ static int using_xenoprof;
int __init oprofile_arch_init(struct oprofile_operations * ops)
{
struct xenoprof_init init;
struct xenoprof_buf *buf;
int npages, ret, i;
struct vm_struct *area;
int ret, i;
init.max_samples = 16;
ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init);
if (!ret) {
pgprot_t prot = __pgprot(_KERNPG_TABLE);
num_events = init.num_events;
is_primary = init.is_primary;
nbuf = init.nbuf;
/* just in case - make sure we do not overflow event list
(i.e. counter_config list) */
(i.e. counter_config list) */
if (num_events > OP_MAX_COUNTER)
num_events = OP_MAX_COUNTER;
npages = (init.bufsize * nbuf - 1) / PAGE_SIZE + 1;
area = alloc_vm_area(npages * PAGE_SIZE);
if (area == NULL) {
ret = -ENOMEM;
goto out;
}
ret = direct_kernel_remap_pfn_range(
(unsigned long)area->addr,
init.buf_maddr >> PAGE_SHIFT,
npages * PAGE_SIZE, prot, DOMID_SELF);
if (ret) {
vunmap(area->addr);
goto out;
}
shared_buffer = area->addr;
for (i=0; i< nbuf; i++) {
buf = (struct xenoprof_buf*)
&shared_buffer[i * init.bufsize];
BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
xenoprof_buf[buf->vcpu_id] = buf;
}
/* cpu_type is detected by Xen */
cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
@@ -541,7 +555,6 @@ int __init oprofile_arch_init(struct oprofile_operations * ops)
active_defined = 0;
}
out:
printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, "
"is_primary %d\n", ret, num_events, is_primary);
return ret;
+39 -30
View File
@@ -437,54 +437,59 @@ void xenoprof_log_event(
int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
{
struct xenoprof_init xenoprof_init;
int is_primary, num_events;
struct domain *d = current->domain;
int ret;
if ( copy_from_guest(&xenoprof_init, arg, 1) )
return -EFAULT;
ret = nmi_init(&num_events,
&is_primary,
xenoprof_init.cpu_type);
if ( ret < 0 )
goto err;
if ( (ret = nmi_init(&xenoprof_init.num_events,
&xenoprof_init.is_primary,
xenoprof_init.cpu_type)) )
return ret;
if ( is_primary )
if ( copy_to_guest(arg, &xenoprof_init, 1) )
return -EFAULT;
if ( xenoprof_init.is_primary )
primary_profiler = current->domain;
return 0;
}
int xenoprof_op_get_buffer(XEN_GUEST_HANDLE(void) arg)
{
struct xenoprof_get_buffer xenoprof_get_buffer;
struct domain *d = current->domain;
int ret;
if ( copy_from_guest(&xenoprof_get_buffer, arg, 1) )
return -EFAULT;
/*
* We allocate xenoprof struct and buffers only at first time xenoprof_init
* We allocate xenoprof struct and buffers only at first time xenoprof_get_buffer
* is called. Memory is then kept until domain is destroyed.
*/
if ( (d->xenoprof == NULL) &&
((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples, 0)) < 0) )
goto err;
((ret = alloc_xenoprof_struct(d, xenoprof_get_buffer.max_samples, 0)) < 0) )
return ret;
xenoprof_reset_buf(d);
d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED;
d->xenoprof->domain_ready = 0;
d->xenoprof->is_primary = is_primary;
xenoprof_init.is_primary = is_primary;
xenoprof_init.num_events = num_events;
xenoprof_init.nbuf = d->xenoprof->nbuf;
xenoprof_init.bufsize = d->xenoprof->bufsize;
xenoprof_init.buf_maddr = __pa(d->xenoprof->rawbuf);
if ( copy_to_guest(arg, &xenoprof_init, 1) )
{
ret = -EFAULT;
goto err;
}
return ret;
err:
if ( primary_profiler == current->domain )
primary_profiler = NULL;
return ret;
d->xenoprof->is_primary = 1;
else
d->xenoprof->is_primary = 0;
xenoprof_get_buffer.nbuf = d->xenoprof->nbuf;
xenoprof_get_buffer.bufsize = d->xenoprof->bufsize;
xenoprof_get_buffer.buf_maddr = __pa(d->xenoprof->rawbuf);
if ( copy_to_guest(arg, &xenoprof_get_buffer, 1) )
return -EFAULT;
return 0;
}
#define PRIV_OP(op) ( (op == XENOPROF_set_active) \
@@ -512,6 +517,10 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
ret = xenoprof_op_init(arg);
break;
case XENOPROF_get_buffer:
ret = xenoprof_op_get_buffer(arg);
break;
case XENOPROF_reset_active_list:
{
reset_active_list();
+11 -4
View File
@@ -28,6 +28,8 @@
#define XENOPROF_disable_virq 11
#define XENOPROF_release_counters 12
#define XENOPROF_shutdown 13
#define XENOPROF_get_buffer 14
#define XENOPROF_last_op 14
#define MAX_OPROF_EVENTS 32
#define MAX_OPROF_DOMAINS 25
@@ -56,17 +58,22 @@ typedef struct xenoprof_buf xenoprof_buf_t;
DEFINE_XEN_GUEST_HANDLE(xenoprof_buf_t);
struct xenoprof_init {
int32_t max_samples;
int32_t num_events;
int32_t is_primary;
int32_t nbuf;
int32_t bufsize;
uint64_t buf_maddr;
char cpu_type[XENOPROF_CPU_TYPE_SIZE];
};
typedef struct xenoprof_init xenoprof_init_t;
DEFINE_XEN_GUEST_HANDLE(xenoprof_init_t);
struct xenoprof_get_buffer {
int32_t max_samples;
int32_t nbuf;
int32_t bufsize;
uint64_t buf_maddr;
};
typedef struct xenoprof_get_buffer xenoprof_get_buffer_t;
DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t);
struct xenoprof_counter {
uint32_t ind;
uint64_t count;
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.