[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 for-next 7/9] coverage: introduce support for llvm profiling
Introduce the functionality in order to fill the hooks of the cov_sysctl_ops struct. Note that the functionality is still not wired into the build system. Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Cc: George Dunlap <George.Dunlap@xxxxxxxxxxxxx> Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Cc: Jan Beulich <jbeulich@xxxxxxxx> Cc: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx> Cc: Tim Deegan <tim@xxxxxxx> Cc: Wei Liu <wei.liu2@xxxxxxxxxx> --- Note that the file that contains the helpers is under a BSD 2-clause license. This is done so it can be shared with other OSes that use the llvm/clang compiler. --- Changes since v1: - Include private coverage.h header. - Define LLVM_PROFILE_MAGIC based on the bitness of the arch. - Add a comment regarding __llvm_profile_runtime. - Constify data/names extern symbols. - Use defines instead of variables to store the addresses of the external symbols. - Parenthesize size in APPEND_TO_BUFFER. - Use >= for minor version check. - Use sizeof(header). --- xen/common/coverage/Makefile | 2 + xen/common/coverage/llvm.c | 154 +++++++++++++++++++++++++++++++++++++++++++ xen/include/public/sysctl.h | 6 ++ 3 files changed, 162 insertions(+) create mode 100644 xen/common/coverage/llvm.c diff --git a/xen/common/coverage/Makefile b/xen/common/coverage/Makefile index 1039a160c4..46c78d1086 100644 --- a/xen/common/coverage/Makefile +++ b/xen/common/coverage/Makefile @@ -6,4 +6,6 @@ obj-y += $(call cc-ifversion,lt,0x040700, \ gcc_4_7.o, $(call cc-ifversion,lt,0x050000, \ gcc_4_9.o, $(call cc-ifversion,lt,0x070000, \ gcc_5.o, gcc_7.o)))) +else +obj-y += llvm.o endif diff --git a/xen/common/coverage/llvm.c b/xen/common/coverage/llvm.c new file mode 100644 index 0000000000..889699a9a0 --- /dev/null +++ b/xen/common/coverage/llvm.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2017 Citrix Systems R&D + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <xen/errno.h> +#include <xen/guest_access.h> +#include <xen/types.h> + +#include "coverage.h" + +#ifndef __clang__ +#error "LLVM coverage selected without clang compiler" +#endif + +#if BITS_PER_LONG == 64 +#define LLVM_PROFILE_MAGIC (((uint64_t)255 << 56) | ((uint64_t)'l' << 48) | \ + ((uint64_t)'p' << 40) | ((uint64_t)'r' << 32) | ((uint64_t)'o' << 24) | \ + ((uint64_t)'f' << 16) | ((uint64_t)'r' << 8) | ((uint64_t)129)) +#else +#define LLVM_PROFILE_MAGIC (((uint64_t)255 << 56) | ((uint64_t)'l' << 48) | \ + ((uint64_t)'p' << 40) | ((uint64_t)'r' << 32) | ((uint64_t)'o' << 24) | \ + ((uint64_t)'f' << 16) | ((uint64_t)'R' << 8) | ((uint64_t)129) +#endif + +#if __clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ >= 9) +#define LLVM_PROFILE_VERSION 4 +#define LLVM_PROFILE_NUM_KINDS 2 +#else +#error "clang version not supported with coverage" +#endif + +struct llvm_profile_data { + uint64_t name_ref; + uint64_t function_hash; + void *counter; + void *function; + void *values; + uint32_t nr_counters; + uint16_t nr_value_sites[LLVM_PROFILE_NUM_KINDS]; +}; + +struct llvm_profile_header { + uint64_t magic; + uint64_t version; + uint64_t data_size; + uint64_t counters_size; + uint64_t names_size; + uint64_t counters_delta; + uint64_t names_delta; + uint64_t value_kind_last; +}; + +/* + * Since Xen uses the llvm code coverage support without the run time library + * __llvm_profile_runtime must be defined according to the docs at: + * + * https://clang.llvm.org/docs/SourceBasedCodeCoverage.html + */ +int __llvm_profile_runtime; + +extern const struct llvm_profile_data __start___llvm_prf_data[]; +extern const struct llvm_profile_data __stop___llvm_prf_data[]; +extern const char __start___llvm_prf_names[]; +extern const char __stop___llvm_prf_names[]; +extern uint64_t __start___llvm_prf_cnts[]; +extern uint64_t __stop___llvm_prf_cnts[]; + +#define START_DATA ((const void *)__start___llvm_prf_data) +#define END_DATA ((const void *)__stop___llvm_prf_data) +#define START_NAMES ((const void *)__start___llvm_prf_names) +#define END_NAMES ((const void *)__stop___llvm_prf_names) +#define START_COUNTERS ((void *)__start___llvm_prf_cnts) +#define END_COUNTERS ((void *)__stop___llvm_prf_cnts) + +static void reset_counters(void) +{ + memset(START_COUNTERS, 0, END_COUNTERS - START_COUNTERS); +} + +static uint32_t get_size(void) +{ + return ROUNDUP(sizeof(struct llvm_profile_header) + END_DATA - START_DATA + + END_COUNTERS - START_COUNTERS + END_NAMES - START_NAMES, 8); +} + +static int dump(XEN_GUEST_HANDLE_PARAM(char) buffer, uint32_t *buf_size) +{ + struct llvm_profile_header header = { + .magic = LLVM_PROFILE_MAGIC, + .version = LLVM_PROFILE_VERSION, + .data_size = (END_DATA - START_DATA) / sizeof(struct llvm_profile_data), + .counters_size = (END_COUNTERS - START_COUNTERS) / sizeof(uint64_t), + .names_size = END_NAMES - START_NAMES, + .counters_delta = (uintptr_t)START_COUNTERS, + .names_delta = (uintptr_t)START_NAMES, + .value_kind_last = LLVM_PROFILE_NUM_KINDS - 1, + }; + unsigned int off = 0; + +#define APPEND_TO_BUFFER(src, size) \ +({ \ + if ( off + (size) > *buf_size ) \ + return -ENOMEM; \ + copy_to_guest_offset(buffer, off, (const char *)src, size); \ + off += (size); \ +}) + APPEND_TO_BUFFER(&header, sizeof(header)); + APPEND_TO_BUFFER(START_DATA, END_DATA - START_DATA); + APPEND_TO_BUFFER(START_COUNTERS, END_COUNTERS - START_COUNTERS); + APPEND_TO_BUFFER(START_NAMES, END_NAMES - START_NAMES); +#undef APPEND_TO_BUFFER + + clear_guest_offset(buffer, off, *buf_size - off); + + return 0; +} + +const struct cov_sysctl_ops cov_ops = { + .get_size = get_size, + .reset_counters = reset_counters, + .dump = dump, +}; + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 3566f2eb69..8db22ac803 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -646,6 +646,12 @@ struct xen_sysctl_scheduler_op { #define XEN_GCOV_FORMAT_MAGIC 0x58434f56 /* XCOV */ +/* + * Ouput format of LLVM coverage data is just a raw stream, as would be + * written by the compiler_rt run time library into a .profraw file. There + * are no special Xen tags or delimiters because none are needed. + */ + #define XEN_SYSCTL_COVERAGE_get_size 0 /* Get total size of output data */ #define XEN_SYSCTL_COVERAGE_read 1 /* Read output data */ #define XEN_SYSCTL_COVERAGE_reset 2 /* Reset all counters */ -- 2.13.6 (Apple Git-96) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |