diff -Naurp --exclude=configure --exclude=doc oprofile-0.8.1/daemon/init.c oprofile-0.8.1.xenoprof/daemon/init.c --- oprofile-0.8.1/daemon/init.c 2004-05-30 01:02:58.000000000 +0800 +++ oprofile-0.8.1.xenoprof/daemon/init.c 2005-08-14 19:13:33.000000000 +0800 @@ -7,6 +7,9 @@ * * @author John Levon * @author Philippe Elie + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. */ #include "config.h" @@ -221,6 +224,9 @@ static void opd_26_init(void) size_t opd_buf_size; opd_create_vmlinux(vmlinux, kernel_range); + opd_create_xen(xenimage, xen_range); + if (passive_ids) + opd_create_passive(passive_ids); opd_buf_size = opd_read_fs_int("/dev/oprofile/", "buffer_size", 1); kernel_pointer_size = opd_read_fs_int("/dev/oprofile/", "pointer_size", 1); diff -Naurp --exclude=configure --exclude=doc oprofile-0.8.1/daemon/opd_interface.h oprofile-0.8.1.xenoprof/daemon/opd_interface.h --- oprofile-0.8.1/daemon/opd_interface.h 2004-05-30 01:02:58.000000000 +0800 +++ oprofile-0.8.1.xenoprof/daemon/opd_interface.h 2005-08-02 15:28:37.000000000 +0800 @@ -8,6 +8,9 @@ * * @author John Levon * @author Philippe Elie + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. */ #ifndef OPD_INTERFACE_H @@ -17,11 +20,13 @@ #define CPU_SWITCH_CODE 2 #define COOKIE_SWITCH_CODE 3 #define KERNEL_ENTER_SWITCH_CODE 4 -#define KERNEL_EXIT_SWITCH_CODE 5 +#define USER_ENTER_SWITCH_CODE 5 #define MODULE_LOADED_CODE 6 #define CTX_TGID_CODE 7 #define TRACE_BEGIN_CODE 8 #define TRACE_END_CODE 9 -#define LAST_CODE 10 +#define XEN_ENTER_SWITCH_CODE 10 +#define DOMAIN_SWITCH_CODE 11 +#define LAST_CODE 12 #endif /* OPD_INTERFACE_H */ diff -Naurp --exclude=configure --exclude=doc oprofile-0.8.1/daemon/opd_kernel.c oprofile-0.8.1.xenoprof/daemon/opd_kernel.c --- oprofile-0.8.1/daemon/opd_kernel.c 2004-05-30 01:02:58.000000000 +0800 +++ oprofile-0.8.1.xenoprof/daemon/opd_kernel.c 2005-08-24 19:35:12.000000000 +0800 @@ -7,6 +7,9 @@ * * @author John Levon * @author Philippe Elie + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. */ #include "opd_kernel.h" @@ -24,10 +27,18 @@ #include #include #include +#include static LIST_HEAD(modules); +static LIST_HEAD(other_domains); + +static LIST_HEAD(passive_vmlinux); +static LIST_HEAD(passive_xen); +static LIST_HEAD(passive_apps); + static struct kernel_image vmlinux_image; +static struct kernel_image xen_image; void opd_create_vmlinux(char const * name, char const * arg) { @@ -54,6 +65,76 @@ void opd_create_vmlinux(char const * nam } } +void opd_create_xen(char const * name, char const * arg) +{ + /* xen is *not* on the list of modules */ + list_init(&xen_image.list); + + /* for no xen */ + if (no_xen) { + xen_image.name = "no-xen"; + return; + } + + xen_image.name = xstrdup(name); + + sscanf(arg, "%llx,%llx", &xen_image.start, &xen_image.end); + + verbprintf(vmisc, "xen_start = %llx, xen_end = %llx\n", + xen_image.start, xen_image.end); + + if (!xen_image.start && !xen_image.end) { + fprintf(stderr, "error: mis-parsed xen range: %llx-%llx\n", + xen_image.start, xen_image.end); + exit(EXIT_FAILURE); + } +} + +void opd_create_passive(char const *name) +{ + char *p; + int id; + char file[64]; + struct kernel_image * image; + + while (1) { + id = strtol(name, &p, 0); + if (p == name) + break; + + sprintf(file, "/boot/pvmlinux%d-syms", id); + printf("shine: %s\n", file); + image = xmalloc(sizeof(struct kernel_image)); + image->name = xstrdup(file); + // start/end VM should be more accurate, but it works now + image->start = 0xc0100000; + image->end = 0xc0600000; + image->id = id; + list_add(&image->list, &passive_vmlinux); + + sprintf(file, "/boot/pxen%d-syms", id); + printf("shine: %s\n", file); + image = xmalloc(sizeof(struct kernel_image)); + image->name = xstrdup(file); + image->start = xen_image.start; + image->end = xen_image.end; + image->id = id; + list_add(&image->list, &passive_xen); + + sprintf(file, "/boot/papps%d-syms", id); + printf("shine: %s\n", file); + image = xmalloc(sizeof(struct kernel_image)); + image->name = xstrdup(file); + image->start = 0; + image->end = 0; + image->id = id; + list_add(&image->list, &passive_apps); + + while (ispunct(*p)) + p++; + name = p; + } +} /** * Allocate and initialise a kernel image description @@ -166,6 +247,7 @@ void opd_reread_module_info(void) op_close_file(fp); } +extern long long other_domain; /** * find a kernel image by PC value @@ -179,6 +261,37 @@ struct kernel_image * find_kernel_image( { struct list_head * pos; struct kernel_image * image = &vmlinux_image; + + if (other_domain != -1) { + list_for_each(pos, &passive_xen) { + image = list_entry(pos, struct kernel_image, list); + if (image->id == other_domain + && image->start <= trans->pc + && image->end > trans->pc) { + printf("shine: in pxen, id=%lld, %p\n", other_domain, trans->pc); + return image; + } + } + list_for_each(pos, &passive_vmlinux) { + image = list_entry(pos, struct kernel_image, list); + if (image->id == other_domain + && image->start <= trans->pc + && image->end > trans->pc) { + printf("shine: in pvmlinux, id=%lld, %p\n", other_domain, trans->pc); + return image; + } + } + list_for_each(pos, &passive_apps) { + image = list_entry(pos, struct kernel_image, list); + if (image->id == other_domain) { + printf("shine: in papps, id=%lld, %p\n", other_domain, trans->pc); + return image; + } + } + } + + if (xen_image.start <= trans->pc && xen_image.end > trans->pc) + return &xen_image; if (no_vmlinux) return image; diff -Naurp --exclude=configure --exclude=doc oprofile-0.8.1/daemon/opd_kernel.h oprofile-0.8.1.xenoprof/daemon/opd_kernel.h --- oprofile-0.8.1/daemon/opd_kernel.h 2004-05-30 01:02:58.000000000 +0800 +++ oprofile-0.8.1.xenoprof/daemon/opd_kernel.h 2005-08-23 13:40:42.000000000 +0800 @@ -7,6 +7,9 @@ * * @author John Levon * @author Philippe Elie + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. */ #ifndef OPD_KERNEL_H @@ -20,6 +23,9 @@ struct transient; /** create the kernel image */ void opd_create_vmlinux(char const * name, char const * arg); +void opd_create_xen(char const * name, char const * arg); +void opd_create_passive(char const * name); + /** opd_reread_module_info - parse /proc/modules for kernel modules */ void opd_reread_module_info(void); @@ -28,6 +34,7 @@ struct kernel_image { char * name; vma_t start; vma_t end; + int id; struct list_head list; }; diff -Naurp --exclude=configure --exclude=doc oprofile-0.8.1/daemon/opd_trans.c oprofile-0.8.1.xenoprof/daemon/opd_trans.c --- oprofile-0.8.1/daemon/opd_trans.c 2004-05-30 01:02:58.000000000 +0800 +++ oprofile-0.8.1.xenoprof/daemon/opd_trans.c 2005-08-23 13:33:25.000000000 +0800 @@ -7,6 +7,9 @@ * * @author John Levon * @author Philippe Elie + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. */ #include "opd_trans.h" @@ -189,7 +192,7 @@ static void code_kernel_enter(struct tra } -static void code_kernel_exit(struct transient * trans) +static void code_user_enter(struct transient * trans) { verbprintf(vmisc, "KERNEL_EXIT_SWITCH to user-space\n"); trans->in_kernel = 0; @@ -218,6 +221,30 @@ static void code_trace_end(struct transi trans->tracing = TRACING_OFF; } +static void code_xen_enter(struct transient *trans) +{ + verbprintf(vmisc, "XEN_ENTER_SWITCH to xen\n"); + trans->in_kernel = 1; + trans->current = NULL; + /* subtlety: we must keep trans->cookie cached, + * even though it's meaningless for Xen - + * we won't necessarily get a cookie switch on + * Xen exit. See comments in opd_sfile.c. + * It seems that we can get away with in_kernel = 1 as long as we + * supply the correct Xen image, and its address range in startup + * find_kernel_image is modified to look in the Xen image also + */ +} + +long long other_domain = -1; + +static void code_domain_switch(struct transient *trans) +{ + /* We have to remember the old kernel value, so we do the safe thing: increment */ + trans->in_kernel++; + trans->current = NULL; + other_domain = pop_buffer_value(trans); +} typedef void (*handler_t)(struct transient *); @@ -227,12 +254,14 @@ static handler_t handlers[LAST_CODE + 1] &code_cpu_switch, &code_cookie_switch, &code_kernel_enter, - &code_kernel_exit, + &code_user_enter, &code_module_loaded, /* tgid handled differently */ &code_unknown, &code_trace_begin, &code_trace_end, + &code_xen_enter, + &code_domain_switch, }; @@ -266,6 +295,14 @@ void opd_process_samples(char const * bu if (!is_escape_code(code)) { opd_put_sample(&trans, code); + if (other_domain != -1) { + /* if last sample was for another domain, + restore trans fields */ + printf("shine: %p\n", code); + other_domain = -1; + trans.current = NULL; + trans.in_kernel--; + } continue; } diff -Naurp --exclude=configure --exclude=doc oprofile-0.8.1/daemon/oprofiled.c oprofile-0.8.1.xenoprof/daemon/oprofiled.c --- oprofile-0.8.1/daemon/oprofiled.c 2004-05-30 01:02:58.000000000 +0800 +++ oprofile-0.8.1.xenoprof/daemon/oprofiled.c 2005-08-14 19:14:27.000000000 +0800 @@ -7,6 +7,9 @@ * * @author John Levon * @author Philippe Elie + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. */ #include "config.h" @@ -60,6 +63,10 @@ int separate_cpu; int no_vmlinux; char * vmlinux; char * kernel_range; +int no_xen; +char * xenimage; +char * xen_range; +char * passive_ids; static char * verbose; static char * binary_name_filter; static char * events; @@ -75,7 +82,11 @@ static struct poptOption options[] = { { "kernel-range", 'r', POPT_ARG_STRING, &kernel_range, 0, "Kernel VMA range", "start-end", }, { "vmlinux", 'k', POPT_ARG_STRING, &vmlinux, 0, "vmlinux kernel image", "file", }, { "no-vmlinux", 0, POPT_ARG_NONE, &no_vmlinux, 0, "vmlinux kernel image file not available", NULL, }, + { "xen-range", 0, POPT_ARG_STRING, &xen_range, 0, "Xen VMA range", "start-end", }, + { "xen-image", 0, POPT_ARG_STRING, &xenimage, 0, "Xen image", "file", }, + { "no-xen", 0, POPT_ARG_NONE, &no_xen, 0, "xen image not available", NULL, }, { "image", 0, POPT_ARG_STRING, &binary_name_filter, 0, "image name filter", "profile these comma separated image" }, + { "passive-domains", 0, POPT_ARG_STRING, &passive_ids, 0, "Passive domains list", "list", }, { "separate-lib", 0, POPT_ARG_INT, &separate_lib, 0, "separate library samples for each distinct application", "[0|1]", }, { "separate-kernel", 0, POPT_ARG_INT, &separate_kernel, 0, "separate kernel samples for each distinct application", "[0|1]", }, { "separate-thread", 0, POPT_ARG_INT, &separate_thread, 0, "thread-profiling mode", "[0|1]" }, @@ -402,6 +413,27 @@ static void opd_options(int argc, char c } } + if (!no_xen) { + if (!xenimage || !strcmp("", xenimage)) { + fprintf(stderr, "oprofiled: no xen image specified.\n"); + poptPrintHelp(optcon, stderr, 0); + exit(EXIT_FAILURE); + } + + /* canonicalise xen image filename. fix #637805 */ + tmp = xmalloc(PATH_MAX); + if (realpath(xenimage, tmp)) + xenimage = tmp; + else + free(tmp); + + if (!xen_range || !strcmp("", xen_range)) { + fprintf(stderr, "oprofiled: no Xen VMA range specified.\n"); + poptPrintHelp(optcon, stderr, 0); + exit(EXIT_FAILURE); + } + } + opd_parse_events(events); opd_parse_image_filter(); diff -Naurp --exclude=configure --exclude=doc oprofile-0.8.1/daemon/oprofiled.h oprofile-0.8.1.xenoprof/daemon/oprofiled.h --- oprofile-0.8.1/daemon/oprofiled.h 2004-05-30 01:02:58.000000000 +0800 +++ oprofile-0.8.1.xenoprof/daemon/oprofiled.h 2005-08-14 19:15:43.000000000 +0800 @@ -7,6 +7,9 @@ * * @author John Levon * @author Philippe Elie + * Modified by Aravind Menon for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. */ #ifndef OPROFILED_H @@ -68,5 +71,9 @@ extern int separate_cpu; extern int no_vmlinux; extern char * vmlinux; extern char * kernel_range; +extern int no_xen; +extern char * xenimage; +extern char * xen_range; +extern char * passive_ids; #endif /* OPROFILED_H */ diff -Naurp --exclude=configure --exclude=doc oprofile-0.8.1/utils/opcontrol oprofile-0.8.1.xenoprof/utils/opcontrol --- oprofile-0.8.1/utils/opcontrol 2004-07-07 06:20:44.000000000 +0800 +++ oprofile-0.8.1.xenoprof/utils/opcontrol 2005-08-14 19:16:36.000000000 +0800 @@ -140,6 +140,13 @@ do_help() --vmlinux=file vmlinux kernel image --no-vmlinux no kernel image (vmlinux) available --kernel-range=start,end kernel range vma address in hexadecimal + + --xen=file xen image + --xen-range=start,end xen range vma address in hexadecimal + --active-domains=id[,ids] active domains id list + --passive-domains=id[,ids] passive domains id list + --passive-images=file[,files] passive domains image list + --buffer-size=num kernel buffer size in sample units --cpu-buffer-size=num per-cpu buffer size in units (2.6 only) --note-table-size kernel notes buffer size in notes units (2.4 only) @@ -245,6 +252,7 @@ do_init() CPU_BUF_SIZE=0 NOTE_SIZE=0 VMLINUX= + XENIMAGE="none" VERBOSE="" SEPARATE_LIB=0 SEPARATE_KERNEL=0 @@ -362,7 +370,7 @@ do_load_setup() } -check_valid_args() +check_valid_vmlinux() { if test -z "$VMLINUX"; then echo "No vmlinux file specified. You must specify the correct vmlinux file, e.g." >&2 @@ -386,6 +394,22 @@ check_valid_args() } +# aravind: similar check for Xen image +check_valid_xen() +{ + if test -f "$XENIMAGE"; then + return + fi + + if test "$XENIMAGE" = "none"; then + return + fi + + echo "The spcefified Xen image file \"$XENIMAGE\" does not exist." >&2 + exit 1 +} + + # get start and end points of the kernel get_kernel_range() { @@ -398,6 +422,7 @@ get_kernel_range() fi # start from section 0 and then continue till end of .text + # buggy, should at least include range of .init.* range_info=`objdump -h $VMLINUX 2>/dev/null | grep -w "0 "` tmp1=`echo $range_info | awk '{print $4}'` range_info=`objdump -h $VMLINUX 2>/dev/null | grep " .text "` @@ -414,6 +439,32 @@ get_kernel_range() vecho "KERNEL_RANGE $KERNEL_RANGE" } +# get start and end points of xen +get_xen_range() +{ + if test ! -z "$XEN_RANGE"; then + return; + fi + + if test "$XENIMAGE" = "none"; then + return; + fi + + # start from section 0 and then continue till end of .text + range_info=`objdump -h $XENIMAGE 2>/dev/null | grep -w "0 "` + tmp1=`echo $range_info | awk '{print $4}'` + range_info=`objdump -h $XENIMAGE 2>/dev/null | grep " .text "` + tmp_length=`echo $range_info | awk '{print $3}'` + tmp2=`objdump -h $XENIMAGE --adjust-vma=0x$tmp_length 2>/dev/null | grep " .text " | awk '{print $4}'` + + if test -z "$tmp1" -o -z "$tmp2"; then + echo "The specified file $XENIMAGE does not seem to be valid" >&2 + vecho "found start as \"$tmp1\", end as \"$tmp2\"" >&2 + exit 1 + fi + XEN_RANGE="`echo $tmp1`,`echo $tmp2`" + vecho "XEN_RANGE $XEN_RANGE" +} # validate --separate= parameters. This function is called with IFS=, # so on each argument is splitted @@ -698,6 +749,33 @@ do_options() KERNEL_RANGE=$val DO_SETUP=yes ;; +# aravind menon: xen image option + --xen) + error_if_empty $arg $val + XENIMAGE=$val + DO_SETUP=yes + get_xen_range + ;; + --xen-range) + error_if_empty $arg $val + XEN_RANGE=$val + DO_SETUP=yes + ;; + --active-domains) + error_if_empty $arg $val + ACTIVE_DOMAINS=$val + DO_SETUP=yes + ;; + --passive-domains) + error_if_empty $arg $val + PASSIVE_DOMAINS=$val + DO_SETUP=yes + ;; + --passive-images) + error_if_empty $arg $val + PASSIVE_IMAGES=$val + DO_SETUP=yes + ;; --note-table-size) error_if_empty $arg $val if test $"KERNEL_SUPPORT" = "yes"; then @@ -929,6 +1007,23 @@ do_param_setup() fi fi + if test -n "$ACTIVE_DOMAINS"; then + if test "$KERNEL_SUPPORT" = "yes"; then + echo $ACTIVE_DOMAINS >$MOUNT/active_domains + else + echo "active-domains not supported - ignored" >&2 + fi + fi + + if test -n "$PASSIVE_DOMAINS"; then + if test "$KERNEL_SUPPORT" = "yes"; then + echo $PASSIVE_DOMAINS >$MOUNT/passive_domains + do_symlink + else + echo "passive-domains not supported - ignored" >&2 + fi + fi + if test $NOTE_SIZE != 0; then set_param notesize $NOTE_SIZE fi @@ -990,6 +1085,23 @@ do_param_setup() done } +do_symlink() +{ + NDOMAINS=`echo "$PASSIVE_DOMAINS" | awk -F',' '{print NF}'` + NIMAGES=`echo "$PASSIVE_IMAGES" | awk -F',' '{print NF}'` + if [ $NDOMAINS != $NIMAGES ]; then + echo "# of passive domains and # of passive images doesn't match." >&2 + do_help + exit 1 + fi + + for (( i=1; i<=$NDOMAINS; i++ )); do + ID=`echo "$PASSIVE_DOMAINS" | awk -F"," '{print $'$i'}'` + FILE=`echo "$PASSIVE_IMAGES" | awk -F',' '{print $'$i'}'` + ln -sf $FILE /boot/pvmlinux$ID-syms + ln -sf /boot/xen-syms /boot/pxen$ID-syms + done +} do_start_daemon() { @@ -1006,7 +1118,8 @@ do_start_daemon() do_setup do_load_setup - check_valid_args + check_valid_vmlinux + check_valid_xen get_kernel_range do_param_setup @@ -1024,18 +1137,28 @@ do_start_daemon() OPD_ARGS="$OPD_ARGS --vmlinux=$VMLINUX --kernel-range=$KERNEL_RANGE" fi + if test "$XENIMAGE" = "none"; then + OPD_ARGS="$OPD_ARGS --no-xen" + else + OPD_ARGS="$OPD_ARGS --xen-image=$XENIMAGE --xen-range=$XEN_RANGE" + fi + if ! test -z "$IMAGE_FILTER"; then OPD_ARGS="$OPD_ARGS --image=$IMAGE_FILTER" fi + if ! test -z "$PASSIVE_DOMAINS"; then + OPD_ARGS="$OPD_ARGS --passive-domains=$PASSIVE_DOMAINS" + fi + if test -n "$VERBOSE"; then OPD_ARGS="$OPD_ARGS --verbose=$VERBOSE" fi vecho "executing oprofiled $OPD_ARGS" - + $OPROFILED $OPD_ARGS - + COUNT=0 while ! test -f "$DIR/lock" do @@ -1189,6 +1312,8 @@ do_deinit() echo "Unloading oprofile module" >& 2 rmmod oprofile fi + + rm -f /boot/pvmlinux*-syms /boot/pxen*-syms } @@ -1199,7 +1324,8 @@ do_operations() # thus INIT is a noop if test "$SETUP" = "yes"; then - check_valid_args + check_valid_vmlinux + check_valid_xen do_save_setup fi