aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xentrace
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-01-20 20:33:35 +0000
committerKeir Fraser <keir.fraser@citrix.com>2010-01-20 20:33:35 +0000
commit650afa3995c32c50f3272dbe4514781abed8bdc0 (patch)
treefe5662f5a55bdc654d48b93c20bbf1514174764b /tools/xentrace
parent9e5e0eb8408c37b42411c6686c36eccd2426e7fd (diff)
downloadxen-650afa3995c32c50f3272dbe4514781abed8bdc0.tar.gz
xen-650afa3995c32c50f3272dbe4514781abed8bdc0.tar.bz2
xen-650afa3995c32c50f3272dbe4514781abed8bdc0.zip
xentrace: Per-cpu xentrace buffers
In the current xentrace configuration, xentrace buffers are all allocated in a single contiguous chunk, and then divided among logical cpus, one buffer per cpu. The size of an allocatable chunk is fairly limited, in my experience about 128 pages (512KiB). As the number of logical cores increase, this means a much smaller maximum per-cpu trace buffer per cpu; on my dual-socket quad-core nehalem box with hyperthreading (16 logical cpus), that comes to 8 pages per logical cpu. This patch addresses this issue by allocating per-cpu buffers separately. Signed-off-by: George Dunlap <dunlapg@umich.edu>
Diffstat (limited to 'tools/xentrace')
-rw-r--r--tools/xentrace/xentrace.c133
1 files changed, 60 insertions, 73 deletions
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
index 2b5647e6fb..b6da08e38c 100644
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -61,6 +61,12 @@ typedef struct settings_st {
disable_tracing:1;
} settings_t;
+struct t_struct {
+ struct t_info *t_info; /* Structure with information about individual buffers */
+ struct t_buf **meta; /* Pointers to trace buffer metadata */
+ unsigned char **data; /* Pointers to trace buffer data areas */
+};
+
settings_t opts;
int interrupted = 0; /* gets set if we get a SIGHUP */
@@ -446,22 +452,61 @@ static void get_tbufs(unsigned long *mfn, unsigned long *size)
*
* Maps the Xen trace buffers them into process address space.
*/
-static struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
- unsigned long size)
+static struct t_struct *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
+ unsigned long tinfo_size)
{
- struct t_buf *tbufs_mapped;
+ static struct t_struct tbufs = { 0 };
+ int i;
- tbufs_mapped = xc_map_foreign_range(xc_handle, DOMID_XEN,
- size * num, PROT_READ | PROT_WRITE,
+ /* Map t_info metadata structure */
+ tbufs.t_info = xc_map_foreign_range(xc_handle, DOMID_XEN,
+ tinfo_size, PROT_READ | PROT_WRITE,
tbufs_mfn);
- if ( tbufs_mapped == 0 )
+ if ( tbufs.t_info == 0 )
{
PERROR("Failed to mmap trace buffers");
exit(EXIT_FAILURE);
}
- return tbufs_mapped;
+ if ( tbufs.t_info->tbuf_size == 0 )
+ {
+ fprintf(stderr, "%s: tbuf_size 0!\n", __func__);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Map per-cpu buffers */
+ tbufs.meta = (struct t_buf **)calloc(num, sizeof(struct t_buf *));
+ tbufs.data = (unsigned char **)calloc(num, sizeof(unsigned char *));
+ if ( tbufs.meta == NULL || tbufs.data == NULL )
+ {
+ PERROR( "Failed to allocate memory for buffer pointers\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for(i=0; i<num; i++)
+ {
+
+ uint32_t *mfn_list = ((uint32_t *)tbufs.t_info) + tbufs.t_info->mfn_offset[i];
+ int j;
+ xen_pfn_t pfn_list[tbufs.t_info->tbuf_size];
+
+ for ( j=0; j<tbufs.t_info->tbuf_size; j++)
+ pfn_list[j] = (xen_pfn_t)mfn_list[j];
+
+ tbufs.meta[i] = xc_map_foreign_batch(xc_handle, DOMID_XEN,
+ PROT_READ | PROT_WRITE,
+ pfn_list,
+ tbufs.t_info->tbuf_size);
+ if ( tbufs.meta[i] == NULL )
+ {
+ PERROR("Failed to map cpu buffer!");
+ exit(EXIT_FAILURE);
+ }
+ tbufs.data[i] = (unsigned char *)(tbufs.meta[i]+1);
+ }
+
+ return &tbufs;
}
/**
@@ -490,66 +535,6 @@ static void set_mask(uint32_t mask, int type)
}
/**
- * init_bufs_ptrs - initialises an array of pointers to the trace buffers
- * @bufs_mapped: the userspace address where the trace buffers are mapped
- * @num: number of trace buffers
- * @size: trace buffer size
- *
- * Initialises an array of pointers to individual trace buffers within the
- * mapped region containing all trace buffers.
- */
-static struct t_buf **init_bufs_ptrs(void *bufs_mapped, unsigned int num,
- unsigned long size)
-{
- int i;
- struct t_buf **user_ptrs;
-
- user_ptrs = (struct t_buf **)calloc(num, sizeof(struct t_buf *));
- if ( user_ptrs == NULL )
- {
- PERROR( "Failed to allocate memory for buffer pointers\n");
- exit(EXIT_FAILURE);
- }
-
- /* initialise pointers to the trace buffers - given the size of a trace
- * buffer and the value of bufs_maped, we can easily calculate these */
- for ( i = 0; i<num; i++ )
- user_ptrs[i] = (struct t_buf *)((unsigned long)bufs_mapped + size * i);
-
- return user_ptrs;
-}
-
-
-/**
- * init_rec_ptrs - initialises data area pointers to locations in user space
- * @tbufs_mfn: base mfn of the trace buffer area
- * @tbufs_mapped: user virtual address of base of trace buffer area
- * @meta: array of user-space pointers to struct t_buf's of metadata
- * @num: number of trace buffers
- *
- * Initialises data area pointers to the locations that data areas have been
- * mapped in user space. Note that the trace buffer metadata contains machine
- * pointers - the array returned allows more convenient access to them.
- */
-static unsigned char **init_rec_ptrs(struct t_buf **meta, unsigned int num)
-{
- int i;
- unsigned char **data;
-
- data = calloc(num, sizeof(unsigned char *));
- if ( data == NULL )
- {
- PERROR("Failed to allocate memory for data pointers\n");
- exit(EXIT_FAILURE);
- }
-
- for ( i = 0; i < num; i++ )
- data[i] = (unsigned char *)(meta[i] + 1);
-
- return data;
-}
-
-/**
* get_num_cpus - get the number of logical CPUs
*/
static unsigned int get_num_cpus(void)
@@ -638,12 +623,13 @@ static int monitor_tbufs(void)
{
int i;
- void *tbufs_mapped; /* pointer to where the tbufs are mapped */
+ struct t_struct *tbufs; /* Pointer to hypervisor maps */
struct t_buf **meta; /* pointers to the trace buffer metadata */
unsigned char **data; /* pointers to the trace buffer data areas
* where they are mapped into user space. */
unsigned long tbufs_mfn; /* mfn of the tbufs */
unsigned int num; /* number of trace buffers / logical CPUS */
+ unsigned long tinfo_size; /* size of t_info metadata map */
unsigned long size; /* size of a single trace buffer */
unsigned long data_size;
@@ -655,14 +641,15 @@ static int monitor_tbufs(void)
num = get_num_cpus();
/* setup access to trace buffers */
- get_tbufs(&tbufs_mfn, &size);
- tbufs_mapped = map_tbufs(tbufs_mfn, num, size);
+ get_tbufs(&tbufs_mfn, &tinfo_size);
+ tbufs = map_tbufs(tbufs_mfn, num, tinfo_size);
+
+ size = tbufs->t_info->tbuf_size * PAGE_SIZE;
data_size = size - sizeof(struct t_buf);
- /* build arrays of convenience ptrs */
- meta = init_bufs_ptrs(tbufs_mapped, num, size);
- data = init_rec_ptrs(meta, num);
+ meta = tbufs->meta;
+ data = tbufs->data;
if ( opts.discard )
for ( i = 0; i < num; i++ )