From 87a7c0317e0abe487ad06ab326f71536a6545f26 Mon Sep 17 00:00:00 2001 From: "Nakamura, Yuuichi" Date: Thu, 23 Jul 2020 22:18:14 +0900 Subject: [PATCH] Add note_syscall args support --- include/nuttx/sched_note.h | 14 ++++++++++-- sched/Kconfig | 3 ++- sched/sched/sched_note.c | 45 +++++++++++++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/include/nuttx/sched_note.h b/include/nuttx/sched_note.h index 51011631b9a..90baedfa2a3 100644 --- a/include/nuttx/sched_note.h +++ b/include/nuttx/sched_note.h @@ -69,6 +69,9 @@ #ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER #define NOTE_FILTER_MODE_FLAG_IRQ (1 << 2) /* Enable IRQ instrumentaiton */ #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL +#define NOTE_FILTER_MODE_FLAG_SYSCALL_ARGS (1 << 3) /* Enable collecting syscall arguments */ +#endif /* Helper macros for syscall instrumentation filter */ @@ -278,10 +281,17 @@ struct note_spinlock_s #ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL /* This is the specific form of the NOTE_SYSCALL_ENTER/LEAVE notes */ +#define MAX_SYSCALL_ARGS 6 +#define SIZEOF_NOTE_SYSCALL_ENTER(n) (sizeof(struct note_common_s) + \ + sizeof(uint8_t) + sizeof(uint8_t) + \ + (sizeof(uintptr_t) * (n))) + struct note_syscall_enter_s { - struct note_common_s nsc_cmn; /* Common note parameters */ - uint8_t nsc_nr; /* System call number */ + struct note_common_s nsc_cmn; /* Common note parameters */ + uint8_t nsc_nr; /* System call number */ + uint8_t nsc_argc; /* Number of system call arguments */ + uint8_t nsc_args[sizeof(uintptr_t) * MAX_SYSCALL_ARGS]; /* System call arguments */ }; struct note_syscall_leave_s diff --git a/sched/Kconfig b/sched/Kconfig index 840f5897999..6ebfcf9eb7b 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -1003,12 +1003,13 @@ config SCHED_INSTRUMENTATION_FILTER config SCHED_INSTRUMENTATION_FILTER_DEFAULT_MODE hex "Default instrumentation filter mode" depends on SCHED_INSTRUMENTATION_FILTER - default 0x7 + default 0xf ---help--- Default mode of the instrumentation filter logic. Bit 0 = Enable instrumentation Bit 1 = Enable syscall instrumentation Bit 2 = Enable IRQ instrumentation + Bit 3 = Enable collecting syscall arguments endif # SCHED_INSTRUMENTATION endmenu # Performance Monitoring diff --git a/sched/sched/sched_note.c b/sched/sched/sched_note.c index bf8d22fc8aa..02f5b244eb2 100644 --- a/sched/sched/sched_note.c +++ b/sched/sched/sched_note.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -651,22 +652,60 @@ void sched_note_syscall_enter(int nr, int argc, ...) { struct note_syscall_enter_s note; FAR struct tcb_s *tcb = this_task(); + unsigned int length; + va_list ap; + uintptr_t arg; + int i; + uint8_t *args; if (!note_isenabled_syscall(nr)) { return; } +#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER + if (!(g_note_filter.mode.flag & NOTE_FILTER_MODE_FLAG_SYSCALL_ARGS)) + { + argc = 0; + } +#endif + /* Format the note */ - note_common(tcb, ¬e.nsc_cmn, sizeof(struct note_syscall_enter_s), - NOTE_SYSCALL_ENTER); + length = SIZEOF_NOTE_SYSCALL_ENTER(argc); + note_common(tcb, ¬e.nsc_cmn, length, NOTE_SYSCALL_ENTER); DEBUGASSERT(nr <= UCHAR_MAX); note.nsc_nr = nr; + DEBUGASSERT(argc <= MAX_SYSCALL_ARGS); + note.nsc_argc = argc; + + /* If needed, retrieve the given syscall arguments */ + + va_start(ap, argc); + + args = note.nsc_args; + for (i = 0; i < argc; i++) + { + arg = (uintptr_t)va_arg(ap, uintptr_t); + *args++ = (uint8_t)(arg & 0xff); + *args++ = (uint8_t)((arg >> 8) & 0xff); +#if UINTPTR_MAX > UINT16_MAX + *args++ = (uint8_t)((arg >> 16) & 0xff); + *args++ = (uint8_t)((arg >> 24) & 0xff); +#if UINTPTR_MAX > UINT32_MAX + *args++ = (uint8_t)((arg >> 32) & 0xff); + *args++ = (uint8_t)((arg >> 40) & 0xff); + *args++ = (uint8_t)((arg >> 48) & 0xff); + *args++ = (uint8_t)((arg >> 56) & 0xff); +#endif +#endif + } + + va_end(ap); /* Add the note to circular buffer */ - sched_note_add(¬e, sizeof(struct note_syscall_enter_s)); + sched_note_add((FAR const uint8_t *)¬e, length); } void sched_note_syscall_leave(int nr, uintptr_t result)