ia64/xen-unstable
changeset 1125:5640beab0342
bitkeeper revision 1.748.1.1 (403cc0a2uogkgkA4n8xi9XH9sph-GQ)
Add support for setting the trace buffer size as a boot parameter, for
returning the trace buffer size to user space and dynamically determining the
number of CPUs to map in xentrace.
Add support for setting the trace buffer size as a boot parameter, for
returning the trace buffer size to user space and dynamically determining the
number of CPUs to map in xentrace.
author | mwilli2@equilibrium.research.intel-research.net |
---|---|
date | Wed Feb 25 15:34:58 2004 +0000 (2004-02-25) |
parents | 6e6ef033e4fc |
children | bd4df43914c9 |
files | docs/Xeno-HOWTO.txt tools/xentrace/xentrace.c xen/common/dom0_ops.c xen/common/kernel.c xen/common/trace.c xen/include/hypervisor-ifs/dom0_ops.h xen/include/xeno/trace.h |
line diff
1.1 --- a/docs/Xeno-HOWTO.txt Tue Feb 24 18:28:43 2004 +0000 1.2 +++ b/docs/Xeno-HOWTO.txt Wed Feb 25 15:34:58 2004 +0000 1.3 @@ -225,6 +225,10 @@ The following is a list of command line 1.4 1.5 dom0_mem=xxx Set the maximum amount of memory for domain0. 1.6 1.7 + tbuf_size=xxx Set the size of the per-cpu trace buffers, in pages 1.8 + (default 1). Note that the trace buffers are only 1.9 + enabled in debug builds. Most users can ignore 1.10 + this feature completely. 1.11 1.12 Boot into Domain 0 1.13 ==============================
2.1 --- a/tools/xentrace/xentrace.c Tue Feb 24 18:28:43 2004 +0000 2.2 +++ b/tools/xentrace/xentrace.c Wed Feb 25 15:34:58 2004 +0000 2.3 @@ -27,23 +27,20 @@ 2.4 2.5 extern FILE *stdout; 2.6 2.7 + 2.8 /***** Compile time configuration of defaults ********************************/ 2.9 2.10 -#define NUM_CPUS 1 /* XXX this ought to be removed and replaced with something 2.11 - * cleverer to dynamically query the machine - I'll use a 2.12 - * dom0 op once I've implemented it! :-) */ 2.13 - 2.14 /* when we've got more records than this waiting, we log it to the output */ 2.15 #define NEW_DATA_THRESH 1 2.16 2.17 /* sleep for this long (milliseconds) between checking the trace buffers */ 2.18 #define POLL_SLEEP_MILLIS 100 2.19 2.20 + 2.21 /***** The code **************************************************************/ 2.22 2.23 typedef struct settings_st { 2.24 char *outfile; 2.25 - unsigned int num_cpus; 2.26 struct timespec poll_sleep; 2.27 unsigned long new_data_thresh; 2.28 } settings_t; 2.29 @@ -90,13 +87,14 @@ void print_rec(unsigned int cpu, struct 2.30 2.31 2.32 /** 2.33 - * get_tbuf_ptrs - get pointer to trace buffers 2.34 + * get_tbufs - get pointer to and size of the trace buffers 2.35 + * @phys_addr: location to store physical address if the trace buffers to 2.36 + * @size: location to store the size of a trace buffer to 2.37 * 2.38 - * Does a dom0 op to fetch a "pointer" to the trace buffers. The pointer can't 2.39 - * be dereferenced immediately, since it is a physical address of memory in Xen 2.40 - * space - they are used in this program to mmap the right area from /dev/mem. 2.41 + * Gets the physical address of the trace pointer area and the size of the 2.42 + * per CPU buffers. 2.43 */ 2.44 -unsigned long get_tbuf_ptrs(void) 2.45 +void get_tbufs(unsigned long *phys_addr, unsigned long *size) 2.46 { 2.47 int ret; 2.48 dom0_op_t op; /* dom0 op we'll build */ 2.49 @@ -114,22 +112,29 @@ unsigned long get_tbuf_ptrs(void) 2.50 PERROR("Failure to get trace buffer pointer from Xen"); 2.51 exit(EXIT_FAILURE); 2.52 } 2.53 - 2.54 - return op.u.gettbufs.phys_addr; 2.55 + 2.56 + *phys_addr = op.u.gettbufs.phys_addr; 2.57 + *size = op.u.gettbufs.size; 2.58 } 2.59 2.60 /** 2.61 * map_tbufs - memory map Xen trace buffers into user space 2.62 * @tbufs: physical address of the trace buffers 2.63 + * @num: number of trace buffers to map 2.64 + * @size: size of each trace buffer 2.65 * 2.66 - * Given the physical address of the Xen trace buffers, maps them into process 2.67 - * address space by memory mapping /dev/mem. Returns a pointer to the location 2.68 - * the buffers have been mapped to. 2.69 + * Maps the Xen trace buffers them into process address space by memory mapping 2.70 + * /dev/mem. Returns the location the buffers have been mapped to. 2.71 */ 2.72 -struct t_buf *map_tbufs(unsigned long tbufs_phys) 2.73 +struct t_buf *map_tbufs(unsigned long tbufs_phys, unsigned int num, 2.74 + unsigned long size) 2.75 { 2.76 - int dm_fd; /* file descriptor for /dev/mem */ 2.77 + int dm_fd; /* file descriptor for /dev/mem */ 2.78 struct t_buf *tbufs_mapped; 2.79 + unsigned int page_size = getpagesize(); 2.80 + unsigned int off_in_pg = (tbufs_phys % page_size); 2.81 + 2.82 + tbufs_phys -= off_in_pg; /* correct tbufs_phys if not page-aligned */ 2.83 2.84 dm_fd = open("/dev/mem", O_RDONLY); 2.85 if ( dm_fd < 0 ) 2.86 @@ -137,8 +142,8 @@ struct t_buf *map_tbufs(unsigned long tb 2.87 PERROR("Open /dev/mem when mapping trace buffers\n"); 2.88 exit(EXIT_FAILURE); 2.89 } 2.90 - 2.91 - tbufs_mapped = (struct t_buf *)mmap(NULL, opts.num_cpus * TB_SIZE, 2.92 + 2.93 + tbufs_mapped = (struct t_buf *)mmap(NULL, size * num + off_in_pg, 2.94 PROT_READ, MAP_SHARED, 2.95 dm_fd, (off_t)tbufs_phys); 2.96 2.97 @@ -149,24 +154,28 @@ struct t_buf *map_tbufs(unsigned long tb 2.98 PERROR("Failed to mmap trace buffers"); 2.99 exit(EXIT_FAILURE); 2.100 } 2.101 - 2.102 - return tbufs_mapped; 2.103 + 2.104 + /* add offset to get buffers in case original address wasn't pg aligned */ 2.105 + return (struct t_buf *)((unsigned long)tbufs_mapped + off_in_pg); 2.106 } 2.107 2.108 2.109 /** 2.110 * init_bufs_ptrs - initialises an array of pointers to the trace buffers 2.111 * @bufs_mapped: the userspace address where the trace buffers are mapped 2.112 + * @num: number of trace buffers 2.113 + * @size: trace buffer size 2.114 * 2.115 * Initialises an array of pointers to individual trace buffers within the 2.116 * mapped region containing all trace buffers. 2.117 */ 2.118 -struct t_buf **init_bufs_ptrs(void *bufs_mapped) 2.119 +struct t_buf **init_bufs_ptrs(void *bufs_mapped, unsigned int num, 2.120 + unsigned long size) 2.121 { 2.122 int i; 2.123 struct t_buf **user_ptrs; 2.124 2.125 - user_ptrs = (struct t_buf **)calloc(opts.num_cpus, sizeof(struct t_buf *)); 2.126 + user_ptrs = (struct t_buf **)calloc(num, sizeof(struct t_buf *)); 2.127 if ( user_ptrs == NULL ) 2.128 { 2.129 PERROR( "Failed to allocate memory for buffer pointers\n"); 2.130 @@ -175,9 +184,9 @@ struct t_buf **init_bufs_ptrs(void *bufs 2.131 2.132 /* initialise pointers to the trace buffers - given the size of a trace 2.133 * buffer and the value of bufs_maped, we can easily calculate these */ 2.134 - for ( i = 0; i<opts.num_cpus; i++ ) 2.135 + for ( i = 0; i<num; i++ ) 2.136 user_ptrs[i] = (struct t_buf *)( 2.137 - (unsigned long)bufs_mapped + TB_SIZE * i); 2.138 + (unsigned long)bufs_mapped + size * i); 2.139 2.140 return user_ptrs; 2.141 } 2.142 @@ -188,6 +197,7 @@ struct t_buf **init_bufs_ptrs(void *bufs 2.143 * @tbufs_phys: physical base address of the trace buffer area 2.144 * @tbufs_mapped: user virtual address of base of trace buffer area 2.145 * @meta: array of user-space pointers to struct t_buf's of metadata 2.146 + * @num: number of trace buffers 2.147 * 2.148 * Initialises data area pointers to the locations that data areas have been 2.149 * mapped in user space. Note that the trace buffer metadata contains physical 2.150 @@ -195,19 +205,20 @@ struct t_buf **init_bufs_ptrs(void *bufs 2.151 */ 2.152 struct t_rec **init_rec_ptrs(unsigned long tbufs_phys, 2.153 struct t_buf *tbufs_mapped, 2.154 - struct t_buf **meta) 2.155 + struct t_buf **meta, 2.156 + unsigned int num) 2.157 { 2.158 int i; 2.159 struct t_rec **data; 2.160 2.161 - data = calloc(opts.num_cpus, sizeof(struct t_rec *)); 2.162 + data = calloc(num, sizeof(struct t_rec *)); 2.163 if ( data == NULL ) 2.164 { 2.165 PERROR("Failed to allocate memory for data pointers\n"); 2.166 exit(EXIT_FAILURE); 2.167 } 2.168 2.169 - for ( i = 0; i<opts.num_cpus; i++ ) 2.170 + for ( i = 0; i<num; i++ ) 2.171 data[i] = (struct t_rec *)((unsigned long)meta[i]->data - 2.172 tbufs_phys + (unsigned long)tbufs_mapped); 2.173 2.174 @@ -216,16 +227,17 @@ struct t_rec **init_rec_ptrs(unsigned lo 2.175 2.176 /** 2.177 * init_tail_idxs - initialise an array of tail indexes 2.178 - * @bufs: array of pointers to trace buffer metadata in struct t_buf's 2.179 + * @bufs: array of pointers to trace buffer metadata 2.180 + * @num: number of trace buffers 2.181 * 2.182 * The tail indexes indicate where we're read to so far in the data array of a 2.183 * trace buffer. Each entry in this table corresponds to the tail index for a 2.184 * particular trace buffer. 2.185 */ 2.186 -int *init_tail_idxs(struct t_buf **bufs) 2.187 +int *init_tail_idxs(struct t_buf **bufs, unsigned int num) 2.188 { 2.189 int i; 2.190 - int *tails = calloc(opts.num_cpus, sizeof(unsigned int)); 2.191 + int *tails = calloc(num, sizeof(unsigned int)); 2.192 2.193 if ( tails == NULL ) 2.194 { 2.195 @@ -233,12 +245,37 @@ int *init_tail_idxs(struct t_buf **bufs) 2.196 exit(EXIT_FAILURE); 2.197 } 2.198 2.199 - for ( i = 0; i<opts.num_cpus; i++ ) 2.200 + for ( i = 0; i<num; i++ ) 2.201 tails[i] = bufs[i]->head; 2.202 2.203 return tails; 2.204 } 2.205 2.206 +/** 2.207 + * get_num_cpus - get the number of logical CPUs 2.208 + */ 2.209 +unsigned int get_num_cpus() 2.210 +{ 2.211 + dom0_op_t op; 2.212 + int xc_handle = xc_interface_open(); 2.213 + int ret; 2.214 + 2.215 + op.cmd = DOM0_PHYSINFO; 2.216 + op.interface_version = DOM0_INTERFACE_VERSION; 2.217 + 2.218 + ret = do_dom0_op(xc_handle, &op); 2.219 + 2.220 + if ( ret != 0 ) 2.221 + { 2.222 + PERROR("Failure to get logical CPU count from Xen"); 2.223 + exit(EXIT_FAILURE); 2.224 + } 2.225 + 2.226 + xc_interface_close(xc_handle); 2.227 + 2.228 + return op.u.physinfo.ht_per_core * op.u.physinfo.cores; 2.229 +} 2.230 + 2.231 2.232 /** 2.233 * monitor_tbufs - monitor the contents of tbufs and output to a file 2.234 @@ -253,20 +290,25 @@ int monitor_tbufs(FILE *logfile) 2.235 * where they are mapped into user space. */ 2.236 int *tails; /* store tail indexes for the trace buffers */ 2.237 unsigned long tbufs_phys; /* physical address of the tbufs */ 2.238 - 2.239 + unsigned int num; /* number of trace buffers / logical CPUS */ 2.240 + unsigned long size; /* size of a single trace buffer */ 2.241 + 2.242 + /* get number of logical CPUs (and therefore number of trace buffers) */ 2.243 + num = get_num_cpus(); 2.244 + 2.245 /* setup access to trace buffers */ 2.246 - tbufs_phys = get_tbuf_ptrs(); 2.247 - tbufs_mapped = map_tbufs(tbufs_phys); 2.248 + get_tbufs(&tbufs_phys, &size); 2.249 + tbufs_mapped = map_tbufs(tbufs_phys, num, size); 2.250 2.251 /* build arrays of convenience ptrs */ 2.252 - meta = init_bufs_ptrs (tbufs_mapped); 2.253 - data = init_rec_ptrs (tbufs_phys, tbufs_mapped, meta); 2.254 - tails = init_tail_idxs (meta); 2.255 + meta = init_bufs_ptrs (tbufs_mapped, num, size); 2.256 + data = init_rec_ptrs (tbufs_phys, tbufs_mapped, meta, num); 2.257 + tails = init_tail_idxs (meta, num); 2.258 2.259 /* now, scan buffers for events */ 2.260 while ( !interrupted ) 2.261 { 2.262 - for ( i = 0; i < opts.num_cpus; i++ ) 2.263 + for ( i = 0; ( i < num ) && !interrupted; i++ ) 2.264 { 2.265 signed long newdata = meta[i]->head - tails[i]; 2.266 signed long prewrap = newdata; 2.267 @@ -335,15 +377,6 @@ error_t cmd_parser(int key, char *arg, s 2.268 argp_usage(state); 2.269 } 2.270 break; 2.271 - 2.272 - case 'n': /* set number of CPU trace buffers to map */ 2.273 - { 2.274 - char *inval; 2.275 - setup->num_cpus = strtol(arg, &inval, 0); 2.276 - if (inval == arg ) 2.277 - argp_usage(state); 2.278 - } 2.279 - break; 2.280 2.281 case ARGP_KEY_ARG: 2.282 { 2.283 @@ -376,11 +409,6 @@ const struct argp_option cmd_opts[] = 2.284 "Set sleep time, p, in milliseconds between polling the trace buffer " 2.285 "for new data (default " xstr(POLL_SLEEP_MILLIS) ")." }, 2.286 2.287 - { .name = "num-cpus", .key = 'n', .arg="i", 2.288 - .doc = 2.289 - "Set number, i, of CPU trace buffers to map. This should not exceed " 2.290 - "the number of CPUs in the system (default " xstr(NUM_CPUS) ")." }, 2.291 - 2.292 {0} 2.293 }; 2.294 2.295 @@ -399,7 +427,7 @@ const struct argp parser_def = 2.296 }; 2.297 2.298 2.299 -const char *argp_program_version = "xentrace v1.0"; 2.300 +const char *argp_program_version = "xentrace v1.1"; 2.301 const char *argp_program_bug_address = "<mark.a.williamson@intel.com>"; 2.302 2.303 2.304 @@ -411,7 +439,6 @@ int main(int argc, char **argv) 2.305 const struct sigaction act = { .sa_handler = close_handler }; 2.306 2.307 opts.outfile = 0; 2.308 - opts.num_cpus = 1; 2.309 opts.poll_sleep = millis_to_timespec(POLL_SLEEP_MILLIS); 2.310 opts.new_data_thresh = NEW_DATA_THRESH; 2.311
3.1 --- a/xen/common/dom0_ops.c Tue Feb 24 18:28:43 2004 +0000 3.2 +++ b/xen/common/dom0_ops.c Wed Feb 25 15:34:58 2004 +0000 3.3 @@ -436,9 +436,8 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 3.4 #ifdef TRACE_BUFFER 3.5 case DOM0_GETTBUFS: 3.6 { 3.7 - op->u.gettbufs.phys_addr = get_tb_ptr(); 3.8 + ret = get_tb_info(&op->u.gettbufs); 3.9 copy_to_user(u_dom0_op, op, sizeof(*op)); 3.10 - ret = 0; 3.11 } 3.12 break; 3.13 #endif
4.1 --- a/xen/common/kernel.c Tue Feb 24 18:28:43 2004 +0000 4.2 +++ b/xen/common/kernel.c Wed Feb 25 15:34:58 2004 +0000 4.3 @@ -77,6 +77,8 @@ int opt_ignorebiostables=0; 4.4 int opt_watchdog=0; 4.5 /* opt_pdb: Name of serial port for Xen pervasive debugger (and enable pdb) */ 4.6 unsigned char opt_pdb[10] = "none"; 4.7 +/* opt_tbuf_size: trace buffer size (in pages) */ 4.8 +unsigned int opt_tbuf_size = 1; 4.9 4.10 static struct { 4.11 unsigned char *name; 4.12 @@ -96,6 +98,7 @@ static struct { 4.13 { "ignorebiostables", OPT_BOOL, &opt_ignorebiostables }, 4.14 { "watchdog", OPT_BOOL, &opt_watchdog }, 4.15 { "pdb", OPT_STR, &opt_pdb }, 4.16 + { "tbuf_size", OPT_UINT, &opt_tbuf_size }, 4.17 { NULL, 0, NULL } 4.18 }; 4.19
5.1 --- a/xen/common/trace.c Tue Feb 24 18:28:43 2004 +0000 5.2 +++ b/xen/common/trace.c Wed Feb 25 15:34:58 2004 +0000 5.3 @@ -29,7 +29,9 @@ 5.4 #include <xeno/smp.h> 5.5 #include <xeno/spinlock.h> 5.6 #include <xeno/trace.h> 5.7 +#include <xeno/errno.h> 5.8 #include <asm/atomic.h> 5.9 +#include <hypervisor-ifs/dom0_ops.h> 5.10 5.11 /* Pointers to the meta-data objects for all system trace buffers */ 5.12 struct t_buf *t_bufs[NR_CPUS]; 5.13 @@ -46,11 +48,20 @@ int tb_init_done = 0; 5.14 */ 5.15 void init_trace_bufs(void) 5.16 { 5.17 + extern int opt_tbuf_size; 5.18 + 5.19 int i; 5.20 char *rawbuf; 5.21 struct t_buf *buf; 5.22 + 5.23 + if ( opt_tbuf_size == 0 ) 5.24 + { 5.25 + printk("Xen trace buffers: disabled\n"); 5.26 + return; 5.27 + } 5.28 5.29 - if ( (rawbuf = kmalloc(smp_num_cpus * TB_SIZE, GFP_KERNEL)) == NULL ) 5.30 + if ( (rawbuf = kmalloc(smp_num_cpus * opt_tbuf_size * PAGE_SIZE, 5.31 + GFP_KERNEL)) == NULL ) 5.32 { 5.33 printk("Xen trace buffers: memory allocation failed\n"); 5.34 return; 5.35 @@ -58,7 +69,7 @@ void init_trace_bufs(void) 5.36 5.37 for ( i = 0; i < smp_num_cpus; i++ ) 5.38 { 5.39 - buf = t_bufs[i] = (struct t_buf *)&rawbuf[i*TB_SIZE]; 5.40 + buf = t_bufs[i] = (struct t_buf *)&rawbuf[i*opt_tbuf_size*PAGE_SIZE]; 5.41 5.42 /* For use in Xen. */ 5.43 buf->vdata = (struct t_rec *)(buf+1); 5.44 @@ -70,7 +81,8 @@ void init_trace_bufs(void) 5.45 buf->head = 0; 5.46 5.47 /* For use in both. */ 5.48 - buf->size = (TB_SIZE - sizeof(struct t_buf)) / sizeof(struct t_rec); 5.49 + buf->size = (opt_tbuf_size * PAGE_SIZE - sizeof(struct t_buf)) 5.50 + / sizeof(struct t_rec); 5.51 } 5.52 5.53 printk("Xen trace buffers: initialised\n"); 5.54 @@ -81,15 +93,29 @@ void init_trace_bufs(void) 5.55 } 5.56 5.57 /** 5.58 - * get_tb_ptr - return physical address of the trace buffers. 5.59 + * get_tb_info - get trace buffer details 5.60 + * @st: a pointer to a dom0_gettbufs_t to be filled out 5.61 * 5.62 * Called by the %DOM0_GETTBUFS dom0 op to fetch the physical address of the 5.63 * trace buffers. 5.64 */ 5.65 -unsigned long get_tb_ptr(void) 5.66 +int get_tb_info(dom0_gettbufs_t *st) 5.67 { 5.68 - /* Return the physical address. */ 5.69 - return __pa(t_bufs[0]); 5.70 + if(tb_init_done) 5.71 + { 5.72 + extern unsigned int opt_tbuf_size; 5.73 + 5.74 + st->phys_addr = __pa(t_bufs[0]); 5.75 + st->size = opt_tbuf_size * PAGE_SIZE; 5.76 + 5.77 + return 0; 5.78 + } 5.79 + else 5.80 + { 5.81 + st->phys_addr = 0; 5.82 + st->size = 0; 5.83 + return -ENODATA; 5.84 + } 5.85 } 5.86 5.87 #endif /* TRACE_BUFFER */
6.1 --- a/xen/include/hypervisor-ifs/dom0_ops.h Tue Feb 24 18:28:43 2004 +0000 6.2 +++ b/xen/include/hypervisor-ifs/dom0_ops.h Wed Feb 25 15:34:58 2004 +0000 6.3 @@ -17,7 +17,7 @@ 6.4 * This makes sure that old versions of dom0 tools will stop working in a 6.5 * well-defined way (rather than crashing the machine, for instance). 6.6 */ 6.7 -#define DOM0_INTERFACE_VERSION 0xAAAA0007 6.8 +#define DOM0_INTERFACE_VERSION 0xAAAA0008 6.9 6.10 /* 6.11 * The following is all CPU context. Note that the i387_ctxt block is filled 6.12 @@ -213,8 +213,9 @@ typedef struct dom0_pincpudomain_st 6.13 #define DOM0_GETTBUFS 21 6.14 typedef struct dom0_gettbufs_st 6.15 { 6.16 - /* OUT variable - location of the trace buffers */ 6.17 - unsigned long phys_addr; 6.18 + /* OUT variables */ 6.19 + unsigned long phys_addr; /* location of the trace buffers */ 6.20 + unsigned long size; /* size of each trace buffer, in bytes */ 6.21 } dom0_gettbufs_t; 6.22 6.23 /*
7.1 --- a/xen/include/xeno/trace.h Tue Feb 24 18:28:43 2004 +0000 7.2 +++ b/xen/include/xeno/trace.h Wed Feb 25 15:34:58 2004 +0000 7.3 @@ -21,12 +21,6 @@ 7.4 #ifndef __XENO_TRACE_H__ 7.5 #define __XENO_TRACE_H__ 7.6 7.7 -/* 7.8 - * How much space is allowed for a single trace buffer, including data and 7.9 - * metadata (and maybe some waste). 7.10 - */ 7.11 -#define TB_SIZE PAGE_SIZE 7.12 - 7.13 /* This structure represents a single trace buffer record. */ 7.14 struct t_rec { 7.15 u64 cycles; /* 64 bit cycle counter timestamp */ 7.16 @@ -63,12 +57,13 @@ struct t_buf { 7.17 #include <asm/atomic.h> 7.18 #include <asm/current.h> 7.19 #include <asm/msr.h> 7.20 +#include <hypervisor-ifs/dom0_ops.h> 7.21 7.22 /* Used to initialise trace buffer functionality */ 7.23 void init_trace_bufs(void); 7.24 7.25 /* used to retrieve the physical address of the trace buffers */ 7.26 -struct t_buf *get_tb_ptr(void); 7.27 +int get_tb_info(dom0_gettbufs_t *st); 7.28 7.29 /** 7.30 * trace - Enters a trace tuple into the trace buffer for the current CPU.