[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/4] Implement code to read coverage informations
Operations are handled by a sysctl specific operation. Implement 4 operations - check if coverage is compiled in - read size of coverage information - read coverage information - reset coverage counters Information are stored in a single blob in a format specific to Xen designed to make code that generate coverage as small as possible. This patch add a public header with the structure of blob exported by Xen. This avoid problems distributing header which is GPL2. Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx> --- xen/common/gcov/gcov.c | 151 ++++++++++++++++++++++++++++++++++++++++++- xen/common/sysctl.c | 5 ++ xen/include/public/gcov.h | 92 ++++++++++++++++++++++++++ xen/include/public/sysctl.h | 38 +++++++++++ xen/include/xen/gcov.h | 14 ++++ 5 files changed, 297 insertions(+), 3 deletions(-) create mode 100644 xen/include/public/gcov.h diff --git a/xen/common/gcov/gcov.c b/xen/common/gcov/gcov.c index e7efa21..6b95cd0 100644 --- a/xen/common/gcov/gcov.c +++ b/xen/common/gcov/gcov.c @@ -19,9 +19,11 @@ #include <xen/hypercall.h> #include <xen/gcov.h> #include <xen/errno.h> +#include <xen/guest_access.h> +#include <public/xen.h> +#include <public/gcov.h> static struct gcov_info *info_list; -static unsigned num_info = 0; /* * __gcov_init is called by gcc-generated constructor code for each object @@ -36,7 +38,6 @@ void __gcov_init(struct gcov_info *info) /* add new profiling data structure to list */ info->next = info_list; info_list = info; - ++num_info; } /* @@ -77,12 +78,156 @@ void __init init_coverage(void) __CTOR_LIST__.funcs[n](); #ifndef NDEBUG - printk(XENLOG_INFO "Initialized %u coverage strucures\n", num_info); if ( info_list ) printk(XENLOG_INFO "First coverage file %s\n", info_list->filename); #endif } +static inline int counter_active(const struct gcov_info *info, unsigned int type) +{ + return (1 << type) & info->ctr_mask; +} + +typedef struct write_iter_t +{ + XEN_GUEST_HANDLE(uint8) ptr; + int real; + uint32_t write_offset; +} write_iter_t; + +static int write_raw(struct write_iter_t *iter, const void *data, + size_t data_len) +{ + if ( iter->real && + copy_to_guest_offset(iter->ptr, iter->write_offset, + (const unsigned char *) data, data_len) ) + return -EFAULT; + + iter->write_offset = + (iter->write_offset + data_len + (sizeof(uint32_t) - 1)) & + -sizeof(uint32_t); + return 0; +} + +#define chk(v) do { ret=(v); if ( ret ) return ret; } while(0) + +static inline int write32(write_iter_t *iter, uint32_t val) +{ + return write_raw(iter, &val, sizeof(val)); +} + +static int write_string(write_iter_t *iter, const char *s) +{ + int ret; + size_t len = strlen(s); + + chk(write32(iter, len)); + return write_raw(iter, s, len); +} + +static inline int next_type(const struct gcov_info *info, int *type) +{ + while ( ++*type < XENCOV_COUNTERS && !counter_active(info, *type) ) + continue; + return *type; +} + +static int write_gcov(write_iter_t *iter) +{ + struct gcov_info *info; + int ret; + + /* reset offset */ + iter->write_offset = 0; + + /* dump all files */ + for ( info = info_list ; info; info = info->next ) + { + const struct gcov_ctr_info *ctr; + int type; + size_t size_fn = sizeof(struct gcov_fn_info); + + chk(write32(iter, XENCOV_TAG_FILE)); + chk(write_string(iter, info->filename)); + chk(write32(iter, info->version)); + chk(write32(iter, info->stamp)); + + /* dump counters */ + ctr = info->counts; + for ( type = -1; next_type(info, &type) < XENCOV_COUNTERS; ++ctr ) + { + chk(write32(iter, XENCOV_TAG_COUNTER(type))); + chk(write32(iter, ctr->num)); + chk(write_raw(iter, ctr->values, + ctr->num * sizeof(ctr->values[0]))); + + size_fn += sizeof(unsigned); + } + + /* dump all functions together */ + chk(write32(iter, XENCOV_TAG_FUNC)); + chk(write32(iter, info->n_functions)); + chk(write_raw(iter, info->functions, info->n_functions * size_fn)); + } + + /* stop tag */ + chk(write32(iter, XENCOV_TAG_END)); + return 0; +} + +static int reset_counters(void) +{ + struct gcov_info *info; + + for ( info = info_list ; info; info = info->next ) + { + const struct gcov_ctr_info *ctr; + int type; + + /* reset counters */ + ctr = info->counts; + for ( type = -1; next_type(info, &type) < XENCOV_COUNTERS; ++ctr ) + memset(ctr->values, 0, ctr->num * sizeof(ctr->values[0])); + } + + return 0; +} + +int sysctl_coverage_op(xen_sysctl_coverage_op_t *op) +{ + long ret = 0; + write_iter_t iter; + + switch ( op->cmd ) + { + case XEN_SYSCTL_COVERAGE_enabled: + break; + + case XEN_SYSCTL_COVERAGE_get_total_size: + iter.real = 0; + + write_gcov(&iter); + if ( copy_to_guest(op->u.total_size, &iter.write_offset, 1) ) + ret = -EFAULT; + break; + + case XEN_SYSCTL_COVERAGE_read: + iter.ptr = op->u.raw_info; + iter.real = 1; + + ret = write_gcov(&iter); + break; + + case XEN_SYSCTL_COVERAGE_reset: + ret = reset_counters(); + break; + + default: + ret = -EINVAL; + } + return ret; +} + /* * Local variables: * mode: C diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c index d663ed7..fa3ef0a 100644 --- a/xen/common/sysctl.c +++ b/xen/common/sysctl.c @@ -26,6 +26,7 @@ #include <xen/nodemask.h> #include <xsm/xsm.h> #include <xen/pmstat.h> +#include <xen/gcov.h> long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl) { @@ -249,6 +250,10 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl) ret = sched_adjust_global(&op->u.scheduler_op); break; + case XEN_SYSCTL_coverage_op: + ret = sysctl_coverage_op(&op->u.coverage_op); + break; + default: ret = arch_do_sysctl(op, u_sysctl); copyback = 0; diff --git a/xen/include/public/gcov.h b/xen/include/public/gcov.h new file mode 100644 index 0000000..5224249 --- /dev/null +++ b/xen/include/public/gcov.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * gcov.h + * + * Coverage structures exported by Xen. + * Structure is different from Gcc one. + * + * 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. + * + * Copyright (c) 2013, Frediano Ziglio + */ + +#ifndef __XEN_PUBLIC_GCOV_H__ +#define __XEN_PUBLIC_GCOV_H__ __XEN_PUBLIC_GCOV_H__ + +#define XENCOV_COUNTERS 5 +#define XENCOV_TAG_BASE 0x58430000u +#define XENCOV_TAG_FILE (XENCOV_TAG_BASE+0x0100u) +#define XENCOV_TAG_FUNC (XENCOV_TAG_BASE+0x0200u) +#define XENCOV_TAG_COUNTER(n) (XENCOV_TAG_BASE+0x0300u+((n)&0xffu)) +#define XENCOV_TAG_END (XENCOV_TAG_BASE+0xff00u) +#define XENCOV_IS_TAG_COUNTER(n) \ + ((n) >= XENCOV_TAG_COUNTER(0) && (n) < XENCOV_TAG_COUNTER(XENCOV_COUNTERS)) +#define XENCOV_COUNTER_NUM(n) ((n)-XENCOV_TAG_COUNTER(0)) + +/* + * The main structure for the blob is + * BLOB := FILE.. END + * FILE := TAG_FILE FILENAME xencov_file COUNTERS FUNCTIONS + * FILENAME := LEN characters + * characters are padded to 32 bit + * LEN := 32 bit value + * COUNTERS := TAG_COUNTER(n) NUM COUNTER.. + * NUM := 32 bit valie + * COUNTER := 64 bit value + * FUNCTIONS := TAG_FUNC NUM xencov_function.. + */ + +/** + * File information + * Prefixed with XENCOV_TAG_FILE and a string with filename + */ +struct xencov_file +{ + uint32_t version; + uint32_t stamp; +} __attribute__((packed)); + +/** + * Counters information + * Prefixed with XENCOV_TAG_COUNTER(n) where n is 0..(XENCOV_COUNTERS-1) + */ +struct xencov_counter +{ + uint32_t num; + uint64_t values[0]; +} __attribute__((packed)); + +/** + * Information for each function + * Prefixed with XENCOV_TAG_FUNC + * Number of counter is equal to the number of counter got before + */ +struct xencov_function +{ + uint32_t ident; + uint32_t checksum; + uint32_t n_ctrs[0]; +} __attribute__((packed)); + +struct xencov_functions +{ + uint32_t num; + uint32_t xencov_function[0]; +} __attribute__((packed)); + +#endif /* __XEN_PUBLIC_GCOV_H__ */ diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 3225b2a..5e80400 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -596,6 +596,42 @@ struct xen_sysctl_scheduler_op { typedef struct xen_sysctl_scheduler_op xen_sysctl_scheduler_op_t; DEFINE_XEN_GUEST_HANDLE(xen_sysctl_scheduler_op_t); +/* XEN_SYSCTL_coverage_op */ +/* + * Check if coverage informations are available + * return just success or error, no parameters + */ +#define XEN_SYSCTL_COVERAGE_enabled 0 + +/* + * Get total size of information, to help allocate + * the buffer. The pointer points to a 32 bit value. + */ +#define XEN_SYSCTL_COVERAGE_get_total_size 1 + +/* + * Read coverage information in a single run + * You must use a tool to split them + */ +#define XEN_SYSCTL_COVERAGE_read 2 + +/* + * Reset all the coverage counters to 0 + * No parameters. + */ +#define XEN_SYSCTL_COVERAGE_reset 3 + +struct xen_sysctl_coverage_op { + uint32_t cmd; /* XEN_SYSCTL_COVERAGE_* */ + union { + XEN_GUEST_HANDLE_64(uint32) total_size; /* OUT */ + XEN_GUEST_HANDLE_64(uint8) raw_info; /* OUT */ + } u; +}; +typedef struct xen_sysctl_coverage_op xen_sysctl_coverage_op_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_coverage_op_t); + + struct xen_sysctl { uint32_t cmd; #define XEN_SYSCTL_readconsole 1 @@ -616,6 +652,7 @@ struct xen_sysctl { #define XEN_SYSCTL_numainfo 17 #define XEN_SYSCTL_cpupool_op 18 #define XEN_SYSCTL_scheduler_op 19 +#define XEN_SYSCTL_coverage_op 20 uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ union { struct xen_sysctl_readconsole readconsole; @@ -636,6 +673,7 @@ struct xen_sysctl { struct xen_sysctl_lockprof_op lockprof_op; struct xen_sysctl_cpupool_op cpupool_op; struct xen_sysctl_scheduler_op scheduler_op; + struct xen_sysctl_coverage_op coverage_op; uint8_t pad[128]; } u; }; diff --git a/xen/include/xen/gcov.h b/xen/include/xen/gcov.h index 360b880..306d7fe 100644 --- a/xen/include/xen/gcov.h +++ b/xen/include/xen/gcov.h @@ -14,6 +14,8 @@ #ifndef __XEN_GCOV_H__ #define __XEN_GCOV_H__ __XEN_GCOV_H__ +#include <public/sysctl.h> + /* * Profiling data types used for gcc 3.4 and above - these are defined by * gcc and need to be kept as close to the original definition as possible to @@ -94,4 +96,16 @@ static inline void init_coverage(void) } #endif +/** + * Sysctl operations for coverage + */ +#ifdef TEST_COVERAGE +int sysctl_coverage_op(xen_sysctl_coverage_op_t *op); +#else +static inline int sysctl_coverage_op(xen_sysctl_coverage_op_t *op) +{ + return -ENOSYS; +} +#endif + #endif /* __XEN_GCOV_H__ */ -- 1.7.9.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |