[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH 3/8] lib/ukdebug: save actual data into a tracebuffer
Hi Yuri, Please see my comment inline. On 5/10/19 9:29 PM, Yuri Volchkov wrote: > 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 The '-R .uk_trace_keyvals' part should have been in the next patch, right? > 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; > _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |