# HG changeset patch
# User yamahata@xxxxxxxxxxxxx
# 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@xxxxxxxxxxxxx>
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@xxxxxxxxxxxxx)
+ *
+ * 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@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|