This commit makes the changes to the hypervisor, the build system as well as libxc necessary in order to facilitate tracing of program counters.
A discussion of the design can be found in the mailing list: https://lists.xen.org/archives/html/xen-devel/2017-05/threads.html#02210 The list of files to be included for tracing might still be too extensive, resulting in indeterministic tracing output for some use cases. Signed-off-by: Felix Schmoll <eggi.innovati...@gmail.com> --- Changed since v2: * Fix bug that hypercall wouldn't return -EFAULT * Adjust error return codes of hypercall * Add description to Kconfig * Move compile-option from Kconfig to Kconfig.debug * Formatting changes --- CC: Andrew Cooper <andrew.coop...@citrix.com> CC: George Dunlap <george.dun...@eu.citrix.com> CC: Ian Jackson <ian.jack...@eu.citrix.com> CC: Jan Beulich <jbeul...@suse.com> CC: Konrad Rzeszutek Wilk <konrad.w...@oracle.com> CC: Stefano Stabellini <sstabell...@kernel.org> CC: Tim Deegan <t...@xen.org> CC: Wei Liu <wei.l...@citrix.com> CC: Julien Grall <julien.gr...@arm.com> CC: xen-devel@lists.xen.org --- xen/Kconfig.debug | 7 +++- xen/Rules.mk | 4 ++ xen/arch/arm/traps.c | 1 + xen/arch/x86/Makefile | 2 + xen/arch/x86/hvm/hypercall.c | 1 + xen/arch/x86/hypercall.c | 1 + xen/arch/x86/pv/Makefile | 2 + xen/arch/x86/pv/hypercall.c | 1 + xen/common/Makefile | 13 ++++++ xen/common/domain.c | 4 ++ xen/common/trace_pc.c | 96 +++++++++++++++++++++++++++++++++++++++++++ xen/common/trace_pc_stub.c | 39 ++++++++++++++++++ xen/include/public/trace_pc.h | 38 +++++++++++++++++ xen/include/public/xen.h | 1 + xen/include/xen/hypercall.h | 7 ++++ xen/include/xen/sched.h | 6 +++ xen/include/xen/trace_pc.h | 31 ++++++++++++++ 17 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 xen/common/trace_pc.c create mode 100644 xen/common/trace_pc_stub.c create mode 100644 xen/include/public/trace_pc.h create mode 100644 xen/include/xen/trace_pc.h diff --git a/xen/Kconfig.debug b/xen/Kconfig.debug index 689f2974c0..d87dcd78f4 100644 --- a/xen/Kconfig.debug +++ b/xen/Kconfig.debug @@ -98,7 +98,6 @@ config PERF_ARRAYS ---help--- Enables software performance counter array histograms. - config VERBOSE_DEBUG bool "Verbose debug messages" default DEBUG @@ -114,6 +113,12 @@ config DEVICE_TREE_DEBUG logged in the Xen ring buffer. If unsure, say N here. +config TRACE_PC + bool "Enable pc-tracing" + default false + ---help--- + Adds tracing support to the hypervisor (needed for the trace_pc hypercall). + endif # DEBUG || EXPERT endmenu diff --git a/xen/Rules.mk b/xen/Rules.mk index 77bcd44922..dde14e3228 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -170,6 +170,10 @@ clean:: $(addprefix _clean_, $(subdir-all)) _clean_%/: FORCE $(MAKE) -f $(BASEDIR)/Rules.mk -C $* clean +ifeq ($(CONFIG_TRACE_PC),y) +$(objs-need-tracing): CFLAGS += -fsanitize-coverage=trace-pc +endif + %.o: %.c Makefile $(CC) $(CFLAGS) -c $< -o $@ diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index c07999b518..247a68c964 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -1419,6 +1419,7 @@ static arm_hypercall_t arm_hypercall_table[] = { HYPERCALL(platform_op, 1), HYPERCALL_ARM(vcpu_op, 3), HYPERCALL(vm_assist, 2), + HYPERCALL(trace_pc, 4), }; #ifndef NDEBUG diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 93ead6e5dd..b283c3e22c 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -74,6 +74,8 @@ efi-y := $(shell if [ ! -r $(BASEDIR)/include/xen/compile.h -o \ -O $(BASEDIR)/include/xen/compile.h ]; then \ echo '$(TARGET).efi'; fi) +objs-need-tracing := cpuid.o hypercall.o + ifneq ($(build_id_linker),) notes_phdrs = --notes else diff --git a/xen/arch/x86/hvm/hypercall.c b/xen/arch/x86/hvm/hypercall.c index e7238ce293..b59d7d481e 100644 --- a/xen/arch/x86/hvm/hypercall.c +++ b/xen/arch/x86/hvm/hypercall.c @@ -132,6 +132,7 @@ static const hypercall_table_t hvm_hypercall_table[] = { COMPAT_CALL(mmuext_op), HYPERCALL(xenpmu_op), COMPAT_CALL(dm_op), + HYPERCALL(trace_pc), HYPERCALL(arch_1) }; diff --git a/xen/arch/x86/hypercall.c b/xen/arch/x86/hypercall.c index e30181817a..672ffe7ef5 100644 --- a/xen/arch/x86/hypercall.c +++ b/xen/arch/x86/hypercall.c @@ -68,6 +68,7 @@ const hypercall_args_t hypercall_args_table[NR_hypercalls] = ARGS(xenpmu_op, 2), ARGS(dm_op, 3), ARGS(mca, 1), + ARGS(trace_pc, 4), ARGS(arch_1, 1), }; diff --git a/xen/arch/x86/pv/Makefile b/xen/arch/x86/pv/Makefile index 4e15484471..8c3eccdfd7 100644 --- a/xen/arch/x86/pv/Makefile +++ b/xen/arch/x86/pv/Makefile @@ -11,3 +11,5 @@ obj-y += traps.o obj-bin-y += dom0_build.init.o obj-bin-y += gpr_switch.o + +objs-need-tracing += hypercall.o diff --git a/xen/arch/x86/pv/hypercall.c b/xen/arch/x86/pv/hypercall.c index f79f7eef62..13eb2e86a2 100644 --- a/xen/arch/x86/pv/hypercall.c +++ b/xen/arch/x86/pv/hypercall.c @@ -80,6 +80,7 @@ static const hypercall_table_t pv_hypercall_table[] = { HYPERCALL(xenpmu_op), COMPAT_CALL(dm_op), HYPERCALL(mca), + HYPERCALL(trace_pc), HYPERCALL(arch_1), }; diff --git a/xen/common/Makefile b/xen/common/Makefile index 26c5a64337..4e39dc66e0 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -55,6 +55,8 @@ obj-y += tasklet.o obj-y += time.o obj-y += timer.o obj-y += trace.o +obj-y += trace_pc.o +obj-$(CONFIG_TRACE_PC) += trace_pc_stub.o obj-y += version.o obj-y += virtual_region.o obj-y += vm_event.o @@ -80,3 +82,14 @@ subdir-$(CONFIG_GCOV) += gcov subdir-y += libelf subdir-$(CONFIG_HAS_DEVICE_TREE) += libfdt + +objs-need-tracing := bsearch.o \ + decompress.o device_tree.o domain.o domctl.o earlycpio.o grant_table.o \ + guestcopy.o gunzip.o inflate.o kernel.o kexec.o keyhandler.o kimage.o \ + lib.o livepatch.o lzo.o mem_access.o memory.o multicall.o notifier.o \ + page_alloc.o pdx.o perfc.o radix_tree.o rangeset.o \ + rbtree.o shutdown.o sort.o stop_machine.o \ + symbols.o symbols-dummy.o sysctl.o time.o tmem.o \ + tmem_control.o tmem_xen.o trace.o unlz4.o unlzo.o unxz.o version.o \ + virtual_region.o vmap.o vm_event.o warning.o xenoprof.o \ + xmalloc_tlsf.o diff --git a/xen/common/domain.c b/xen/common/domain.c index b22aacc57e..c98a0a94ec 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -874,6 +874,10 @@ void domain_destroy(struct domain *d) rcu_assign_pointer(*pd, d->next_in_hashbucket); spin_unlock(&domlist_update_lock); +#ifdef CONFIG_TRACE_PC + xfree(d->tracing_buffer); +#endif + /* Schedule RCU asynchronous completion of domain destroy. */ call_rcu(&d->rcu, complete_domain_destroy); } diff --git a/xen/common/trace_pc.c b/xen/common/trace_pc.c new file mode 100644 index 0000000000..722572c500 --- /dev/null +++ b/xen/common/trace_pc.c @@ -0,0 +1,96 @@ +/****************************************************************************** + * trace_pc.c + * + * Implementation of the program counter tracing hypercall. + * + * Copyright (c) 2017 Felix Schmoll <eggi.innovati...@gmail.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see <http://www.gnu.org/licenses/>. + */ + +#include <xen/guest_access.h> +#include <xen/sched.h> +#include <xen/xmalloc.h> +#include <public/trace_pc.h> + +long do_trace_pc(domid_t dom, int mode, unsigned int size, + XEN_GUEST_HANDLE_PARAM(uint64_t) buf) +{ +#ifdef CONFIG_TRACE_PC + int ret = 0; + struct domain *d; + + if ( dom == DOMID_SELF ) + d = current->domain; + else + d = get_domain_by_id(dom); + + if ( !d ) + return -ESRCH; /* invalid domain */ + + switch ( mode ) + { + case XEN_TRACE_PC_START: + { + if ( d->tracing_buffer ) + { + ret = -EBUSY; /* domain already being traced */ + break; + } + + d->tracing_buffer_pos = 0; + d->tracing_buffer_size = size; + d->tracing_buffer = xmalloc_array(uint64_t, size); + + if ( !d->tracing_buffer ) + ret = -ENOMEM; + break; + } + + case XEN_TRACE_PC_STOP: + { + uint64_t *temp = d->tracing_buffer; + d->tracing_buffer = NULL; + + if ( copy_to_guest(buf, temp, d->tracing_buffer_pos) ) + ret = -EFAULT; + else + ret = d->tracing_buffer_pos; + + xfree(temp); + + break; + } + + default: + ret = -ENOSYS; + } + + if ( dom != DOMID_SELF ) + put_domain(d); + + return ret; +#else + return -EOPNOTSUPP; +#endif +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/trace_pc_stub.c b/xen/common/trace_pc_stub.c new file mode 100644 index 0000000000..4aba7dba9f --- /dev/null +++ b/xen/common/trace_pc_stub.c @@ -0,0 +1,39 @@ +/****************************************************************************** + * trace_pc_stub.c + * + * Edge function/stub for the program counter tracing hypercall. + * + * Copyright (c) 2017 Felix Schmoll <eggi.innovati...@gmail.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see <http://www.gnu.org/licenses/>. + */ + +#include <xen/trace_pc.h> +#include <xen/kernel.h> + +void __sanitizer_cov_trace_pc(void) +{ + struct domain *d; + + if ( system_state < SYS_STATE_active ) + return; + + d = current->domain; + + if ( d->tracing_buffer && + (d->tracing_buffer_pos < d->tracing_buffer_size) ) + { + d->tracing_buffer[d->tracing_buffer_pos++] = + (uint64_t) __builtin_return_address(0); + } +} diff --git a/xen/include/public/trace_pc.h b/xen/include/public/trace_pc.h new file mode 100644 index 0000000000..54e430a561 --- /dev/null +++ b/xen/include/public/trace_pc.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * trace_pc.h + * + * Macros for program counter tracing hypercall. + * + * Copyright (C) 2017 Felix Schmoll <eggi.innovati...@gmail.com> + * + * 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. + */ + +#ifndef __XEN_PUBLIC_TRACE_PC_H__ +#define __XEN_PUBLIC_TRACE_PC_H__ + +#if defined(__XEN__) || defined(__XEN_TOOLS__) + +#define XEN_TRACE_PC_START 0 +#define XEN_TRACE_PC_STOP 1 + +#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ + +#endif /* __XEN_PUBLIC_TRACE_PC_H__ */ diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 2ac6b1e24d..95d83c21ce 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -121,6 +121,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t); #define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */ #define __HYPERVISOR_xenpmu_op 40 #define __HYPERVISOR_dm_op 41 +#define __HYPERVISOR_trace_pc 42 /* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48 diff --git a/xen/include/xen/hypercall.h b/xen/include/xen/hypercall.h index cc99aea57d..aa6269e7b7 100644 --- a/xen/include/xen/hypercall.h +++ b/xen/include/xen/hypercall.h @@ -83,6 +83,13 @@ do_xen_version( XEN_GUEST_HANDLE_PARAM(void) arg); extern long +do_trace_pc( + domid_t dom_id, + int mode, + unsigned int size, + XEN_GUEST_HANDLE_PARAM(uint64_t) buf); + +extern long do_console_io( int cmd, int count, diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 6673b27d88..4bd3fe2417 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -483,6 +483,12 @@ struct domain unsigned int guest_request_enabled : 1; unsigned int guest_request_sync : 1; } monitor; + +#ifdef CONFIG_TRACE_PC + uint64_t* tracing_buffer; + unsigned int tracing_buffer_pos; + unsigned int tracing_buffer_size; +#endif }; /* Protect updates/reads (resp.) of domain_list and domain_hash. */ diff --git a/xen/include/xen/trace_pc.h b/xen/include/xen/trace_pc.h new file mode 100644 index 0000000000..631815de30 --- /dev/null +++ b/xen/include/xen/trace_pc.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * trace_pc.h + * + * Declarations for the program counter tracing hypercall + * + * Copyright (C) 2017 Felix Schmoll <eggi.innovati...@gmail.com> + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __TRACE_PC_H__ +#define __TRACE_PC_H__ + +#include <xen/sched.h> +#include <xen/types.h> + +#include <asm/current.h> + +void __sanitizer_cov_trace_pc(void); + +#endif /* __TRACE_PC_H__ */ -- 2.11.0 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org https://lists.xen.org/xen-devel