mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Merge
This commit is contained in:
commit
c17db2f3e0
5 files changed
+345
-378
No files matched your search
+300
-295
@@ -12,7 +12,8 @@
|
||||
* Authors: Diwaker Gupta, diwaker.gupta@hp.com
|
||||
* Rob Gardner, rob.gardner@hp.com
|
||||
* Lucy Cherkasova, lucy.cherkasova.hp.com
|
||||
* Much code based on xentrace, authored by Mark Williamson, mark.a.williamson@intel.com
|
||||
* Much code based on xentrace, authored by Mark Williamson,
|
||||
* mark.a.williamson@intel.com
|
||||
* Date: November, 2005
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -107,31 +108,31 @@ int NCPU = 0;
|
||||
|
||||
void init_current(int ncpu)
|
||||
{
|
||||
running = calloc(ncpu, sizeof(int));
|
||||
NCPU = ncpu;
|
||||
printf("Initialized with %d %s\n", ncpu, (ncpu == 1) ? "cpu" : "cpu's");
|
||||
running = calloc(ncpu, sizeof(int));
|
||||
NCPU = ncpu;
|
||||
printf("Initialized with %d %s\n", ncpu, (ncpu == 1) ? "cpu" : "cpu's");
|
||||
}
|
||||
|
||||
int is_current(int domain, int cpu)
|
||||
{
|
||||
// int i;
|
||||
// int i;
|
||||
|
||||
// for (i=0; i<NCPU; i++)
|
||||
// for (i=0; i<NCPU; i++)
|
||||
if (running[cpu] == domain)
|
||||
return 1;
|
||||
return 0;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// return the domain that's currently running on the given cpu
|
||||
int current(int cpu)
|
||||
{
|
||||
return running[cpu];
|
||||
return running[cpu];
|
||||
}
|
||||
|
||||
void set_current(int cpu, int domain)
|
||||
{
|
||||
running[cpu] = domain;
|
||||
running[cpu] = domain;
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +146,7 @@ void close_handler(int signal)
|
||||
void dump_record(int cpu, struct t_rec *x)
|
||||
{
|
||||
printf("record: cpu=%x, tsc=%lx, event=%x, d1=%lx\n",
|
||||
cpu, x->cycles, x->event, x->data[0]);
|
||||
cpu, x->cycles, x->event, x->data[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -198,15 +199,15 @@ void check_gotten_sum(void)
|
||||
int i;
|
||||
|
||||
for (i=0; i<NCPU; i++) {
|
||||
new_qos = cpu_qos_data[i];
|
||||
ns = billion;
|
||||
sum = total_ns_gotten(&ns);
|
||||
new_qos = cpu_qos_data[i];
|
||||
ns = billion;
|
||||
sum = total_ns_gotten(&ns);
|
||||
|
||||
printf("[cpu%d] ns_gotten over all domains = %lldns, over %lldns\n",
|
||||
i, sum, ns);
|
||||
percent = (double) sum;
|
||||
percent = (100.0*percent) / (double)ns;
|
||||
printf(" ==> ns_gotten = %7.3f%%\n", percent);
|
||||
printf("[cpu%d] ns_gotten over all domains = %lldns, over %lldns\n",
|
||||
i, sum, ns);
|
||||
percent = (double) sum;
|
||||
percent = (100.0*percent) / (double)ns;
|
||||
printf(" ==> ns_gotten = %7.3f%%\n", percent);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -229,7 +230,7 @@ void dump_stats(void)
|
||||
}
|
||||
|
||||
printf("processed %d total records in %d seconds (%ld per second)\n",
|
||||
rec_count, (int)run_time, rec_count/run_time);
|
||||
rec_count, (int)run_time, rec_count/run_time);
|
||||
|
||||
printf("woke up %d times in %d seconds (%ld per second)\n", wakeups,
|
||||
(int) run_time, wakeups/run_time);
|
||||
@@ -261,56 +262,56 @@ int xce_handle = -1;
|
||||
/* Stolen from xenstore code */
|
||||
int eventchn_init(void)
|
||||
{
|
||||
int rc;
|
||||
int rc;
|
||||
|
||||
// to revert to old way:
|
||||
if (0)
|
||||
return -1;
|
||||
// to revert to old way:
|
||||
if (0)
|
||||
return -1;
|
||||
|
||||
xce_handle = xc_evtchn_open();
|
||||
xce_handle = xc_evtchn_open();
|
||||
|
||||
if (xce_handle < 0)
|
||||
perror("Failed to open evtchn device");
|
||||
if (xce_handle < 0)
|
||||
perror("Failed to open evtchn device");
|
||||
|
||||
if ((rc = xc_evtchn_bind_virq(xce_handle, VIRQ_TBUF)) == -1)
|
||||
perror("Failed to bind to domain exception virq port");
|
||||
virq_port = rc;
|
||||
if ((rc = xc_evtchn_bind_virq(xce_handle, VIRQ_TBUF)) == -1)
|
||||
perror("Failed to bind to domain exception virq port");
|
||||
virq_port = rc;
|
||||
|
||||
return xce_handle;
|
||||
return xce_handle;
|
||||
}
|
||||
|
||||
void wait_for_event(void)
|
||||
{
|
||||
int ret;
|
||||
fd_set inset;
|
||||
evtchn_port_t port;
|
||||
struct timeval tv;
|
||||
int evtchn_fd;
|
||||
int ret;
|
||||
fd_set inset;
|
||||
evtchn_port_t port;
|
||||
struct timeval tv;
|
||||
int evtchn_fd;
|
||||
|
||||
if (xce_handle < 0) {
|
||||
nanosleep(&opts.poll_sleep, NULL);
|
||||
return;
|
||||
}
|
||||
if (xce_handle < 0) {
|
||||
nanosleep(&opts.poll_sleep, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
evtchn_fd = xc_evtchn_fd(xce_handle);
|
||||
evtchn_fd = xc_evtchn_fd(xce_handle);
|
||||
|
||||
FD_ZERO(&inset);
|
||||
FD_SET(evtchn_fd, &inset);
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
// tv = millis_to_timespec(&opts.poll_sleep);
|
||||
ret = select(evtchn_fd+1, &inset, NULL, NULL, &tv);
|
||||
FD_ZERO(&inset);
|
||||
FD_SET(evtchn_fd, &inset);
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
// tv = millis_to_timespec(&opts.poll_sleep);
|
||||
ret = select(evtchn_fd+1, &inset, NULL, NULL, &tv);
|
||||
|
||||
if ( (ret == 1) && FD_ISSET(evtchn_fd, &inset)) {
|
||||
if ((port = xc_evtchn_pending(xce_handle)) == -1)
|
||||
perror("Failed to read from event fd");
|
||||
if ( (ret == 1) && FD_ISSET(evtchn_fd, &inset)) {
|
||||
if ((port = xc_evtchn_pending(xce_handle)) == -1)
|
||||
perror("Failed to read from event fd");
|
||||
|
||||
// if (port == virq_port)
|
||||
// printf("got the event I was looking for\r\n");
|
||||
// if (port == virq_port)
|
||||
// printf("got the event I was looking for\r\n");
|
||||
|
||||
if (xc_evtchn_unmask(xce_handle, port) == -1)
|
||||
perror("Failed to write to event fd");
|
||||
}
|
||||
if (xc_evtchn_unmask(xce_handle, port) == -1)
|
||||
perror("Failed to write to event fd");
|
||||
}
|
||||
}
|
||||
|
||||
static void get_tbufs(unsigned long *mfn, unsigned long *size)
|
||||
@@ -336,9 +337,9 @@ static void get_tbufs(unsigned long *mfn, unsigned long *size)
|
||||
|
||||
void disable_tracing(void)
|
||||
{
|
||||
int xc_handle = xc_interface_open();
|
||||
xc_tbuf_disable(xc_handle);
|
||||
xc_interface_close(xc_handle);
|
||||
int xc_handle = xc_interface_open();
|
||||
xc_tbuf_disable(xc_handle);
|
||||
xc_interface_close(xc_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -387,7 +388,7 @@ struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
|
||||
* mapped region containing all trace buffers.
|
||||
*/
|
||||
struct t_buf **init_bufs_ptrs(void *bufs_mapped, unsigned int num,
|
||||
unsigned long size)
|
||||
unsigned long size)
|
||||
{
|
||||
int i;
|
||||
struct t_buf **user_ptrs;
|
||||
@@ -472,7 +473,7 @@ unsigned int get_num_cpus(void)
|
||||
int monitor_tbufs(void)
|
||||
{
|
||||
int i;
|
||||
extern void process_record(int, struct t_rec *);
|
||||
extern int process_record(int, struct t_rec *);
|
||||
extern void alloc_qos_data(int ncpu);
|
||||
|
||||
void *tbufs_mapped; /* pointer to where the tbufs are mapped */
|
||||
@@ -483,7 +484,7 @@ int monitor_tbufs(void)
|
||||
unsigned int num; /* number of trace buffers / logical CPUS */
|
||||
unsigned long size; /* size of a single trace buffer */
|
||||
|
||||
int size_in_recs;
|
||||
unsigned long data_size, rec_size;
|
||||
|
||||
/* get number of logical CPUs (and therefore number of trace buffers) */
|
||||
num = get_num_cpus();
|
||||
@@ -496,34 +497,32 @@ int monitor_tbufs(void)
|
||||
/* setup access to trace buffers */
|
||||
get_tbufs(&tbufs_mfn, &size);
|
||||
|
||||
// printf("from dom0op: %ld, t_buf: %d, t_rec: %d\n",
|
||||
// size, sizeof(struct t_buf), sizeof(struct t_rec));
|
||||
|
||||
tbufs_mapped = map_tbufs(tbufs_mfn, num, size);
|
||||
|
||||
size_in_recs = (size - sizeof(struct t_buf)) / sizeof(struct t_rec);
|
||||
// fprintf(stderr, "size_in_recs = %d\n", size_in_recs);
|
||||
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);
|
||||
|
||||
// Set up event channel for select()
|
||||
if (eventchn_init() < 0) {
|
||||
fprintf(stderr, "Failed to initialize event channel; Using POLL method\r\n");
|
||||
}
|
||||
if ( eventchn_init() < 0 )
|
||||
fprintf(stderr, "Failed to initialize event channel; "
|
||||
"Using POLL method\r\n");
|
||||
|
||||
/* now, scan buffers for events */
|
||||
while ( !interrupted )
|
||||
{
|
||||
for ( i = 0; ( i < num ) && !interrupted; i++ )
|
||||
for ( i = 0; (i < num) && !interrupted; i++ )
|
||||
{
|
||||
while ( meta[i]->cons != meta[i]->prod )
|
||||
{
|
||||
rmb(); /* read prod, then read item. */
|
||||
process_record(i, data[i] + meta[i]->cons % size_in_recs);
|
||||
rec_size = process_record(
|
||||
i, data[i] + meta[i]->cons % data_size);
|
||||
mb(); /* read item, then update cons. */
|
||||
meta[i]->cons++;
|
||||
meta[i]->cons += rec_size;
|
||||
}
|
||||
}
|
||||
|
||||
wait_for_event();
|
||||
wakeups++;
|
||||
@@ -550,44 +549,44 @@ error_t cmd_parser(int key, char *arg, struct argp_state *state)
|
||||
|
||||
switch ( key )
|
||||
{
|
||||
case 't': /* set new records threshold for logging */
|
||||
{
|
||||
char *inval;
|
||||
setup->new_data_thresh = strtol(arg, &inval, 0);
|
||||
if ( inval == arg )
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
case 't': /* set new records threshold for logging */
|
||||
{
|
||||
char *inval;
|
||||
setup->new_data_thresh = strtol(arg, &inval, 0);
|
||||
if ( inval == arg )
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
|
||||
case 's': /* set sleep time (given in milliseconds) */
|
||||
{
|
||||
char *inval;
|
||||
setup->poll_sleep = millis_to_timespec(strtol(arg, &inval, 0));
|
||||
if ( inval == arg )
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
case 's': /* set sleep time (given in milliseconds) */
|
||||
{
|
||||
char *inval;
|
||||
setup->poll_sleep = millis_to_timespec(strtol(arg, &inval, 0));
|
||||
if ( inval == arg )
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm': /* set ms_per_sample */
|
||||
{
|
||||
char *inval;
|
||||
setup->ms_per_sample = strtol(arg, &inval, 0);
|
||||
if ( inval == arg )
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
case 'm': /* set ms_per_sample */
|
||||
{
|
||||
char *inval;
|
||||
setup->ms_per_sample = strtol(arg, &inval, 0);
|
||||
if ( inval == arg )
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
|
||||
case ARGP_KEY_ARG:
|
||||
{
|
||||
if ( state->arg_num == 0 )
|
||||
setup->outfile = arg;
|
||||
else
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
{
|
||||
if ( state->arg_num == 0 )
|
||||
setup->outfile = arg;
|
||||
else
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -614,27 +613,27 @@ void alloc_qos_data(int ncpu)
|
||||
|
||||
for (n=0; n<ncpu; n++) {
|
||||
|
||||
for (i=0; i<sizeof(_new_qos_data); i=i+pgsize)
|
||||
if ((write(qos_fd, dummy, pgsize)) != pgsize) {
|
||||
PERROR(SHARED_MEM_FILE);
|
||||
exit(2);
|
||||
}
|
||||
for (i=0; i<sizeof(_new_qos_data); i=i+pgsize)
|
||||
if ((write(qos_fd, dummy, pgsize)) != pgsize) {
|
||||
PERROR(SHARED_MEM_FILE);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
new_qos = (_new_qos_data *) mmap(0, sizeof(_new_qos_data), PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED, qos_fd, off);
|
||||
off += i;
|
||||
if (new_qos == NULL) {
|
||||
PERROR("mmap");
|
||||
exit(3);
|
||||
}
|
||||
// printf("new_qos = %p\n", new_qos);
|
||||
memset(new_qos, 0, sizeof(_new_qos_data));
|
||||
new_qos->next_datapoint = 0;
|
||||
advance_next_datapoint(0);
|
||||
new_qos->structlen = i;
|
||||
new_qos->ncpu = ncpu;
|
||||
// printf("structlen = 0x%x\n", i);
|
||||
cpu_qos_data[n] = new_qos;
|
||||
new_qos = (_new_qos_data *) mmap(0, sizeof(_new_qos_data), PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED, qos_fd, off);
|
||||
off += i;
|
||||
if (new_qos == NULL) {
|
||||
PERROR("mmap");
|
||||
exit(3);
|
||||
}
|
||||
// printf("new_qos = %p\n", new_qos);
|
||||
memset(new_qos, 0, sizeof(_new_qos_data));
|
||||
new_qos->next_datapoint = 0;
|
||||
advance_next_datapoint(0);
|
||||
new_qos->structlen = i;
|
||||
new_qos->ncpu = ncpu;
|
||||
// printf("structlen = 0x%x\n", i);
|
||||
cpu_qos_data[n] = new_qos;
|
||||
}
|
||||
free(dummy);
|
||||
new_qos = NULL;
|
||||
@@ -647,19 +646,19 @@ void alloc_qos_data(int ncpu)
|
||||
const struct argp_option cmd_opts[] =
|
||||
{
|
||||
{ .name = "log-thresh", .key='t', .arg="l",
|
||||
.doc =
|
||||
"Set number, l, of new records required to trigger a write to output "
|
||||
"(default " xstr(NEW_DATA_THRESH) ")." },
|
||||
.doc =
|
||||
"Set number, l, of new records required to trigger a write to output "
|
||||
"(default " xstr(NEW_DATA_THRESH) ")." },
|
||||
|
||||
{ .name = "poll-sleep", .key='s', .arg="p",
|
||||
.doc =
|
||||
"Set sleep time, p, in milliseconds between polling the trace buffer "
|
||||
"for new data (default " xstr(POLL_SLEEP_MILLIS) ")." },
|
||||
.doc =
|
||||
"Set sleep time, p, in milliseconds between polling the trace buffer "
|
||||
"for new data (default " xstr(POLL_SLEEP_MILLIS) ")." },
|
||||
|
||||
{ .name = "ms_per_sample", .key='m', .arg="MS",
|
||||
.doc =
|
||||
"Specify the number of milliseconds per sample "
|
||||
" (default " xstr(MS_PER_SAMPLE) ")." },
|
||||
.doc =
|
||||
"Specify the number of milliseconds per sample "
|
||||
" (default " xstr(MS_PER_SAMPLE) ")." },
|
||||
|
||||
{0}
|
||||
};
|
||||
@@ -670,10 +669,10 @@ const struct argp parser_def =
|
||||
.parser = cmd_parser,
|
||||
// .args_doc = "[output file]",
|
||||
.doc =
|
||||
"Tool to capture and partially process Xen trace buffer data"
|
||||
"\v"
|
||||
"This tool is used to capture trace buffer data from Xen. The data is "
|
||||
"saved in a shared memory structure to be further processed by xenmon."
|
||||
"Tool to capture and partially process Xen trace buffer data"
|
||||
"\v"
|
||||
"This tool is used to capture trace buffer data from Xen. The data is "
|
||||
"saved in a shared memory structure to be further processed by xenmon."
|
||||
};
|
||||
|
||||
|
||||
@@ -716,101 +715,101 @@ int main(int argc, char **argv)
|
||||
|
||||
void qos_init_domain(int domid, int idx)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
memset(&new_qos->domain_info[idx], 0, sizeof(_domain_info));
|
||||
new_qos->domain_info[idx].last_update_time = global_now;
|
||||
// runnable_start_time[idx] = 0;
|
||||
new_qos->domain_info[idx].runnable_start_time = 0; // invalidate
|
||||
new_qos->domain_info[idx].in_use = 1;
|
||||
new_qos->domain_info[idx].blocked_start_time = 0;
|
||||
new_qos->domain_info[idx].id = domid;
|
||||
if (domid == IDLE_DOMAIN_ID)
|
||||
sprintf(new_qos->domain_info[idx].name, "Idle Task%d", global_cpu);
|
||||
else
|
||||
sprintf(new_qos->domain_info[idx].name, "Domain#%d", domid);
|
||||
memset(&new_qos->domain_info[idx], 0, sizeof(_domain_info));
|
||||
new_qos->domain_info[idx].last_update_time = global_now;
|
||||
// runnable_start_time[idx] = 0;
|
||||
new_qos->domain_info[idx].runnable_start_time = 0; // invalidate
|
||||
new_qos->domain_info[idx].in_use = 1;
|
||||
new_qos->domain_info[idx].blocked_start_time = 0;
|
||||
new_qos->domain_info[idx].id = domid;
|
||||
if (domid == IDLE_DOMAIN_ID)
|
||||
sprintf(new_qos->domain_info[idx].name, "Idle Task%d", global_cpu);
|
||||
else
|
||||
sprintf(new_qos->domain_info[idx].name, "Domain#%d", domid);
|
||||
|
||||
for (i=0; i<NSAMPLES; i++) {
|
||||
new_qos->qdata[i].ns_gotten[idx] = 0;
|
||||
new_qos->qdata[i].ns_allocated[idx] = 0;
|
||||
new_qos->qdata[i].ns_waiting[idx] = 0;
|
||||
new_qos->qdata[i].ns_blocked[idx] = 0;
|
||||
new_qos->qdata[i].switchin_count[idx] = 0;
|
||||
new_qos->qdata[i].io_count[idx] = 0;
|
||||
}
|
||||
for (i=0; i<NSAMPLES; i++) {
|
||||
new_qos->qdata[i].ns_gotten[idx] = 0;
|
||||
new_qos->qdata[i].ns_allocated[idx] = 0;
|
||||
new_qos->qdata[i].ns_waiting[idx] = 0;
|
||||
new_qos->qdata[i].ns_blocked[idx] = 0;
|
||||
new_qos->qdata[i].switchin_count[idx] = 0;
|
||||
new_qos->qdata[i].io_count[idx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void global_init_domain(int domid, int idx)
|
||||
{
|
||||
int cpu;
|
||||
_new_qos_data *saved_qos;
|
||||
int cpu;
|
||||
_new_qos_data *saved_qos;
|
||||
|
||||
saved_qos = new_qos;
|
||||
saved_qos = new_qos;
|
||||
|
||||
for (cpu=0; cpu<NCPU; cpu++) {
|
||||
new_qos = cpu_qos_data[cpu];
|
||||
qos_init_domain(domid, idx);
|
||||
}
|
||||
new_qos = saved_qos;
|
||||
for (cpu=0; cpu<NCPU; cpu++) {
|
||||
new_qos = cpu_qos_data[cpu];
|
||||
qos_init_domain(domid, idx);
|
||||
}
|
||||
new_qos = saved_qos;
|
||||
}
|
||||
|
||||
|
||||
// give index of this domain in the qos data array
|
||||
int indexof(int domid)
|
||||
{
|
||||
int idx;
|
||||
xc_dominfo_t dominfo[NDOMAINS];
|
||||
int xc_handle, ndomains;
|
||||
extern void qos_kill_thread(int domid);
|
||||
int idx;
|
||||
xc_dominfo_t dominfo[NDOMAINS];
|
||||
int xc_handle, ndomains;
|
||||
extern void qos_kill_thread(int domid);
|
||||
|
||||
if (domid < 0) { // shouldn't happen
|
||||
printf("bad domain id: %d\r\n", domid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (idx=0; idx<NDOMAINS; idx++)
|
||||
if ( (new_qos->domain_info[idx].id == domid) && new_qos->domain_info[idx].in_use)
|
||||
return idx;
|
||||
|
||||
// not found, make a new entry
|
||||
for (idx=0; idx<NDOMAINS; idx++)
|
||||
if (new_qos->domain_info[idx].in_use == 0) {
|
||||
global_init_domain(domid, idx);
|
||||
return idx;
|
||||
if (domid < 0) { // shouldn't happen
|
||||
printf("bad domain id: %d\r\n", domid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// call domaininfo hypercall to try and garbage collect unused entries
|
||||
xc_handle = xc_interface_open();
|
||||
ndomains = xc_domain_getinfo(xc_handle, 0, NDOMAINS, dominfo);
|
||||
xc_interface_close(xc_handle);
|
||||
for (idx=0; idx<NDOMAINS; idx++)
|
||||
if ( (new_qos->domain_info[idx].id == domid) && new_qos->domain_info[idx].in_use)
|
||||
return idx;
|
||||
|
||||
// for each domain in our data, look for it in the system dominfo structure
|
||||
// and purge the domain's data from our state if it does not exist in the
|
||||
// dominfo structure
|
||||
for (idx=0; idx<NDOMAINS; idx++) {
|
||||
int domid = new_qos->domain_info[idx].id;
|
||||
int jdx;
|
||||
// not found, make a new entry
|
||||
for (idx=0; idx<NDOMAINS; idx++)
|
||||
if (new_qos->domain_info[idx].in_use == 0) {
|
||||
global_init_domain(domid, idx);
|
||||
return idx;
|
||||
}
|
||||
|
||||
// call domaininfo hypercall to try and garbage collect unused entries
|
||||
xc_handle = xc_interface_open();
|
||||
ndomains = xc_domain_getinfo(xc_handle, 0, NDOMAINS, dominfo);
|
||||
xc_interface_close(xc_handle);
|
||||
|
||||
// for each domain in our data, look for it in the system dominfo structure
|
||||
// and purge the domain's data from our state if it does not exist in the
|
||||
// dominfo structure
|
||||
for (idx=0; idx<NDOMAINS; idx++) {
|
||||
int domid = new_qos->domain_info[idx].id;
|
||||
int jdx;
|
||||
|
||||
for (jdx=0; jdx<ndomains; jdx++) {
|
||||
if (dominfo[jdx].domid == domid)
|
||||
break;
|
||||
for (jdx=0; jdx<ndomains; jdx++) {
|
||||
if (dominfo[jdx].domid == domid)
|
||||
break;
|
||||
}
|
||||
if (jdx == ndomains) // we didn't find domid in the dominfo struct
|
||||
if (domid != IDLE_DOMAIN_ID) // exception for idle domain, which is not
|
||||
// contained in dominfo
|
||||
qos_kill_thread(domid); // purge our stale data
|
||||
}
|
||||
if (jdx == ndomains) // we didn't find domid in the dominfo struct
|
||||
if (domid != IDLE_DOMAIN_ID) // exception for idle domain, which is not
|
||||
// contained in dominfo
|
||||
qos_kill_thread(domid); // purge our stale data
|
||||
}
|
||||
|
||||
// look again for a free slot
|
||||
for (idx=0; idx<NDOMAINS; idx++)
|
||||
if (new_qos->domain_info[idx].in_use == 0) {
|
||||
global_init_domain(domid, idx);
|
||||
return idx;
|
||||
}
|
||||
// look again for a free slot
|
||||
for (idx=0; idx<NDOMAINS; idx++)
|
||||
if (new_qos->domain_info[idx].in_use == 0) {
|
||||
global_init_domain(domid, idx);
|
||||
return idx;
|
||||
}
|
||||
|
||||
// still no space found, so bail
|
||||
fprintf(stderr, "out of space in domain table, increase NDOMAINS\r\n");
|
||||
exit(2);
|
||||
// still no space found, so bail
|
||||
fprintf(stderr, "out of space in domain table, increase NDOMAINS\r\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int domain_runnable(int domid)
|
||||
@@ -879,25 +878,25 @@ void qos_update_thread(int cpu, int domid, uint64_t now)
|
||||
time_since_update = now - last_update_time;
|
||||
|
||||
if (time_since_update < 0) {
|
||||
// what happened here? either a timestamp wraparound, or more likely,
|
||||
// a slight inconsistency among timestamps from various cpu's
|
||||
if (-time_since_update < billion) {
|
||||
// fairly small difference, let's just adjust 'now' to be a little
|
||||
// beyond last_update_time
|
||||
time_since_update = -time_since_update;
|
||||
}
|
||||
else if ( ((~0ULL - last_update_time) < billion) && (now < billion) ) {
|
||||
// difference is huge, must be a wraparound
|
||||
// last_update time should be "near" ~0ULL,
|
||||
// and now should be "near" 0
|
||||
time_since_update = now + (~0ULL - last_update_time);
|
||||
printf("time wraparound\n");
|
||||
}
|
||||
else {
|
||||
// none of the above, may be an out of order record
|
||||
// no good solution, just ignore and update again later
|
||||
return;
|
||||
}
|
||||
// what happened here? either a timestamp wraparound, or more likely,
|
||||
// a slight inconsistency among timestamps from various cpu's
|
||||
if (-time_since_update < billion) {
|
||||
// fairly small difference, let's just adjust 'now' to be a little
|
||||
// beyond last_update_time
|
||||
time_since_update = -time_since_update;
|
||||
}
|
||||
else if ( ((~0ULL - last_update_time) < billion) && (now < billion) ) {
|
||||
// difference is huge, must be a wraparound
|
||||
// last_update time should be "near" ~0ULL,
|
||||
// and now should be "near" 0
|
||||
time_since_update = now + (~0ULL - last_update_time);
|
||||
printf("time wraparound\n");
|
||||
}
|
||||
else {
|
||||
// none of the above, may be an out of order record
|
||||
// no good solution, just ignore and update again later
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
new_qos->domain_info[id].last_update_time = now;
|
||||
@@ -985,7 +984,7 @@ void qos_switch_in(int cpu, int domid, uint64_t now, unsigned long ns_alloc, uns
|
||||
|
||||
// count up page flips for dom0 execution
|
||||
if (domid == 0)
|
||||
dom0_flips = 0;
|
||||
dom0_flips = 0;
|
||||
}
|
||||
|
||||
// called when the current thread is taken off the cpu
|
||||
@@ -1011,8 +1010,8 @@ void qos_switch_out(int cpu, int domid, uint64_t now, unsigned long gotten)
|
||||
#if 0
|
||||
new_qos->qdata[n].ns_gotten[idx] += gotten;
|
||||
if (gotten > new_qos->qdata[n].ns_passed)
|
||||
printf("inconsistency #257, diff = %lld\n",
|
||||
gotten - new_qos->qdata[n].ns_passed );
|
||||
printf("inconsistency #257, diff = %lld\n",
|
||||
gotten - new_qos->qdata[n].ns_passed );
|
||||
#endif
|
||||
new_qos->domain_info[idx].ns_oncpu_since_boot += gotten;
|
||||
new_qos->domain_info[idx].runnable_start_time = now;
|
||||
@@ -1021,8 +1020,8 @@ void qos_switch_out(int cpu, int domid, uint64_t now, unsigned long gotten)
|
||||
|
||||
// process dom0 page flips
|
||||
if (domid == 0)
|
||||
if (dom0_flips == 0)
|
||||
new_qos->qdata[n].flip_free_periods++;
|
||||
if (dom0_flips == 0)
|
||||
new_qos->qdata[n].flip_free_periods++;
|
||||
}
|
||||
|
||||
// called when domain is put to sleep, may also be called
|
||||
@@ -1047,11 +1046,11 @@ void qos_state_sleeping(int cpu, int domid, uint64_t now)
|
||||
// domain died, presume it's dead on all cpu's, not just mostly dead
|
||||
void qos_kill_thread(int domid)
|
||||
{
|
||||
int cpu;
|
||||
int cpu;
|
||||
|
||||
for (cpu=0; cpu<NCPU; cpu++) {
|
||||
cpu_qos_data[cpu]->domain_info[indexof(domid)].in_use = 0;
|
||||
}
|
||||
for (cpu=0; cpu<NCPU; cpu++) {
|
||||
cpu_qos_data[cpu]->domain_info[indexof(domid)].in_use = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1060,7 +1059,7 @@ void qos_kill_thread(int domid)
|
||||
// when thread is already runnable
|
||||
void qos_state_runnable(int cpu, int domid, uint64_t now)
|
||||
{
|
||||
int idx;
|
||||
int idx;
|
||||
|
||||
|
||||
qos_update_thread_stats(cpu, domid, now);
|
||||
@@ -1080,79 +1079,85 @@ void qos_state_runnable(int cpu, int domid, uint64_t now)
|
||||
|
||||
void qos_count_packets(domid_t domid, uint64_t now)
|
||||
{
|
||||
int i, idx = indexof(domid);
|
||||
_new_qos_data *cpu_data;
|
||||
int i, idx = indexof(domid);
|
||||
_new_qos_data *cpu_data;
|
||||
|
||||
for (i=0; i<NCPU; i++) {
|
||||
cpu_data = cpu_qos_data[i];
|
||||
if (cpu_data->domain_info[idx].in_use) {
|
||||
cpu_data->qdata[cpu_data->next_datapoint].io_count[idx]++;
|
||||
for (i=0; i<NCPU; i++) {
|
||||
cpu_data = cpu_qos_data[i];
|
||||
if (cpu_data->domain_info[idx].in_use) {
|
||||
cpu_data->qdata[cpu_data->next_datapoint].io_count[idx]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new_qos->qdata[new_qos->next_datapoint].io_count[0]++;
|
||||
dom0_flips++;
|
||||
new_qos->qdata[new_qos->next_datapoint].io_count[0]++;
|
||||
dom0_flips++;
|
||||
}
|
||||
|
||||
|
||||
void process_record(int cpu, struct t_rec *r)
|
||||
int process_record(int cpu, struct t_rec *r)
|
||||
{
|
||||
uint64_t now;
|
||||
uint64_t now = 0;
|
||||
uint32_t *extra_u32 = r->u.nocycles.extra_u32;
|
||||
|
||||
new_qos = cpu_qos_data[cpu];
|
||||
new_qos = cpu_qos_data[cpu];
|
||||
|
||||
rec_count++;
|
||||
rec_count++;
|
||||
|
||||
now = ((double)r->cycles) / (opts.cpu_freq / 1000.0);
|
||||
if ( r->cycles_included )
|
||||
{
|
||||
now = ((uint64_t)r->u.cycles.cycles_hi << 32) | r->u.cycles.cycles_lo;
|
||||
now = ((double)now) / (opts.cpu_freq / 1000.0);
|
||||
extra_u32 = r->u.cycles.extra_u32;
|
||||
}
|
||||
|
||||
global_now = now;
|
||||
global_cpu = cpu;
|
||||
global_now = now;
|
||||
global_cpu = cpu;
|
||||
|
||||
log_event(r->event);
|
||||
log_event(r->event);
|
||||
|
||||
switch (r->event) {
|
||||
switch (r->event) {
|
||||
|
||||
case TRC_SCHED_SWITCH_INFPREV:
|
||||
// domain data[0] just switched out and received data[1] ns of cpu time
|
||||
qos_switch_out(cpu, r->data[0], now, r->data[1]);
|
||||
// printf("ns_gotten %ld\n", r->data[1]);
|
||||
break;
|
||||
case TRC_SCHED_SWITCH_INFPREV:
|
||||
// domain data[0] just switched out and received data[1] ns of cpu time
|
||||
qos_switch_out(cpu, extra_u32[0], now, extra_u32[1]);
|
||||
// printf("ns_gotten %ld\n", extra_u32[1]);
|
||||
break;
|
||||
|
||||
case TRC_SCHED_SWITCH_INFNEXT:
|
||||
// domain data[0] just switched in and
|
||||
// waited data[1] ns, and was allocated data[2] ns of cpu time
|
||||
qos_switch_in(cpu, r->data[0], now, r->data[2], r->data[1]);
|
||||
break;
|
||||
case TRC_SCHED_SWITCH_INFNEXT:
|
||||
// domain data[0] just switched in and
|
||||
// waited data[1] ns, and was allocated data[2] ns of cpu time
|
||||
qos_switch_in(cpu, extra_u32[0], now, extra_u32[2], extra_u32[1]);
|
||||
break;
|
||||
|
||||
case TRC_SCHED_DOM_ADD:
|
||||
(void) indexof(r->data[0]);
|
||||
break;
|
||||
case TRC_SCHED_DOM_ADD:
|
||||
(void) indexof(extra_u32[0]);
|
||||
break;
|
||||
|
||||
case TRC_SCHED_DOM_REM:
|
||||
qos_kill_thread(r->data[0]);
|
||||
break;
|
||||
case TRC_SCHED_DOM_REM:
|
||||
qos_kill_thread(extra_u32[0]);
|
||||
break;
|
||||
|
||||
case TRC_SCHED_SLEEP:
|
||||
qos_state_sleeping(cpu, r->data[0], now);
|
||||
break;
|
||||
case TRC_SCHED_SLEEP:
|
||||
qos_state_sleeping(cpu, extra_u32[0], now);
|
||||
break;
|
||||
|
||||
case TRC_SCHED_WAKE:
|
||||
qos_state_runnable(cpu, r->data[0], now);
|
||||
break;
|
||||
case TRC_SCHED_WAKE:
|
||||
qos_state_runnable(cpu, extra_u32[0], now);
|
||||
break;
|
||||
|
||||
case TRC_SCHED_BLOCK:
|
||||
qos_state_sleeping(cpu, r->data[0], now);
|
||||
break;
|
||||
case TRC_SCHED_BLOCK:
|
||||
qos_state_sleeping(cpu, extra_u32[0], now);
|
||||
break;
|
||||
|
||||
case TRC_MEM_PAGE_GRANT_TRANSFER:
|
||||
qos_count_packets(r->data[0], now);
|
||||
break;
|
||||
case TRC_MEM_PAGE_GRANT_TRANSFER:
|
||||
qos_count_packets(extra_u32[0], now);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
new_qos = NULL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
new_qos = NULL;
|
||||
|
||||
return 4 + (r->cycles_included ? 8 : 0) + (r->extra_u32 * 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ void write_buffer(unsigned int cpu, unsigned char *start, int size,
|
||||
/* Write a CPU_BUF record on each buffer "window" written. Wrapped
|
||||
* windows may involve two writes, so only write the record on the
|
||||
* first write. */
|
||||
if(total_size)
|
||||
if ( total_size != 0 )
|
||||
{
|
||||
struct {
|
||||
uint32_t header;
|
||||
@@ -119,7 +119,8 @@ void write_buffer(unsigned int cpu, unsigned char *start, int size,
|
||||
|
||||
written = write(outfd, &rec, sizeof(rec));
|
||||
|
||||
if(written!=sizeof(rec)) {
|
||||
if ( written != sizeof(rec) )
|
||||
{
|
||||
fprintf(stderr, "Cannot write cpu change (write returned %d)\n",
|
||||
written);
|
||||
goto fail;
|
||||
@@ -127,12 +128,15 @@ void write_buffer(unsigned int cpu, unsigned char *start, int size,
|
||||
}
|
||||
|
||||
written = write(outfd, start, size);
|
||||
if ( written != size ) {
|
||||
if ( written != size )
|
||||
{
|
||||
fprintf(stderr, "Write failed! (size %d, returned %d)\n",
|
||||
size, written);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
PERROR("Failed to write trace data");
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -337,7 +341,7 @@ int monitor_tbufs(int outfd)
|
||||
get_tbufs(&tbufs_mfn, &size);
|
||||
tbufs_mapped = map_tbufs(tbufs_mfn, num, size);
|
||||
|
||||
data_size = (size - sizeof(struct t_buf));
|
||||
data_size = size - sizeof(struct t_buf);
|
||||
|
||||
/* build arrays of convenience ptrs */
|
||||
meta = init_bufs_ptrs(tbufs_mapped, num, size);
|
||||
@@ -353,13 +357,13 @@ int monitor_tbufs(int outfd)
|
||||
for ( i = 0; (i < num) && !interrupted; i++ )
|
||||
{
|
||||
unsigned long start_offset, end_offset, window_size, cons, prod;
|
||||
rmb(); /* read prod, then read item. */
|
||||
|
||||
/* Read window information only once. */
|
||||
cons = meta[i]->cons;
|
||||
prod = meta[i]->prod;
|
||||
rmb(); /* read prod, then read item. */
|
||||
|
||||
if(cons == prod)
|
||||
if ( cons == prod )
|
||||
continue;
|
||||
|
||||
assert(prod > cons);
|
||||
@@ -368,7 +372,7 @@ int monitor_tbufs(int outfd)
|
||||
start_offset = cons % data_size;
|
||||
end_offset = prod % data_size;
|
||||
|
||||
if(end_offset > start_offset)
|
||||
if ( end_offset > start_offset )
|
||||
{
|
||||
/* If window does not wrap, write in one big chunk */
|
||||
write_buffer(i, data[i]+start_offset,
|
||||
@@ -382,7 +386,7 @@ int monitor_tbufs(int outfd)
|
||||
* - first, start to the end of the buffer
|
||||
* - second, start of buffer to end of window
|
||||
*/
|
||||
write_buffer(i, data[i]+start_offset,
|
||||
write_buffer(i, data[i] + start_offset,
|
||||
data_size - start_offset,
|
||||
window_size,
|
||||
outfd);
|
||||
|
||||
+26
-57
@@ -233,7 +233,7 @@ static inline int calc_rec_size(int cycles, int extra)
|
||||
{
|
||||
int rec_size;
|
||||
rec_size = 4;
|
||||
if(cycles)
|
||||
if ( cycles )
|
||||
rec_size += 8;
|
||||
rec_size += extra;
|
||||
return rec_size;
|
||||
@@ -254,10 +254,10 @@ static inline int __insert_record(struct t_buf *buf,
|
||||
int extra,
|
||||
int cycles,
|
||||
int rec_size,
|
||||
unsigned char * extra_data)
|
||||
unsigned char *extra_data)
|
||||
{
|
||||
struct t_rec *rec;
|
||||
unsigned char * dst;
|
||||
unsigned char *dst;
|
||||
unsigned long extra_word = extra/sizeof(u32);
|
||||
int local_rec_size = calc_rec_size(cycles, extra);
|
||||
|
||||
@@ -266,7 +266,7 @@ static inline int __insert_record(struct t_buf *buf,
|
||||
/* Double-check once more that we have enough space.
|
||||
* Don't bugcheck here, in case the userland tool is doing
|
||||
* something stupid. */
|
||||
if(calc_bytes_avail(buf) < rec_size )
|
||||
if ( calc_bytes_avail(buf) < rec_size )
|
||||
{
|
||||
printk("%s: %u bytes left (%u - (%u - %u)) recsize %u.\n",
|
||||
__func__,
|
||||
@@ -278,25 +278,22 @@ static inline int __insert_record(struct t_buf *buf,
|
||||
rmb();
|
||||
|
||||
rec = (struct t_rec *)&this_cpu(t_data)[buf->prod % data_size];
|
||||
rec->header = event;
|
||||
rec->header |= extra_word << TRACE_EXTRA_SHIFT;
|
||||
if(cycles)
|
||||
rec->event = event;
|
||||
rec->extra_u32 = extra_word;
|
||||
dst = (unsigned char *)rec->u.nocycles.extra_u32;
|
||||
if ( (rec->cycles_included = cycles) != 0 )
|
||||
{
|
||||
u64 tsc = (u64)get_cycles();
|
||||
|
||||
rec->header |= TRC_HD_CYCLE_FLAG;
|
||||
rec->u.cycles.cycles_lo = tsc & ((((u64)1)<<32)-1);
|
||||
rec->u.cycles.cycles_hi = tsc >> 32;
|
||||
dst = rec->u.cycles.data;
|
||||
rec->u.cycles.cycles_lo = (uint32_t)tsc;
|
||||
rec->u.cycles.cycles_hi = (uint32_t)(tsc >> 32);
|
||||
dst = (unsigned char *)rec->u.cycles.extra_u32;
|
||||
}
|
||||
else
|
||||
dst = rec->u.nocycles.data;
|
||||
|
||||
if(extra_data && extra)
|
||||
if ( extra_data && extra )
|
||||
memcpy(dst, extra_data, extra);
|
||||
|
||||
wmb();
|
||||
buf->prod+=rec_size;
|
||||
buf->prod += rec_size;
|
||||
|
||||
return rec_size;
|
||||
}
|
||||
@@ -305,24 +302,18 @@ static inline int insert_wrap_record(struct t_buf *buf, int size)
|
||||
{
|
||||
int space_left = calc_bytes_to_wrap(buf);
|
||||
unsigned long extra_space = space_left - sizeof(u32);
|
||||
int cycles=0;
|
||||
|
||||
if(space_left > size)
|
||||
printk("%s: space_left %d, size %d!\n",
|
||||
__func__, space_left, size);
|
||||
int cycles = 0;
|
||||
|
||||
BUG_ON(space_left > size);
|
||||
|
||||
/* We may need to add cycles to take up enough space... */
|
||||
if((extra_space/sizeof(u32)) > TRACE_EXTRA_MAX)
|
||||
if ( (extra_space/sizeof(u32)) > TRACE_EXTRA_MAX )
|
||||
{
|
||||
cycles = 1;
|
||||
extra_space -= sizeof(u64);
|
||||
|
||||
ASSERT((extra_space/sizeof(u32)) <= TRACE_EXTRA_MAX);
|
||||
}
|
||||
|
||||
|
||||
return __insert_record(buf,
|
||||
TRC_TRACE_WRAP_BUFFER,
|
||||
extra_space,
|
||||
@@ -433,9 +424,9 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
|
||||
* avoid if we can. So do the math, check it in debug versions, and
|
||||
* do a final check always if we happen to write a record.
|
||||
*/
|
||||
if(this_cpu(lost_records))
|
||||
if ( this_cpu(lost_records) )
|
||||
{
|
||||
if(LOST_REC_SIZE > bytes_to_wrap)
|
||||
if ( LOST_REC_SIZE > bytes_to_wrap )
|
||||
{
|
||||
total_size += bytes_to_wrap;
|
||||
bytes_to_wrap = data_size;
|
||||
@@ -443,7 +434,7 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
|
||||
else
|
||||
{
|
||||
bytes_to_wrap -= LOST_REC_SIZE;
|
||||
if(bytes_to_wrap == 0)
|
||||
if ( bytes_to_wrap == 0 )
|
||||
bytes_to_wrap == data_size;
|
||||
}
|
||||
total_size += LOST_REC_SIZE;
|
||||
@@ -451,7 +442,7 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
|
||||
|
||||
ASSERT(bytes_to_wrap == calc_bytes_to_wrap(buf));
|
||||
|
||||
if(rec_size > bytes_to_wrap)
|
||||
if ( rec_size > bytes_to_wrap )
|
||||
{
|
||||
total_size += bytes_to_wrap;
|
||||
bytes_to_wrap = data_size;
|
||||
@@ -464,7 +455,7 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
|
||||
total_size += rec_size;
|
||||
|
||||
/* Do we have enough space for everything? */
|
||||
if(total_size > bytes_to_tail)
|
||||
if ( total_size > bytes_to_tail )
|
||||
{
|
||||
this_cpu(lost_records)++;
|
||||
local_irq_restore(flags);
|
||||
@@ -476,9 +467,9 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
|
||||
*/
|
||||
bytes_to_wrap = calc_bytes_to_wrap(buf);
|
||||
|
||||
if(this_cpu(lost_records))
|
||||
if ( this_cpu(lost_records) )
|
||||
{
|
||||
if(LOST_REC_SIZE > bytes_to_wrap)
|
||||
if ( LOST_REC_SIZE > bytes_to_wrap )
|
||||
{
|
||||
insert_wrap_record(buf, LOST_REC_SIZE);
|
||||
bytes_to_wrap = data_size;
|
||||
@@ -487,7 +478,7 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
|
||||
{
|
||||
bytes_to_wrap -= LOST_REC_SIZE;
|
||||
/* LOST_REC might line up perfectly with the buffer wrap */
|
||||
if(bytes_to_wrap == 0)
|
||||
if ( bytes_to_wrap == 0 )
|
||||
bytes_to_wrap = data_size;
|
||||
}
|
||||
insert_lost_records(buf);
|
||||
@@ -495,42 +486,20 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
|
||||
|
||||
ASSERT(bytes_to_wrap == calc_bytes_to_wrap(buf));
|
||||
|
||||
if(rec_size > bytes_to_wrap)
|
||||
{
|
||||
if ( rec_size > bytes_to_wrap )
|
||||
insert_wrap_record(buf, rec_size);
|
||||
}
|
||||
|
||||
/* Write the original record */
|
||||
__insert_record(buf, event, extra, cycles, rec_size, extra_data);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
/*
|
||||
* Notify trace buffer consumer that we've crossed the high water mark.
|
||||
*
|
||||
*/
|
||||
/* Notify trace buffer consumer that we've crossed the high water mark. */
|
||||
if ( started_below_highwater
|
||||
&& ( (buf->prod - buf->cons) > t_buf_highwater ) )
|
||||
&& ((buf->prod - buf->cons) > t_buf_highwater) )
|
||||
raise_softirq(TRACE_SOFTIRQ);
|
||||
}
|
||||
|
||||
|
||||
void __trace_fixed(u32 event, unsigned long d1, unsigned long d2,
|
||||
unsigned long d3, unsigned long d4, unsigned long d5)
|
||||
{
|
||||
u32 extra_data[5];
|
||||
|
||||
/* In a 64-bit hypervisor, this will truncate to 32 bits. */
|
||||
extra_data[0]=d1;
|
||||
extra_data[1]=d2;
|
||||
extra_data[2]=d3;
|
||||
extra_data[3]=d4;
|
||||
extra_data[4]=d5;
|
||||
|
||||
__trace_var(event, 1/* include cycles */, sizeof(*extra_data)*5,
|
||||
(unsigned char *)extra_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -103,23 +103,22 @@
|
||||
#define TRC_HVM_MMIO_ASSIST (TRC_HVM_HANDLER + 0x17)
|
||||
#define TRC_HVM_CLTS (TRC_HVM_HANDLER + 0x18)
|
||||
#define TRC_HVM_LMSW (TRC_HVM_HANDLER + 0x19)
|
||||
#define TRC_HVM_PF_XEN64 (TRC_HVM_HANDLER + 0x20)
|
||||
#define TRC_HVM_PF_XEN64 (TRC_HVM_HANDLER + 0x20)
|
||||
|
||||
/* This structure represents a single trace buffer record. */
|
||||
struct t_rec {
|
||||
uint32_t header; /* 31 : Cycles included?
|
||||
30-28: # of extra words
|
||||
27- 0: event ID */
|
||||
uint32_t event:28;
|
||||
uint32_t extra_u32:3; /* # entries in trailing extra_u32[] array */
|
||||
uint32_t cycles_included:1; /* u.cycles or u.no_cycles? */
|
||||
union {
|
||||
struct {
|
||||
uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */
|
||||
unsigned char data[28]; /* event data items */
|
||||
uint32_t extra_u32[7]; /* event data items */
|
||||
} cycles;
|
||||
struct {
|
||||
unsigned char data[28]; /* event data items */
|
||||
uint32_t extra_u32[7]; /* event data items */
|
||||
} nocycles;
|
||||
}u;
|
||||
|
||||
} u;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -33,18 +33,8 @@ void init_trace_bufs(void);
|
||||
/* used to retrieve the physical address of the trace buffers */
|
||||
int tb_control(struct xen_sysctl_tbuf_op *tbc);
|
||||
|
||||
void __trace_fixed(u32 event, unsigned long d1, unsigned long d2,
|
||||
unsigned long d3, unsigned long d4, unsigned long d5);
|
||||
void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data);
|
||||
|
||||
static inline void trace_fixed(u32 event, unsigned long d1,
|
||||
unsigned long d2, unsigned long d3,
|
||||
unsigned long d4, unsigned long d5)
|
||||
{
|
||||
if( unlikely(tb_init_done) )
|
||||
__trace_fixed(event, d1, d2, d3, d4, d5);
|
||||
}
|
||||
|
||||
static inline void trace_var(u32 event, int cycles, int extra,
|
||||
unsigned char *extra_data)
|
||||
{
|
||||
|
||||