|
[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 |