From 90a420d8bbe1efb10cfc6b976139d1bcae3f6170 Mon Sep 17 00:00:00 2001 From: Matheus Date: Wed, 22 Apr 2026 19:44:08 -0300 Subject: [PATCH] prof: add user/kernel statistics --- kernel-src/arch/x86-64/arch_prof.c | 8 ++----- kernel-src/sys/prof.c | 37 +++++++++++++++++++++++------- tools/prof/main.c | 24 ++++++++++++++----- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/kernel-src/arch/x86-64/arch_prof.c b/kernel-src/arch/x86-64/arch_prof.c index d533c315..de599efe 100644 --- a/kernel-src/arch/x86-64/arch_prof.c +++ b/kernel-src/arch/x86-64/arch_prof.c @@ -99,10 +99,8 @@ static bool intel_irq(context_t *context) { uint8_t data[1 + sizeof(uintptr_t) * 256]; uint8_t size = get_backtrace(context, (uintptr_t *)(data + 1)); - if (size) { - *data = size; - profiling_insert(size, data); - } + *data = size; + profiling_insert(size, data); arch_apic_init_perf(); // SDM LVT figure says a PMC irq masks itself, so unmask it reset_intel_pmc(); @@ -118,8 +116,6 @@ static void init_amd_pmc(void) { __assert(!"Unimplemented"); } - - bool arch_profiling_irq(context_t *context) { if (!strcmp(current_cpu()->vendor, "AuthenticAMD")) return amd_irq(context); diff --git a/kernel-src/sys/prof.c b/kernel-src/sys/prof.c index 7e33ac98..e8160b3e 100644 --- a/kernel-src/sys/prof.c +++ b/kernel-src/sys/prof.c @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef ENABLE_PROFILING @@ -19,9 +20,17 @@ static MUTEX_DEFINE(mutex); static pollheader_t pollheader; static semaphore_t wait_sem; static int remaining; +static size_t userspace_hits; +static size_t kernel_hits; // called from a possibly NMI context! void profiling_insert(uint8_t size, void *data) { + if (!size) { + __atomic_fetch_add(&userspace_hits, 1, __ATOMIC_SEQ_CST); + return; + } + + __atomic_fetch_add(&kernel_hits, 1, __ATOMIC_SEQ_CST); size_t write_size = sizeof(uint8_t) + sizeof(uintptr_t) * size; if (current_cpu()->prof_ringbuffer && RINGBUFFER_FREESPACE(current_cpu()->prof_ringbuffer) >= write_size) { size_t written = ringbuffer_write(current_cpu()->prof_ringbuffer, data, write_size); @@ -149,19 +158,31 @@ static int device_read(int minor, iovec_iterator_t *iovec_iterator, size_t size, return error; } -static int device_ioctl(int, unsigned long request, void *, int *result, cred_t *cred) { - if (request != 12345678) - return ENOTTY; - +static int device_ioctl(int, unsigned long request, void *addr, int *result, cred_t *cred) { + *result = 0; // only supported ioctl is a truncation one: remove all previous data - MUTEX_ACQUIRE(&mutex); + switch (request) { + case 12345678: + MUTEX_ACQUIRE(&mutex); - ringbuffer_truncate(&global_ringbuffer, PROFILING_GLOBAL_BUFFER_SIZE); + ringbuffer_truncate(&global_ringbuffer, PROFILING_GLOBAL_BUFFER_SIZE); - MUTEX_RELEASE(&mutex); + MUTEX_RELEASE(&mutex); + + __atomic_store_n(&userspace_hits, 0, __ATOMIC_SEQ_CST); + __atomic_store_n(&kernel_hits, 0, __ATOMIC_SEQ_CST); + break; + case 87654321: + size_t outputs[2] = { + __atomic_load_n(&userspace_hits, __ATOMIC_SEQ_CST), + __atomic_load_n(&kernel_hits, __ATOMIC_SEQ_CST) + }; + + + return USERCOPY_POSSIBLY_TO_USER(addr, outputs, sizeof(outputs)); + } - *result = 0; return 0; } diff --git a/tools/prof/main.c b/tools/prof/main.c index 6c247a36..5e8abd0f 100644 --- a/tools/prof/main.c +++ b/tools/prof/main.c @@ -22,8 +22,8 @@ static int open_or_die(const char *name, int flag, mode_t mode) { int main(int argc, char *argv[]) { progname = argv[0]; - if (argc != 2) { - fprintf(stderr, "%s: usage: %s FILE\n", argv[0], argv[0]); + if (argc < 2 || argc > 3) { + fprintf(stderr, "%s: usage: %s FILE [-n]\n", argv[0], argv[0]); return EXIT_FAILURE; } @@ -42,10 +42,12 @@ int main(int argc, char *argv[]) { tcsetattr(outfd, TCSANOW, &termios); } - printf("%s: draining /dev/prof\n", argv[0]); - // empty it - if (ioctl(infd, 12345678, NULL) < 0) - return EXIT_FAILURE; + if (argc == 2 || (strcmp(argv[1], "-n") && strcmp(argv[2], "-n"))) { + printf("%s: draining /dev/prof\n", argv[0]); + // empty it + if (ioctl(infd, 12345678, NULL) < 0) + return EXIT_FAILURE; + } struct pollfd pollfd[2]; @@ -68,6 +70,16 @@ int main(int argc, char *argv[]) { write(outfd, buf, 8 * count); } + size_t hits[2]; + ioctl(infd, 87654321, hits); + + size_t total = hits[0] + hits[1]; + float u_ratio = (float)hits[0] / (float)total; + float k_ratio = 1.f - u_ratio; + + printf("%s: %lu hits\n", argv[0], total); + printf("%s: %lu userspace hits (%01.02f%%)\n", argv[0], hits[0], u_ratio * 100); + printf("%s: %lu kernel hits (%01.02f%%)\n", argv[0], hits[1], k_ratio * 100); printf("%s: done\n", argv[0]); return EXIT_SUCCESS;