[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, &regdata_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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.