This is an automated email from the ASF dual-hosted git repository. michallenc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit c0238938105420d26a3ae2bcf55e21461d2fc1df Author: mazhuang <[email protected]> AuthorDate: Mon Nov 2 19:03:01 2026 +0800 drivers/rpmsg: record the received messages in the note stream Add rpmsg_trace() and rpmsg_vtrace(), which write a formatted record and, optionally, a copy of the message to the note stream under the new NOTE_TAG_RPMSG tag. The note drivers then keep the last messages that went through an rpmsg transport, which helps to find out what a peer sent before a hang or a crash. The text is written with sched_note_vprintf() and the payload as a NOTE_DUMP_BINARY event; a spinlock keeps the two records of one call together when several CPUs trace at the same time. CONFIG_RPMSG_TRACE_BACKTRACE appends a backtrace of the caller to the records that ask for one. rpmsg_port traces the start and the end of every endpoint callback. Signed-off-by: yangao1 <[email protected]> Signed-off-by: mazhuang <[email protected]> Signed-off-by: Bowen Wang <[email protected]> --- drivers/rpmsg/CMakeLists.txt | 4 ++ drivers/rpmsg/Kconfig | 18 ++++++ drivers/rpmsg/Make.defs | 4 ++ drivers/rpmsg/rpmsg_port.c | 12 ++++ drivers/rpmsg/rpmsg_trace.c | 146 +++++++++++++++++++++++++++++++++++++++++++ include/nuttx/rpmsg/rpmsg.h | 27 ++++++++ include/nuttx/sched_note.h | 1 + 7 files changed, 212 insertions(+) diff --git a/drivers/rpmsg/CMakeLists.txt b/drivers/rpmsg/CMakeLists.txt index 8cfb58d5b44..cc79e76393b 100644 --- a/drivers/rpmsg/CMakeLists.txt +++ b/drivers/rpmsg/CMakeLists.txt @@ -25,6 +25,10 @@ if(CONFIG_RPMSG) list(APPEND SRCS rpmsg.c) + if(CONFIG_RPMSG_TRACE) + list(APPEND SRCS rpmsg_trace.c) + endif() + if(CONFIG_RPMSG_PING) list(APPEND SRCS rpmsg_ping.c) endif() diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index 2939850e1af..78a038b1f7b 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig @@ -10,6 +10,24 @@ config RPMSG if RPMSG +config RPMSG_TRACE + bool "rpmsg trace" + default n + depends on SCHED_INSTRUMENTATION_DUMP + ---help--- + Record the messages passed through the rpmsg transports in the + note stream under NOTE_TAG_RPMSG, so they can be read back with + the note drivers (e.g. /dev/note/ram). + +config RPMSG_TRACE_BACKTRACE + int "rpmsg trace backtrace depth" + default 0 + range 0 16 + depends on RPMSG_TRACE + ---help--- + Number of frames recorded with a trace that asks for a + backtrace. 0 disables backtraces. + config RPMSG_LOCAL_CPUNAME string "Rpmsg Local Cpuname" default LIBC_HOSTNAME diff --git a/drivers/rpmsg/Make.defs b/drivers/rpmsg/Make.defs index 5ac4247cb8b..cc43f7834be 100644 --- a/drivers/rpmsg/Make.defs +++ b/drivers/rpmsg/Make.defs @@ -26,6 +26,10 @@ ifeq ($(CONFIG_RPMSG),y) CSRCS += rpmsg.c +ifeq ($(CONFIG_RPMSG_TRACE),y) +CSRCS += rpmsg_trace.c +endif + ifeq ($(CONFIG_RPMSG_PING),y) CSRCS += rpmsg_ping.c endif diff --git a/drivers/rpmsg/rpmsg_port.c b/drivers/rpmsg/rpmsg_port.c index 62cacf033d0..025696840dc 100644 --- a/drivers/rpmsg/rpmsg_port.c +++ b/drivers/rpmsg/rpmsg_port.c @@ -439,6 +439,7 @@ static void rpmsg_port_rx_callback(FAR struct rpmsg_port_s *port, FAR struct rpmsg_hdr *rphdr = (FAR struct rpmsg_hdr *)hdr->buf; FAR void *data = RPMSG_LOCATE_DATA(rphdr); FAR struct rpmsg_endpoint *ept; + size_t len = rphdr->len + sizeof(*rphdr); int status = 0; metal_mutex_acquire(&rdev->lock); @@ -454,7 +455,18 @@ static void rpmsg_port_rx_callback(FAR struct rpmsg_port_s *port, ept->dest_addr = rphdr->src; } + rpmsg_trace(ept->name, false, rphdr, len, + "[Port] rx ept->cb start ept:%p name:%s cb:%p " + "rdev:%p hdr:%p len:%zu\n", + ept, ept->name, ept->cb, rdev, rphdr, len); + status = ept->cb(ept, data, rphdr->len, rphdr->src, ept->priv); + + rpmsg_trace(ept->name, false, NULL, 0, + "[Port] rx ept->cb end ept:%p name:%s cb:%p " + "rdev:%p hdr:%p len:%zu\n", + ept, ept->name, ept->cb, rdev, rphdr, len); + if (status < 0 && status != RPMSG_SUCCESS_BUFFER_RELEASED) { RPMSG_ASSERT(0, "unexpected callback status\n"); diff --git a/drivers/rpmsg/rpmsg_trace.c b/drivers/rpmsg/rpmsg_trace.c new file mode 100644 index 00000000000..f5e52a9fbbf --- /dev/null +++ b/drivers/rpmsg/rpmsg_trace.c @@ -0,0 +1,146 @@ +/**************************************************************************** + * drivers/rpmsg/rpmsg_trace.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdarg.h> +#include <stdint.h> +#include <sys/param.h> +#include <stdbool.h> +#include <stdio.h> +#include <execinfo.h> + +#include <nuttx/sched_note.h> +#include <nuttx/spinlock.h> +#include <nuttx/streams.h> +#include <nuttx/rpmsg/rpmsg.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* nc_length is a uint8_t, so a payload has to be split into notes that + * each fit in it. + */ + +#define RPMSG_TRACE_CHUNK (UINT8_MAX - SIZEOF_NOTE_EVENT(0)) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Keeps a text record and its binary payload next to each other in the + * note stream when several CPUs trace at the same time. + */ + +static spinlock_t g_rpmsg_trace_lock = SP_UNLOCKED; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rpmsg_trace + ****************************************************************************/ + +void rpmsg_trace(FAR const char *name, bool bt, FAR const void *buf, + size_t len, FAR const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + rpmsg_vtrace(name, bt, buf, len, format, ap); + va_end(ap); +} + +/**************************************************************************** + * Name: rpmsg_vtrace + ****************************************************************************/ + +void rpmsg_vtrace(FAR const char *name, bool bt, FAR const void *buf, + size_t len, FAR const char *format, va_list ap) +{ + irqstate_t flags; + + UNUSED(name); + +#if CONFIG_RPMSG_TRACE_BACKTRACE > 0 + if (bt) + { + FAR void *frames[CONFIG_RPMSG_TRACE_BACKTRACE]; + char btbuf[BACKTRACE_BUFFER_SIZE(CONFIG_RPMSG_TRACE_BACKTRACE)]; + char line[256]; + va_list copy; + int n; + + /* The note driver keeps the raw arguments and formats them later, + * so the message must already be a string. 256 bytes is the size + * of one note printf record. + */ + + va_copy(copy, ap); + n = vsnprintf(line, sizeof(line), format, copy); + va_end(copy); + + n = MIN(MAX(n, 0), (int)sizeof(line) - 1); + if (n > 0 && line[n - 1] == '\n') + { + n--; + } + + backtrace(frames, CONFIG_RPMSG_TRACE_BACKTRACE); + backtrace_format(btbuf, sizeof(btbuf), frames, + CONFIG_RPMSG_TRACE_BACKTRACE); + snprintf(line + n, sizeof(line) - n, ", %s", btbuf); + flags = spin_lock_irqsave(&g_rpmsg_trace_lock); + sched_note_printf(NOTE_TAG_RPMSG, "%s", line); + } + else +#endif + { + va_list copy; + + /* va_list is an array on some ABIs, so &ap of a parameter is not a + * va_list *; take a local copy. + */ + + va_copy(copy, ap); + flags = spin_lock_irqsave(&g_rpmsg_trace_lock); + sched_note_vprintf(NOTE_TAG_RPMSG, format, copy); + va_end(copy); + } + + while (buf != NULL && len > 0) + { + size_t chunk = MIN(len, RPMSG_TRACE_CHUNK); + + sched_note_event(NOTE_TAG_RPMSG, NOTE_DUMP_BINARY, buf, chunk); + buf = (FAR const uint8_t *)buf + chunk; + len -= chunk; + } + + spin_unlock_irqrestore(&g_rpmsg_trace_lock, flags); +} diff --git a/include/nuttx/rpmsg/rpmsg.h b/include/nuttx/rpmsg/rpmsg.h index 6aa96baccc3..72fe42f7ae4 100644 --- a/include/nuttx/rpmsg/rpmsg.h +++ b/include/nuttx/rpmsg/rpmsg.h @@ -29,6 +29,7 @@ #include <nuttx/config.h> #include <nuttx/atomic.h> +#include <nuttx/compiler.h> #ifdef CONFIG_RPMSG @@ -116,6 +117,32 @@ int rpmsg_ioctl(FAR const char *cpuname, int cmd, unsigned long arg); int rpmsg_panic(FAR const char *cpuname); void rpmsg_dump_all(void); +#ifdef CONFIG_RPMSG_TRACE +void rpmsg_trace(FAR const char *name, bool bt, FAR const void *buf, + size_t len, FAR const char *format, ...) + printf_like(5, 6); +void rpmsg_vtrace(FAR const char *name, bool bt, FAR const void *buf, + size_t len, FAR const char *format, va_list ap) + printf_like(5, 0); +#else +# define rpmsg_trace(name, bt, buf, len, format, ...) \ + do \ + { \ + (void)(name); \ + (void)(buf); \ + (void)(len); \ + } \ + while (0) +# define rpmsg_vtrace(name, bt, buf, len, format, ap) \ + do \ + { \ + (void)(name); \ + (void)(buf); \ + (void)(len); \ + } \ + while (0) +#endif + #ifdef __cplusplus } #endif diff --git a/include/nuttx/sched_note.h b/include/nuttx/sched_note.h index 316df77320d..f509047a603 100644 --- a/include/nuttx/sched_note.h +++ b/include/nuttx/sched_note.h @@ -306,6 +306,7 @@ enum note_tag_e NOTE_TAG_SCHED, NOTE_TAG_VIDEO, NOTE_TAG_WIRLESS, + NOTE_TAG_RPMSG, /* Always last */
