|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 1 of 2] xenalyze: decode PV_HYPERCALL_V2 records
On Thu, Oct 4, 2012 at 1:28 PM, David Vrabel <david.vrabel@xxxxxxxxxx> wrote:
> Newer version of Xen produce TRC_PV_HYPERCALL_V2 records instead of
> the older TRC_PV_HYPERCALL format. This updated format doesn't
> included the IP but it does include select hypercall arguments.
>
> Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>
You had a couple of stray SUBCALL things in this patch which cause it
to fail compilation; I moved them to the next patch and have committed
both patches. Thanks.
-George.
>
> diff --git a/analyze.h b/analyze.h
> --- a/analyze.h
> +++ b/analyze.h
> @@ -3,6 +3,8 @@
>
> #include <stdint.h>
>
> +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
> +
> #define TRC_GEN_MAIN 0
> #define TRC_SCHED_MAIN 1
> #define TRC_DOM0OP_MAIN 2
> diff --git a/pv.h b/pv.h
> new file mode 100644
> --- /dev/null
> +++ b/pv.h
> @@ -0,0 +1,41 @@
> +/*
> + * PV event decoding.
> + *
> + * Copyright (C) 2012 Citrix Systems R&D Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + */
> +#ifndef __PV_H
> +
> +#include "analyze.h"
> +#include "trace.h"
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#define ARG_MISSING 0x0
> +#define ARG_32BIT 0x1
> +#define ARG_64BIT 0x2
> +
> +#define MMU_UPDATE_PREEMPTED (~(~0U>>1))
> +
> +static inline uint32_t pv_hypercall_op(const struct record_info *ri)
> +{
> + return ri->d[0] & ~TRC_PV_HYPERCALL_V2_ARG_MASK;
> +}
> +
> +static inline int pv_hypercall_arg_present(const struct record_info *ri, int
> arg)
> +{
> + return (ri->d[0] >> (20 + 2*arg)) & 0x3;
> +}
> +
> +void pv_hypercall_gather_args(const struct record_info *ri, uint64_t *args);
> +
> +#ifdef __cplusplus
> +} /* extern "C" */
> +#endif
> +
> +#endif
> diff --git a/xenalyze.c b/xenalyze.c
> --- a/xenalyze.c
> +++ b/xenalyze.c
> @@ -32,6 +32,7 @@
> #include "trace.h"
> #include "analyze.h"
> #include "mread.h"
> +#include "pv.h"
> #include <errno.h>
> #include <strings.h>
> #include <string.h>
> @@ -1485,6 +1486,7 @@ enum {
> PV_GDT_LDT_MAPPING_FAULT,
> PV_PTWR_EMULATION,
> PV_PTWR_EMULATION_PAE,
> + PV_HYPERCALL_V2 = 13,
> PV_MAX
> };
>
> @@ -1499,7 +1501,9 @@ char *pv_name[PV_MAX] = {
> [PV_PAGING_FIXUP]="paging fixup",
> [PV_GDT_LDT_MAPPING_FAULT]="gdt/ldt mapping fault",
> [PV_PTWR_EMULATION]="ptwr",
> - [PV_PTWR_EMULATION_PAE]="ptwr(pae)"
> + [PV_PTWR_EMULATION_PAE]="ptwr(pae)",
> + [PV_HYPERCALL_V2]="hypercall",
> + [PV_HYPERCALL_SUBCALL]="hypercall (subcall)",
> };
>
> #define PV_HYPERCALL_MAX 56
> @@ -6500,10 +6504,20 @@ void pv_summary(struct pv_data *pv) {
>
> printf("PV events:\n");
> for(i=0; i<PV_MAX; i++) {
> - if(pv->count[i])
> - printf(" %s %d\n", pv_name[i], pv->count[i]);
> + int count;
> +
> + count = pv->count[i];
> + if (i == PV_HYPERCALL_V2)
> + count += pv->count[PV_HYPERCALL_SUBCALL];
> +
> + if (count == 0)
> + continue;
> +
> + printf(" %s %d\n", pv_name[i], count);
> +
> switch(i) {
> case PV_HYPERCALL:
> + case PV_HYPERCALL_V2:
> for(j=0; j<PV_HYPERCALL_MAX; j++) {
> if(pv->hypercall_count[j])
> printf(" %-29s[%2d]: %6d\n",
> @@ -6523,6 +6537,145 @@ void pv_summary(struct pv_data *pv) {
> }
> }
>
> +static const char *grant_table_op_str[] = {
> + "map_grant_ref", "unmap_grant_ref", "setup_table", "dump_table",
> + "transfer", "copy", "query_size", "unmap_and_replace",
> + "set_version", "get_status_frames", "get_version", "swap_grant_ref",
> +};
> +
> +static const char *vcpu_op_str[] = {
> + "initialise", "up", "down", "is_up", "get_runstate_info",
> + "register_runstate_memory_area", "set_periodic_timer",
> + "stop_periodic_timer", "set_singleshot_timer", "stop_singleshot_timer",
> + "register_vcpu_info", "send_nmi", "get_physid",
> + "register_vcpu_time_memory_area",
> +};
> +
> +static const char *sched_op_str[] = {
> + "yield", "block", "shutdown", "poll", "remote_shutdown", "shutdown_code",
> + "watchdog",
> +};
> +
> +static const char *cmd_to_str(const char *strings[], size_t n, uint32_t cmd)
> +{
> + static char buf[32];
> +
> + if (cmd < n)
> + return strings[cmd];
> +
> + snprintf(buf, sizeof(buf), "unknown (%d)", cmd);
> + return buf;
> +}
> +
> +#define CMD_TO_STR(op) \
> + static const char * op ## _to_str(uint32_t cmd) { \
> + return cmd_to_str(op ## _str, ARRAY_SIZE(op ## _str), cmd); \
> + }
> +
> +CMD_TO_STR(grant_table_op);
> +CMD_TO_STR(vcpu_op);
> +CMD_TO_STR(sched_op);
> +
> +void pv_hypercall_gather_args(const struct record_info *ri, uint64_t *args)
> +{
> + int i, word;
> +
> + /* Missing arguments are zeroed. */
> + memset(args, 0, 6 * sizeof(uint64_t));
> +
> + for (i = 0, word = 1; i < 6 && word < ri->extra_words; i++) {
> + int present = pv_hypercall_arg_present(ri, i);
> +
> + switch (present) {
> + case ARG_32BIT:
> + args[i] = ri->d[word];
> + break;
> + case ARG_64BIT:
> + args[i] = ((uint64_t)ri->d[word + 1] << 32) | ri->d[word];
> + break;
> + }
> +
> + /* Skip over any words for this argument. */
> + word += present;
> + }
> +}
> +
> +static void pv_hypercall_print_args(const struct record_info *ri)
> +{
> + int i, word;
> +
> + for (i = 0, word = 1; i < 6 && word < ri->extra_words; i++) {
> + int present = pv_hypercall_arg_present(ri, i);
> +
> + switch (present) {
> + case ARG_MISSING:
> + printf(" ??");
> + break;
> + case ARG_32BIT:
> + printf(" %08x", ri->d[word]);
> + break;
> + case ARG_64BIT:
> + printf(" %016"PRIu64"", ((uint64_t)ri->d[word + 1] << 32) |
> ri->d[word]);
> + break;
> + }
> +
> + word += present;
> + }
> +}
> +
> +void pv_hypercall_v2_process(struct record_info *ri, struct pv_data *pv)
> +{
> + int op = pv_hypercall_op(ri);
> +
> + if(opt.summary_info) {
> + if(op < PV_HYPERCALL_MAX)
> + pv->hypercall_count[op]++;
> + }
> +
> + if(opt.dump_all) {
> + uint64_t args[6];
> +
> + if(op < HYPERCALL_MAX)
> + printf(" %s hypercall %2x (%s)",
> + ri->dump_header, op, hypercall_name[op]);
> + else
> + printf(" %s hypercall %2x",
> + ri->dump_header, op);
> +
> + switch(op) {
> + case HYPERCALL_mmu_update:
> + pv_hypercall_gather_args(ri, args);
> + printf(" %d updates%s", (uint32_t)args[1] &
> ~MMU_UPDATE_PREEMPTED,
> + (args[1] & MMU_UPDATE_PREEMPTED) ? " (preempted)" : "");
> + break;
> + case HYPERCALL_multicall:
> + pv_hypercall_gather_args(ri, args);
> + printf(" %d calls", (uint32_t)args[1]);
> + break;
> + case HYPERCALL_grant_table_op:
> + pv_hypercall_gather_args(ri, args);
> + printf(" %s %d ops", grant_table_op_to_str(args[0]),
> (uint32_t)args[2]);
> + break;
> + case HYPERCALL_vcpu_op:
> + pv_hypercall_gather_args(ri, args);
> + printf(" %s vcpu %d", vcpu_op_to_str(args[0]),
> (uint32_t)args[1]);
> + break;
> + case HYPERCALL_mmuext_op:
> + pv_hypercall_gather_args(ri, args);
> + printf(" %d ops", (uint32_t)args[1]);
> + break;
> + case HYPERCALL_sched_op:
> + pv_hypercall_gather_args(ri, args);
> + printf(" %s", sched_op_to_str(args[0]));
> + break;
> + default:
> + pv_hypercall_print_args(ri);
> + break;
> + }
> + printf("\n");
> + }
> +}
> +
> void pv_process(struct pcpu_info *p)
> {
> struct record_info *ri = &p->ri;
> @@ -6555,9 +6708,9 @@ void pv_process(struct pcpu_info *p)
> case PV_PTWR_EMULATION_PAE:
> pv_ptwr_emulation_process(ri, pv);
> break;
> - case PV_PAGE_FAULT:
> - //pv_pf_process(ri, pv);
> - //break;
> + case PV_HYPERCALL_V2:
> + pv_hypercall_v2_process(ri, pv);
> + break;
> default:
> pv_generic_process(ri, pv);
> break;
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |