# HG changeset patch # User yamahata@xxxxxxxxxxxxx # 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 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@xxxxxxxxxxxxx) + * + * arch generic xenoprof and IA64 support. + * dynamic map/unmap xenoprof buffer support. * Copyright (c) 2006 Isaku Yamahata * VA Linux Systems Japan K.K. - * arch generic xenoprof and IA64 support. */ #include #include #include -#include +#include /* 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__ */