diff -r b1ab0c6c6019 xen/Rules.mk --- a/xen/Rules.mk Mon Feb 16 20:52:23 2009 +0530 +++ b/xen/Rules.mk Mon Feb 16 21:03:21 2009 +0530 @@ -9,6 +9,10 @@ crash_debug ?= n frame_pointer ?= n +# xen source path to get update in .gcno files +xen_src := $(CURDIR) +xentree := $(if $(xen_src),$(xen_src),$(CURDIR)) + XEN_ROOT=$(BASEDIR)/.. include $(XEN_ROOT)/Config.mk @@ -56,6 +60,7 @@ ALL_OBJS-y += $(BASEDIR)/arch/$(TARGET_ARCH)/built_in.o CFLAGS-y += -g -D__XEN__ +CFLAGS-y += -fprofile-arcs -ftest-coverage CFLAGS-$(XSM_ENABLE) += -DXSM_ENABLE CFLAGS-$(FLASK_ENABLE) += -DFLASK_ENABLE -DXSM_MAGIC=0xf97cff8c CFLAGS-$(FLASK_ENABLE) += -DFLASK_DEVELOP -DFLASK_BOOTPARAM -DFLASK_AVC_STATS @@ -117,7 +122,9 @@ $(MAKE) -f $(BASEDIR)/Rules.mk -C $* clean %.o: %.c $(HDRS) Makefile - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -c -o $@ \ + $(if $(filter-out /%,$<),$(xentree)/$<,$<) + %.o: %.S $(AHDRS) Makefile $(CC) $(AFLAGS) -c $< -o $@ diff -r b1ab0c6c6019 xen/arch/x86/mm/hap/Makefile --- a/xen/arch/x86/mm/hap/Makefile Mon Feb 16 20:52:23 2009 +0530 +++ b/xen/arch/x86/mm/hap/Makefile Mon Feb 16 21:03:21 2009 +0530 @@ -4,8 +4,17 @@ obj-y += guest_walk_4level.o obj-y += p2m-ept.o +LN = /bin/ln +xen_src := $(CURDIR) +xentree := $(if $(xen_src),$(xen_src),$(CURDIR)) + guest_levels = $(subst level,,$(filter %level,$(subst ., ,$(subst _, ,$(1))))) guest_walk_defns = -DGUEST_PAGING_LEVELS=$(call guest_levels,$(1)) +num = $(call guest_levels,$(@F))level.c + guest_walk_%level.o: guest_walk.c $(HDRS) Makefile - $(CC) $(CFLAGS) $(call guest_walk_defns,$(@F)) -c $< -o $@ + $(CC) $(CFLAGS) $(call guest_walk_defns,$(@F)) -c -o $@ \ + $(if $(filter-out /%,$<),$(xentree)/$<,$<) + $(LN) -f -s guest_walk.c guest_walk_$(num) + diff -r b1ab0c6c6019 xen/arch/x86/mm/shadow/Makefile --- a/xen/arch/x86/mm/shadow/Makefile Mon Feb 16 20:52:23 2009 +0530 +++ b/xen/arch/x86/mm/shadow/Makefile Mon Feb 16 21:03:21 2009 +0530 @@ -1,5 +1,10 @@ obj-$(x86_32) += common.o guest_2.o guest_3.o obj-$(x86_64) += common.o guest_2.o guest_3.o guest_4.o +LN = /bin/ln +num=$*.c + guest_%.o: multi.c $(HDRS) Makefile - $(CC) $(CFLAGS) -DGUEST_PAGING_LEVELS=$* -c $< -o $@ + $(CC) $(CFLAGS) -DGUEST_PAGING_LEVELS=$* -c -o $@ \ + $(if $(filter-out /%,$<),$(xentree)/$<,$<) + $(LN) -f -s multi.c guest_$(num) diff -r b1ab0c6c6019 xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Mon Feb 16 20:52:23 2009 +0530 +++ b/xen/arch/x86/x86_32/entry.S Mon Feb 16 21:03:21 2009 +0530 @@ -703,6 +703,7 @@ .long do_sysctl /* 35 */ .long do_domctl .long do_kexec_op + .long do_gcovprof_op .rept __HYPERVISOR_arch_0-((.-hypercall_table)/4) .long do_ni_hypercall .endr @@ -750,6 +751,7 @@ .byte 1 /* do_sysctl */ /* 35 */ .byte 1 /* do_domctl */ .byte 2 /* do_kexec_op */ + .byte 3 /* do_gcovprof_op */ .rept __HYPERVISOR_arch_0-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff -r b1ab0c6c6019 xen/common/Makefile --- a/xen/common/Makefile Mon Feb 16 20:52:23 2009 +0530 +++ b/xen/common/Makefile Mon Feb 16 21:03:21 2009 +0530 @@ -27,6 +27,7 @@ obj-y += vsprintf.o obj-y += xmalloc.o obj-y += rcupdate.o +obj-y += xen-gcov-core.o obj-$(perfc) += perfc.o obj-$(crash_debug) += gdbstub.o @@ -42,6 +43,8 @@ subdir-y += libelf +CFLAGS += -DSRC_PATH='"$(BASEDIR)"' + # Object file contains changeset and compiler information. version.o: $(BASEDIR)/include/xen/compile.h diff -r b1ab0c6c6019 xen/common/xen-gcov-core.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/common/xen-gcov-core.c Mon Feb 16 21:03:21 2009 +0530 @@ -0,0 +1,242 @@ +/** + * xen-gcov-core.c: arch dependent code for hypervisor profiling + * + * Written by tej parkash and team(tej.parkash@xxxxxx) + * + */ +/***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define XEN_GCOV_CORE "xen-gcov-core:" + +static int num_xen_files; +gcov_unsigned_t gcov_version = 0; +struct gcov_info *bb_head; + +struct ctor_list { + unsigned long num; + ctor_t ctor[]; +}; +extern struct ctor_list __CTOR_LIST__; + + +static inline int +counter_active(struct gcov_info *bb, unsigned int type) +{ + return (1 << type) & bb->ctr_mask; +} + +static inline unsigned int +get_fn_stride(struct gcov_info *bb) +{ + unsigned int stride; + + stride = sizeof(struct gcov_fn_info) + sizeof(unsigned int); + if (__alignof__(struct gcov_fn_info) > sizeof(unsigned int)) { + stride += __alignof__(struct gcov_fn_info) - 1; + stride &= ~(__alignof__(struct gcov_fn_info) - 1); + } + return stride; +} + +static inline struct gcov_fn_info * +get_fn_info(struct gcov_info *bb, unsigned int func) +{ + return (struct gcov_fn_info *) + ((char *)bb->functions + func * get_fn_stride(bb)); +} + +static void reset_gcda(struct gcov_info *bb) +{ + + unsigned int i; + struct gcov_ctr_info *ctr; + ctr = bb->counts; + for (i=0; i < GCOV_COUNTERS; i++) + if (counter_active(bb, i)) { + memset(ctr->values, 0, ctr->num * sizeof(gcov_type)); + ctr++; + } +} + +/* Function to reset the bb counter. */ +static int reset_bb(XEN_GUEST_HANDLE(void) arg, int val) +{ + struct gcov_info *tmp=bb_head; + char bb_file[100]; + if ( val == 0){ + /* reset single data file */ + if ( copy_from_guest(&bb_file, arg, 1) ) + return -EFAULT; + for(;tmp!=NULL;tmp=tmp->next){ + if(!strcmp(tmp->filename,bb_file)){ + reset_gcda(tmp); + break; + } + else + continue; + } + } + else { + /* reset all data files */ + for(;tmp!=NULL;tmp=tmp->next) + reset_gcda(tmp); + } + return 0; +} + + +/*copy bb_head info */ + +static int start_prof(XEN_GUEST_HANDLE(void) arg, int val) +{ + /*Add the code to copy the no of files to be add to xen */ + struct xen_gcov_info bb_tmp; + struct gcov_info *tmp = bb_head; + struct gcov_fn_info *func; + struct gcov_ctr_info *ctr; + struct xen_gcov_ctr_info *xctr; + struct xen_gcov_info *bb = &bb_tmp; + int i,j; + + if ( copy_from_guest(&bb_tmp, arg, 1) ) + return -EFAULT; + for(;tmp!=NULL&&bb!=NULL;tmp=tmp->next){ + ctr = tmp->counts; + xctr = bb->counts; + memcpy(bb->counts[0].values, ctr->values, ctr->num*sizeof(gcov_type)); + xctr->num = ctr->num; + xctr->merge = ctr->merge; + bb->version = tmp->version; + bb->stamp = tmp->stamp; + safe_strcpy(bb->file, tmp->filename); + bb->ctr_mask = tmp->ctr_mask; + bb->n_functions = tmp->n_functions; + for(i=0;in_functions;i++) { + func = get_fn_info(tmp,i); + bb->functions[i].ident=func->ident; + bb->functions[i].checksum=func->checksum; + for (j=0;jfunctions[i].n_ctrs[j]=func->n_ctrs[j]; + } + } + /*increment the bb_head pointers*/ + bb=bb->next; + } + if ( copy_to_guest(arg, &bb_tmp, 1) ) + return -EFAULT; + return 0; +} + + +static int var_info(XEN_GUEST_HANDLE(void) arg,int val) +{ + struct gcov_variables gcov_var; + struct gcov_variables *tmp=&gcov_var; + struct gcov_info *bb; + int i; + if( copy_from_guest(&gcov_var, arg, 1) ) + return -EFAULT; + if ( val == 0 ) { + safe_strcpy(tmp->src_path,SRC_PATH); + tmp->g_version=gcov_version; + tmp->n_files=num_xen_files; + } else { + for(i=0,bb=bb_head;bb!=NULL;bb=bb->next,i++){ + tmp->ctr_num[i]=bb->counts->num; + tmp->n_funcs[i]=bb->n_functions; + } + } + + if( copy_to_guest(arg, &gcov_var, 1) ) + return -EFAULT; + return 0; +} + +/*internal hyercall functions*/ +int do_gcovprof_op(int op, XEN_GUEST_HANDLE(void) arg, int val) +{ + int ret = 0; + if ((op < 0) || (op > GCOVPROF_last_op)) { + printk(KERN_ERR XEN_GCOV_CORE "Invalid operation %d\n", op); + return -EINVAL; + } + switch (op) { + case GCOVPROF_seek_vars: + /*fun seeks vars to be used by proc code */ + ret = var_info(arg, val); + break; + case GCOVPROF_start: + /*update linux kernel with profiling info */ + ret = start_prof(arg,val); + break; + case GCOVPROF_reset: + /*reset the gcda or vmlinux*/ + ret = reset_bb(arg,val); + break; + default: + ret = -ENOSYS; + } + return ret; +} + +void do_global_ctors(ctor_t ctor[], unsigned long num) +{ + unsigned long i; + + /* Call constructors and create gcov_info linked list*/ + for (i = 0; i < num && ctor[i]; i++) + ctor[i] (); +} + + /*Register supplied struct BB. Called by each object code constructor. */ +void __gcov_init(struct gcov_info *bb) +{ + if (!bb->version) + return; + /*Check for compatible gcc version */ + if (gcov_version == 0) + gcov_version = bb->version; + else if (bb->version != gcov_version) { + printk(KERN_WARNING XEN_GCOV_CORE "gcc version mismatch in " + "file '%s'!\n", bb->filename); + return; + } + /*Set up linked list */ + bb->version = 0; + bb->next = bb_head; + bb_head = bb; +} + +static int __init gcov_init(void) +{ + num_xen_files = __CTOR_LIST__.num; + do_global_ctors(__CTOR_LIST__.ctor, __CTOR_LIST__.num); + printk(KERN_INFO XEN_GCOV_CORE "init done\n"); + return 0; +} + +/* Unused functions needed to prevent linker errors. */ +void __gcov_flush(void) {} +void __gcov_merge_add(gcov_type * counters, unsigned int n_counters){} +void __gcov_merge_single(gcov_type * counters, unsigned int n_counters){} +void __gcov_merge_delta(gcov_type * counters, unsigned int n_counters){} + +EXPORT_SYMBOL(__gcov_init); +EXPORT_SYMBOL(do_global_ctors); +EXPORT_SYMBOL(__gcov_flush); +EXPORT_SYMBOL(__gcov_merge_add); +EXPORT_SYMBOL(__gcov_merge_single); +EXPORT_SYMBOL(__gcov_merge_delta); +__initcall(gcov_init); diff -r b1ab0c6c6019 xen/include/public/xen-gcov.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/public/xen-gcov.h Mon Feb 16 21:03:21 2009 +0530 @@ -0,0 +1,139 @@ +/****************************************************************************** + * xen-gcov.h + * + * Interface for enabling and populating hypervisor profiling info. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: tej parkash + * Written by tej parkash and team + * + */ +/********************************************************************************/ + +#ifndef __XEN_PUBLIC_GCOVPROF_H__ +#define __XEN_PUBLIC_GCOVPROF_H__ + +#include "xen.h" + +/* + * Commands to HYPERVISOR_gcovprof_op() + */ +#define GCOVPROF_seek_vars 0 +#define GCOVPROF_start 1 +#define GCOVPROF_reset 2 +#define GCOVPROF_last_op 3 + +/*gcc specific macros*/ +#define GCOV_COUNTERS 5 +#define GCOV_DATA_MAGIC ((gcov_unsigned_t) 0x67636461) +#define GCOV_TAG_FUNCTION ((gcov_unsigned_t) 0x01000000) +#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t) 0x01a10000) +#define GCOV_TAG_FOR_COUNTER(COUNT) \ + (GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t) (COUNT) << 17)) + + + +typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI))); +typedef signed gcov_type __attribute__ ((mode (DI))); +typedef void (*gcov_merge_fn) (gcov_type *, gcov_unsigned_t); +typedef void (*ctor_t)(void); + +struct gcov_fn_info{ + gcov_unsigned_t ident; /* unique ident of function */ + gcov_unsigned_t checksum; /* function checksum */ + unsigned n_ctrs[0]; /* instrumented counters */ +}; + +struct gcov_ctr_info +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_type *values; /* their values. */ + gcov_merge_fn merge; /* The function used to merge them. */ +}; + +/* Information about a single object file. */ +struct gcov_info +{ + gcov_unsigned_t version; /* expected version number */ + struct gcov_info *next; /* link to next, used by libgcov */ + + gcov_unsigned_t stamp; /* uniquifying time stamp */ + const char *filename; + + unsigned n_functions; /* number of functions */ + struct gcov_fn_info *functions; /* table of functions */ + + unsigned ctr_mask; /* mask of counters instrumented. */ + struct gcov_ctr_info counts[0]; /* count data. The number of bits + set in the ctr_mask field + determines how big this array + is. */ +}; + + +struct xen_gcov_fn_info{ + gcov_unsigned_t ident; /* unique ident of function */ + gcov_unsigned_t checksum; /* function checksum */ + unsigned int n_ctrs[GCOV_COUNTERS]; /* instrumented counters */ +}; +typedef struct xen_gcov_fn_info xen_gcov_fn_info_t; +DEFINE_XEN_GUEST_HANDLE(xen_gcov_fn_info_t); + + + +struct xen_gcov_ctr_info +{ + gcov_unsigned_t num; /* number of counters. */ + gcov_type *values; /* their values. */ + gcov_merge_fn merge; /* The function used to merge them. */ +}; +typedef struct xen_gcov_ctr_info xen_gcov_ctr_info_t; +DEFINE_XEN_GUEST_HANDLE(xen_gcov_ctr_info_t); + +/* Information about a single object file. */ +struct xen_gcov_info +{ + gcov_unsigned_t version; /* expected version number */ + struct xen_gcov_info *next; /* link to next, used by libgcov */ + + gcov_unsigned_t stamp; /* uniquifying time stamp */ + char file[100]; + + unsigned int n_functions; /* number of functions */ + struct xen_gcov_fn_info *functions; /* table of functions */ + + unsigned int ctr_mask; /* mask of counters instrumented. */ + struct xen_gcov_ctr_info counts[GCOV_COUNTERS]; /* count data.*/ +}; +typedef struct xen_gcov_info xen_gcov_info_t; +DEFINE_XEN_GUEST_HANDLE(xen_gcov_info_t); + +struct gcov_variables +{ + char src_path[100]; + unsigned long g_version; + unsigned int n_files; + gcov_unsigned_t *ctr_num; + unsigned int *n_funcs; +}; +typedef struct gcov_variables gcov_variables_t; +DEFINE_XEN_GUEST_HANDLE(gcov_variables_t); + +#endif /* __XEN_PUBLIC_GCOVPROF_H__ */ diff -r b1ab0c6c6019 xen/include/xen/config.h --- a/xen/include/xen/config.h Mon Feb 16 20:52:23 2009 +0530 +++ b/xen/include/xen/config.h Mon Feb 16 21:03:21 2009 +0530 @@ -96,4 +96,20 @@ #define __cpuinitdata #define __cpuinit +#define SORT(x) x +#define CONSTRUCTORS \ + __CTOR_LIST__ = .; \ + LONG((__CTOR_END__ - __CTOR_LIST__) / \ + (__CTOR_LIST2__ - __CTOR_LIST__) - 2) \ + __CTOR_LIST2__ = .; \ + *(SORT(.ctors)) \ + LONG(0) \ + __CTOR_END__ = .; \ + __DTOR_LIST__ = .; \ + LONG((__DTOR_END__ - __DTOR_LIST__) / \ + (__CTOR_LIST2__ - __CTOR_LIST__) - 2) \ + *(SORT(.dtors)) \ + LONG(0) \ + __DTOR_END__ = .; + #endif /* __XEN_CONFIG_H__ */