[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, &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;
-- 
2.19.2


_______________________________________________
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®.