Isaku Yamahata
2006-Nov-14 07:01 UTC
[Xen-devel] [PATCH 0/5 TAKE 2] xenoprof: preliminary patches for xenoprof/ia64
Those patches are preliminary clean-ups to support xenoprof on ia64. They split the current x86-specific code into arch dependent/independent code and make them more arch-generic. Those include also bug fixes, clean-ups and dynamic mapping/unmapping xenoprof buffer support. I''ll post the IA64 part to xen-ia64-devel. [PATCH 1/5] xenoprof: split xen x86 xenoprof code [PATCH 2/5] xenoprof: make xen xenoprof code slight arch-generic [PATCH 3/5] xenoprof: split linux x86 xenoprof code [PATCH 4/5] xenoprof: make linux xenoprof code arch-generic [PATCH 5/5] xenoprof: make xen xenoprof code arch-generic Changes: TAKE 2 - broke patches into smaller ones for review. The final code is almost same as TAKE 1. thanks yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-14 07:01 UTC
[Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split xen x86 xenoprof code
# HG changeset patch # User yamahata@valinux.co.jp # Date 1163486059 -32400 # Node ID 24e1dacab1545640701709be7742608de73063cc # Parent 45d6a5bc857817fb8f541b410920e59bf1417ac2 move xenoprof code under xen/arch/x86/oprofile to xen/common without code changes excpet slight adjustment to compile. PATCHNAME: move_xen_x86_xenoprof_code_under_xen_common Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> diff -r 45d6a5bc8578 -r 24e1dacab154 xen/arch/x86/Rules.mk --- a/xen/arch/x86/Rules.mk Tue Nov 14 15:34:18 2006 +0900 +++ b/xen/arch/x86/Rules.mk Tue Nov 14 15:34:19 2006 +0900 @@ -3,6 +3,7 @@ HAS_ACPI := y HAS_VGA := y +xenoprof := y # # If you change any of these configuration options then you must diff -r 45d6a5bc8578 -r 24e1dacab154 xen/arch/x86/oprofile/xenoprof.c --- a/xen/arch/x86/oprofile/xenoprof.c Tue Nov 14 15:34:18 2006 +0900 +++ b/xen/arch/x86/oprofile/xenoprof.c Tue Nov 14 15:34:19 2006 +0900 @@ -2,699 +2,16 @@ * Copyright (C) 2005 Hewlett-Packard Co. * written by Aravind Menon & Jose Renato Santos * (email: xenoprof@groups.hp.com) + * + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * x86 specific part */ #include <xen/guest_access.h> #include <xen/sched.h> #include <public/xenoprof.h> #include <asm/hvm/support.h> - -#include "op_counter.h" - -/* Limit amount of pages used for shared buffer (per domain) */ -#define MAX_OPROF_SHARED_PAGES 32 - -/* Lock protecting the following global state */ -static DEFINE_SPINLOCK(xenoprof_lock); - -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; - -u64 total_samples; -u64 invalid_buffer_samples; -u64 corrupted_buffer_samples; -u64 lost_samples; -u64 active_samples; -u64 passive_samples; -u64 idle_samples; -u64 others_samples; - - -extern int nmi_init(int *num_events, int *is_primary, char *cpu_type); -extern int nmi_reserve_counters(void); -extern int nmi_setup_events(void); -extern int nmi_enable_virq(void); -extern int nmi_start(void); -extern void nmi_stop(void); -extern void nmi_disable_virq(void); -extern void nmi_release_counters(void); - -int is_active(struct domain *d) -{ - struct xenoprof *x = d->xenoprof; - 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) || is_passive(d)); -} - -static void xenoprof_reset_stat(void) -{ - total_samples = 0; - invalid_buffer_samples = 0; - corrupted_buffer_samples = 0; - lost_samples = 0; - active_samples = 0; - passive_samples = 0; - idle_samples = 0; - others_samples = 0; -} - -static void xenoprof_reset_buf(struct domain *d) -{ - int j; - struct xenoprof_buf *buf; - - if ( d->xenoprof == NULL ) - { - printk("xenoprof_reset_buf: ERROR - Unexpected " - "Xenoprof NULL pointer \n"); - return; - } - - for ( j = 0; j < MAX_VIRT_CPUS; j++ ) - { - buf = d->xenoprof->vcpu[j].buffer; - if ( buf != NULL ) - { - buf->event_head = 0; - buf->event_tail = 0; - } - } -} - -static 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; -} - -static int alloc_xenoprof_struct( - struct domain *d, int max_samples, int is_passive) -{ - struct vcpu *v; - int nvcpu, npages, bufsize, max_bufsize; - unsigned max_max_samples; - 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 max_samples if necessary to limit pages allocated */ - max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu; - max_max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) / - sizeof(struct event_log) ) + 1; - if ( (unsigned)max_samples > max_max_samples ) - max_samples = max_max_samples; - - bufsize = sizeof(struct xenoprof_buf) + - (max_samples - 1) * sizeof(struct event_log); - 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; -} - -static int active_index(struct domain *d) -{ - int i; - - for ( i = 0; i < adomains; i++ ) - if ( active_domains[i] == d ) - return i; - - return -1; -} - -static int set_active(struct domain *d) -{ - int ind; - struct xenoprof *x; - - ind = active_index(d); - if ( ind < 0 ) - return -EPERM; - - x = d->xenoprof; - if ( x == NULL ) - return -EPERM; - - x->domain_ready = 1; - x->domain_type = XENOPROF_DOMAIN_ACTIVE; - active_ready[ind] = 1; - activated++; - - return 0; -} - -static int reset_active(struct domain *d) -{ - int ind; - struct xenoprof *x; - - ind = active_index(d); - if ( ind < 0 ) - return -EPERM; - - x = d->xenoprof; - if ( x == NULL ) - return -EPERM; - - 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; -} - -static 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; -} - -static void reset_active_list(void) -{ - int i; - - for ( i = 0; i < adomains; i++ ) - { - if ( active_ready[i] ) - { - reset_active(active_domains[i]); - } - } - - adomains = 0; - activated = 0; -} - -static 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; -} - -static int add_active_list(domid_t domid) -{ - struct domain *d; - - if ( adomains >= MAX_OPROF_DOMAINS ) - return -E2BIG; - - d = find_domain_by_id(domid); - if ( d == NULL ) - return -EINVAL; - - active_domains[adomains] = d; - active_ready[adomains] = 0; - adomains++; - - return 0; -} - -static 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) -{ - struct xenoprof_vcpu *v; - struct xenoprof_buf *buf; - int head; - int tail; - int size; - - - total_samples++; - - /* ignore samples of un-monitored domains */ - /* Count samples in idle separate from other unmonitored domains */ - if ( !is_profiled(vcpu->domain) ) - { - others_samples++; - return; - } - - v = &vcpu->domain->xenoprof->vcpu[vcpu->vcpu_id]; - - /* Sanity check. Should never happen */ - if ( v->buffer == NULL ) - { - invalid_buffer_samples++; - return; - } - - buf = vcpu->domain->xenoprof->vcpu[vcpu->vcpu_id].buffer; - - head = buf->event_head; - tail = buf->event_tail; - size = v->event_size; - - /* make sure indexes in shared buffer are sane */ - if ( (head < 0) || (head >= size) || (tail < 0) || (tail >= size) ) - { - corrupted_buffer_samples++; - return; - } - - if ( (head == tail - 1) || (head == size - 1 && tail == 0) ) - { - buf->lost_samples++; - lost_samples++; - } - else - { - buf->event_log[head].eip = eip; - buf->event_log[head].mode = mode; - buf->event_log[head].event = event; - head++; - if ( head >= size ) - head = 0; - buf->event_head = head; - if ( is_active(vcpu->domain) ) - active_samples++; - else - passive_samples++; - if ( mode == 0 ) - buf->user_samples++; - else if ( mode == 1 ) - buf->kernel_samples++; - else - buf->xen_samples++; - } -} - -static int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg) -{ - struct xenoprof_init xenoprof_init; - int ret; - - if ( copy_from_guest(&xenoprof_init, arg, 1) ) - return -EFAULT; - - if ( (ret = nmi_init(&xenoprof_init.num_events, - &xenoprof_init.is_primary, - xenoprof_init.cpu_type)) ) - return ret; - - if ( copy_to_guest(arg, &xenoprof_init, 1) ) - return -EFAULT; - - if ( xenoprof_init.is_primary ) - primary_profiler = current->domain; - - return 0; -} - -static 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_get_buffer - * is called. Memory is then kept until domain is destroyed. - */ - if ( (d->xenoprof == NULL) && - ((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; - if ( primary_profiler == current->domain ) - 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 NONPRIV_OP(op) ( (op == XENOPROF_init) \ - || (op == XENOPROF_enable_virq) \ - || (op == XENOPROF_disable_virq) \ - || (op == XENOPROF_get_buffer)) - -int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg) -{ - int ret = 0; - - if ( (op < 0) || (op>XENOPROF_last_op) ) - { - printk("xenoprof: invalid operation %d for domain %d\n", - op, current->domain->domain_id); - return -EINVAL; - } - - if ( !NONPRIV_OP(op) && (current->domain != primary_profiler) ) - { - printk("xenoprof: dom %d denied privileged operation %d\n", - current->domain->domain_id, op); - return -EPERM; - } - - spin_lock(&xenoprof_lock); - - switch ( op ) - { - case XENOPROF_init: - 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(); - ret = 0; - break; - } - case XENOPROF_reset_passive_list: - { - reset_passive_list(); - ret = 0; - break; - } - case XENOPROF_set_active: - { - domid_t domid; - if ( xenoprof_state != XENOPROF_IDLE ) { - ret = -EPERM; - break; - } - if ( copy_from_guest(&domid, arg, 1) ) { - ret = -EFAULT; - break; - } - ret = add_active_list(domid); - break; - } - case XENOPROF_set_passive: - { - if ( xenoprof_state != XENOPROF_IDLE ) { - ret = -EPERM; - break; - } - ret = add_passive_list(arg); - break; - } - case XENOPROF_reserve_counters: - if ( xenoprof_state != XENOPROF_IDLE ) { - ret = -EPERM; - break; - } - ret = nmi_reserve_counters(); - if ( !ret ) - xenoprof_state = XENOPROF_COUNTERS_RESERVED; - break; - - case XENOPROF_counter: - { - struct xenoprof_counter counter; - if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED || adomains == 0) { - ret = -EPERM; - break; - } - - if ( copy_from_guest(&counter, arg, 1) ) { - ret = -EFAULT; - break; - } - - if ( counter.ind > OP_MAX_COUNTER ) { - ret = -E2BIG; - break; - } - - counter_config[counter.ind].count = (unsigned long) counter.count; - counter_config[counter.ind].enabled = (unsigned long) counter.enabled; - counter_config[counter.ind].event = (unsigned long) counter.event; - counter_config[counter.ind].kernel = (unsigned long) counter.kernel; - counter_config[counter.ind].user = (unsigned long) counter.user; - counter_config[counter.ind].unit_mask = (unsigned long) counter.unit_mask; - - ret = 0; - break; - } - - case XENOPROF_setup_events: - if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED ) { - ret = -EPERM; - break; - } - ret = nmi_setup_events(); - if ( !ret ) - xenoprof_state = XENOPROF_READY; - 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; - if ( (xenoprof_state == XENOPROF_READY) && - (activated == adomains) ) - ret = nmi_start(); - - if ( ret == 0 ) - xenoprof_state = XENOPROF_PROFILING; - break; - - case XENOPROF_stop: - if ( xenoprof_state != XENOPROF_PROFILING ) { - ret = -EPERM; - break; - } - nmi_stop(); - xenoprof_state = XENOPROF_READY; - break; - - case XENOPROF_disable_virq: - if ( (xenoprof_state == XENOPROF_PROFILING) && - (is_active(current->domain)) ) { - ret = -EPERM; - break; - } - ret = reset_active(current->domain); - break; - - case XENOPROF_release_counters: - ret = -EPERM; - if ( (xenoprof_state == XENOPROF_COUNTERS_RESERVED) || - (xenoprof_state == XENOPROF_READY) ) - { - xenoprof_state = XENOPROF_IDLE; - nmi_release_counters(); - nmi_disable_virq(); - reset_passive_list(); - ret = 0; - } - break; - - case XENOPROF_shutdown: - ret = -EPERM; - if ( xenoprof_state == XENOPROF_IDLE ) - { - activated = 0; - adomains=0; - primary_profiler = NULL; - ret = 0; - } - break; - - default: - ret = -ENOSYS; - } - - spin_unlock(&xenoprof_lock); - - if ( ret < 0 ) - printk("xenoprof: operation %d failed for dom %d (status : %d)\n", - op, current->domain->domain_id, ret); - - return ret; -} int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs) { diff -r 45d6a5bc8578 -r 24e1dacab154 xen/common/Makefile --- a/xen/common/Makefile Tue Nov 14 15:34:18 2006 +0900 +++ b/xen/common/Makefile Tue Nov 14 15:34:19 2006 +0900 @@ -29,6 +29,7 @@ obj-y += xmalloc.o obj-$(perfc) += perfc.o obj-$(crash_debug) += gdbstub.o +obj-$(xenoprof) += xenoprof.o # Object file contains changeset and compiler information. version.o: $(BASEDIR)/include/xen/compile.h diff -r 45d6a5bc8578 -r 24e1dacab154 xen/common/xenoprof.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/common/xenoprof.c Tue Nov 14 15:34:19 2006 +0900 @@ -0,0 +1,706 @@ +/* + * Copyright (C) 2005 Hewlett-Packard Co. + * written by Aravind Menon & Jose Renato Santos + * (email: xenoprof@groups.hp.com) + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * arch generic xenoprof and IA64 support. + */ + +#include <xen/guest_access.h> +#include <xen/sched.h> +#include <public/xenoprof.h> +#include <asm/hvm/support.h> + +#include "../arch/x86/oprofile/op_counter.h" + +/* Limit amount of pages used for shared buffer (per domain) */ +#define MAX_OPROF_SHARED_PAGES 32 + +/* Lock protecting the following global state */ +static DEFINE_SPINLOCK(xenoprof_lock); + +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; + +u64 total_samples; +u64 invalid_buffer_samples; +u64 corrupted_buffer_samples; +u64 lost_samples; +u64 active_samples; +u64 passive_samples; +u64 idle_samples; +u64 others_samples; + + +extern int nmi_init(int *num_events, int *is_primary, char *cpu_type); +extern int nmi_reserve_counters(void); +extern int nmi_setup_events(void); +extern int nmi_enable_virq(void); +extern int nmi_start(void); +extern void nmi_stop(void); +extern void nmi_disable_virq(void); +extern void nmi_release_counters(void); + +int is_active(struct domain *d) +{ + struct xenoprof *x = d->xenoprof; + 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) || is_passive(d)); +} + +static void xenoprof_reset_stat(void) +{ + total_samples = 0; + invalid_buffer_samples = 0; + corrupted_buffer_samples = 0; + lost_samples = 0; + active_samples = 0; + passive_samples = 0; + idle_samples = 0; + others_samples = 0; +} + +static void xenoprof_reset_buf(struct domain *d) +{ + int j; + struct xenoprof_buf *buf; + + if ( d->xenoprof == NULL ) + { + printk("xenoprof_reset_buf: ERROR - Unexpected " + "Xenoprof NULL pointer \n"); + return; + } + + for ( j = 0; j < MAX_VIRT_CPUS; j++ ) + { + buf = d->xenoprof->vcpu[j].buffer; + if ( buf != NULL ) + { + buf->event_head = 0; + buf->event_tail = 0; + } + } +} + +static 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; +} + +static int alloc_xenoprof_struct( + struct domain *d, int max_samples, int is_passive) +{ + struct vcpu *v; + int nvcpu, npages, bufsize, max_bufsize; + unsigned max_max_samples; + 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 max_samples if necessary to limit pages allocated */ + max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu; + max_max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) / + sizeof(struct event_log) ) + 1; + if ( (unsigned)max_samples > max_max_samples ) + max_samples = max_max_samples; + + bufsize = sizeof(struct xenoprof_buf) + + (max_samples - 1) * sizeof(struct event_log); + 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; +} + +static int active_index(struct domain *d) +{ + int i; + + for ( i = 0; i < adomains; i++ ) + if ( active_domains[i] == d ) + return i; + + return -1; +} + +static int set_active(struct domain *d) +{ + int ind; + struct xenoprof *x; + + ind = active_index(d); + if ( ind < 0 ) + return -EPERM; + + x = d->xenoprof; + if ( x == NULL ) + return -EPERM; + + x->domain_ready = 1; + x->domain_type = XENOPROF_DOMAIN_ACTIVE; + active_ready[ind] = 1; + activated++; + + return 0; +} + +static int reset_active(struct domain *d) +{ + int ind; + struct xenoprof *x; + + ind = active_index(d); + if ( ind < 0 ) + return -EPERM; + + x = d->xenoprof; + if ( x == NULL ) + return -EPERM; + + 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; +} + +static 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; +} + +static void reset_active_list(void) +{ + int i; + + for ( i = 0; i < adomains; i++ ) + { + if ( active_ready[i] ) + { + reset_active(active_domains[i]); + } + } + + adomains = 0; + activated = 0; +} + +static 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; +} + +static int add_active_list(domid_t domid) +{ + struct domain *d; + + if ( adomains >= MAX_OPROF_DOMAINS ) + return -E2BIG; + + d = find_domain_by_id(domid); + if ( d == NULL ) + return -EINVAL; + + active_domains[adomains] = d; + active_ready[adomains] = 0; + adomains++; + + return 0; +} + +static 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) +{ + struct xenoprof_vcpu *v; + struct xenoprof_buf *buf; + int head; + int tail; + int size; + + + total_samples++; + + /* ignore samples of un-monitored domains */ + /* Count samples in idle separate from other unmonitored domains */ + if ( !is_profiled(vcpu->domain) ) + { + others_samples++; + return; + } + + v = &vcpu->domain->xenoprof->vcpu[vcpu->vcpu_id]; + + /* Sanity check. Should never happen */ + if ( v->buffer == NULL ) + { + invalid_buffer_samples++; + return; + } + + buf = vcpu->domain->xenoprof->vcpu[vcpu->vcpu_id].buffer; + + head = buf->event_head; + tail = buf->event_tail; + size = v->event_size; + + /* make sure indexes in shared buffer are sane */ + if ( (head < 0) || (head >= size) || (tail < 0) || (tail >= size) ) + { + corrupted_buffer_samples++; + return; + } + + if ( (head == tail - 1) || (head == size - 1 && tail == 0) ) + { + buf->lost_samples++; + lost_samples++; + } + else + { + buf->event_log[head].eip = eip; + buf->event_log[head].mode = mode; + buf->event_log[head].event = event; + head++; + if ( head >= size ) + head = 0; + buf->event_head = head; + if ( is_active(vcpu->domain) ) + active_samples++; + else + passive_samples++; + if ( mode == 0 ) + buf->user_samples++; + else if ( mode == 1 ) + buf->kernel_samples++; + else + buf->xen_samples++; + } +} + +static int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg) +{ + struct xenoprof_init xenoprof_init; + int ret; + + if ( copy_from_guest(&xenoprof_init, arg, 1) ) + return -EFAULT; + + if ( (ret = nmi_init(&xenoprof_init.num_events, + &xenoprof_init.is_primary, + xenoprof_init.cpu_type)) ) + return ret; + + if ( copy_to_guest(arg, &xenoprof_init, 1) ) + return -EFAULT; + + if ( xenoprof_init.is_primary ) + primary_profiler = current->domain; + + return 0; +} + +static 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_get_buffer + * is called. Memory is then kept until domain is destroyed. + */ + if ( (d->xenoprof == NULL) && + ((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; + if ( primary_profiler == current->domain ) + 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 NONPRIV_OP(op) ( (op == XENOPROF_init) \ + || (op == XENOPROF_enable_virq) \ + || (op == XENOPROF_disable_virq) \ + || (op == XENOPROF_get_buffer)) + +int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg) +{ + int ret = 0; + + if ( (op < 0) || (op>XENOPROF_last_op) ) + { + printk("xenoprof: invalid operation %d for domain %d\n", + op, current->domain->domain_id); + return -EINVAL; + } + + if ( !NONPRIV_OP(op) && (current->domain != primary_profiler) ) + { + printk("xenoprof: dom %d denied privileged operation %d\n", + current->domain->domain_id, op); + return -EPERM; + } + + spin_lock(&xenoprof_lock); + + switch ( op ) + { + case XENOPROF_init: + 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(); + ret = 0; + break; + } + case XENOPROF_reset_passive_list: + { + reset_passive_list(); + ret = 0; + break; + } + case XENOPROF_set_active: + { + domid_t domid; + if ( xenoprof_state != XENOPROF_IDLE ) { + ret = -EPERM; + break; + } + if ( copy_from_guest(&domid, arg, 1) ) { + ret = -EFAULT; + break; + } + ret = add_active_list(domid); + break; + } + case XENOPROF_set_passive: + { + if ( xenoprof_state != XENOPROF_IDLE ) { + ret = -EPERM; + break; + } + ret = add_passive_list(arg); + break; + } + case XENOPROF_reserve_counters: + if ( xenoprof_state != XENOPROF_IDLE ) { + ret = -EPERM; + break; + } + ret = nmi_reserve_counters(); + if ( !ret ) + xenoprof_state = XENOPROF_COUNTERS_RESERVED; + break; + + case XENOPROF_counter: + { + struct xenoprof_counter counter; + if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED || adomains == 0) { + ret = -EPERM; + break; + } + + if ( copy_from_guest(&counter, arg, 1) ) + return -EFAULT; + + if ( counter.ind > OP_MAX_COUNTER ) + return -E2BIG; + + counter_config[counter.ind].count = (unsigned long) counter.count; + counter_config[counter.ind].enabled = (unsigned long) counter.enabled; + counter_config[counter.ind].event = (unsigned long) counter.event; + counter_config[counter.ind].kernel = (unsigned long) counter.kernel; + counter_config[counter.ind].user = (unsigned long) counter.user; + counter_config[counter.ind].unit_mask = (unsigned long) counter.unit_mask; + + ret = 0; + break; + } + + case XENOPROF_setup_events: + if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED ) { + ret = -EPERM; + break; + } + ret = nmi_setup_events(); + if ( !ret ) + xenoprof_state = XENOPROF_READY; + 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; + if ( (xenoprof_state == XENOPROF_READY) && + (activated == adomains) ) + ret = nmi_start(); + + if ( ret == 0 ) + xenoprof_state = XENOPROF_PROFILING; + break; + + case XENOPROF_stop: + if ( xenoprof_state != XENOPROF_PROFILING ) { + ret = -EPERM; + break; + } + nmi_stop(); + xenoprof_state = XENOPROF_READY; + break; + + case XENOPROF_disable_virq: + if ( (xenoprof_state == XENOPROF_PROFILING) && + (is_active(current->domain)) ) { + ret = -EPERM; + break; + } + ret = reset_active(current->domain); + break; + + case XENOPROF_release_counters: + ret = -EPERM; + if ( (xenoprof_state == XENOPROF_COUNTERS_RESERVED) || + (xenoprof_state == XENOPROF_READY) ) + { + xenoprof_state = XENOPROF_IDLE; + nmi_release_counters(); + nmi_disable_virq(); + reset_passive_list(); + ret = 0; + } + break; + + case XENOPROF_shutdown: + ret = -EPERM; + if ( xenoprof_state == XENOPROF_IDLE ) + { + activated = 0; + adomains=0; + primary_profiler = NULL; + ret = 0; + } + break; + + default: + ret = -ENOSYS; + } + + spin_unlock(&xenoprof_lock); + + if ( ret < 0 ) + printk("xenoprof: operation %d failed for dom %d (status : %d)\n", + op, current->domain->domain_id, ret); + + return ret; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-14 07:01 UTC
[Xen-devel] [PATCH 2/5 TAKE 2] xenoprof: make xen xenoprof code slight arch generic
# HG changeset patch # User yamahata@valinux.co.jp # Date 1163486060 -32400 # Node ID 0b4114873d25138823956186a87b34f884be6d9a # Parent 24e1dacab1545640701709be7742608de73063cc replace x86 specific code in xen/common/xenoprof.c - replace nmi_ prefix with xenoprof_arch_ prefix - move config_counter to xen/arch/x86/oprofile/xenoprof.c PATCHNAME: remove_x86_specific_code_from_xen_common_xenoprof_c Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> diff -r 24e1dacab154 -r 0b4114873d25 xen/arch/x86/oprofile/xenoprof.c --- a/xen/arch/x86/oprofile/xenoprof.c Tue Nov 14 15:34:19 2006 +0900 +++ b/xen/arch/x86/oprofile/xenoprof.c Tue Nov 14 15:34:20 2006 +0900 @@ -12,6 +12,27 @@ #include <xen/sched.h> #include <public/xenoprof.h> #include <asm/hvm/support.h> + +#include "op_counter.h" + +int xenoprof_arch_counter(XEN_GUEST_HANDLE(void) arg) +{ + struct xenoprof_counter counter; + if ( copy_from_guest(&counter, arg, 1) ) + return -EFAULT; + + if ( counter.ind > OP_MAX_COUNTER ) + return -E2BIG; + + counter_config[counter.ind].count = (unsigned long) counter.count; + counter_config[counter.ind].enabled = (unsigned long) counter.enabled; + counter_config[counter.ind].event = (unsigned long) counter.event; + counter_config[counter.ind].kernel = (unsigned long) counter.kernel; + counter_config[counter.ind].user = (unsigned long) counter.user; + counter_config[counter.ind].unit_mask = (unsigned long) counter.unit_mask; + + return 0; +} int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs) { diff -r 24e1dacab154 -r 0b4114873d25 xen/common/xenoprof.c --- a/xen/common/xenoprof.c Tue Nov 14 15:34:19 2006 +0900 +++ b/xen/common/xenoprof.c Tue Nov 14 15:34:20 2006 +0900 @@ -12,8 +12,6 @@ #include <public/xenoprof.h> #include <asm/hvm/support.h> -#include "../arch/x86/oprofile/op_counter.h" - /* Limit amount of pages used for shared buffer (per domain) */ #define MAX_OPROF_SHARED_PAGES 32 @@ -39,16 +37,6 @@ u64 passive_samples; u64 passive_samples; u64 idle_samples; u64 others_samples; - - -extern int nmi_init(int *num_events, int *is_primary, char *cpu_type); -extern int nmi_reserve_counters(void); -extern int nmi_setup_events(void); -extern int nmi_enable_virq(void); -extern int nmi_start(void); -extern void nmi_stop(void); -extern void nmi_disable_virq(void); -extern void nmi_release_counters(void); int is_active(struct domain *d) { @@ -449,9 +437,9 @@ static int xenoprof_op_init(XEN_GUEST_HA if ( copy_from_guest(&xenoprof_init, arg, 1) ) return -EFAULT; - if ( (ret = nmi_init(&xenoprof_init.num_events, - &xenoprof_init.is_primary, - xenoprof_init.cpu_type)) ) + if ( (ret = xenoprof_arch_init(&xenoprof_init.num_events, + &xenoprof_init.is_primary, + xenoprof_init.cpu_type)) ) return ret; if ( copy_to_guest(arg, &xenoprof_init, 1) ) @@ -574,42 +562,26 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN ret = -EPERM; break; } - ret = nmi_reserve_counters(); + ret = xenoprof_arch_reserve_counters(); if ( !ret ) xenoprof_state = XENOPROF_COUNTERS_RESERVED; break; case XENOPROF_counter: - { - struct xenoprof_counter counter; if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED || adomains == 0) { ret = -EPERM; break; } - if ( copy_from_guest(&counter, arg, 1) ) - return -EFAULT; - - if ( counter.ind > OP_MAX_COUNTER ) - return -E2BIG; - - counter_config[counter.ind].count = (unsigned long) counter.count; - counter_config[counter.ind].enabled = (unsigned long) counter.enabled; - counter_config[counter.ind].event = (unsigned long) counter.event; - counter_config[counter.ind].kernel = (unsigned long) counter.kernel; - counter_config[counter.ind].user = (unsigned long) counter.user; - counter_config[counter.ind].unit_mask = (unsigned long) counter.unit_mask; - - ret = 0; - break; - } + ret = xenoprof_arch_counter(arg); + break; case XENOPROF_setup_events: if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED ) { ret = -EPERM; break; } - ret = nmi_setup_events(); + ret = xenoprof_arch_setup_events(); if ( !ret ) xenoprof_state = XENOPROF_READY; break; @@ -619,7 +591,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN int i; if ( current->domain == primary_profiler ) { - nmi_enable_virq(); + xenoprof_arch_enable_virq(); xenoprof_reset_stat(); for ( i = 0; i < pdomains; i++ ) { xenoprof_reset_buf(passive_domains[i]); @@ -634,7 +606,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN ret = -EPERM; if ( (xenoprof_state == XENOPROF_READY) && (activated == adomains) ) - ret = nmi_start(); + ret = xenoprof_arch_start(); if ( ret == 0 ) xenoprof_state = XENOPROF_PROFILING; @@ -645,7 +617,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN ret = -EPERM; break; } - nmi_stop(); + xenoprof_arch_stop(); xenoprof_state = XENOPROF_READY; break; @@ -664,8 +636,8 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN (xenoprof_state == XENOPROF_READY) ) { xenoprof_state = XENOPROF_IDLE; - nmi_release_counters(); - nmi_disable_virq(); + xenoprof_arch_release_counters(); + xenoprof_arch_disable_virq(); reset_passive_list(); ret = 0; } diff -r 24e1dacab154 -r 0b4114873d25 xen/include/asm-x86/xenoprof.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/asm-x86/xenoprof.h Tue Nov 14 15:34:20 2006 +0900 @@ -0,0 +1,58 @@ +/****************************************************************************** + * asm-x86/xenoprof.h + * xenoprof x86 arch specific header file + * + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ASM_XENOPROF_H__ +#define __ASM_XENOPROF_H__ + +int nmi_init(int *num_events, int *is_primary, char *cpu_type); +int nmi_reserve_counters(void); +int nmi_setup_events(void); +int nmi_enable_virq(void); +int nmi_start(void); +void nmi_stop(void); +void nmi_disable_virq(void); +void nmi_release_counters(void); + +#define xenoprof_arch_init(num_events, is_primary, cpu_type) \ + nmi_init(num_events, is_primary, cpu_type) +#define xenoprof_arch_reserve_counters() nmi_reserve_counters() +#define xenoprof_arch_setup_events() nmi_setup_events() +#define xenoprof_arch_enable_virq() nmi_enable_virq() +#define xenoprof_arch_start() nmi_start() +#define xenoprof_arch_stop() nmi_stop() +#define xenoprof_arch_disable_virq() nmi_disable_virq() +#define xenoprof_arch_release_counters() nmi_release_counters() + +int xenoprof_arch_counter(XEN_GUEST_HANDLE(void) arg); + +#endif /* __ASM_XENOPROF_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 24e1dacab154 -r 0b4114873d25 xen/include/xen/xenoprof.h --- a/xen/include/xen/xenoprof.h Tue Nov 14 15:34:19 2006 +0900 +++ b/xen/include/xen/xenoprof.h Tue Nov 14 15:34:20 2006 +0900 @@ -11,6 +11,7 @@ #define __XEN_XENOPROF_H__ #include <public/xenoprof.h> +#include <asm/xenoprof.h> #define XENOPROF_DOMAIN_IGNORED 0 #define XENOPROF_DOMAIN_ACTIVE 1 yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-14 07:01 UTC
[Xen-devel] [PATCH 3/5 TAKE 2] xenoprof: split linux x86 xenoprof code
# HG changeset patch # User yamahata@valinux.co.jp # Date 1163486061 -32400 # Node ID 384cb18e094aa5baa633598850b1370f6196abae # Parent 0b4114873d25138823956186a87b34f884be6d9a split linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c into linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c without code changes except slight adjustment to compile. PATCHNAME: split_i386_xenoprof_linux_side Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> diff -r 0b4114873d25 -r 384cb18e094a linux-2.6-xen-sparse/arch/i386/oprofile/Makefile --- a/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile Tue Nov 14 15:34:20 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile Tue Nov 14 15:34:21 2006 +0900 @@ -7,7 +7,10 @@ DRIVER_OBJS = $(addprefix ../../../drive timer_int.o ) ifdef CONFIG_XEN -oprofile-y := $(DRIVER_OBJS) xenoprof.o +XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \ + xenoprofile.o) +oprofile-y := $(DRIVER_OBJS) \ + $(XENOPROF_COMMON_OBJS) xenoprof.o else oprofile-y := $(DRIVER_OBJS) init.o backtrace.o oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \ diff -r 0b4114873d25 -r 384cb18e094a linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:20 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:21 2006 +0900 @@ -9,481 +9,21 @@ * Modified by Aravind Menon and Jose Renato Santos for Xen * These modifications are: * Copyright (C) 2005 Hewlett-Packard Co. + * + * x86-specific part + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. */ -#include <linux/init.h> -#include <linux/notifier.h> -#include <linux/smp.h> #include <linux/oprofile.h> -#include <linux/sysdev.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/vmalloc.h> -#include <asm/nmi.h> -#include <asm/msr.h> -#include <asm/apic.h> -#include <asm/pgtable.h> -#include <xen/evtchn.h> + +#include <xen/xenoprof.h> #include "op_counter.h" -#include <xen/driver_util.h> -#include <xen/interface/xen.h> -#include <xen/interface/xenoprof.h> -#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); - -static int xenoprof_enabled = 0; -static unsigned int num_events = 0; -static int is_primary = 0; -static int active_defined; - -/* sample buffers shared with Xen */ -xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS]; -/* Shared buffer area */ -char * shared_buffer = NULL; -/* Number of buffers in shared area (one per VCPU) */ -int nbuf; -/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */ -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) -{ - if (xenoprof_enabled == 1) - xenoprof_stop(); - return 0; -} - - -static int xenoprof_resume(struct sys_device * dev) -{ - if (xenoprof_enabled == 1) - xenoprof_start(); - return 0; -} - - -static struct sysdev_class oprofile_sysclass = { - set_kset_name("oprofile"), - .resume = xenoprof_resume, - .suspend = xenoprof_suspend -}; - - -static struct sys_device device_oprofile = { - .id = 0, - .cls = &oprofile_sysclass, -}; - - -static int __init init_driverfs(void) -{ - int error; - if (!(error = sysdev_class_register(&oprofile_sysclass))) - error = sysdev_register(&device_oprofile); - return error; -} - - -static void __exit exit_driverfs(void) -{ - sysdev_unregister(&device_oprofile); - sysdev_class_unregister(&oprofile_sysclass); -} - -#else -#define init_driverfs() do { } while (0) -#define exit_driverfs() do { } while (0) -#endif /* CONFIG_PM */ - -unsigned long long oprofile_samples = 0; -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; - - head = buf->event_head; - tail = buf->event_tail; - size = buf->event_size; - - if (tail > head) { - while (tail < size) { - oprofile_add_pc(buf->event_log[tail].eip, - buf->event_log[tail].mode, - buf->event_log[tail].event); - if (!is_passive) - oprofile_samples++; - else - p_oprofile_samples++; - tail++; - } - tail = 0; - } - while (tail < head) { - oprofile_add_pc(buf->event_log[tail].eip, - buf->event_log[tail].mode, - buf->event_log[tail].event); - if (!is_passive) - oprofile_samples++; - else - p_oprofile_samples++; - tail++; - } - - buf->event_tail = tail; -} - -static void xenoprof_handle_passive(void) -{ - int i, j; - int flag_domain, flag_switch = 0; - - for (i = 0; i < pdomains; i++) { - flag_domain = 0; - 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; - if (!flag_domain) { - if (!oprofile_add_domain_switch(passive_domains[i]. - domain_id)) - goto done; - flag_domain = 1; - } - xenoprof_add_pc(buf, 1); - flag_switch = 1; - } - } -done: - if (flag_switch) - oprofile_add_domain_switch(COORDINATOR_DOMAIN); -} - -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(); - smp_mb__before_clear_bit(); - clear_bit(0, &flag); - } - - return IRQ_HANDLED; -} - - -static void unbind_virq(void) -{ - int i; - - for_each_cpu(i) { - if (ovf_irq[i] >= 0) { - unbind_from_irqhandler(ovf_irq[i], NULL); - ovf_irq[i] = -1; - } - } -} - - -static int bind_virq(void) -{ - int i, result; - - for_each_cpu(i) { - result = bind_virq_to_irqhandler(VIRQ_XENOPROF, - i, - xenoprof_ovf_interrupt, - SA_INTERRUPT, - "xenoprof", - NULL); - - if (result < 0) { - unbind_virq(); - return result; - } - - ovf_irq[i] = result; - } - - return 0; -} - - -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; - - if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) ) - return ret; - - if ( (ret = bind_virq()) ) - return ret; - - if (is_primary) { - struct xenoprof_counter counter; - - /* Define dom0 as an active domain if not done yet */ - if (!active_defined) { - domid_t domid; - ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL); - if (ret) - goto err; - domid = 0; - ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid); - if (ret) - goto err; - active_defined = 1; - } - - ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL); - if (ret) - goto err; - for (i=0; i<num_events; i++) { - counter.ind = i; - counter.count = (uint64_t)counter_config[i].count; - counter.enabled = (uint32_t)counter_config[i].enabled; - counter.event = (uint32_t)counter_config[i].event; - counter.kernel = (uint32_t)counter_config[i].kernel; - counter.user = (uint32_t)counter_config[i].user; - counter.unit_mask = (uint64_t)counter_config[i].unit_mask; - HYPERVISOR_xenoprof_op(XENOPROF_counter, - &counter); - } - ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL); - - if (ret) - goto err; - } - - ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq, NULL); - if (ret) - goto err; - - xenoprof_enabled = 1; - return 0; - err: - unbind_virq(); - return ret; -} - - -static void xenoprof_shutdown(void) -{ - xenoprof_enabled = 0; - - HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL); - - if (is_primary) { - HYPERVISOR_xenoprof_op(XENOPROF_release_counters, NULL); - active_defined = 0; - } - - unbind_virq(); - -} - - -static int xenoprof_start(void) -{ - int ret = 0; - - if (is_primary) - ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL); - - return ret; -} - - -static void xenoprof_stop(void) -{ - if (is_primary) - HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL); -} - - -static int xenoprof_set_active(int * active_domains, - unsigned int adomains) -{ - int ret = 0; - int i; - int set_dom0 = 0; - domid_t domid; - - if (!is_primary) - return 0; - - if (adomains > MAX_OPROF_DOMAINS) - return -E2BIG; - - ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL); - if (ret) - return ret; - - for (i=0; i<adomains; i++) { - domid = active_domains[i]; - if (domid != active_domains[i]) { - ret = -EINVAL; - goto out; - } - ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid); - if (ret) - goto out; - if (active_domains[i] == 0) - set_dom0 = 1; - } - /* dom0 must always be active but may not be in the list */ - if (!set_dom0) { - domid = 0; - ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid); - } - -out: - if (ret) - HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL); - active_defined = !ret; - return ret; -} - -static int xenoprof_set_passive(int * p_domains, - unsigned int pdoms) -{ - int ret; - int i, j; - int npages; - struct xenoprof_buf *buf; - struct vm_struct *area; - 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) - goto out; - - npages = (passive_domains[i].bufsize * passive_domains[i].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, - passive_domains[i].buf_maddr >> PAGE_SHIFT, - npages * PAGE_SIZE, prot, DOMID_SELF); - if (ret) { - vunmap(area->addr); - goto out; - } - - p_shared_buffer[i] = area->addr; - - 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; -} - +unsigned int num_events = 0; struct op_counter_config counter_config[OP_MAX_COUNTER]; -static int xenoprof_create_files(struct super_block * sb, struct dentry * root) +int xenoprof_create_files(struct super_block * sb, struct dentry * root) { unsigned int i; @@ -509,76 +49,3 @@ static int xenoprof_create_files(struct return 0; } - - -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, - .stop = xenoprof_stop -}; - - -/* in order to get driverfs right */ -static int using_xenoprof; - -int __init oprofile_arch_init(struct oprofile_operations * ops) -{ - struct xenoprof_init init; - int ret, i; - - ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init); - - if (!ret) { - num_events = init.num_events; - is_primary = init.is_primary; - - /* just in case - make sure we do not overflow event list - (i.e. counter_config list) */ - if (num_events > OP_MAX_COUNTER) - num_events = OP_MAX_COUNTER; - - /* 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); - xenoprof_ops.cpu_type = cpu_type; - - init_driverfs(); - using_xenoprof = 1; - *ops = xenoprof_ops; - - for (i=0; i<NR_CPUS; i++) - ovf_irq[i] = -1; - - active_defined = 0; - } - printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, " - "is_primary %d\n", ret, num_events, is_primary); - return ret; -} - - -void __exit oprofile_arch_exit(void) -{ - int i; - - if (using_xenoprof) - exit_driverfs(); - - if (shared_buffer) { - vunmap(shared_buffer); - shared_buffer = NULL; - } - 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 0b4114873d25 -r 384cb18e094a linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile --- a/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile Tue Nov 14 15:34:20 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile Tue Nov 14 15:34:21 2006 +0900 @@ -12,6 +12,8 @@ DRIVER_OBJS = $(addprefix ../../../drive timer_int.o ) ifdef CONFIG_XEN +XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \ + xenoprofile.o) OPROFILE-y := xenoprof.o else OPROFILE-y := init.o backtrace.o @@ -19,4 +21,5 @@ OPROFILE-$(CONFIG_X86_LOCAL_APIC) += nmi op_model_ppro.o OPROFILE-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o endif -oprofile-y = $(DRIVER_OBJS) $(addprefix ../../i386/oprofile/, $(OPROFILE-y)) +oprofile-y = $(DRIVER_OBJS) $(XENOPROF_COMMON_OBJS) \ + $(addprefix ../../i386/oprofile/, $(OPROFILE-y)) diff -r 0b4114873d25 -r 384cb18e094a linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c Tue Nov 14 15:34:21 2006 +0900 @@ -0,0 +1,559 @@ +/** + * @file xenoprof.c + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon <levon@movementarian.org> + * + * Modified by Aravind Menon and Jose Renato Santos for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. + * + * Separated out arch-generic part + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + */ + +#include <linux/init.h> +#include <linux/notifier.h> +#include <linux/smp.h> +#include <linux/oprofile.h> +#include <linux/sysdev.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/vmalloc.h> +#include <asm/nmi.h> +#include <asm/msr.h> +#include <asm/apic.h> +#include <asm/pgtable.h> +#include <xen/evtchn.h> +#include <xen/xenoprof.h> +#include "../../../arch/i386/oprofile/op_counter.h" + +#include <xen/driver_util.h> +#include <xen/interface/xen.h> +#include <xen/interface/xenoprof.h> +#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); + +static int xenoprof_enabled = 0; +extern unsigned int num_events; +static int is_primary = 0; +static int active_defined; + +/* sample buffers shared with Xen */ +xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS]; +/* Shared buffer area */ +char * shared_buffer = NULL; +/* Number of buffers in shared area (one per VCPU) */ +int nbuf; +/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */ +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) +{ + if (xenoprof_enabled == 1) + xenoprof_stop(); + return 0; +} + + +static int xenoprof_resume(struct sys_device * dev) +{ + if (xenoprof_enabled == 1) + xenoprof_start(); + return 0; +} + + +static struct sysdev_class oprofile_sysclass = { + set_kset_name("oprofile"), + .resume = xenoprof_resume, + .suspend = xenoprof_suspend +}; + + +static struct sys_device device_oprofile = { + .id = 0, + .cls = &oprofile_sysclass, +}; + + +static int __init init_driverfs(void) +{ + int error; + if (!(error = sysdev_class_register(&oprofile_sysclass))) + error = sysdev_register(&device_oprofile); + return error; +} + + +static void __exit exit_driverfs(void) +{ + sysdev_unregister(&device_oprofile); + sysdev_class_unregister(&oprofile_sysclass); +} + +#else +#define init_driverfs() do { } while (0) +#define exit_driverfs() do { } while (0) +#endif /* CONFIG_PM */ + +unsigned long long oprofile_samples = 0; +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; + + head = buf->event_head; + tail = buf->event_tail; + size = buf->event_size; + + if (tail > head) { + while (tail < size) { + oprofile_add_pc(buf->event_log[tail].eip, + buf->event_log[tail].mode, + buf->event_log[tail].event); + if (!is_passive) + oprofile_samples++; + else + p_oprofile_samples++; + tail++; + } + tail = 0; + } + while (tail < head) { + oprofile_add_pc(buf->event_log[tail].eip, + buf->event_log[tail].mode, + buf->event_log[tail].event); + if (!is_passive) + oprofile_samples++; + else + p_oprofile_samples++; + tail++; + } + + buf->event_tail = tail; +} + +static void xenoprof_handle_passive(void) +{ + int i, j; + int flag_domain, flag_switch = 0; + + for (i = 0; i < pdomains; i++) { + flag_domain = 0; + 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; + if (!flag_domain) { + if (!oprofile_add_domain_switch(passive_domains[i]. + domain_id)) + goto done; + flag_domain = 1; + } + xenoprof_add_pc(buf, 1); + flag_switch = 1; + } + } +done: + if (flag_switch) + oprofile_add_domain_switch(COORDINATOR_DOMAIN); +} + +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(); + smp_mb__before_clear_bit(); + clear_bit(0, &flag); + } + + return IRQ_HANDLED; +} + + +static void unbind_virq(void) +{ + int i; + + for_each_cpu(i) { + if (ovf_irq[i] >= 0) { + unbind_from_irqhandler(ovf_irq[i], NULL); + ovf_irq[i] = -1; + } + } +} + + +static int bind_virq(void) +{ + int i, result; + + for_each_cpu(i) { + result = bind_virq_to_irqhandler(VIRQ_XENOPROF, + i, + xenoprof_ovf_interrupt, + SA_INTERRUPT, + "xenoprof", + NULL); + + if (result < 0) { + unbind_virq(); + return result; + } + + ovf_irq[i] = result; + } + + return 0; +} + + +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; + + if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) ) + return ret; + + if ( (ret = bind_virq()) ) + return ret; + + if (is_primary) { + struct xenoprof_counter counter; + + /* Define dom0 as an active domain if not done yet */ + if (!active_defined) { + domid_t domid; + ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL); + if (ret) + goto err; + domid = 0; + ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid); + if (ret) + goto err; + active_defined = 1; + } + + ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL); + if (ret) + goto err; + for (i=0; i<num_events; i++) { + counter.ind = i; + counter.count = (uint64_t)counter_config[i].count; + counter.enabled = (uint32_t)counter_config[i].enabled; + counter.event = (uint32_t)counter_config[i].event; + counter.kernel = (uint32_t)counter_config[i].kernel; + counter.user = (uint32_t)counter_config[i].user; + counter.unit_mask = (uint64_t)counter_config[i].unit_mask; + HYPERVISOR_xenoprof_op(XENOPROF_counter, + &counter); + } + ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL); + + if (ret) + goto err; + } + + ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq, NULL); + if (ret) + goto err; + + xenoprof_enabled = 1; + return 0; + err: + unbind_virq(); + return ret; +} + + +static void xenoprof_shutdown(void) +{ + xenoprof_enabled = 0; + + HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL); + + if (is_primary) { + HYPERVISOR_xenoprof_op(XENOPROF_release_counters, NULL); + active_defined = 0; + } + + unbind_virq(); + +} + + +static int xenoprof_start(void) +{ + int ret = 0; + + if (is_primary) + ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL); + + return ret; +} + + +static void xenoprof_stop(void) +{ + if (is_primary) + HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL); +} + + +static int xenoprof_set_active(int * active_domains, + unsigned int adomains) +{ + int ret = 0; + int i; + int set_dom0 = 0; + domid_t domid; + + if (!is_primary) + return 0; + + if (adomains > MAX_OPROF_DOMAINS) + return -E2BIG; + + ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL); + if (ret) + return ret; + + for (i=0; i<adomains; i++) { + domid = active_domains[i]; + if (domid != active_domains[i]) { + ret = -EINVAL; + goto out; + } + ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid); + if (ret) + goto out; + if (active_domains[i] == 0) + set_dom0 = 1; + } + /* dom0 must always be active but may not be in the list */ + if (!set_dom0) { + domid = 0; + ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid); + } + +out: + if (ret) + HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL); + active_defined = !ret; + return ret; +} + +static int xenoprof_set_passive(int * p_domains, + unsigned int pdoms) +{ + int ret; + int i, j; + int npages; + struct xenoprof_buf *buf; + struct vm_struct *area; + 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) + goto out; + + npages = (passive_domains[i].bufsize * passive_domains[i].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, + passive_domains[i].buf_maddr >> PAGE_SHIFT, + npages * PAGE_SIZE, prot, DOMID_SELF); + if (ret) { + vunmap(area->addr); + goto out; + } + + p_shared_buffer[i] = area->addr; + + 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 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, + .stop = xenoprof_stop +}; + + +/* in order to get driverfs right */ +static int using_xenoprof; + +int __init oprofile_arch_init(struct oprofile_operations * ops) +{ + struct xenoprof_init init; + int ret, i; + + ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init); + + if (!ret) { + num_events = init.num_events; + is_primary = init.is_primary; + + /* just in case - make sure we do not overflow event list + (i.e. counter_config list) */ + if (num_events > OP_MAX_COUNTER) + num_events = OP_MAX_COUNTER; + + /* 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); + xenoprof_ops.cpu_type = cpu_type; + + init_driverfs(); + using_xenoprof = 1; + *ops = xenoprof_ops; + + for (i=0; i<NR_CPUS; i++) + ovf_irq[i] = -1; + + active_defined = 0; + } + printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, " + "is_primary %d\n", ret, num_events, is_primary); + return ret; +} + + +void __exit oprofile_arch_exit(void) +{ + int i; + + if (using_xenoprof) + exit_driverfs(); + + if (shared_buffer) { + vunmap(shared_buffer); + shared_buffer = NULL; + } + 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 0b4114873d25 -r 384cb18e094a linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h Tue Nov 14 15:34:21 2006 +0900 @@ -0,0 +1,31 @@ +/****************************************************************************** + * asm-i386/mach-xen/asm/xenoprof.h + * + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __ASM_XENOPROF_H__ +#define __ASM_XENOPROF_H__ +#ifdef CONFIG_OPROFILE + +struct super_block; +struct dentry; +int xenoprof_create_files(struct super_block * sb, struct dentry * root); + +#endif /* CONFIG_OPROFILE */ +#endif /* __ASM_XENOPROF_H__ */ diff -r 0b4114873d25 -r 384cb18e094a linux-2.6-xen-sparse/include/xen/xenoprof.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/include/xen/xenoprof.h Tue Nov 14 15:34:21 2006 +0900 @@ -0,0 +1,30 @@ +/****************************************************************************** + * xen/xenoprof.h + * + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __XEN_XENOPROF_H__ +#define __XEN_XENOPROF_H__ +#ifdef CONFIG_OPROFILE + +#include <asm/xenoprof.h> + +#endif /* CONFIG_OPROFILE */ +#endif /* __XEN_XENOPROF_H__ */ yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-14 07:02 UTC
[Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make linux xenoprof code arch-generic
# HG changeset patch # User yamahata@valinux.co.jp # Date 1163486062 -32400 # Node ID 3bebc37b149280f5ff1e6091d578c7da73820f16 # Parent 384cb18e094aa5baa633598850b1370f6196abae make xenoprof of linux side arch generic with some bug fixes. PATCHNAME: make_xenoprof_of_linux_side_arch_generic Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> diff -r 384cb18e094a -r 3bebc37b1492 linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:22 2006 +0900 @@ -15,12 +15,130 @@ * VA Linux Systems Japan K.K. */ +#include <linux/init.h> #include <linux/oprofile.h> +#include <linux/sched.h> +#include <asm/pgtable.h> +#include <xen/driver_util.h> +#include <xen/interface/xen.h> +#include <xen/interface/xenoprof.h> #include <xen/xenoprof.h> #include "op_counter.h" -unsigned int num_events = 0; +static unsigned int num_events = 0; + +void __init xenoprof_arch_init_counter(struct xenoprof_init *init) +{ + num_events = init->num_events; + /* just in case - make sure we do not overflow event list + (i.e. counter_config list) */ + if (num_events > OP_MAX_COUNTER) { + num_events = OP_MAX_COUNTER; + init->num_events = num_events; + } +} + +void xenoprof_arch_counter(void) +{ + int i; + struct xenoprof_counter counter; + + for (i=0; i<num_events; i++) { + counter.ind = i; + counter.count = (uint64_t)counter_config[i].count; + counter.enabled = (uint32_t)counter_config[i].enabled; + counter.event = (uint32_t)counter_config[i].event; + counter.kernel = (uint32_t)counter_config[i].kernel; + counter.user = (uint32_t)counter_config[i].user; + counter.unit_mask = (uint64_t)counter_config[i].unit_mask; + HYPERVISOR_xenoprof_op(XENOPROF_counter, + &counter); + } +} + +void xenoprof_arch_start(void) +{ + /* nothing */ +} + +void xenoprof_arch_stop(void) +{ + /* nothing */ +} + +void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer * sbuf) +{ + if (sbuf->buffer) { + vunmap(sbuf->buffer); + sbuf->buffer = NULL; + } +} + +int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer * get_buffer, + struct xenoprof_shared_buffer * sbuf) +{ + int npages, ret; + struct vm_struct *area; + + sbuf->buffer = NULL; + if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, get_buffer)) ) + return ret; + + npages = (get_buffer->bufsize * get_buffer->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; + } + + sbuf->buffer = area->addr; + return ret; +} + +int xenoprof_arch_set_passive(struct xenoprof_passive * pdomain, + struct xenoprof_shared_buffer * sbuf) +{ + int ret; + int npages; + struct vm_struct *area; + pgprot_t prot = __pgprot(_KERNPG_TABLE); + + sbuf->buffer = NULL; + ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive, pdomain); + if (ret) + goto out; + + npages = (pdomain->bufsize * pdomain->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, + pdomain->buf_maddr >> PAGE_SHIFT, + npages * PAGE_SIZE, prot, DOMID_SELF); + if (ret) { + vunmap(area->addr); + goto out; + } + sbuf->buffer = area->addr; + +out: + return ret; +} + struct op_counter_config counter_config[OP_MAX_COUNTER]; int xenoprof_create_files(struct super_block * sb, struct dentry * root) @@ -49,3 +167,13 @@ int xenoprof_create_files(struct super_b return 0; } + +int __init oprofile_arch_init(struct oprofile_operations * ops) +{ + return xenoprofile_init(ops); +} + +void __exit oprofile_arch_exit(void) +{ + xenoprofile_exit(); +} diff -r 384cb18e094a -r 3bebc37b1492 linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c --- a/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c Tue Nov 14 15:34:22 2006 +0900 @@ -1,5 +1,5 @@ /** - * @file xenoprof.c + * @file xenoprofile.c * * @remark Copyright 2002 OProfile authors * @remark Read the file COPYING @@ -23,14 +23,9 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/vmalloc.h> -#include <asm/nmi.h> -#include <asm/msr.h> -#include <asm/apic.h> #include <asm/pgtable.h> #include <xen/evtchn.h> #include <xen/xenoprof.h> -#include "../../../arch/i386/oprofile/op_counter.h" - #include <xen/driver_util.h> #include <xen/interface/xen.h> #include <xen/interface/xenoprof.h> @@ -39,18 +34,23 @@ #define MAX_XENOPROF_SAMPLES 16 -static int xenoprof_start(void); -static void xenoprof_stop(void); - -static int xenoprof_enabled = 0; -extern unsigned int num_events; -static int is_primary = 0; -static int active_defined; - /* sample buffers shared with Xen */ xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS]; /* Shared buffer area */ -char * shared_buffer = NULL; +struct xenoprof_shared_buffer shared_buffer; + +/* Passive sample buffers shared with Xen */ +xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS]; +/* Passive shared buffer area */ +struct xenoprof_shared_buffer p_shared_buffer[MAX_OPROF_DOMAINS]; + +static int xenoprof_start(void); +static void xenoprof_stop(void); + +static int xenoprof_enabled = 0; +int xenoprof_is_primary = 0; +static int active_defined; + /* Number of buffers in shared area (one per VCPU) */ int nbuf; /* Mappings of VIRQ_XENOPROF to irq number (per cpu) */ @@ -58,11 +58,6 @@ 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) @@ -103,7 +98,7 @@ static int __init init_driverfs(void) } -static void __exit exit_driverfs(void) +static void /* __exit */ exit_driverfs(void) { sysdev_unregister(&device_oprofile); sysdev_class_unregister(&oprofile_sysclass); @@ -193,7 +188,7 @@ xenoprof_ovf_interrupt(int irq, void * d xenoprof_add_pc(buf, 0); - if (is_primary && !test_and_set_bit(0, &flag)) { + if (xenoprof_is_primary && !test_and_set_bit(0, &flag)) { xenoprof_handle_passive(); smp_mb__before_clear_bit(); clear_bit(0, &flag); @@ -207,7 +202,7 @@ static void unbind_virq(void) { int i; - for_each_cpu(i) { + for_each_online_cpu(i) { if (ovf_irq[i] >= 0) { unbind_from_irqhandler(ovf_irq[i], NULL); ovf_irq[i] = -1; @@ -220,7 +215,7 @@ static int bind_virq(void) { int i, result; - for_each_cpu(i) { + for_each_online_cpu(i) { result = bind_virq_to_irqhandler(VIRQ_XENOPROF, i, xenoprof_ovf_interrupt, @@ -240,40 +235,33 @@ static int bind_virq(void) } +static void unmap_passive_list(void) +{ + int i; + for (i = 0; i < pdomains; i++) + xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]); + pdomains = 0; +} + + 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 ) + int ret, i; + + if ( shared_buffer.buffer ) return 0; get_buffer.max_samples = max_samples; - - if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, &get_buffer)) ) + ret = xenoprof_arch_map_shared_buffer(&get_buffer, &shared_buffer); + if (ret) 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]; + &shared_buffer.buffer[i * get_buffer.bufsize]; BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS); xenoprof_buf[buf->vcpu_id] = buf; } @@ -285,7 +273,6 @@ static int xenoprof_setup(void) static int xenoprof_setup(void) { int ret; - int i; if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) ) return ret; @@ -293,9 +280,7 @@ static int xenoprof_setup(void) if ( (ret = bind_virq()) ) return ret; - if (is_primary) { - struct xenoprof_counter counter; - + if (xenoprof_is_primary) { /* Define dom0 as an active domain if not done yet */ if (!active_defined) { domid_t domid; @@ -312,17 +297,7 @@ static int xenoprof_setup(void) ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL); if (ret) goto err; - for (i=0; i<num_events; i++) { - counter.ind = i; - counter.count = (uint64_t)counter_config[i].count; - counter.enabled = (uint32_t)counter_config[i].enabled; - counter.event = (uint32_t)counter_config[i].event; - counter.kernel = (uint32_t)counter_config[i].kernel; - counter.user = (uint32_t)counter_config[i].user; - counter.unit_mask = (uint64_t)counter_config[i].unit_mask; - HYPERVISOR_xenoprof_op(XENOPROF_counter, - &counter); - } + xenoprof_arch_counter(); ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL); if (ret) @@ -347,13 +322,16 @@ static void xenoprof_shutdown(void) HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL); - if (is_primary) { + if (xenoprof_is_primary) { HYPERVISOR_xenoprof_op(XENOPROF_release_counters, NULL); active_defined = 0; } unbind_virq(); + xenoprof_arch_unmap_shared_buffer(&shared_buffer); + if (xenoprof_is_primary) + unmap_passive_list(); } @@ -361,17 +339,19 @@ static int xenoprof_start(void) { int ret = 0; - if (is_primary) + if (xenoprof_is_primary) ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL); - + if (!ret) + xenoprof_arch_start(); return ret; } static void xenoprof_stop(void) { - if (is_primary) + if (xenoprof_is_primary) HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL); + xenoprof_arch_stop(); } @@ -383,7 +363,7 @@ static int xenoprof_set_active(int * act int set_dom0 = 0; domid_t domid; - if (!is_primary) + if (!xenoprof_is_primary) return 0; if (adomains > MAX_OPROF_DOMAINS) @@ -423,12 +403,9 @@ static int xenoprof_set_passive(int * p_ { int ret; int i, j; - int npages; struct xenoprof_buf *buf; - struct vm_struct *area; - pgprot_t prot = __pgprot(_KERNPG_TABLE); - - if (!is_primary) + + if (!xenoprof_is_primary) return 0; if (pdoms > MAX_OPROF_DOMAINS) @@ -437,57 +414,37 @@ static int xenoprof_set_passive(int * p_ ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL); if (ret) return ret; + unmap_passive_list(); 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]); + ret = xenoprof_arch_set_passive(&passive_domains[i], + &p_shared_buffer[i]); if (ret) goto out; - - npages = (passive_domains[i].bufsize * passive_domains[i].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, - passive_domains[i].buf_maddr >> PAGE_SHIFT, - npages * PAGE_SIZE, prot, DOMID_SELF); - if (ret) { - vunmap(area->addr); - goto out; - } - - p_shared_buffer[i] = area->addr; - for (j = 0; j < passive_domains[i].nbuf; j++) { buf = (struct xenoprof_buf *) - &p_shared_buffer[i][j * passive_domains[i].bufsize]; + &p_shared_buffer[i].buffer[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; - } + for (j = 0; j < i; j++) + xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]); return ret; } struct oprofile_operations xenoprof_ops = { +#ifdef HAVE_XENOPROF_CREATE_FILES .create_files = xenoprof_create_files, +#endif .set_active = xenoprof_set_active, .set_passive = xenoprof_set_passive, .setup = xenoprof_setup, @@ -500,21 +457,15 @@ struct oprofile_operations xenoprof_ops /* in order to get driverfs right */ static int using_xenoprof; -int __init oprofile_arch_init(struct oprofile_operations * ops) +int __init xenoprofile_init(struct oprofile_operations * ops) { struct xenoprof_init init; int ret, i; ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init); - if (!ret) { - num_events = init.num_events; - is_primary = init.is_primary; - - /* just in case - make sure we do not overflow event list - (i.e. counter_config list) */ - if (num_events > OP_MAX_COUNTER) - num_events = OP_MAX_COUNTER; + xenoprof_arch_init_counter(&init); + xenoprof_is_primary = init.is_primary; /* cpu_type is detected by Xen */ cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0; @@ -530,30 +481,20 @@ int __init oprofile_arch_init(struct opr active_defined = 0; } - printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, " - "is_primary %d\n", ret, num_events, is_primary); + printk(KERN_INFO "%s: ret %d, events %d, xenoprof_is_primary %d\n", + __func__, ret, init.num_events, xenoprof_is_primary); return ret; } -void __exit oprofile_arch_exit(void) -{ - int i; - +void xenoprofile_exit(void) +{ if (using_xenoprof) exit_driverfs(); - if (shared_buffer) { - vunmap(shared_buffer); - shared_buffer = NULL; - } - if (is_primary) { - for (i = 0; i < pdomains; i++) - if (p_shared_buffer[i]) { - vunmap(p_shared_buffer[i]); - p_shared_buffer[i] = NULL; - } + xenoprof_arch_unmap_shared_buffer(&shared_buffer); + if (xenoprof_is_primary) { + unmap_passive_list(); HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL); } - -} +} diff -r 384cb18e094a -r 3bebc37b1492 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 @@ -21,11 +21,28 @@ */ #ifndef __ASM_XENOPROF_H__ #define __ASM_XENOPROF_H__ -#ifdef CONFIG_OPROFILE +#ifdef CONFIG_OPROFILE struct super_block; struct dentry; int xenoprof_create_files(struct super_block * sb, struct dentry * root); +#define HAVE_XENOPROF_CREATE_FILES + +struct xenoprof_init; +void xenoprof_arch_init_counter(struct xenoprof_init *init); +void xenoprof_arch_counter(void); +void xenoprof_arch_start(void); +void xenoprof_arch_stop(void); + +struct xenoprof_arch_shared_buffer { + /* nothing */ +}; +struct xenoprof_shared_buffer; +void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer* sbuf); +struct xenoprof_get_buffer; +int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer* get_buffer, struct xenoprof_shared_buffer* sbuf); +struct xenoprof_passive; +int xenoprof_arch_set_passive(struct xenoprof_passive* pdomain, struct xenoprof_shared_buffer* sbuf); #endif /* CONFIG_OPROFILE */ #endif /* __ASM_XENOPROF_H__ */ diff -r 384cb18e094a -r 3bebc37b1492 linux-2.6-xen-sparse/include/xen/xenoprof.h --- a/linux-2.6-xen-sparse/include/xen/xenoprof.h Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/include/xen/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 @@ -22,9 +22,25 @@ #ifndef __XEN_XENOPROF_H__ #define __XEN_XENOPROF_H__ + #ifdef CONFIG_OPROFILE - #include <asm/xenoprof.h> +struct oprofile_operations; +int xenoprofile_init(struct oprofile_operations * ops); +void xenoprofile_exit(void); + +// for perfmon/xen +extern int xenoprof_is_primary; +#define is_xenoprof_primary() (xenoprof_is_primary) +struct xenoprof_shared_buffer { + char *buffer; + struct xenoprof_arch_shared_buffer arch; +}; +#else +#define xenoprofile_init(ops) do { } while (0) +#define xenoprofile_exit() do { } while (0) +#define is_xenoprof_primary() (0) #endif /* CONFIG_OPROFILE */ + #endif /* __XEN_XENOPROF_H__ */ yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-14 07:02 UTC
[Xen-devel] [PATCH 5/5 TAKE 2] xenoprof: make xen xenoprof code arch-generic
# HG changeset patch # User yamahata@valinux.co.jp # Date 1163486063 -32400 # Node ID 236b3f5ec6bfef2971864dd7bb16f286e5e83a83 # Parent 3bebc37b149280f5ff1e6091d578c7da73820f16 make xenoprof arch-generic with dynamic mapping/unmapping xenoprof buffer support and auto translated mode support. renamed xenoprof_get_buffer::buf_maddr, xenoprof_passive::buf_maddr to xenoprof_get_buffer::buf_gmaddr, xenoprof_passive::buf_gmaddr to support auto translated mode. With auto translated mode enabled, it is gmaddr, not maddr. PATCHNAME: make_xenoprof_of_xen_side_arch_generic Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> diff -r 3bebc37b1492 -r 236b3f5ec6bf linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:22 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:23 2006 +0900 @@ -93,7 +93,7 @@ int xenoprof_arch_map_shared_buffer(stru if ( (ret = direct_kernel_remap_pfn_range( (unsigned long)area->addr, - get_buffer->buf_maddr >> PAGE_SHIFT, + get_buffer->buf_gmaddr >> PAGE_SHIFT, npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE), DOMID_SELF)) ) { vunmap(area->addr); @@ -127,7 +127,7 @@ int xenoprof_arch_set_passive(struct xen ret = direct_kernel_remap_pfn_range( (unsigned long)area->addr, - pdomain->buf_maddr >> PAGE_SHIFT, + pdomain->buf_gmaddr >> PAGE_SHIFT, npages * PAGE_SIZE, prot, DOMID_SELF); if (ret) { vunmap(area->addr); diff -r 3bebc37b1492 -r 236b3f5ec6bf xen/arch/x86/oprofile/nmi_int.c --- a/xen/arch/x86/oprofile/nmi_int.c Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/arch/x86/oprofile/nmi_int.c Tue Nov 14 15:34:23 2006 +0900 @@ -33,7 +33,6 @@ static unsigned long saved_lvtpc[NR_CPUS #define VIRQ_BITMASK_SIZE (MAX_OPROF_DOMAINS/32 + 1) extern int active_domains[MAX_OPROF_DOMAINS]; extern unsigned int adomains; -extern struct domain *primary_profiler; extern struct domain *adomain_ptrs[MAX_OPROF_DOMAINS]; extern unsigned long virq_ovf_pending[VIRQ_BITMASK_SIZE]; extern int is_active(struct domain *d); @@ -337,10 +336,10 @@ int nmi_init(int *num_events, int *is_pr return -ENODEV; } - if (primary_profiler == NULL) { + if (xenoprof_primary_profiler == NULL) { /* For now, only dom0 can be the primary profiler */ if (current->domain->domain_id == 0) { - primary_profiler = current->domain; + xenoprof_primary_profiler = current->domain; prim = 1; } } diff -r 3bebc37b1492 -r 236b3f5ec6bf xen/common/xenoprof.c --- a/xen/common/xenoprof.c Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/common/xenoprof.c Tue Nov 14 15:34:23 2006 +0900 @@ -2,15 +2,17 @@ * Copyright (C) 2005 Hewlett-Packard Co. * written by Aravind Menon & Jose Renato Santos * (email: xenoprof@groups.hp.com) + * + * arch generic xenoprof and IA64 support. + * dynamic map/unmap xenoprof buffer support. * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> * VA Linux Systems Japan K.K. - * arch generic xenoprof and IA64 support. */ #include <xen/guest_access.h> #include <xen/sched.h> #include <public/xenoprof.h> -#include <asm/hvm/support.h> +#include <asm/shadow.h> /* Limit amount of pages used for shared buffer (per domain) */ #define MAX_OPROF_SHARED_PAGES 32 @@ -26,7 +28,7 @@ unsigned int pdomains; unsigned int pdomains; unsigned int activated; -struct domain *primary_profiler; +struct domain *xenoprof_primary_profiler; int xenoprof_state = XENOPROF_IDLE; u64 total_samples; @@ -90,10 +92,58 @@ static void xenoprof_reset_buf(struct do } } -static char *alloc_xenoprof_buf(struct domain *d, int npages) +static int +share_xenoprof_page_with_guest(struct domain* d, unsigned long mfn, int npages) +{ + int i; + + /* Share pages so that kernel can map it */ + for (i = 0; i < npages; i++) { + struct page_info* page = mfn_to_page(mfn + i); + if ((page->count_info & (PGC_allocated|PGC_count_mask)) != 0) { + gdprintk(XENLOG_INFO, "%s: mfn 0x%lx page->count_info 0x%x\n", + __func__, mfn + i, page->count_info); + return -EBUSY; + } + page->count_info = 0; + page_set_owner(page, NULL); + } + + for (i = 0; i < npages; i++) + share_xen_page_with_guest(mfn_to_page(mfn + i), d, XENSHARE_writable); + return 0; +} + +static void +unshare_xenoprof_page_with_guest(unsigned long mfn, int npages) +{ + int i; + + for (i = 0; i < npages; i++) { + struct page_info* page = mfn_to_page(mfn + i); + BUG_ON(page_get_owner(page) != current->domain); + if (test_and_clear_bit(_PGC_allocated, &page->count_info)) + put_page(page); + } +} + +static void +xenoprof_shared_gmfn_with_guest(struct domain* d, + unsigned long maddr, unsigned long gmaddr, + int npages) +{ + int i; + + for (i = 0; i < npages; i++, maddr += PAGE_SIZE, gmaddr += PAGE_SIZE) { + BUG_ON(page_get_owner(maddr_to_page(maddr)) != d); + xenoprof_shared_gmfn(d, gmaddr, maddr); + } +} + +static char *alloc_xenoprof_buf(struct domain *d, int npages, uint64_t gmaddr) { char *rawbuf; - int i, order; + int order; /* allocate pages to store sample buffer shared with domain */ order = get_order_from_pages(npages); @@ -104,17 +154,11 @@ static char *alloc_xenoprof_buf(struct d 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; } static int alloc_xenoprof_struct( - struct domain *d, int max_samples, int is_passive) + struct domain *d, int max_samples, int is_passive, uint64_t gmaddr) { struct vcpu *v; int nvcpu, npages, bufsize, max_bufsize; @@ -147,7 +191,8 @@ static int alloc_xenoprof_struct( (max_samples - 1) * sizeof(struct event_log); npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1; - d->xenoprof->rawbuf = alloc_xenoprof_buf(is_passive ? dom0 : d, npages); + d->xenoprof->rawbuf = alloc_xenoprof_buf(is_passive ? dom0 : d, npages, + gmaddr); if ( d->xenoprof->rawbuf == NULL ) { @@ -269,6 +314,7 @@ static void reset_passive(struct domain if ( x == NULL ) return; + unshare_xenoprof_page_with_guest(virt_to_mfn(x->rawbuf), x->npages); x->domain_type = XENOPROF_DOMAIN_IGNORED; return; @@ -339,15 +385,26 @@ static int add_passive_list(XEN_GUEST_HA return -EINVAL; if ( (d->xenoprof == NULL) && - ((ret = alloc_xenoprof_struct(d, passive.max_samples, 1)) < 0) ) { + ((ret = alloc_xenoprof_struct(d, passive.max_samples, 1, + passive.buf_gmaddr)) < 0) ) { put_domain(d); return -ENOMEM; + } + + ret = share_xenoprof_page_with_guest(current->domain, + virt_to_mfn(d->xenoprof->rawbuf), d->xenoprof->npages); + if (ret) { + put_domain(d); + return ret; } 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 (!shadow_mode_translate(d)) + passive.buf_gmaddr = __pa(d->xenoprof->rawbuf); + else + xenoprof_shared_gmfn_with_guest(current->domain, __pa(d->xenoprof->rawbuf), passive.buf_gmaddr, d->xenoprof->npages); if ( copy_to_guest(arg, &passive, 1) ) { put_domain(d); @@ -446,7 +503,7 @@ static int xenoprof_op_init(XEN_GUEST_HA return -EFAULT; if ( xenoprof_init.is_primary ) - primary_profiler = current->domain; + xenoprof_primary_profiler = current->domain; return 0; } @@ -465,21 +522,32 @@ static int xenoprof_op_get_buffer(XEN_GU * is called. Memory is then kept until domain is destroyed. */ if ( (d->xenoprof == NULL) && - ((ret = alloc_xenoprof_struct(d, xenoprof_get_buffer.max_samples, 0)) < 0) ) + ((ret = alloc_xenoprof_struct(d, xenoprof_get_buffer.max_samples, 0, + xenoprof_get_buffer.buf_gmaddr)) < 0) ) + return ret; + + ret = share_xenoprof_page_with_guest(d, virt_to_mfn(d->xenoprof->rawbuf), + d->xenoprof->npages); + if (ret) return ret; xenoprof_reset_buf(d); d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; d->xenoprof->domain_ready = 0; - if ( primary_profiler == current->domain ) + if ( xenoprof_primary_profiler == current->domain ) 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 (!shadow_mode_translate(d)) + xenoprof_get_buffer.buf_gmaddr = __pa(d->xenoprof->rawbuf); + else + xenoprof_shared_gmfn_with_guest(d, __pa(d->xenoprof->rawbuf), + xenoprof_get_buffer.buf_gmaddr, + d->xenoprof->npages); if ( copy_to_guest(arg, &xenoprof_get_buffer, 1) ) return -EFAULT; @@ -503,7 +571,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN return -EINVAL; } - if ( !NONPRIV_OP(op) && (current->domain != primary_profiler) ) + if ( !NONPRIV_OP(op) && (current->domain != xenoprof_primary_profiler) ) { printk("xenoprof: dom %d denied privileged operation %d\n", current->domain->domain_id, op); @@ -589,7 +657,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN case XENOPROF_enable_virq: { int i; - if ( current->domain == primary_profiler ) + if ( current->domain == xenoprof_primary_profiler ) { xenoprof_arch_enable_virq(); xenoprof_reset_stat(); @@ -607,7 +675,6 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN if ( (xenoprof_state == XENOPROF_READY) && (activated == adomains) ) ret = xenoprof_arch_start(); - if ( ret == 0 ) xenoprof_state = XENOPROF_PROFILING; break; @@ -622,14 +689,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN break; case XENOPROF_disable_virq: + { + struct xenoprof *x = current->domain->xenoprof; if ( (xenoprof_state == XENOPROF_PROFILING) && (is_active(current->domain)) ) { ret = -EPERM; break; } ret = reset_active(current->domain); - break; - + if (ret) + break; + x = current->domain->xenoprof; /*reset_active() guarantees x != NULL*/ + unshare_xenoprof_page_with_guest(virt_to_mfn(x->rawbuf), x->npages); + break; + } case XENOPROF_release_counters: ret = -EPERM; if ( (xenoprof_state == XENOPROF_COUNTERS_RESERVED) || @@ -649,7 +722,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN { activated = 0; adomains=0; - primary_profiler = NULL; + xenoprof_primary_profiler = NULL; ret = 0; } break; diff -r 3bebc37b1492 -r 236b3f5ec6bf xen/include/asm-x86/xenoprof.h --- a/xen/include/asm-x86/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/include/asm-x86/xenoprof.h Tue Nov 14 15:34:23 2006 +0900 @@ -45,6 +45,17 @@ void nmi_release_counters(void); int xenoprof_arch_counter(XEN_GUEST_HANDLE(void) arg); +struct vcpu; +struct cpu_user_regs; +int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs); +#define xenoprof_shared_gmfn(d, gmaddr, maddr) \ + do { \ + (void)(maddr); \ + gdprintk(XENLOG_ERR, \ + "xenoprof/x86 with autotranslated mode enabled" \ + "isn''t supported yet\n"); \ + } while (0) + #endif /* __ASM_XENOPROF_H__ */ /* diff -r 3bebc37b1492 -r 236b3f5ec6bf xen/include/public/xenoprof.h --- a/xen/include/public/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/include/public/xenoprof.h Tue Nov 14 15:34:23 2006 +0900 @@ -87,7 +87,7 @@ struct xenoprof_get_buffer { int32_t max_samples; int32_t nbuf; int32_t bufsize; - uint64_t buf_maddr; + uint64_t buf_gmaddr; }; typedef struct xenoprof_get_buffer xenoprof_get_buffer_t; DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t); @@ -110,7 +110,7 @@ typedef struct xenoprof_passive { int32_t max_samples; int32_t nbuf; int32_t bufsize; - uint64_t buf_maddr; + uint64_t buf_gmaddr; } xenoprof_passive_t; DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t); diff -r 3bebc37b1492 -r 236b3f5ec6bf xen/include/xen/xenoprof.h --- a/xen/include/xen/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/include/xen/xenoprof.h Tue Nov 14 15:34:23 2006 +0900 @@ -41,4 +41,8 @@ struct domain; struct domain; void free_xenoprof_pages(struct domain *d); +int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg); + +extern struct domain *xenoprof_primary_profiler; + #endif /* __XEN__XENOPROF_H__ */ yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2006-Nov-14 11:59 UTC
Re: [Xen-devel] [PATCH 0/5 TAKE 2] xenoprof: preliminary patches for xenoprof/ia64
Renato needs to review and ack these patches before I''ll apply them. -- Keir On 14/11/06 07:01, "Isaku Yamahata" <yamahata@valinux.co.jp> wrote:> > Those patches are preliminary clean-ups to support xenoprof on ia64. > They split the current x86-specific code into arch dependent/independent > code and make them more arch-generic. > Those include also bug fixes, clean-ups and dynamic mapping/unmapping > xenoprof buffer support. I''ll post the IA64 part to xen-ia64-devel. > > [PATCH 1/5] xenoprof: split xen x86 xenoprof code > [PATCH 2/5] xenoprof: make xen xenoprof code slight arch-generic > [PATCH 3/5] xenoprof: split linux x86 xenoprof code > [PATCH 4/5] xenoprof: make linux xenoprof code arch-generic > [PATCH 5/5] xenoprof: make xen xenoprof code arch-generic > > Changes: > > TAKE 2 > - broke patches into smaller ones for review. > The final code is almost same as TAKE 1. > > thanks > yamahata > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Santos, Jose Renato G
2006-Nov-14 17:23 UTC
RE: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split xen x86 xenoprof code
> -----Original Message----- > From: xen-devel-bounces@lists.xensource.com > [mailto:xen-devel-bounces@lists.xensource.com] On Behalf Of > Isaku Yamahata > Sent: Monday, November 13, 2006 11:02 PM > To: xen-devel@lists.xensource.com; Isaku Yamahata > Cc: Isaku Yamahata; xen-ia64-devel@lists.xensource.com > Subject: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split xen > x86 xenoprof code > > # HG changeset patch > # User yamahata@valinux.co.jp > # Date 1163486059 -32400 > # Node ID 24e1dacab1545640701709be7742608de73063cc > # Parent 45d6a5bc857817fb8f541b410920e59bf1417ac2 > move xenoprof code under xen/arch/x86/oprofile to xen/common > without code changes excpet slight adjustment to compile. > PATCHNAME: move_xen_x86_xenoprof_code_under_xen_common > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> > > diff -r 45d6a5bc8578 -r 24e1dacab154 xen/arch/x86/Rules.mk > --- a/xen/arch/x86/Rules.mk Tue Nov 14 15:34:18 2006 +0900 > +++ b/xen/arch/x86/Rules.mk Tue Nov 14 15:34:19 2006 +0900 > @@ -3,6 +3,7 @@<deleted>> int xenoprofile_get_mode(struct vcpu *v, struct > cpu_user_regs * const regs) { diff -r 45d6a5bc8578 -r > 24e1dacab154 xen/common/Makefile > --- a/xen/common/Makefile Tue Nov 14 15:34:18 2006 +0900 > +++ b/xen/common/Makefile Tue Nov 14 15:34:19 2006 +0900 > @@ -29,6 +29,7 @@ obj-y += xmalloc.oIsaku, This patch is corrupt. It does not apply cleanly. It has several missing "newlines" such as for example the line above. Could you please regenerate ? I am not sure about the other patches, but it would help if you can make sure they are all OK and resend. Thanks Renato _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-15 02:14 UTC
Re: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split xen x86 xenoprof code
On Tue, Nov 14, 2006 at 11:23:42AM -0600, Santos, Jose Renato G wrote:> This patch is corrupt. It does not apply cleanly. It has several missing > "newlines" such as for example the line above. > Could you please regenerate ? > I am not sure about the other patches, but it would help if you can make > sure they are all OK and resend.I regenerated them for 12446:fb107b9eee86 of xen-unstable.hg. They should apply cleanly and compile. To make sure not to corrupt the patches, I attached them as a tar ball. Please find it. -- yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Santos, Jose Renato G
2006-Nov-16 03:58 UTC
RE: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split xen x86 xenoprof code
Isaku, Mostly, the patches look good. I have a few questions though , mostly for clarification Keir, Could you please wait until I have a chance to test the patches on my machine before applying. I will be out all day tomorrow (Thursday) to attend an external event so I will only be able to do this on Friday. Also, I think it would be good if you could review parts of patch 5. There are some changes on how xenoprof shares page with the guest. The patch decouples the code for allocating xenoprof buffer from the code for sharing it with the domain. This is very welcome as it has been on my wish list for a while. This modification should remove the current limitation that guests cannot use different profiling modes (active and passive) in different profiling sessions. But I am afraid I do not understand Xen memory management in detail to review this part of the patch. Please, take a look. ----------------------- QUESTIONS for Isaku: patch 4/5: =========> +struct xenoprof_shared_buffer { > + char *buffer; > + struct xenoprof_arch_shared_buffer arch; > +};The arch field has no extra info for x86. Why do you need this?> @@ -103,7 +98,7 @@ static int __init init_driverfs(void) > } > > > -static void __exit exit_driverfs(void) > +static void /* __exit */ exit_driverfs(void) > { > sysdev_unregister(&device_oprofile); > sysdev_class_unregister(&oprofile_sysclass);Why removing "__exit" is needed?> +void xenoprof_arch_start(void) > +{ > + /* nothing */ > +} > + > +void xenoprof_arch_stop(void) > +{ > + /* nothing */ > +} > +Why do we need arch specific functions for start and stop?> @@ -22,9 +22,25 @@ > > #ifndef __XEN_XENOPROF_H__ > #define __XEN_XENOPROF_H__ > + > #ifdef CONFIG_OPROFILE > - > #include <asm/xenoprof.h> > > +struct oprofile_operations; > +int xenoprofile_init(struct oprofile_operations * ops); > +void xenoprofile_exit(void); > + > +// for perfmon/xenPlease drop the comment or change it (xenoprofile is not using perfmon) patch 5/5: ========> -static char *alloc_xenoprof_buf(struct domain *d, int npages) > +static char *alloc_xenoprof_buf(struct domain *d, int npages,uint64_t gmaddr) The extra parameter gmaddr is not needed since if it is not used by the function. Regards Renato> -----Original Message----- > From: Isaku Yamahata [mailto:yamahata@valinux.co.jp] > Sent: Tuesday, November 14, 2006 6:14 PM > To: Santos, Jose Renato G > Cc: xen-devel@lists.xensource.com; xen-ia64-devel@lists.xensource.com > Subject: Re: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split > xen x86 xenoprof code > > On Tue, Nov 14, 2006 at 11:23:42AM -0600, Santos, Jose Renato G wrote: > > > This patch is corrupt. It does not apply cleanly. It has several > > missing "newlines" such as for example the line above. > > Could you please regenerate ? > > I am not sure about the other patches, but it would help if you can > > make sure they are all OK and resend. > > I regenerated them for 12446:fb107b9eee86 of xen-unstable.hg. > They should apply cleanly and compile. > To make sure not to corrupt the patches, I attached them as a > tar ball. > Please find it. > > -- > yamahata >_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-16 05:54 UTC
Re: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split xen x86 xenoprof code
On Wed, Nov 15, 2006 at 09:58:40PM -0600, Santos, Jose Renato G wrote:> Mostly, the patches look good. > I have a few questions though , mostly for clarificationThank you for your review.> QUESTIONS for Isaku: > > patch 4/5: > =========> > > +struct xenoprof_shared_buffer { > > + char *buffer; > > + struct xenoprof_arch_shared_buffer arch; > > +}; > > The arch field has no extra info for x86. Why do you need this?On IA64 it is defined as struct xenoprof_arch_shared_buffer { struct resource* res; }; On IA64, auto translated mode feature is enabled. It means that page mapping from xen is based on pseudo physical address, not virtual address. Pseudo physical address used to map pages must be recorded somewhere in order to unmap. I guess, if xenoprof/x86 supported auto translated guest mode something similar structure would be necessary.> > @@ -103,7 +98,7 @@ static int __init init_driverfs(void) > > } > > > > > > -static void __exit exit_driverfs(void) > > +static void /* __exit */ exit_driverfs(void) > > { > > sysdev_unregister(&device_oprofile); > > sysdev_class_unregister(&oprofile_sysclass); > > Why removing "__exit" is needed?Because it is called by non-"__exit" function. __init oprofile_init() => oprofile_arch_exit() // error recovery => xenoprof_arch_exit() => exit_driver() When I compiled xenLinux/IA64, linker complained. I suspect that "__exit" of the original oprofile_arch_exit() of linux-2.6-xen-sparse/arch/i386/oprofile/xenropof.c is wrong. Actually the vanilla oprofile_arch_exit() of linux/arch/i386/oprofile/init.c doesn''t carry "__exit". Gcc didn''t complain when I compiled xenLinux/i386, though.> > +void xenoprof_arch_start(void) > > +{ > > + /* nothing */ > > +} > > + > > +void xenoprof_arch_stop(void) > > +{ > > + /* nothing */ > > +} > > + > > Why do we need arch specific functions for start and stop?On IA64 they are defined as void xenoprof_arch_start(void) { perfmon_start(); } void xenoprof_arch_stop(void) { perfmon_stop(); } struct op_counter_config is x86 specific. I chose to define op_counter_config related operation as nop on IA64 and to add those two hooks. On IA64, registers related to performance monitoring are manipulated through perfmonctl system call. The oprofile/ia64 doesn''t manipulate them directly. It just tells perfmon to start/stop. So those hooks are needed. It would be possible to define more generic interface to manipulated performance monitoring registers. Actually the perfmon project is working on that and the effort is under way. (It is held by hp lab so that you may already know that though.) I think it is too eary to do so for xenoprof.> > @@ -22,9 +22,25 @@ > > > > #ifndef __XEN_XENOPROF_H__ > > #define __XEN_XENOPROF_H__ > > + > > #ifdef CONFIG_OPROFILE > > - > > #include <asm/xenoprof.h> > > > > +struct oprofile_operations; > > +int xenoprofile_init(struct oprofile_operations * ops); > > +void xenoprofile_exit(void); > > + > > +// for perfmon/xen > > Please drop the comment or change it (xenoprofile is not using perfmon)I''ll drop it.> patch 5/5: > ========> > > -static char *alloc_xenoprof_buf(struct domain *d, int npages) > > +static char *alloc_xenoprof_buf(struct domain *d, int npages, > uint64_t gmaddr) > > The extra parameter gmaddr is not needed since if it is not used by the > function.I''ll remove it. -- yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-16 06:12 UTC
Re: [Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make linux xenoprof code arch-generic
Updated following Renato''s comments. Changes: - __exit clean up - removed perfmon comments # HG changeset patch # User yamahata@valinux.co.jp # Date 1163486062 -32400 # Node ID 9bf71c7abb2de71ac233c24d821978ce2e6cc961 # Parent e9e5f10f89615f88d433a670a69a2ba4af60c791 make xenoprof of linux side arch generic with some bug fixes. PATCHNAME: make_xenoprof_of_linux_side_arch_generic Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> diff -r e9e5f10f8961 -r 9bf71c7abb2d linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:22 2006 +0900 @@ -15,12 +15,130 @@ * VA Linux Systems Japan K.K. */ +#include <linux/init.h> #include <linux/oprofile.h> +#include <linux/sched.h> +#include <asm/pgtable.h> +#include <xen/driver_util.h> +#include <xen/interface/xen.h> +#include <xen/interface/xenoprof.h> #include <xen/xenoprof.h> #include "op_counter.h" -unsigned int num_events = 0; +static unsigned int num_events = 0; + +void __init xenoprof_arch_init_counter(struct xenoprof_init *init) +{ + num_events = init->num_events; + /* just in case - make sure we do not overflow event list + (i.e. counter_config list) */ + if (num_events > OP_MAX_COUNTER) { + num_events = OP_MAX_COUNTER; + init->num_events = num_events; + } +} + +void xenoprof_arch_counter(void) +{ + int i; + struct xenoprof_counter counter; + + for (i=0; i<num_events; i++) { + counter.ind = i; + counter.count = (uint64_t)counter_config[i].count; + counter.enabled = (uint32_t)counter_config[i].enabled; + counter.event = (uint32_t)counter_config[i].event; + counter.kernel = (uint32_t)counter_config[i].kernel; + counter.user = (uint32_t)counter_config[i].user; + counter.unit_mask = (uint64_t)counter_config[i].unit_mask; + HYPERVISOR_xenoprof_op(XENOPROF_counter, + &counter); + } +} + +void xenoprof_arch_start(void) +{ + /* nothing */ +} + +void xenoprof_arch_stop(void) +{ + /* nothing */ +} + +void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer * sbuf) +{ + if (sbuf->buffer) { + vunmap(sbuf->buffer); + sbuf->buffer = NULL; + } +} + +int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer * get_buffer, + struct xenoprof_shared_buffer * sbuf) +{ + int npages, ret; + struct vm_struct *area; + + sbuf->buffer = NULL; + if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, get_buffer)) ) + return ret; + + npages = (get_buffer->bufsize * get_buffer->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; + } + + sbuf->buffer = area->addr; + return ret; +} + +int xenoprof_arch_set_passive(struct xenoprof_passive * pdomain, + struct xenoprof_shared_buffer * sbuf) +{ + int ret; + int npages; + struct vm_struct *area; + pgprot_t prot = __pgprot(_KERNPG_TABLE); + + sbuf->buffer = NULL; + ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive, pdomain); + if (ret) + goto out; + + npages = (pdomain->bufsize * pdomain->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, + pdomain->buf_maddr >> PAGE_SHIFT, + npages * PAGE_SIZE, prot, DOMID_SELF); + if (ret) { + vunmap(area->addr); + goto out; + } + sbuf->buffer = area->addr; + +out: + return ret; +} + struct op_counter_config counter_config[OP_MAX_COUNTER]; int xenoprof_create_files(struct super_block * sb, struct dentry * root) @@ -49,3 +167,13 @@ int xenoprof_create_files(struct super_b return 0; } + +int __init oprofile_arch_init(struct oprofile_operations * ops) +{ + return xenoprofile_init(ops); +} + +void oprofile_arch_exit(void) +{ + xenoprofile_exit(); +} diff -r e9e5f10f8961 -r 9bf71c7abb2d linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c --- a/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c Tue Nov 14 15:34:22 2006 +0900 @@ -1,5 +1,5 @@ /** - * @file xenoprof.c + * @file xenoprofile.c * * @remark Copyright 2002 OProfile authors * @remark Read the file COPYING @@ -23,14 +23,9 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/vmalloc.h> -#include <asm/nmi.h> -#include <asm/msr.h> -#include <asm/apic.h> #include <asm/pgtable.h> #include <xen/evtchn.h> #include <xen/xenoprof.h> -#include "../../../arch/i386/oprofile/op_counter.h" - #include <xen/driver_util.h> #include <xen/interface/xen.h> #include <xen/interface/xenoprof.h> @@ -39,18 +34,23 @@ #define MAX_XENOPROF_SAMPLES 16 -static int xenoprof_start(void); -static void xenoprof_stop(void); - -static int xenoprof_enabled = 0; -extern unsigned int num_events; -static int is_primary = 0; -static int active_defined; - /* sample buffers shared with Xen */ xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS]; /* Shared buffer area */ -char * shared_buffer = NULL; +struct xenoprof_shared_buffer shared_buffer; + +/* Passive sample buffers shared with Xen */ +xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS]; +/* Passive shared buffer area */ +struct xenoprof_shared_buffer p_shared_buffer[MAX_OPROF_DOMAINS]; + +static int xenoprof_start(void); +static void xenoprof_stop(void); + +static int xenoprof_enabled = 0; +int xenoprof_is_primary = 0; +static int active_defined; + /* Number of buffers in shared area (one per VCPU) */ int nbuf; /* Mappings of VIRQ_XENOPROF to irq number (per cpu) */ @@ -58,11 +58,6 @@ 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) @@ -103,7 +98,7 @@ static int __init init_driverfs(void) } -static void __exit exit_driverfs(void) +static void exit_driverfs(void) { sysdev_unregister(&device_oprofile); sysdev_class_unregister(&oprofile_sysclass); @@ -193,7 +188,7 @@ xenoprof_ovf_interrupt(int irq, void * d xenoprof_add_pc(buf, 0); - if (is_primary && !test_and_set_bit(0, &flag)) { + if (xenoprof_is_primary && !test_and_set_bit(0, &flag)) { xenoprof_handle_passive(); smp_mb__before_clear_bit(); clear_bit(0, &flag); @@ -207,7 +202,7 @@ static void unbind_virq(void) { int i; - for_each_cpu(i) { + for_each_online_cpu(i) { if (ovf_irq[i] >= 0) { unbind_from_irqhandler(ovf_irq[i], NULL); ovf_irq[i] = -1; @@ -220,7 +215,7 @@ static int bind_virq(void) { int i, result; - for_each_cpu(i) { + for_each_online_cpu(i) { result = bind_virq_to_irqhandler(VIRQ_XENOPROF, i, xenoprof_ovf_interrupt, @@ -240,40 +235,33 @@ static int bind_virq(void) } +static void unmap_passive_list(void) +{ + int i; + for (i = 0; i < pdomains; i++) + xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]); + pdomains = 0; +} + + 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 ) + int ret, i; + + if ( shared_buffer.buffer ) return 0; get_buffer.max_samples = max_samples; - - if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, &get_buffer)) ) + ret = xenoprof_arch_map_shared_buffer(&get_buffer, &shared_buffer); + if (ret) 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]; + &shared_buffer.buffer[i * get_buffer.bufsize]; BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS); xenoprof_buf[buf->vcpu_id] = buf; } @@ -285,7 +273,6 @@ static int xenoprof_setup(void) static int xenoprof_setup(void) { int ret; - int i; if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) ) return ret; @@ -293,9 +280,7 @@ static int xenoprof_setup(void) if ( (ret = bind_virq()) ) return ret; - if (is_primary) { - struct xenoprof_counter counter; - + if (xenoprof_is_primary) { /* Define dom0 as an active domain if not done yet */ if (!active_defined) { domid_t domid; @@ -312,17 +297,7 @@ static int xenoprof_setup(void) ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL); if (ret) goto err; - for (i=0; i<num_events; i++) { - counter.ind = i; - counter.count = (uint64_t)counter_config[i].count; - counter.enabled = (uint32_t)counter_config[i].enabled; - counter.event = (uint32_t)counter_config[i].event; - counter.kernel = (uint32_t)counter_config[i].kernel; - counter.user = (uint32_t)counter_config[i].user; - counter.unit_mask = (uint64_t)counter_config[i].unit_mask; - HYPERVISOR_xenoprof_op(XENOPROF_counter, - &counter); - } + xenoprof_arch_counter(); ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL); if (ret) @@ -347,13 +322,16 @@ static void xenoprof_shutdown(void) HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL); - if (is_primary) { + if (xenoprof_is_primary) { HYPERVISOR_xenoprof_op(XENOPROF_release_counters, NULL); active_defined = 0; } unbind_virq(); + xenoprof_arch_unmap_shared_buffer(&shared_buffer); + if (xenoprof_is_primary) + unmap_passive_list(); } @@ -361,17 +339,19 @@ static int xenoprof_start(void) { int ret = 0; - if (is_primary) + if (xenoprof_is_primary) ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL); - + if (!ret) + xenoprof_arch_start(); return ret; } static void xenoprof_stop(void) { - if (is_primary) + if (xenoprof_is_primary) HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL); + xenoprof_arch_stop(); } @@ -383,7 +363,7 @@ static int xenoprof_set_active(int * act int set_dom0 = 0; domid_t domid; - if (!is_primary) + if (!xenoprof_is_primary) return 0; if (adomains > MAX_OPROF_DOMAINS) @@ -423,12 +403,9 @@ static int xenoprof_set_passive(int * p_ { int ret; int i, j; - int npages; struct xenoprof_buf *buf; - struct vm_struct *area; - pgprot_t prot = __pgprot(_KERNPG_TABLE); - - if (!is_primary) + + if (!xenoprof_is_primary) return 0; if (pdoms > MAX_OPROF_DOMAINS) @@ -437,57 +414,37 @@ static int xenoprof_set_passive(int * p_ ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL); if (ret) return ret; + unmap_passive_list(); 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]); + ret = xenoprof_arch_set_passive(&passive_domains[i], + &p_shared_buffer[i]); if (ret) goto out; - - npages = (passive_domains[i].bufsize * passive_domains[i].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, - passive_domains[i].buf_maddr >> PAGE_SHIFT, - npages * PAGE_SIZE, prot, DOMID_SELF); - if (ret) { - vunmap(area->addr); - goto out; - } - - p_shared_buffer[i] = area->addr; - for (j = 0; j < passive_domains[i].nbuf; j++) { buf = (struct xenoprof_buf *) - &p_shared_buffer[i][j * passive_domains[i].bufsize]; + &p_shared_buffer[i].buffer[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; - } + for (j = 0; j < i; j++) + xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]); return ret; } struct oprofile_operations xenoprof_ops = { +#ifdef HAVE_XENOPROF_CREATE_FILES .create_files = xenoprof_create_files, +#endif .set_active = xenoprof_set_active, .set_passive = xenoprof_set_passive, .setup = xenoprof_setup, @@ -500,21 +457,15 @@ struct oprofile_operations xenoprof_ops /* in order to get driverfs right */ static int using_xenoprof; -int __init oprofile_arch_init(struct oprofile_operations * ops) +int __init xenoprofile_init(struct oprofile_operations * ops) { struct xenoprof_init init; int ret, i; ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init); - if (!ret) { - num_events = init.num_events; - is_primary = init.is_primary; - - /* just in case - make sure we do not overflow event list - (i.e. counter_config list) */ - if (num_events > OP_MAX_COUNTER) - num_events = OP_MAX_COUNTER; + xenoprof_arch_init_counter(&init); + xenoprof_is_primary = init.is_primary; /* cpu_type is detected by Xen */ cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0; @@ -530,30 +481,20 @@ int __init oprofile_arch_init(struct opr active_defined = 0; } - printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, " - "is_primary %d\n", ret, num_events, is_primary); + printk(KERN_INFO "%s: ret %d, events %d, xenoprof_is_primary %d\n", + __func__, ret, init.num_events, xenoprof_is_primary); return ret; } -void __exit oprofile_arch_exit(void) -{ - int i; - +void xenoprofile_exit(void) +{ if (using_xenoprof) exit_driverfs(); - if (shared_buffer) { - vunmap(shared_buffer); - shared_buffer = NULL; - } - if (is_primary) { - for (i = 0; i < pdomains; i++) - if (p_shared_buffer[i]) { - vunmap(p_shared_buffer[i]); - p_shared_buffer[i] = NULL; - } + xenoprof_arch_unmap_shared_buffer(&shared_buffer); + if (xenoprof_is_primary) { + unmap_passive_list(); HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL); } - -} +} diff -r e9e5f10f8961 -r 9bf71c7abb2d linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 @@ -21,11 +21,28 @@ */ #ifndef __ASM_XENOPROF_H__ #define __ASM_XENOPROF_H__ -#ifdef CONFIG_OPROFILE +#ifdef CONFIG_OPROFILE struct super_block; struct dentry; int xenoprof_create_files(struct super_block * sb, struct dentry * root); +#define HAVE_XENOPROF_CREATE_FILES + +struct xenoprof_init; +void xenoprof_arch_init_counter(struct xenoprof_init *init); +void xenoprof_arch_counter(void); +void xenoprof_arch_start(void); +void xenoprof_arch_stop(void); + +struct xenoprof_arch_shared_buffer { + /* nothing */ +}; +struct xenoprof_shared_buffer; +void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer* sbuf); +struct xenoprof_get_buffer; +int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer* get_buffer, struct xenoprof_shared_buffer* sbuf); +struct xenoprof_passive; +int xenoprof_arch_set_passive(struct xenoprof_passive* pdomain, struct xenoprof_shared_buffer* sbuf); #endif /* CONFIG_OPROFILE */ #endif /* __ASM_XENOPROF_H__ */ diff -r e9e5f10f8961 -r 9bf71c7abb2d linux-2.6-xen-sparse/include/xen/xenoprof.h --- a/linux-2.6-xen-sparse/include/xen/xenoprof.h Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/include/xen/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 @@ -22,9 +22,24 @@ #ifndef __XEN_XENOPROF_H__ #define __XEN_XENOPROF_H__ + #ifdef CONFIG_OPROFILE - #include <asm/xenoprof.h> +struct oprofile_operations; +int xenoprofile_init(struct oprofile_operations * ops); +void xenoprofile_exit(void); + +extern int xenoprof_is_primary; +#define is_xenoprof_primary() (xenoprof_is_primary) +struct xenoprof_shared_buffer { + char *buffer; + struct xenoprof_arch_shared_buffer arch; +}; +#else +#define xenoprofile_init(ops) do { } while (0) +#define xenoprofile_exit() do { } while (0) +#define is_xenoprof_primary() (0) #endif /* CONFIG_OPROFILE */ + #endif /* __XEN_XENOPROF_H__ */ -- yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-16 06:14 UTC
Re: [Xen-devel] [PATCH 5/5 TAKE 2] xenoprof: make xen xenoprof code arch-generic
Updated following Renato''s comments. Changes - changed alloc_xenoprof_buf() signature. removed third gmaddr argument. # HG changeset patch # User yamahata@valinux.co.jp # Date 1163486063 -32400 # Node ID 996212ae7f052348a22f8c06d5a2958fca39c6ff # Parent 9bf71c7abb2de71ac233c24d821978ce2e6cc961 make xenoprof arch-generic with dynamic mapping/unmapping xenoprof buffer support and auto translated mode support. renamed xenoprof_get_buffer::buf_maddr, xenoprof_passive::buf_maddr to xenoprof_get_buffer::buf_gmaddr, xenoprof_passive::buf_gmaddr to support auto translated mode. With auto translated mode enabled, it is gmaddr, not maddr. PATCHNAME: make_xenoprof_of_xen_side_arch_generic Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> diff -r 9bf71c7abb2d -r 996212ae7f05 linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:22 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:23 2006 +0900 @@ -93,7 +93,7 @@ int xenoprof_arch_map_shared_buffer(stru if ( (ret = direct_kernel_remap_pfn_range( (unsigned long)area->addr, - get_buffer->buf_maddr >> PAGE_SHIFT, + get_buffer->buf_gmaddr >> PAGE_SHIFT, npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE), DOMID_SELF)) ) { vunmap(area->addr); @@ -127,7 +127,7 @@ int xenoprof_arch_set_passive(struct xen ret = direct_kernel_remap_pfn_range( (unsigned long)area->addr, - pdomain->buf_maddr >> PAGE_SHIFT, + pdomain->buf_gmaddr >> PAGE_SHIFT, npages * PAGE_SIZE, prot, DOMID_SELF); if (ret) { vunmap(area->addr); diff -r 9bf71c7abb2d -r 996212ae7f05 xen/arch/x86/oprofile/nmi_int.c --- a/xen/arch/x86/oprofile/nmi_int.c Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/arch/x86/oprofile/nmi_int.c Tue Nov 14 15:34:23 2006 +0900 @@ -33,7 +33,6 @@ static unsigned long saved_lvtpc[NR_CPUS #define VIRQ_BITMASK_SIZE (MAX_OPROF_DOMAINS/32 + 1) extern int active_domains[MAX_OPROF_DOMAINS]; extern unsigned int adomains; -extern struct domain *primary_profiler; extern struct domain *adomain_ptrs[MAX_OPROF_DOMAINS]; extern unsigned long virq_ovf_pending[VIRQ_BITMASK_SIZE]; extern int is_active(struct domain *d); @@ -337,10 +336,10 @@ int nmi_init(int *num_events, int *is_pr return -ENODEV; } - if (primary_profiler == NULL) { + if (xenoprof_primary_profiler == NULL) { /* For now, only dom0 can be the primary profiler */ if (current->domain->domain_id == 0) { - primary_profiler = current->domain; + xenoprof_primary_profiler = current->domain; prim = 1; } } diff -r 9bf71c7abb2d -r 996212ae7f05 xen/common/xenoprof.c --- a/xen/common/xenoprof.c Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/common/xenoprof.c Tue Nov 14 15:34:23 2006 +0900 @@ -2,15 +2,17 @@ * Copyright (C) 2005 Hewlett-Packard Co. * written by Aravind Menon & Jose Renato Santos * (email: xenoprof@groups.hp.com) + * + * arch generic xenoprof and IA64 support. + * dynamic map/unmap xenoprof buffer support. * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> * VA Linux Systems Japan K.K. - * arch generic xenoprof and IA64 support. */ #include <xen/guest_access.h> #include <xen/sched.h> #include <public/xenoprof.h> -#include <asm/hvm/support.h> +#include <asm/shadow.h> /* Limit amount of pages used for shared buffer (per domain) */ #define MAX_OPROF_SHARED_PAGES 32 @@ -26,7 +28,7 @@ unsigned int pdomains; unsigned int pdomains; unsigned int activated; -struct domain *primary_profiler; +struct domain *xenoprof_primary_profiler; int xenoprof_state = XENOPROF_IDLE; u64 total_samples; @@ -90,10 +92,58 @@ static void xenoprof_reset_buf(struct do } } +static int +share_xenoprof_page_with_guest(struct domain* d, unsigned long mfn, int npages) +{ + int i; + + /* Share pages so that kernel can map it */ + for (i = 0; i < npages; i++) { + struct page_info* page = mfn_to_page(mfn + i); + if ((page->count_info & (PGC_allocated|PGC_count_mask)) != 0) { + gdprintk(XENLOG_INFO, "%s: mfn 0x%lx page->count_info 0x%x\n", + __func__, mfn + i, page->count_info); + return -EBUSY; + } + page->count_info = 0; + page_set_owner(page, NULL); + } + + for (i = 0; i < npages; i++) + share_xen_page_with_guest(mfn_to_page(mfn + i), d, XENSHARE_writable); + return 0; +} + +static void +unshare_xenoprof_page_with_guest(unsigned long mfn, int npages) +{ + int i; + + for (i = 0; i < npages; i++) { + struct page_info* page = mfn_to_page(mfn + i); + BUG_ON(page_get_owner(page) != current->domain); + if (test_and_clear_bit(_PGC_allocated, &page->count_info)) + put_page(page); + } +} + +static void +xenoprof_shared_gmfn_with_guest(struct domain* d, + unsigned long maddr, unsigned long gmaddr, + int npages) +{ + int i; + + for (i = 0; i < npages; i++, maddr += PAGE_SIZE, gmaddr += PAGE_SIZE) { + BUG_ON(page_get_owner(maddr_to_page(maddr)) != d); + xenoprof_shared_gmfn(d, gmaddr, maddr); + } +} + static char *alloc_xenoprof_buf(struct domain *d, int npages) { char *rawbuf; - int i, order; + int order; /* allocate pages to store sample buffer shared with domain */ order = get_order_from_pages(npages); @@ -104,17 +154,11 @@ static char *alloc_xenoprof_buf(struct d 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; } static int alloc_xenoprof_struct( - struct domain *d, int max_samples, int is_passive) + struct domain *d, int max_samples, int is_passive, uint64_t gmaddr) { struct vcpu *v; int nvcpu, npages, bufsize, max_bufsize; @@ -269,6 +313,7 @@ static void reset_passive(struct domain if ( x == NULL ) return; + unshare_xenoprof_page_with_guest(virt_to_mfn(x->rawbuf), x->npages); x->domain_type = XENOPROF_DOMAIN_IGNORED; return; @@ -339,15 +384,26 @@ static int add_passive_list(XEN_GUEST_HA return -EINVAL; if ( (d->xenoprof == NULL) && - ((ret = alloc_xenoprof_struct(d, passive.max_samples, 1)) < 0) ) { + ((ret = alloc_xenoprof_struct(d, passive.max_samples, 1, + passive.buf_gmaddr)) < 0) ) { put_domain(d); return -ENOMEM; + } + + ret = share_xenoprof_page_with_guest(current->domain, + virt_to_mfn(d->xenoprof->rawbuf), d->xenoprof->npages); + if (ret) { + put_domain(d); + return ret; } 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 (!shadow_mode_translate(d)) + passive.buf_gmaddr = __pa(d->xenoprof->rawbuf); + else + xenoprof_shared_gmfn_with_guest(current->domain, __pa(d->xenoprof->rawbuf), passive.buf_gmaddr, d->xenoprof->npages); if ( copy_to_guest(arg, &passive, 1) ) { put_domain(d); @@ -446,7 +502,7 @@ static int xenoprof_op_init(XEN_GUEST_HA return -EFAULT; if ( xenoprof_init.is_primary ) - primary_profiler = current->domain; + xenoprof_primary_profiler = current->domain; return 0; } @@ -465,21 +521,32 @@ static int xenoprof_op_get_buffer(XEN_GU * is called. Memory is then kept until domain is destroyed. */ if ( (d->xenoprof == NULL) && - ((ret = alloc_xenoprof_struct(d, xenoprof_get_buffer.max_samples, 0)) < 0) ) + ((ret = alloc_xenoprof_struct(d, xenoprof_get_buffer.max_samples, 0, + xenoprof_get_buffer.buf_gmaddr)) < 0) ) + return ret; + + ret = share_xenoprof_page_with_guest(d, virt_to_mfn(d->xenoprof->rawbuf), + d->xenoprof->npages); + if (ret) return ret; xenoprof_reset_buf(d); d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; d->xenoprof->domain_ready = 0; - if ( primary_profiler == current->domain ) + if ( xenoprof_primary_profiler == current->domain ) 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 (!shadow_mode_translate(d)) + xenoprof_get_buffer.buf_gmaddr = __pa(d->xenoprof->rawbuf); + else + xenoprof_shared_gmfn_with_guest(d, __pa(d->xenoprof->rawbuf), + xenoprof_get_buffer.buf_gmaddr, + d->xenoprof->npages); if ( copy_to_guest(arg, &xenoprof_get_buffer, 1) ) return -EFAULT; @@ -503,7 +570,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN return -EINVAL; } - if ( !NONPRIV_OP(op) && (current->domain != primary_profiler) ) + if ( !NONPRIV_OP(op) && (current->domain != xenoprof_primary_profiler) ) { printk("xenoprof: dom %d denied privileged operation %d\n", current->domain->domain_id, op); @@ -589,7 +656,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN case XENOPROF_enable_virq: { int i; - if ( current->domain == primary_profiler ) + if ( current->domain == xenoprof_primary_profiler ) { xenoprof_arch_enable_virq(); xenoprof_reset_stat(); @@ -607,7 +674,6 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN if ( (xenoprof_state == XENOPROF_READY) && (activated == adomains) ) ret = xenoprof_arch_start(); - if ( ret == 0 ) xenoprof_state = XENOPROF_PROFILING; break; @@ -622,14 +688,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN break; case XENOPROF_disable_virq: + { + struct xenoprof *x = current->domain->xenoprof; if ( (xenoprof_state == XENOPROF_PROFILING) && (is_active(current->domain)) ) { ret = -EPERM; break; } ret = reset_active(current->domain); - break; - + if (ret) + break; + x = current->domain->xenoprof; /*reset_active() guarantees x != NULL*/ + unshare_xenoprof_page_with_guest(virt_to_mfn(x->rawbuf), x->npages); + break; + } case XENOPROF_release_counters: ret = -EPERM; if ( (xenoprof_state == XENOPROF_COUNTERS_RESERVED) || @@ -649,7 +721,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN { activated = 0; adomains=0; - primary_profiler = NULL; + xenoprof_primary_profiler = NULL; ret = 0; } break; diff -r 9bf71c7abb2d -r 996212ae7f05 xen/include/asm-x86/xenoprof.h --- a/xen/include/asm-x86/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/include/asm-x86/xenoprof.h Tue Nov 14 15:34:23 2006 +0900 @@ -45,6 +45,17 @@ void nmi_release_counters(void); int xenoprof_arch_counter(XEN_GUEST_HANDLE(void) arg); +struct vcpu; +struct cpu_user_regs; +int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs); +#define xenoprof_shared_gmfn(d, gmaddr, maddr) \ + do { \ + (void)(maddr); \ + gdprintk(XENLOG_ERR, \ + "xenoprof/x86 with autotranslated mode enabled" \ + "isn''t supported yet\n"); \ + } while (0) + #endif /* __ASM_XENOPROF_H__ */ /* diff -r 9bf71c7abb2d -r 996212ae7f05 xen/include/public/xenoprof.h --- a/xen/include/public/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/include/public/xenoprof.h Tue Nov 14 15:34:23 2006 +0900 @@ -87,7 +87,7 @@ struct xenoprof_get_buffer { int32_t max_samples; int32_t nbuf; int32_t bufsize; - uint64_t buf_maddr; + uint64_t buf_gmaddr; }; typedef struct xenoprof_get_buffer xenoprof_get_buffer_t; DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t); @@ -110,7 +110,7 @@ typedef struct xenoprof_passive { int32_t max_samples; int32_t nbuf; int32_t bufsize; - uint64_t buf_maddr; + uint64_t buf_gmaddr; } xenoprof_passive_t; DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t); diff -r 9bf71c7abb2d -r 996212ae7f05 xen/include/xen/xenoprof.h --- a/xen/include/xen/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/include/xen/xenoprof.h Tue Nov 14 15:34:23 2006 +0900 @@ -41,4 +41,8 @@ struct domain; struct domain; void free_xenoprof_pages(struct domain *d); +int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg); + +extern struct domain *xenoprof_primary_profiler; + #endif /* __XEN__XENOPROF_H__ */ -- yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-16 06:39 UTC
Re: [Xen-devel] [PATCH 5/5 TAKE 2] xenoprof: make xen xenoprof code arch-generic
I sent out my old patch. Sorry for confusion. # HG changeset patch # User yamahata@valinux.co.jp # Date 1163658590 -32400 # Node ID 2619990fdf3716dacd62f673d1259df26e717e57 # Parent 9bf71c7abb2de71ac233c24d821978ce2e6cc961 make xenoprof arch-generic with dynamic mapping/unmapping xenoprof buffer support and auto translated mode support. renamed xenoprof_get_buffer::buf_maddr, xenoprof_passive::buf_maddr to xenoprof_get_buffer::buf_gmaddr, xenoprof_passive::buf_gmaddr to support auto translated mode. With auto translated mode enabled, it is gmaddr, not maddr. PATCHNAME: make_xenoprof_of_xen_side_arch_generic Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> diff -r 9bf71c7abb2d -r 2619990fdf37 linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:22 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Thu Nov 16 15:29:50 2006 +0900 @@ -93,7 +93,7 @@ int xenoprof_arch_map_shared_buffer(stru if ( (ret = direct_kernel_remap_pfn_range( (unsigned long)area->addr, - get_buffer->buf_maddr >> PAGE_SHIFT, + get_buffer->buf_gmaddr >> PAGE_SHIFT, npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE), DOMID_SELF)) ) { vunmap(area->addr); @@ -127,7 +127,7 @@ int xenoprof_arch_set_passive(struct xen ret = direct_kernel_remap_pfn_range( (unsigned long)area->addr, - pdomain->buf_maddr >> PAGE_SHIFT, + pdomain->buf_gmaddr >> PAGE_SHIFT, npages * PAGE_SIZE, prot, DOMID_SELF); if (ret) { vunmap(area->addr); diff -r 9bf71c7abb2d -r 2619990fdf37 xen/arch/x86/oprofile/nmi_int.c --- a/xen/arch/x86/oprofile/nmi_int.c Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/arch/x86/oprofile/nmi_int.c Thu Nov 16 15:29:50 2006 +0900 @@ -33,7 +33,6 @@ static unsigned long saved_lvtpc[NR_CPUS #define VIRQ_BITMASK_SIZE (MAX_OPROF_DOMAINS/32 + 1) extern int active_domains[MAX_OPROF_DOMAINS]; extern unsigned int adomains; -extern struct domain *primary_profiler; extern struct domain *adomain_ptrs[MAX_OPROF_DOMAINS]; extern unsigned long virq_ovf_pending[VIRQ_BITMASK_SIZE]; extern int is_active(struct domain *d); @@ -337,10 +336,10 @@ int nmi_init(int *num_events, int *is_pr return -ENODEV; } - if (primary_profiler == NULL) { + if (xenoprof_primary_profiler == NULL) { /* For now, only dom0 can be the primary profiler */ if (current->domain->domain_id == 0) { - primary_profiler = current->domain; + xenoprof_primary_profiler = current->domain; prim = 1; } } diff -r 9bf71c7abb2d -r 2619990fdf37 xen/common/xenoprof.c --- a/xen/common/xenoprof.c Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/common/xenoprof.c Thu Nov 16 15:29:50 2006 +0900 @@ -2,15 +2,17 @@ * Copyright (C) 2005 Hewlett-Packard Co. * written by Aravind Menon & Jose Renato Santos * (email: xenoprof@groups.hp.com) + * + * arch generic xenoprof and IA64 support. + * dynamic map/unmap xenoprof buffer support. * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> * VA Linux Systems Japan K.K. - * arch generic xenoprof and IA64 support. */ #include <xen/guest_access.h> #include <xen/sched.h> #include <public/xenoprof.h> -#include <asm/hvm/support.h> +#include <asm/shadow.h> /* Limit amount of pages used for shared buffer (per domain) */ #define MAX_OPROF_SHARED_PAGES 32 @@ -26,7 +28,7 @@ unsigned int pdomains; unsigned int pdomains; unsigned int activated; -struct domain *primary_profiler; +struct domain *xenoprof_primary_profiler; int xenoprof_state = XENOPROF_IDLE; u64 total_samples; @@ -90,10 +92,58 @@ static void xenoprof_reset_buf(struct do } } +static int +share_xenoprof_page_with_guest(struct domain* d, unsigned long mfn, int npages) +{ + int i; + + /* Share pages so that kernel can map it */ + for (i = 0; i < npages; i++) { + struct page_info* page = mfn_to_page(mfn + i); + if ((page->count_info & (PGC_allocated|PGC_count_mask)) != 0) { + gdprintk(XENLOG_INFO, "%s: mfn 0x%lx page->count_info 0x%x\n", + __func__, mfn + i, page->count_info); + return -EBUSY; + } + page->count_info = 0; + page_set_owner(page, NULL); + } + + for (i = 0; i < npages; i++) + share_xen_page_with_guest(mfn_to_page(mfn + i), d, XENSHARE_writable); + return 0; +} + +static void +unshare_xenoprof_page_with_guest(unsigned long mfn, int npages) +{ + int i; + + for (i = 0; i < npages; i++) { + struct page_info* page = mfn_to_page(mfn + i); + BUG_ON(page_get_owner(page) != current->domain); + if (test_and_clear_bit(_PGC_allocated, &page->count_info)) + put_page(page); + } +} + +static void +xenoprof_shared_gmfn_with_guest(struct domain* d, + unsigned long maddr, unsigned long gmaddr, + int npages) +{ + int i; + + for (i = 0; i < npages; i++, maddr += PAGE_SIZE, gmaddr += PAGE_SIZE) { + BUG_ON(page_get_owner(maddr_to_page(maddr)) != d); + xenoprof_shared_gmfn(d, gmaddr, maddr); + } +} + static char *alloc_xenoprof_buf(struct domain *d, int npages) { char *rawbuf; - int i, order; + int order; /* allocate pages to store sample buffer shared with domain */ order = get_order_from_pages(npages); @@ -103,12 +153,6 @@ static char *alloc_xenoprof_buf(struct d 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; } @@ -269,6 +313,7 @@ static void reset_passive(struct domain if ( x == NULL ) return; + unshare_xenoprof_page_with_guest(virt_to_mfn(x->rawbuf), x->npages); x->domain_type = XENOPROF_DOMAIN_IGNORED; return; @@ -344,10 +389,20 @@ static int add_passive_list(XEN_GUEST_HA return -ENOMEM; } + ret = share_xenoprof_page_with_guest(current->domain, + virt_to_mfn(d->xenoprof->rawbuf), d->xenoprof->npages); + if (ret) { + put_domain(d); + return ret; + } + 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 (!shadow_mode_translate(d)) + passive.buf_gmaddr = __pa(d->xenoprof->rawbuf); + else + xenoprof_shared_gmfn_with_guest(current->domain, __pa(d->xenoprof->rawbuf), passive.buf_gmaddr, d->xenoprof->npages); if ( copy_to_guest(arg, &passive, 1) ) { put_domain(d); @@ -446,7 +501,7 @@ static int xenoprof_op_init(XEN_GUEST_HA return -EFAULT; if ( xenoprof_init.is_primary ) - primary_profiler = current->domain; + xenoprof_primary_profiler = current->domain; return 0; } @@ -468,18 +523,28 @@ static int xenoprof_op_get_buffer(XEN_GU ((ret = alloc_xenoprof_struct(d, xenoprof_get_buffer.max_samples, 0)) < 0) ) return ret; + ret = share_xenoprof_page_with_guest(d, virt_to_mfn(d->xenoprof->rawbuf), + d->xenoprof->npages); + if (ret) + return ret; + xenoprof_reset_buf(d); d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; d->xenoprof->domain_ready = 0; - if ( primary_profiler == current->domain ) + if ( xenoprof_primary_profiler == current->domain ) 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 (!shadow_mode_translate(d)) + xenoprof_get_buffer.buf_gmaddr = __pa(d->xenoprof->rawbuf); + else + xenoprof_shared_gmfn_with_guest(d, __pa(d->xenoprof->rawbuf), + xenoprof_get_buffer.buf_gmaddr, + d->xenoprof->npages); if ( copy_to_guest(arg, &xenoprof_get_buffer, 1) ) return -EFAULT; @@ -503,7 +568,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN return -EINVAL; } - if ( !NONPRIV_OP(op) && (current->domain != primary_profiler) ) + if ( !NONPRIV_OP(op) && (current->domain != xenoprof_primary_profiler) ) { printk("xenoprof: dom %d denied privileged operation %d\n", current->domain->domain_id, op); @@ -589,7 +654,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN case XENOPROF_enable_virq: { int i; - if ( current->domain == primary_profiler ) + if ( current->domain == xenoprof_primary_profiler ) { xenoprof_arch_enable_virq(); xenoprof_reset_stat(); @@ -622,14 +687,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN break; case XENOPROF_disable_virq: + { + struct xenoprof *x = current->domain->xenoprof; if ( (xenoprof_state == XENOPROF_PROFILING) && (is_active(current->domain)) ) { ret = -EPERM; break; } ret = reset_active(current->domain); - break; - + if (ret) + break; + x = current->domain->xenoprof; /*reset_active() guarantees x != NULL*/ + unshare_xenoprof_page_with_guest(virt_to_mfn(x->rawbuf), x->npages); + break; + } case XENOPROF_release_counters: ret = -EPERM; if ( (xenoprof_state == XENOPROF_COUNTERS_RESERVED) || @@ -649,7 +720,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN { activated = 0; adomains=0; - primary_profiler = NULL; + xenoprof_primary_profiler = NULL; ret = 0; } break; diff -r 9bf71c7abb2d -r 2619990fdf37 xen/include/asm-x86/xenoprof.h --- a/xen/include/asm-x86/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/include/asm-x86/xenoprof.h Thu Nov 16 15:29:50 2006 +0900 @@ -45,6 +45,17 @@ void nmi_release_counters(void); int xenoprof_arch_counter(XEN_GUEST_HANDLE(void) arg); +struct vcpu; +struct cpu_user_regs; +int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs); +#define xenoprof_shared_gmfn(d, gmaddr, maddr) \ + do { \ + (void)(maddr); \ + gdprintk(XENLOG_ERR, \ + "xenoprof/x86 with autotranslated mode enabled" \ + "isn''t supported yet\n"); \ + } while (0) + #endif /* __ASM_XENOPROF_H__ */ /* diff -r 9bf71c7abb2d -r 2619990fdf37 xen/include/public/xenoprof.h --- a/xen/include/public/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/include/public/xenoprof.h Thu Nov 16 15:29:50 2006 +0900 @@ -87,7 +87,7 @@ struct xenoprof_get_buffer { int32_t max_samples; int32_t nbuf; int32_t bufsize; - uint64_t buf_maddr; + uint64_t buf_gmaddr; }; typedef struct xenoprof_get_buffer xenoprof_get_buffer_t; DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t); @@ -110,7 +110,7 @@ typedef struct xenoprof_passive { int32_t max_samples; int32_t nbuf; int32_t bufsize; - uint64_t buf_maddr; + uint64_t buf_gmaddr; } xenoprof_passive_t; DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t); diff -r 9bf71c7abb2d -r 2619990fdf37 xen/include/xen/xenoprof.h --- a/xen/include/xen/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/xen/include/xen/xenoprof.h Thu Nov 16 15:29:50 2006 +0900 @@ -41,4 +41,8 @@ struct domain; struct domain; void free_xenoprof_pages(struct domain *d); +int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg); + +extern struct domain *xenoprof_primary_profiler; + #endif /* __XEN__XENOPROF_H__ */ -- yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Santos, Jose Renato G
2006-Nov-17 19:26 UTC
RE: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split xen x86 xenoprof code
> -----Original Message----- > From: Isaku Yamahata [mailto:yamahata@valinux.co.jp] > Sent: Wednesday, November 15, 2006 9:54 PM > To: Santos, Jose Renato G > Cc: Keir Fraser; xen-devel@lists.xensource.com; > xen-ia64-devel@lists.xensource.com > Subject: Re: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split > xen x86 xenoprof code > > On Wed, Nov 15, 2006 at 09:58:40PM -0600, Santos, Jose Renato G wrote: > > > Mostly, the patches look good. > > I have a few questions though , mostly for clarification > > Thank you for your review. > > > > QUESTIONS for Isaku: > > > > patch 4/5: > > =========> > > > > +struct xenoprof_shared_buffer { > > > + char *buffer; > > > + struct xenoprof_arch_shared_buffer arch; > > > +}; > > > > The arch field has no extra info for x86. Why do you need this? > > On IA64 it is defined as > struct xenoprof_arch_shared_buffer { > struct resource* res; > }; > > On IA64, auto translated mode feature is enabled. > It means that page mapping from xen is based on pseudo > physical address, not virtual address. Pseudo physical > address used to map pages must be recorded somewhere in order > to unmap. > I guess, if xenoprof/x86 supported auto translated guest mode > something similar structure would be necessary. > >Isaku I am still not convinced that we need this. Since this in the kernel you can always get the pseudo physical address from the virtual address, right? Am I missing something? I applied your patches to changeset 12446 but they are failing to compile. I have attached the make output below Could you please fix this and resend? Thanks Renato =================================================================================== CC [M] arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.o arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:45: error: array type has incomplete element type arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c: In function "unmap_passive_list": arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:242: warning: implicit declaration of function "xenoprof_arch_unmap_shared_buffer" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c: In function "map_xenoprof_buffer": arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:253: error: invalid use of undefined type "struct xenoprof_shared_buffer" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:257: warning: implicit declaration of function "xenoprof_arch_map_shared_buffer" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:264: error: invalid use of undefined type "struct xenoprof_shared_buffer" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c: In function "xenoprof_setup": arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:300: warning: implicit declaration of function "xenoprof_arch_counter" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c: In function "xenoprof_start": arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:345: warning: implicit declaration of function "xenoprof_arch_start" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c: In function "xenoprof_stop": arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:354: warning: implicit declaration of function "xenoprof_arch_stop" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c: In function "xenoprof_set_passive": arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:422: warning: implicit declaration of function "xenoprof_arch_set_passive" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c: At top level: arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:460: error: syntax error before "do" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:465: warning: type defaults to "int" in declaration of "ret" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:465: error: "init" undeclared here (not in a function) arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:465: error: initializer element is not constant arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:465: warning: data definition has no type or storage class arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:466: error: syntax error before "if" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:468: warning: type defaults to "int" in declaration of "xenoprof_is_primary" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:468: error: redefinition of "xenoprof_is_primary" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:51: error: previous definition of "xenoprof_is_primary" was here arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:468: warning: data definition has no type or storage class arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:471: warning: type defaults to "int" in declaration of "cpu_type" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:471: error: conflicting types for "cpu_type" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:59: error: previous declaration of "cpu_type" was here arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:471: error: invalid initializer arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:471: warning: data definition has no type or storage class arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:472: error: syntax error before "." token arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:472: warning: type defaults to "int" in declaration of "strncpy" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:472: warning: function declaration isn"t a prototype arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:472: error: conflicting types for "strncpy" include/asm/string.h:45: error: previous definition of "strncpy" was here arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:472: warning: data definition has no type or storage class arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:473: error: syntax error before "." token arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:475: warning: type defaults to "int" in declaration of "init_driverfs" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:475: warning: function declaration isn"t a prototype arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:475: warning: data definition has no type or storage class arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:476: warning: type defaults to "int" in declaration of "using_xenoprof" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:476: error: non-static declaration of "using_xenoprof" follows static declaration arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:458: error: previous declaration of "using_xenoprof" was here arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:476: warning: data definition has no type or storage class arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:477: warning: type defaults to "int" in declaration of "ops" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:477: error: incompatible types in initialization arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:477: warning: data definition has no type or storage class arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:479: error: syntax error before "for" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:482: warning: type defaults to "int" in declaration of "active_defined" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:482: error: non-static declaration of "active_defined" follows static declaration arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:52: error: previous declaration of "active_defined" was here arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:482: warning: data definition has no type or storage class arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:483: error: syntax error before "}" token arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:484: error: syntax error before string constant arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:485: warning: type defaults to "int" in declaration of "printk" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:485: warning: function declaration isn"t a prototype arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:485: error: conflicting types for "printk" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:485: note: a parameter list with an ellipsis can''t match an empty parameter name list declaration include/linux/kernel.h:134: error: previous declaration of "printk" was here arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:485: warning: data definition has no type or storage class arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:490:27: error: macro "xenoprofile_exit" passed 1 arguments, but takes just 0 arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:491: error: syntax error before "{" token arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:495: error: syntax error before "&" token arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:495: warning: type defaults to "int" in declaration of "xenoprof_arch_unmap_shared_buffer" arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:495: warning: function declaration isn''t a prototype arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:495: warning: data definition has no type or storage class arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.c:498: error: syntax error before numeric constant {standard input}: Assembler messages: {standard input}:72: Error: symbol `xenoprof_is_primary'' is already defined make[4]: *** [arch/i386/oprofile/../../../drivers/xen/xenoprof/xenoprofile.o] Error 1 make[3]: *** [arch/i386/oprofile] Error 2 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-18 02:46 UTC
Re: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split xen x86 xenoprof code
On Fri, Nov 17, 2006 at 01:26:04PM -0600, Santos, Jose Renato G wrote:> > > QUESTIONS for Isaku: > > > > > > patch 4/5: > > > =========> > > > > > > +struct xenoprof_shared_buffer { > > > > + char *buffer; > > > > + struct xenoprof_arch_shared_buffer arch; > > > > +}; > > > > > > The arch field has no extra info for x86. Why do you need this? > > > > On IA64 it is defined as > > struct xenoprof_arch_shared_buffer { > > struct resource* res; > > }; > > > > On IA64, auto translated mode feature is enabled. > > It means that page mapping from xen is based on pseudo > > physical address, not virtual address. Pseudo physical > > address used to map pages must be recorded somewhere in order > > to unmap. > > I guess, if xenoprof/x86 supported auto translated guest mode > > something similar structure would be necessary. > > > > > Isaku > > I am still not convinced that we need this. Since this in the kernel > you can always get the pseudo physical address from the virtual address, > right? Am I missing something?Yes, the pseudo physical address itself can be get. The point is that the pseudo physical addresses aren''t always backed by struct page. In such a case alloc_pages()/free_pages() can''t be used, another structure is necessary. In fact Xen/IA64 allocates the pseudo physical address resion by allocate_resource(&iomem_resource, ...). Not by alloc_pages(). Why doesn''t Xen/IA64 use alloc_pages()? Because it is also used for grant table foreign domain page mapping and its size is very large sometimes. Using alloc_pages() results in OOM. Xen/PPC seems to adopt another approach, though.> I applied your patches to changeset 12446 but they are failing to > compile. I have attached the make output below > > Could you please fix this and resend?Sorry for that. It should compile with CONFIG_PROFILING=y and CONFIG_OPORIFLE=y. Anyway I''ll fix and resend. -- yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-18 04:21 UTC
Re: [Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make linux xenoprof code arch-generic
make xenoprof of linux side arch generic with some bug fixes. Changes: - support modular oprofile - move xenoprof_is_primary from xenoprofile.c. It is referenced by perfmon which isn''t module even when xenoprof is module. # HG changeset patch # User yamahata@valinux.co.jp # Date 1163822321 -32400 # Node ID 5bc23b56ed059dbee77d63d191ad355f7135f9be # Parent 70b1700b6c5ad28ec24a1cb37f4a3afc44347bad make xenoprof of linux side arch generic with some bug fixes. PATCHNAME: make_xenoprof_of_linux_side_arch_generic Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> diff -r 70b1700b6c5a -r 5bc23b56ed05 linux-2.6-xen-sparse/arch/i386/oprofile/Makefile --- a/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile Sat Nov 18 12:58:41 2006 +0900 @@ -8,7 +8,7 @@ DRIVER_OBJS = $(addprefix ../../../drive ifdef CONFIG_XEN XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \ - xenoprofile.o) + xenoprofile.o xenoprof_is_primary.o) oprofile-y := $(DRIVER_OBJS) \ $(XENOPROF_COMMON_OBJS) xenoprof.o else diff -r 70b1700b6c5a -r 5bc23b56ed05 linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c Sat Nov 18 12:58:41 2006 +0900 @@ -15,12 +15,130 @@ * VA Linux Systems Japan K.K. */ +#include <linux/init.h> #include <linux/oprofile.h> +#include <linux/sched.h> +#include <asm/pgtable.h> +#include <xen/driver_util.h> +#include <xen/interface/xen.h> +#include <xen/interface/xenoprof.h> #include <xen/xenoprof.h> #include "op_counter.h" -unsigned int num_events = 0; +static unsigned int num_events = 0; + +void __init xenoprof_arch_init_counter(struct xenoprof_init *init) +{ + num_events = init->num_events; + /* just in case - make sure we do not overflow event list + (i.e. counter_config list) */ + if (num_events > OP_MAX_COUNTER) { + num_events = OP_MAX_COUNTER; + init->num_events = num_events; + } +} + +void xenoprof_arch_counter(void) +{ + int i; + struct xenoprof_counter counter; + + for (i=0; i<num_events; i++) { + counter.ind = i; + counter.count = (uint64_t)counter_config[i].count; + counter.enabled = (uint32_t)counter_config[i].enabled; + counter.event = (uint32_t)counter_config[i].event; + counter.kernel = (uint32_t)counter_config[i].kernel; + counter.user = (uint32_t)counter_config[i].user; + counter.unit_mask = (uint64_t)counter_config[i].unit_mask; + HYPERVISOR_xenoprof_op(XENOPROF_counter, + &counter); + } +} + +void xenoprof_arch_start(void) +{ + /* nothing */ +} + +void xenoprof_arch_stop(void) +{ + /* nothing */ +} + +void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer * sbuf) +{ + if (sbuf->buffer) { + vunmap(sbuf->buffer); + sbuf->buffer = NULL; + } +} + +int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer * get_buffer, + struct xenoprof_shared_buffer * sbuf) +{ + int npages, ret; + struct vm_struct *area; + + sbuf->buffer = NULL; + if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, get_buffer)) ) + return ret; + + npages = (get_buffer->bufsize * get_buffer->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; + } + + sbuf->buffer = area->addr; + return ret; +} + +int xenoprof_arch_set_passive(struct xenoprof_passive * pdomain, + struct xenoprof_shared_buffer * sbuf) +{ + int ret; + int npages; + struct vm_struct *area; + pgprot_t prot = __pgprot(_KERNPG_TABLE); + + sbuf->buffer = NULL; + ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive, pdomain); + if (ret) + goto out; + + npages = (pdomain->bufsize * pdomain->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, + pdomain->buf_maddr >> PAGE_SHIFT, + npages * PAGE_SIZE, prot, DOMID_SELF); + if (ret) { + vunmap(area->addr); + goto out; + } + sbuf->buffer = area->addr; + +out: + return ret; +} + struct op_counter_config counter_config[OP_MAX_COUNTER]; int xenoprof_create_files(struct super_block * sb, struct dentry * root) @@ -49,3 +167,13 @@ int xenoprof_create_files(struct super_b return 0; } + +int __init oprofile_arch_init(struct oprofile_operations * ops) +{ + return xenoprofile_init(ops); +} + +void oprofile_arch_exit(void) +{ + xenoprofile_exit(); +} diff -r 70b1700b6c5a -r 5bc23b56ed05 linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile --- a/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile Sat Nov 18 12:58:41 2006 +0900 @@ -13,7 +13,7 @@ DRIVER_OBJS = $(addprefix ../../../drive ifdef CONFIG_XEN XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \ - xenoprofile.o) + xenoprofile.o xenoprof_is_primary.o) OPROFILE-y := xenoprof.o else OPROFILE-y := init.o backtrace.o diff -r 70b1700b6c5a -r 5bc23b56ed05 linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprof_is_primary.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprof_is_primary.c Sat Nov 18 12:58:41 2006 +0900 @@ -0,0 +1,22 @@ +/** + * @file xenoprof_is_primary.c + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon <levon@movementarian.org> + * + * Modified by Aravind Menon and Jose Renato Santos for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. + * + * Separated out arch-generic part + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + */ + +#include <linux/init.h> +#include <linux/module.h> + +int xenoprof_is_primary = 0; +EXPORT_SYMBOL_GPL(xenoprof_is_primary); diff -r 70b1700b6c5a -r 5bc23b56ed05 linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c --- a/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c Sat Nov 18 12:58:41 2006 +0900 @@ -1,5 +1,5 @@ /** - * @file xenoprof.c + * @file xenoprofile.c * * @remark Copyright 2002 OProfile authors * @remark Read the file COPYING @@ -23,14 +23,9 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/vmalloc.h> -#include <asm/nmi.h> -#include <asm/msr.h> -#include <asm/apic.h> #include <asm/pgtable.h> #include <xen/evtchn.h> #include <xen/xenoprof.h> -#include "../../../arch/i386/oprofile/op_counter.h" - #include <xen/driver_util.h> #include <xen/interface/xen.h> #include <xen/interface/xenoprof.h> @@ -39,18 +34,22 @@ #define MAX_XENOPROF_SAMPLES 16 -static int xenoprof_start(void); -static void xenoprof_stop(void); - -static int xenoprof_enabled = 0; -extern unsigned int num_events; -static int is_primary = 0; -static int active_defined; - /* sample buffers shared with Xen */ xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS]; /* Shared buffer area */ -char * shared_buffer = NULL; +struct xenoprof_shared_buffer shared_buffer; + +/* Passive sample buffers shared with Xen */ +xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS]; +/* Passive shared buffer area */ +struct xenoprof_shared_buffer p_shared_buffer[MAX_OPROF_DOMAINS]; + +static int xenoprof_start(void); +static void xenoprof_stop(void); + +static int xenoprof_enabled = 0; +static int active_defined; + /* Number of buffers in shared area (one per VCPU) */ int nbuf; /* Mappings of VIRQ_XENOPROF to irq number (per cpu) */ @@ -58,11 +57,6 @@ 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) @@ -103,7 +97,7 @@ static int __init init_driverfs(void) } -static void __exit exit_driverfs(void) +static void exit_driverfs(void) { sysdev_unregister(&device_oprofile); sysdev_class_unregister(&oprofile_sysclass); @@ -193,7 +187,7 @@ xenoprof_ovf_interrupt(int irq, void * d xenoprof_add_pc(buf, 0); - if (is_primary && !test_and_set_bit(0, &flag)) { + if (xenoprof_is_primary && !test_and_set_bit(0, &flag)) { xenoprof_handle_passive(); smp_mb__before_clear_bit(); clear_bit(0, &flag); @@ -207,7 +201,7 @@ static void unbind_virq(void) { int i; - for_each_cpu(i) { + for_each_online_cpu(i) { if (ovf_irq[i] >= 0) { unbind_from_irqhandler(ovf_irq[i], NULL); ovf_irq[i] = -1; @@ -220,7 +214,7 @@ static int bind_virq(void) { int i, result; - for_each_cpu(i) { + for_each_online_cpu(i) { result = bind_virq_to_irqhandler(VIRQ_XENOPROF, i, xenoprof_ovf_interrupt, @@ -240,40 +234,33 @@ static int bind_virq(void) } +static void unmap_passive_list(void) +{ + int i; + for (i = 0; i < pdomains; i++) + xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]); + pdomains = 0; +} + + 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 ) + int ret, i; + + if ( shared_buffer.buffer ) return 0; get_buffer.max_samples = max_samples; - - if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, &get_buffer)) ) - return ret; - + ret = xenoprof_arch_map_shared_buffer(&get_buffer, &shared_buffer); + if (ret) + 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]; + &shared_buffer.buffer[i * get_buffer.bufsize]; BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS); xenoprof_buf[buf->vcpu_id] = buf; } @@ -285,7 +272,6 @@ static int xenoprof_setup(void) static int xenoprof_setup(void) { int ret; - int i; if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) ) return ret; @@ -293,9 +279,7 @@ static int xenoprof_setup(void) if ( (ret = bind_virq()) ) return ret; - if (is_primary) { - struct xenoprof_counter counter; - + if (xenoprof_is_primary) { /* Define dom0 as an active domain if not done yet */ if (!active_defined) { domid_t domid; @@ -312,17 +296,7 @@ static int xenoprof_setup(void) ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL); if (ret) goto err; - for (i=0; i<num_events; i++) { - counter.ind = i; - counter.count = (uint64_t)counter_config[i].count; - counter.enabled = (uint32_t)counter_config[i].enabled; - counter.event = (uint32_t)counter_config[i].event; - counter.kernel = (uint32_t)counter_config[i].kernel; - counter.user = (uint32_t)counter_config[i].user; - counter.unit_mask = (uint64_t)counter_config[i].unit_mask; - HYPERVISOR_xenoprof_op(XENOPROF_counter, - &counter); - } + xenoprof_arch_counter(); ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL); if (ret) @@ -347,13 +321,16 @@ static void xenoprof_shutdown(void) HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL); - if (is_primary) { + if (xenoprof_is_primary) { HYPERVISOR_xenoprof_op(XENOPROF_release_counters, NULL); active_defined = 0; } unbind_virq(); + xenoprof_arch_unmap_shared_buffer(&shared_buffer); + if (xenoprof_is_primary) + unmap_passive_list(); } @@ -361,17 +338,19 @@ static int xenoprof_start(void) { int ret = 0; - if (is_primary) + if (xenoprof_is_primary) ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL); - + if (!ret) + xenoprof_arch_start(); return ret; } static void xenoprof_stop(void) { - if (is_primary) + if (xenoprof_is_primary) HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL); + xenoprof_arch_stop(); } @@ -383,7 +362,7 @@ static int xenoprof_set_active(int * act int set_dom0 = 0; domid_t domid; - if (!is_primary) + if (!xenoprof_is_primary) return 0; if (adomains > MAX_OPROF_DOMAINS) @@ -423,12 +402,9 @@ static int xenoprof_set_passive(int * p_ { int ret; int i, j; - int npages; struct xenoprof_buf *buf; - struct vm_struct *area; - pgprot_t prot = __pgprot(_KERNPG_TABLE); - - if (!is_primary) + + if (!xenoprof_is_primary) return 0; if (pdoms > MAX_OPROF_DOMAINS) @@ -437,57 +413,37 @@ static int xenoprof_set_passive(int * p_ ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL); if (ret) return ret; + unmap_passive_list(); 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]); + ret = xenoprof_arch_set_passive(&passive_domains[i], + &p_shared_buffer[i]); if (ret) goto out; - - npages = (passive_domains[i].bufsize * passive_domains[i].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, - passive_domains[i].buf_maddr >> PAGE_SHIFT, - npages * PAGE_SIZE, prot, DOMID_SELF); - if (ret) { - vunmap(area->addr); - goto out; - } - - p_shared_buffer[i] = area->addr; - for (j = 0; j < passive_domains[i].nbuf; j++) { buf = (struct xenoprof_buf *) - &p_shared_buffer[i][j * passive_domains[i].bufsize]; + &p_shared_buffer[i].buffer[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; - } + for (j = 0; j < i; j++) + xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]); return ret; } struct oprofile_operations xenoprof_ops = { +#ifdef HAVE_XENOPROF_CREATE_FILES .create_files = xenoprof_create_files, +#endif .set_active = xenoprof_set_active, .set_passive = xenoprof_set_passive, .setup = xenoprof_setup, @@ -500,21 +456,15 @@ struct oprofile_operations xenoprof_ops /* in order to get driverfs right */ static int using_xenoprof; -int __init oprofile_arch_init(struct oprofile_operations * ops) +int __init xenoprofile_init(struct oprofile_operations * ops) { struct xenoprof_init init; int ret, i; ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init); - if (!ret) { - num_events = init.num_events; - is_primary = init.is_primary; - - /* just in case - make sure we do not overflow event list - (i.e. counter_config list) */ - if (num_events > OP_MAX_COUNTER) - num_events = OP_MAX_COUNTER; + xenoprof_arch_init_counter(&init); + xenoprof_is_primary = init.is_primary; /* cpu_type is detected by Xen */ cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0; @@ -530,30 +480,20 @@ int __init oprofile_arch_init(struct opr active_defined = 0; } - printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, " - "is_primary %d\n", ret, num_events, is_primary); + printk(KERN_INFO "%s: ret %d, events %d, xenoprof_is_primary %d\n", + __func__, ret, init.num_events, xenoprof_is_primary); return ret; } -void __exit oprofile_arch_exit(void) -{ - int i; - +void xenoprofile_exit(void) +{ if (using_xenoprof) exit_driverfs(); - if (shared_buffer) { - vunmap(shared_buffer); - shared_buffer = NULL; - } - if (is_primary) { - for (i = 0; i < pdomains; i++) - if (p_shared_buffer[i]) { - vunmap(p_shared_buffer[i]); - p_shared_buffer[i] = NULL; - } + xenoprof_arch_unmap_shared_buffer(&shared_buffer); + if (xenoprof_is_primary) { + unmap_passive_list(); HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL); } - -} +} diff -r 70b1700b6c5a -r 5bc23b56ed05 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h Sat Nov 18 12:58:41 2006 +0900 @@ -21,11 +21,28 @@ */ #ifndef __ASM_XENOPROF_H__ #define __ASM_XENOPROF_H__ -#ifdef CONFIG_OPROFILE +#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE) struct super_block; struct dentry; int xenoprof_create_files(struct super_block * sb, struct dentry * root); +#define HAVE_XENOPROF_CREATE_FILES -#endif /* CONFIG_OPROFILE */ +struct xenoprof_init; +void xenoprof_arch_init_counter(struct xenoprof_init *init); +void xenoprof_arch_counter(void); +void xenoprof_arch_start(void); +void xenoprof_arch_stop(void); + +struct xenoprof_arch_shared_buffer { + /* nothing */ +}; +struct xenoprof_shared_buffer; +void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer* sbuf); +struct xenoprof_get_buffer; +int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer* get_buffer, struct xenoprof_shared_buffer* sbuf); +struct xenoprof_passive; +int xenoprof_arch_set_passive(struct xenoprof_passive* pdomain, struct xenoprof_shared_buffer* sbuf); + +#endif /* CONFIG_OPROFILE || CONFIG_OPROFILE_MODULE */ #endif /* __ASM_XENOPROF_H__ */ diff -r 70b1700b6c5a -r 5bc23b56ed05 linux-2.6-xen-sparse/include/xen/xenoprof.h --- a/linux-2.6-xen-sparse/include/xen/xenoprof.h Tue Nov 14 15:34:21 2006 +0900 +++ b/linux-2.6-xen-sparse/include/xen/xenoprof.h Sat Nov 18 12:58:41 2006 +0900 @@ -22,9 +22,24 @@ #ifndef __XEN_XENOPROF_H__ #define __XEN_XENOPROF_H__ -#ifdef CONFIG_OPROFILE +#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE) #include <asm/xenoprof.h> -#endif /* CONFIG_OPROFILE */ +struct oprofile_operations; +int xenoprofile_init(struct oprofile_operations * ops); +void xenoprofile_exit(void); + +extern int xenoprof_is_primary; +#define is_xenoprof_primary() (xenoprof_is_primary) +struct xenoprof_shared_buffer { + char *buffer; + struct xenoprof_arch_shared_buffer arch; +}; +#else +#define xenoprofile_init(ops) do { } while (0) +#define xenoprofile_exit() do { } while (0) +#define is_xenoprof_primary() (0) +#endif /* CONFIG_OPROFILE || CONFIG_OPORFILE_MODULE */ + #endif /* __XEN_XENOPROF_H__ */ -- yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Santos, Jose Renato G
2006-Nov-20 18:38 UTC
RE: [Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make linux xenoprof codearch-generic
> -----Original Message----- > From: xen-devel-bounces@lists.xensource.com > [mailto:xen-devel-bounces@lists.xensource.com] On Behalf Of > Isaku Yamahata > Sent: Friday, November 17, 2006 8:22 PM > To: xen-devel@lists.xensource.com > Cc: xen-ia64-devel@lists.xensource.com > Subject: Re: [Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make > linux xenoprof codearch-generic > > > make xenoprof of linux side arch generic with some bug fixes. > > Changes: > - support modular oprofile > - move xenoprof_is_primary from xenoprofile.c. > It is referenced by perfmon which isn''t module even when xenoprof > is module. >Why perfmon needs to access Oprofile? It should be the other way around ... It seems that the only change was to create a new file named xenoprof_is_primary.c to hold the definition of xenoprof_is_primary I don''t like this. And I don''t understand why you need this. You should deal with IA64 specifics in arch specific code as much as possible. Could you please find an IA64 specific solution or explain why this is needed in the generic part? Also, if sending another patch please send me only the changes from the initial 5 patches you sent me. I would like to see only the changes ... (do not use this last patch as reference, I am ignoring it) Thanks Renato _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Santos, Jose Renato G
2006-Nov-20 19:17 UTC
RE: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split xen x86 xenoprof code
> -----Original Message----- > From: Isaku Yamahata [mailto:yamahata@valinux.co.jp] > Sent: Friday, November 17, 2006 6:47 PM > To: Santos, Jose Renato G > Cc: xen-devel@lists.xensource.com; xen-ia64-devel@lists.xensource.com > Subject: Re: [Xen-devel] [PATCH 1/5 TAKE 2] xenoprof: split > xen x86 xenoprof code > > On Fri, Nov 17, 2006 at 01:26:04PM -0600, Santos, Jose Renato G wrote: > > > > > QUESTIONS for Isaku: > > > > > > > > patch 4/5: > > > > =========> > > > > > > > > +struct xenoprof_shared_buffer { > > > > > + char *buffer; > > > > > + struct xenoprof_arch_shared_buffer arch; > > > > > +}; > > > > > > > > The arch field has no extra info for x86. Why do you need this? > > > > > > On IA64 it is defined as > > > struct xenoprof_arch_shared_buffer { > > > struct resource* res; > > > }; > > > > > > On IA64, auto translated mode feature is enabled. > > > It means that page mapping from xen is based on pseudo physical > > > address, not virtual address. Pseudo physical address used to map > > > pages must be recorded somewhere in order to unmap. > > > I guess, if xenoprof/x86 supported auto translated guest mode > > > something similar structure would be necessary. > > > > > > > > Isaku > > > > I am still not convinced that we need this. Since this in > the kernel > > you can always get the pseudo physical address from the > virtual address, > > right? Am I missing something? > > Yes, the pseudo physical address itself can be get. > The point is that the pseudo physical addresses aren''t always > backed by struct page. > In such a case alloc_pages()/free_pages() can''t be used, > another structure > is necessary. > In fact Xen/IA64 allocates the pseudo physical address resion by > allocate_resource(&iomem_resource, ...). Not by alloc_pages(). > Why doesn''t Xen/IA64 use alloc_pages()? > Because it is also used for grant table foreign domain page mapping > and its size is very large sometimes. Using alloc_pages() > results in OOM. > Xen/PPC seems to adopt another approach, though. >OK, I understand now. You want to keep the mem resource info and the buffer virtual address in the same struct which you pass to the arch specific code for mapping and unmapping xenoprof pages. I think that is fine. Regards Renato _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-21 05:47 UTC
Re: [Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make linux xenoprof codearch-generic
On Mon, Nov 20, 2006 at 12:38:51PM -0600, Santos, Jose Renato G wrote:> Why perfmon needs to access Oprofile? It should be the other way > around ... > It seems that the only change was to create a new file named > xenoprof_is_primary.c to hold the definition of xenoprof_is_primary > I don''t like this. And I don''t understand why you need this. You > should deal with IA64 specifics in arch specific code as much as > possible. Could you please find an IA64 specific solution or explain why > this is needed in the generic part?I found the way without referencing it so that I made it static.> Also, if sending another patch please send me only the changes from > the initial 5 patches you sent me. I would like to see only the changes > ... > (do not use this last patch as reference, I am ignoring it)Here is the patch to follow http://lists.xensource.com/archives/html/xen-devel/2006-11/msg00842.html. To make sure, I also attached the patch for PATCH 4/5 TAKE2 http://lists.xensource.com/archives/html/xen-devel/2006-11/msg00689.html thanks, # HG changeset patch # User yamahata@valinux.co.jp # Date 1164087772 -32400 # Node ID ab6c1b607484d3b273d091a11334a3458d36349c # Parent e8fba03edf517b88a91aee47afbc15ab89e5d434 update xenoprof linux side patch following Renato''s comment. - compilation fix when CONFIG_OPROFILE=m with minor clean up - don''t export xenoprof_is_primary. PATCHNAME: xenoprof_linux_side_update Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> diff -r e8fba03edf51 -r ab6c1b607484 linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c --- a/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c Tue Nov 14 15:34:22 2006 +0900 +++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c Tue Nov 21 14:42:52 2006 +0900 @@ -48,7 +48,7 @@ static void xenoprof_stop(void); static void xenoprof_stop(void); static int xenoprof_enabled = 0; -int xenoprof_is_primary = 0; +static int xenoprof_is_primary = 0; static int active_defined; /* Number of buffers in shared area (one per VCPU) */ diff -r e8fba03edf51 -r ab6c1b607484 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h Tue Nov 21 14:42:52 2006 +0900 @@ -21,7 +21,7 @@ */ #ifndef __ASM_XENOPROF_H__ #define __ASM_XENOPROF_H__ -#ifdef CONFIG_OPROFILE +#ifdef CONFIG_XEN struct super_block; struct dentry; @@ -44,5 +44,5 @@ struct xenoprof_passive; struct xenoprof_passive; int xenoprof_arch_set_passive(struct xenoprof_passive* pdomain, struct xenoprof_shared_buffer* sbuf); -#endif /* CONFIG_OPROFILE */ +#endif /* CONFIG_XEN */ #endif /* __ASM_XENOPROF_H__ */ diff -r e8fba03edf51 -r ab6c1b607484 linux-2.6-xen-sparse/include/xen/xenoprof.h --- a/linux-2.6-xen-sparse/include/xen/xenoprof.h Tue Nov 14 15:34:22 2006 +0900 +++ b/linux-2.6-xen-sparse/include/xen/xenoprof.h Tue Nov 21 14:42:52 2006 +0900 @@ -22,24 +22,21 @@ #ifndef __XEN_XENOPROF_H__ #define __XEN_XENOPROF_H__ +#ifdef CONFIG_XEN -#ifdef CONFIG_OPROFILE #include <asm/xenoprof.h> struct oprofile_operations; int xenoprofile_init(struct oprofile_operations * ops); void xenoprofile_exit(void); -extern int xenoprof_is_primary; -#define is_xenoprof_primary() (xenoprof_is_primary) struct xenoprof_shared_buffer { char *buffer; struct xenoprof_arch_shared_buffer arch; }; #else -#define xenoprofile_init(ops) do { } while (0) +#define xenoprofile_init(ops) (-ENOSYS) #define xenoprofile_exit() do { } while (0) -#define is_xenoprof_primary() (0) -#endif /* CONFIG_OPROFILE */ +#endif /* CONFIG_XEN */ #endif /* __XEN_XENOPROF_H__ */ -- yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Santos, Jose Renato G
2006-Nov-22 00:50 UTC
RE: [Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make linux xenoprofcodearch-generic
> -----Original Message----- > From: xen-devel-bounces@lists.xensource.com > [mailto:xen-devel-bounces@lists.xensource.com] On Behalf Of > Isaku Yamahata > Sent: Monday, November 20, 2006 9:48 PM > To: Santos, Jose Renato G > Cc: xen-devel@lists.xensource.com; xen-ia64-devel@lists.xensource.com > Subject: Re: [Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make > linux xenoprofcodearch-generic > > On Mon, Nov 20, 2006 at 12:38:51PM -0600, Santos, Jose Renato G wrote: > > > Why perfmon needs to access Oprofile? It should be the other way > > around ... > > It seems that the only change was to create a new file named > > xenoprof_is_primary.c to hold the definition of xenoprof_is_primary > > I don''t like this. And I don''t understand why you need this. You > > should deal with IA64 specifics in arch specific code as much as > > possible. Could you please find an IA64 specific solution > or explain > > why this is needed in the generic part? > > I found the way without referencing it so that I made it static. > >Good! I am happy with the patches now. I have tested your patches today on x86 32bit Xen and found no problem. I did not test on x86_64 but I do not forsee any problems. I am now able to profile the same domain in different modes (active and passive) during different profiling sessions, which was not possible before your patches. This is good! Thanks. Now, it is up to Keir to apply the patches or request any changes Thanks for providing this. Regards Renato> > Also, if sending another patch please send me only the > changes from > > the initial 5 patches you sent me. I would like to see only the > > changes ... > > (do not use this last patch as reference, I am ignoring it) > > Here is the patch to follow > http://lists.xensource.com/archives/html/xen-devel/2006-11/msg > 00842.html. > > To make sure, I also attached the patch for PATCH 4/5 TAKE2 > http://lists.xensource.com/archives/html/xen-devel/2006-11/msg > 00689.html > > thanks, > > > # HG changeset patch > # User yamahata@valinux.co.jp > # Date 1164087772 -32400 > # Node ID ab6c1b607484d3b273d091a11334a3458d36349c > # Parent e8fba03edf517b88a91aee47afbc15ab89e5d434 > update xenoprof linux side patch following Renato''s comment. > - compilation fix when CONFIG_OPROFILE=m with minor clean up > - don''t export xenoprof_is_primary. > PATCHNAME: xenoprof_linux_side_update > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> > > diff -r e8fba03edf51 -r ab6c1b607484 > linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c > --- a/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c > Tue Nov 14 15:34:22 2006 +0900 > +++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c > Tue Nov 21 14:42:52 2006 +0900 > @@ -48,7 +48,7 @@ static void xenoprof_stop(void); static > void xenoprof_stop(void); > > static int xenoprof_enabled = 0; > -int xenoprof_is_primary = 0; > +static int xenoprof_is_primary = 0; > static int active_defined; > > /* Number of buffers in shared area (one per VCPU) */ diff > -r e8fba03edf51 -r ab6c1b607484 > linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h > --- > a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xen > oprof.h Tue Nov 14 15:34:22 2006 +0900 > +++ > b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xen > oprof.h Tue Nov 21 14:42:52 2006 +0900 > @@ -21,7 +21,7 @@ > */ > #ifndef __ASM_XENOPROF_H__ > #define __ASM_XENOPROF_H__ > -#ifdef CONFIG_OPROFILE > +#ifdef CONFIG_XEN > > struct super_block; > struct dentry; > @@ -44,5 +44,5 @@ struct xenoprof_passive; struct > xenoprof_passive; int xenoprof_arch_set_passive(struct > xenoprof_passive* pdomain, struct xenoprof_shared_buffer* sbuf); > > -#endif /* CONFIG_OPROFILE */ > +#endif /* CONFIG_XEN */ > #endif /* __ASM_XENOPROF_H__ */ > diff -r e8fba03edf51 -r ab6c1b607484 > linux-2.6-xen-sparse/include/xen/xenoprof.h > --- a/linux-2.6-xen-sparse/include/xen/xenoprof.h Tue Nov > 14 15:34:22 2006 +0900 > +++ b/linux-2.6-xen-sparse/include/xen/xenoprof.h Tue Nov > 21 14:42:52 2006 +0900 > @@ -22,24 +22,21 @@ > > #ifndef __XEN_XENOPROF_H__ > #define __XEN_XENOPROF_H__ > +#ifdef CONFIG_XEN > > -#ifdef CONFIG_OPROFILE > #include <asm/xenoprof.h> > > struct oprofile_operations; > int xenoprofile_init(struct oprofile_operations * ops); > void xenoprofile_exit(void); > > -extern int xenoprof_is_primary; > -#define is_xenoprof_primary() (xenoprof_is_primary) > struct xenoprof_shared_buffer { > char *buffer; > struct xenoprof_arch_shared_buffer arch; > }; > #else > -#define xenoprofile_init(ops) do { } while (0) > +#define xenoprofile_init(ops) (-ENOSYS) > #define xenoprofile_exit() do { } while (0) > -#define is_xenoprof_primary() (0) > -#endif /* CONFIG_OPROFILE */ > > +#endif /* CONFIG_XEN */ > #endif /* __XEN_XENOPROF_H__ */ > > > -- > yamahata >_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2006-Nov-22 07:01 UTC
Re: [Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make linux xenoprofcodearch-generic
On 22/11/06 12:50 am, "Santos, Jose Renato G" <joserenato.santos@hp.com> wrote:> Good! I am happy with the patches now. > I have tested your patches today on x86 32bit Xen and found no > problem. > I did not test on x86_64 but I do not forsee any problems. > I am now able to profile the same domain in different modes (active > and passive) during different profiling sessions, which was not > possible before your patches. This is good! Thanks. > > Now, it is up to Keir to apply the patches or request any changesPlease re-send the patches as a single tarball. I''ve lost track of the consistent set. -- Keir _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-22 07:31 UTC
Re: [Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make linux xenoprofcodearch-generic
On Wed, Nov 22, 2006 at 07:01:31AM +0000, Keir Fraser wrote:> On 22/11/06 12:50 am, "Santos, Jose Renato G" <joserenato.santos@hp.com> > wrote: > > > Good! I am happy with the patches now. > > I have tested your patches today on x86 32bit Xen and found no > > problem. > > I did not test on x86_64 but I do not forsee any problems. > > I am now able to profile the same domain in different modes (active > > and passive) during different profiling sessions, which was not > > possible before your patches. This is good! Thanks. > > > > Now, it is up to Keir to apply the patches or request any changes > > Please re-send the patches as a single tarball. I''ve lost track of the > consistent set.Attached. Please find it. Thanks. -- yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Isaku Yamahata
2006-Nov-22 11:50 UTC
Re: [Xen-devel] [PATCH 4/5 TAKE 2] xenoprof: make linux xenoprofcodearch-generic
Accidentaly the attached patch was dropped. Please apply this too. On Wed, Nov 22, 2006 at 04:31:51PM +0900, Isaku Yamahata wrote:> On Wed, Nov 22, 2006 at 07:01:31AM +0000, Keir Fraser wrote: > > On 22/11/06 12:50 am, "Santos, Jose Renato G" <joserenato.santos@hp.com> > > wrote: > > > > > Good! I am happy with the patches now. > > > I have tested your patches today on x86 32bit Xen and found no > > > problem. > > > I did not test on x86_64 but I do not forsee any problems. > > > I am now able to profile the same domain in different modes (active > > > and passive) during different profiling sessions, which was not > > > possible before your patches. This is good! Thanks. > > > > > > Now, it is up to Keir to apply the patches or request any changes > > > > Please re-send the patches as a single tarball. I''ve lost track of the > > consistent set. > > Attached. Please find it. > Thanks. > > -- > yamahata> _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel-- yamahata _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel