Yu Zhiguo
2010-Feb-10 04:28 UTC
[Xen-devel] [PATCH] tools/xenbaked: fix bug of Segmentation fault
Run xenbaked will occur Segmentation fault, because the method to get pointers of trace buffer metadata is wrong. Fix this bug according to xentrace. Signed-off-by: Yu Zhiguo <yuzg@cn.fujitsu.com> diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c --- a/tools/xenmon/xenbaked.c +++ b/tools/xenmon/xenbaked.c @@ -83,6 +83,12 @@ double cpu_freq; } 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 */ @@ -356,96 +362,72 @@ * * 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) { int xc_handle; - struct t_buf *tbufs_mapped; + static struct t_struct tbufs = { 0 }; + int i; xc_handle = xc_interface_open(); - if ( xc_handle < 0 ) { exit(EXIT_FAILURE); } - 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); - xc_interface_close(xc_handle); - - 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); + } -/** - * 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 ) + /* 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); } - /* 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); + 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]; - return user_ptrs; -} + for ( j=0; j<tbufs.t_info->tbuf_size; j++) + pfn_list[j] = (xen_pfn_t)mfn_list[j]; - -/** - * 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 struct t_rec **init_rec_ptrs(struct t_buf **meta, unsigned int num) -{ - int i; - struct t_rec **data; - - data = calloc(num, sizeof(struct t_rec *)); - if ( data == NULL ) - { - PERROR("Failed to allocate memory for data pointers\n"); - exit(EXIT_FAILURE); + 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); } - for ( i = 0; i < num; i++ ) - data[i] = (struct t_rec *)(meta[i] + 1); + xc_interface_close(xc_handle); - return data; + return &tbufs; } - - /** * get_num_cpus - get the number of logical CPUs */ @@ -470,55 +452,19 @@ } /** - * get_tbuf_size - get the size in pages of each trace buffer - */ -uint16_t get_tbuf_size(unsigned long tbufs_mfn, unsigned long tinfo_size) -{ - struct t_info *t_info; - int xc_handle; - - xc_handle = xc_interface_open(); - if ( xc_handle < 0 ) - { - exit(EXIT_FAILURE); - } - - t_info = xc_map_foreign_range(xc_handle, DOMID_XEN, - tinfo_size, PROT_READ | PROT_WRITE, - tbufs_mfn); - - if ( t_info == 0 ) - { - PERROR("Failed to mmap trace buffers"); - exit(EXIT_FAILURE); - } - - if ( t_info->tbuf_size == 0 ) - { - fprintf(stderr, "%s: tbuf_size 0!\n", __func__); - exit(EXIT_FAILURE); - } - - xc_interface_close(xc_handle); - - return t_info->tbuf_size; -} - -/** * monitor_tbufs - monitor the contents of tbufs */ 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 */ - char **data; /* pointers to the trace buffer data areas + 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 */ - uint16_t tbuf_size; /* Size in pages of each trace buffer */ unsigned long size; /* size of a single trace buffer */ unsigned long data_size, rec_size; @@ -533,17 +479,14 @@ /* setup access to trace buffers */ get_tbufs(&tbufs_mfn, &tinfo_size); + tbufs = map_tbufs(tbufs_mfn, num, tinfo_size); - tbufs_mapped = map_tbufs(tbufs_mfn, num, tinfo_size); - - tbuf_size = get_tbuf_size(tbufs_mfn, tinfo_size); - size = tbuf_size * XC_PAGE_SIZE; + size = tbufs->t_info->tbuf_size * XC_PAGE_SIZE; data_size = size - sizeof(struct t_buf); - /* build arrays of convenience ptrs */ - meta = init_bufs_ptrs (tbufs_mapped, num, size); - data = (char **)init_rec_ptrs(meta, num); + meta = tbufs->meta; + data = tbufs->data; if ( eventchn_init() < 0 ) fprintf(stderr, "Failed to initialize event channel; " _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2010-Feb-10 09:14 UTC
[Xen-devel] Re: [PATCH] tools/xenbaked: fix bug of Segmentation fault
On 10/02/2010 04:28, "Yu Zhiguo" <yuzg@cn.fujitsu.com> wrote:> Run xenbaked will occur Segmentation fault, because > the method to get pointers of trace buffer metadata > is wrong. Fix this bug according to xentrace. > > Signed-off-by: Yu Zhiguo <yuzg@cn.fujitsu.com>Doesn''t apply to xen-unstable. For example, removes a function get_tbuf_size() which doesn''t even exist in xen-unstable''s xenbaked.c. -- Keir _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Yu Zhiguo
2010-Feb-10 11:17 UTC
[Xen-devel] Re: [PATCH] tools/xenbaked: fix bug of Segmentation fault
Hi, Keir Fraser wrote:> On 10/02/2010 04:28, "Yu Zhiguo" <yuzg@cn.fujitsu.com> wrote: > >> Run xenbaked will occur Segmentation fault, because >> the method to get pointers of trace buffer metadata >> is wrong. Fix this bug according to xentrace. >> >> Signed-off-by: Yu Zhiguo <yuzg@cn.fujitsu.com> > > Doesn''t apply to xen-unstable. For example, removes a function > get_tbuf_size() which doesn''t even exist in xen-unstable''s xenbaked.c.I''m sorry for this mistake, please use the following patch: ---------------- Run xenbaked will cause Segmentation fault, because the method to get pointers of trace buffer metadata is wrong. Fix this bug according to xentrace. Signed-off-by: Yu Zhiguo <yuzg@cn.fujitsu.com> diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c --- a/tools/xenmon/xenbaked.c +++ b/tools/xenmon/xenbaked.c @@ -83,6 +83,12 @@ double cpu_freq; } 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 */ @@ -356,96 +362,72 @@ * * 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) { int xc_handle; - struct t_buf *tbufs_mapped; + static struct t_struct tbufs = { 0 }; + int i; xc_handle = xc_interface_open(); - if ( xc_handle < 0 ) { exit(EXIT_FAILURE); } - 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); - xc_interface_close(xc_handle); - - 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); + } -/** - * 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 ) + /* 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); } - /* 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); + 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]; - return user_ptrs; -} + for ( j=0; j<tbufs.t_info->tbuf_size; j++) + pfn_list[j] = (xen_pfn_t)mfn_list[j]; - -/** - * 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 struct t_rec **init_rec_ptrs(struct t_buf **meta, unsigned int num) -{ - int i; - struct t_rec **data; - - data = calloc(num, sizeof(struct t_rec *)); - if ( data == NULL ) - { - PERROR("Failed to allocate memory for data pointers\n"); - exit(EXIT_FAILURE); + 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); } - for ( i = 0; i < num; i++ ) - data[i] = (struct t_rec *)(meta[i] + 1); + xc_interface_close(xc_handle); - return data; + return &tbufs; } - - /** * get_num_cpus - get the number of logical CPUs */ @@ -469,7 +451,6 @@ return physinfo.nr_cpus; } - /** * monitor_tbufs - monitor the contents of tbufs */ @@ -477,12 +458,13 @@ { 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 */ - char **data; /* pointers to the trace buffer data areas + 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, rec_size; @@ -496,15 +478,15 @@ printf("CPU Frequency = %7.2f\n", opts.cpu_freq); /* setup access to trace buffers */ - get_tbufs(&tbufs_mfn, &size); + get_tbufs(&tbufs_mfn, &tinfo_size); + tbufs = map_tbufs(tbufs_mfn, num, tinfo_size); - tbufs_mapped = map_tbufs(tbufs_mfn, num, size); + size = tbufs->t_info->tbuf_size * XC_PAGE_SIZE; data_size = size - sizeof(struct t_buf); - /* build arrays of convenience ptrs */ - meta = init_bufs_ptrs (tbufs_mapped, num, size); - data = (char **)init_rec_ptrs(meta, num); + meta = tbufs->meta; + data = tbufs->data; if ( eventchn_init() < 0 ) fprintf(stderr, "Failed to initialize event channel; " _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel