[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH 3/8] lib/ukdebug: save actual data into a tracebuffer
Generate with the macro a static function. One per tracepoint. Later user will call this function to store data into the tracebuffer Signed-off-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx> --- lib/ukdebug/Makefile.uk | 3 +- lib/ukdebug/exportsyms.uk | 2 + lib/ukdebug/include/uk/trace.h | 122 ++++++++++++++++++++++++++++++++- lib/ukdebug/trace.c | 45 ++++++++++++ 4 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 lib/ukdebug/trace.c diff --git a/lib/ukdebug/Makefile.uk b/lib/ukdebug/Makefile.uk index abc340dd..663ac6de 100644 --- a/lib/ukdebug/Makefile.uk +++ b/lib/ukdebug/Makefile.uk @@ -8,6 +8,7 @@ LIBUKDEBUG_CXXFLAGS-y += -D__IN_LIBUKDEBUG__ LIBUKDEBUG_SRCS-y += $(LIBUKDEBUG_BASE)/print.c LIBUKDEBUG_SRCS-y += $(LIBUKDEBUG_BASE)/hexdump.c +LIBUKDEBUG_SRCS-$(CONFIG_LIBUKDEBUG_TRACEPOINTS) += $(LIBUKDEBUG_BASE)/trace.c EXTRA_LD_SCRIPT-$(CONFIG_LIBVFSCORE) += $(LIBUKDEBUG_BASE)/extra.ld -STRIP_SECTIONS_FLAGS-$(CONFIG_LIBUKDEBUG_TRACEPOINTS) += -R .uk_tracepoints_list +STRIP_SECTIONS_FLAGS-$(CONFIG_LIBUKDEBUG_TRACEPOINTS) += -R .uk_tracepoints_list -R .uk_trace_keyvals diff --git a/lib/ukdebug/exportsyms.uk b/lib/ukdebug/exportsyms.uk index cb8d2403..9763768f 100644 --- a/lib/ukdebug/exportsyms.uk +++ b/lib/ukdebug/exportsyms.uk @@ -7,3 +7,5 @@ uk_hexdumpf uk_hexdumpd _uk_hexdumpd _uk_hexdumpk +uk_trace_buffer_free +uk_trace_buffer_writep diff --git a/lib/ukdebug/include/uk/trace.h b/lib/ukdebug/include/uk/trace.h index 34f0ed61..ad87fbc1 100644 --- a/lib/ukdebug/include/uk/trace.h +++ b/lib/ukdebug/include/uk/trace.h @@ -36,7 +36,19 @@ #define _UK_TRACE_H_ #include <uk/essentials.h> #include <stdint.h> +#include <stddef.h> +#include <uk/plat/time.h> +#include <string.h> +#include <uk/arch/lcpu.h> +#include <uk/plat/lcpu.h> +/* There is no justification of the limit of 80 symbols. But there + * must be a limit anyways. Just number from the coding standard is + * used. Feel free to change this limit if you have the actual reason + * for another number + */ +#define __UK_TRACE_MAX_STRLEN 80 +#define UK_TP_HEADER_MAGIC 0x64685254 /* TRhd */ #define UK_TP_DEF_MAGIC 0x65645054 /* TPde */ enum __uk_trace_arg_type { @@ -44,6 +56,16 @@ enum __uk_trace_arg_type { __UK_TRACE_ARG_STRING = 1, }; +struct uk_tracepoint_header { + uint32_t magic; + uint32_t size; + __nsec time; + void *cookie; +}; + +extern size_t uk_trace_buffer_free; +extern char *uk_trace_buffer_writep; + /* TODO: consider to move UK_CONCAT into public headers */ #define __UK_CONCAT_X(a, b) a##b #define UK_CONCAT(a, b) __UK_CONCAT_X(a, b) @@ -51,6 +73,45 @@ enum __uk_trace_arg_type { #define __UK_NARGS_X(a, b, c, d, e, f, g, h, n, ...) n #define UK_NARGS(...) __UK_NARGS_X(, ##__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0) + +static inline void __uk_trace_save_arg(char **pbuff, + size_t *pfree, + enum __uk_trace_arg_type type, + int size, + long arg) +{ + char *buff = *pbuff; + size_t free = *pfree; + int len; + + if (type == __UK_TRACE_ARG_STRING) { + len = strnlen((char *) arg, __UK_TRACE_MAX_STRLEN); + /* The '+1' is for storing length of the string */ + size = len + 1; + } + + if (free < (size_t) size) { + /* Block the next invocations of trace points */ + *pfree = 0; + uk_trace_buffer_free = 0; + return; + } + + switch (type) { + case __UK_TRACE_ARG_INT: + /* for simplicity we do not care about alignment */ + memcpy(buff, &arg, size); + break; + case __UK_TRACE_ARG_STRING: + *((uint8_t *) buff) = len; + memcpy(buff + 1, (char *) arg, len); + break; + } + + *pbuff = buff + size; + *pfree -= size; +} + #define __UK_TRACE_GET_TYPE(arg) ( \ __builtin_types_compatible_p(typeof(arg), const char *) * \ __UK_TRACE_ARG_STRING + \ @@ -58,6 +119,22 @@ enum __uk_trace_arg_type { __UK_TRACE_ARG_STRING + \ 0) +#define __UK_TRACE_SAVE_ONE(arg) __uk_trace_save_arg( \ + &buff, \ + &free, \ + __UK_TRACE_GET_TYPE(arg), \ + sizeof(arg), \ + (long) arg) + +#define __UK_TRACE_SAVE_ARGS0() +#define __UK_TRACE_SAVE_ARGS1() __UK_TRACE_SAVE_ONE(arg1) +#define __UK_TRACE_SAVE_ARGS2() __UK_TRACE_SAVE_ARGS1(); __UK_TRACE_SAVE_ONE(arg2) +#define __UK_TRACE_SAVE_ARGS3() __UK_TRACE_SAVE_ARGS2(); __UK_TRACE_SAVE_ONE(arg3) +#define __UK_TRACE_SAVE_ARGS4() __UK_TRACE_SAVE_ARGS3(); __UK_TRACE_SAVE_ONE(arg4) +#define __UK_TRACE_SAVE_ARGS5() __UK_TRACE_SAVE_ARGS4(); __UK_TRACE_SAVE_ONE(arg5) +#define __UK_TRACE_SAVE_ARGS6() __UK_TRACE_SAVE_ARGS5(); __UK_TRACE_SAVE_ONE(arg6) +#define __UK_TRACE_SAVE_ARGS7() __UK_TRACE_SAVE_ARGS6(); __UK_TRACE_SAVE_ONE(arg7) + #define __UK_GET_ARG1(a1, ...) a1 #define __UK_GET_ARG2(a1, a2, ...) a2 #define __UK_GET_ARG3(a1, a2, a3, ...) a3 @@ -125,6 +202,40 @@ enum __uk_trace_arg_type { __UK_TRACE_ARG_TYPES(NR, __VA_ARGS__), \ #trace_name, fmt } +static inline char *__uk_trace_get_buff(size_t *free) +{ + struct uk_tracepoint_header *ret; + + if (uk_trace_buffer_free < sizeof(*ret)) + return 0; + ret = (struct uk_tracepoint_header *) uk_trace_buffer_writep; + + /* In case we fail to fill the tracepoint for any reason, make + * sure we do not confuse parser. We fill the header only + * after the full tracepoint is completed + */ + ret->magic = 0; + *free = uk_trace_buffer_free - sizeof(*ret); + return (char *) (ret + 1); +} + +static inline void __uk_trace_finalize_buff(char *new_buff_pos, void *cookie) +{ + uint32_t size; + struct uk_tracepoint_header *head = + (struct uk_tracepoint_header *) uk_trace_buffer_writep; + + size = new_buff_pos - uk_trace_buffer_writep; + uk_trace_buffer_writep += size; + uk_trace_buffer_free -= size; + + head->time = ukplat_monotonic_clock(); + head->size = size - sizeof(*head); + head->cookie = cookie; + barrier(); + head->magic = UK_TP_HEADER_MAGIC; +} + /* Makes from "const char*" "const char* arg1". */ #define __UK_ARGS_MAP_FN(n, t) t UK_CONCAT(arg, n) @@ -141,8 +252,17 @@ enum __uk_trace_arg_type { #define ____UK_TRACEPOINT(n, regdata_name, trace_name, fmt, ...) \ __UK_TRACE_REG(n, regdata_name, trace_name, fmt, \ __VA_ARGS__); \ - static inline void trace_name(__UK_TRACE_ARGS_MAP_UNUSED(n, __VA_ARGS__)) \ + static inline void trace_name(__UK_TRACE_ARGS_MAP(n, __VA_ARGS__)) \ { \ + unsigned long flags = ukplat_lcpu_save_irqf(); \ + size_t free __maybe_unused; \ + char *buff = __uk_trace_get_buff(&free); \ + if (buff) { \ + __UK_TRACE_SAVE_ARGS ## n(); \ + __uk_trace_finalize_buff( \ + buff, ®data_name); \ + } \ + ukplat_lcpu_restore_irqf(flags); \ } #else #define ____UK_TRACEPOINT(n, regdata_name, trace_name, fmt, ...) \ diff --git a/lib/ukdebug/trace.c b/lib/ukdebug/trace.c new file mode 100644 index 00000000..f3318557 --- /dev/null +++ b/lib/ukdebug/trace.c @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Authors: Yuri Volchkov <yuri.volchkov@xxxxxxxxx> + * + * Copyright (c) 2019, NEC Laboratories Europe GmbH, NEC Corporation. + * + * 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. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + * + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. + */ + +#include <stddef.h> +#include <uk/essentials.h> + +/* TODO: Implement a circular buffer. Currently, if the buffer is + * full, tracing disables itself. + */ +#define UK_TRACE_BUFFER_SIZE 16384 +char uk_trace_buffer[UK_TRACE_BUFFER_SIZE]; + +size_t uk_trace_buffer_free = UK_TRACE_BUFFER_SIZE; +char *uk_trace_buffer_writep = uk_trace_buffer; -- 2.19.2 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |