Kernel: Add syscall performance event type

This allows tracing the syscalls made by a thread through the kernel's
performance event framework, which is similar in principle to strace.

Currently, this merely logs a stack backtrace to the current thread's
performance event buffer whenever a syscall is made, if profiling is
enabled. Future improvements could include tracing the arguments and
the return value, for example.
This commit is contained in:
Jean-Baptiste Boric 2021-08-10 21:02:59 +02:00 committed by Andreas Kling
parent 4c4b8ea443
commit 0286160b62
Notes: sideshowbarker 2024-07-18 07:09:05 +09:00
6 changed files with 24 additions and 1 deletions

View file

@ -135,6 +135,8 @@ KResult PerformanceEventBuffer::append_with_ip_and_bp(ProcessID pid, ThreadID ti
break; break;
case PERF_EVENT_PAGE_FAULT: case PERF_EVENT_PAGE_FAULT:
break; break;
case PERF_EVENT_SYSCALL:
break;
default: default:
return EINVAL; return EINVAL;
} }
@ -226,6 +228,9 @@ bool PerformanceEventBuffer::to_json_impl(Serializer& object) const
case PERF_EVENT_PAGE_FAULT: case PERF_EVENT_PAGE_FAULT:
event_object.add("type", "page_fault"); event_object.add("type", "page_fault");
break; break;
case PERF_EVENT_SYSCALL:
event_object.add("type", "syscall");
break;
} }
event_object.add("pid", event.pid); event_object.add("pid", event.pid);
event_object.add("tid", event.tid); event_object.add("tid", event.tid);

View file

@ -119,6 +119,17 @@ public:
} }
} }
inline static void add_syscall_event(Thread& thread, const RegisterState& regs)
{
if (thread.is_profiling_suppressed())
return;
if (auto* event_buffer = thread.process().current_perf_events_buffer()) {
[[maybe_unused]] auto rc = event_buffer->append_with_ip_and_bp(
thread.pid(), thread.tid(),
regs.ip(), regs.bp(), PERF_EVENT_SYSCALL, 0, 0, 0, nullptr);
}
}
inline static void timer_tick(RegisterState const& regs) inline static void timer_tick(RegisterState const& regs)
{ {
static Time last_wakeup; static Time last_wakeup;

View file

@ -9,6 +9,7 @@
#include <Kernel/Arch/x86/TrapFrame.h> #include <Kernel/Arch/x86/TrapFrame.h>
#include <Kernel/Memory/MemoryManager.h> #include <Kernel/Memory/MemoryManager.h>
#include <Kernel/Panic.h> #include <Kernel/Panic.h>
#include <Kernel/PerformanceManager.h>
#include <Kernel/Process.h> #include <Kernel/Process.h>
#include <Kernel/Sections.h> #include <Kernel/Sections.h>
#include <Kernel/ThreadTracer.h> #include <Kernel/ThreadTracer.h>
@ -108,6 +109,8 @@ KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F
auto& process = current_thread->process(); auto& process = current_thread->process();
current_thread->did_syscall(); current_thread->did_syscall();
PerformanceManager::add_syscall_event(*current_thread, regs);
if (function >= Function::__Count) { if (function >= Function::__Count) {
dbgln("Unknown syscall {} requested ({:p}, {:p}, {:p}, {:p})", function, arg1, arg2, arg3, arg4); dbgln("Unknown syscall {} requested ({:p}, {:p}, {:p}, {:p})", function, arg1, arg2, arg3, arg4);
return ENOSYS; return ENOSYS;

View file

@ -62,6 +62,7 @@ enum {
PERF_EVENT_KMALLOC = 2048, PERF_EVENT_KMALLOC = 2048,
PERF_EVENT_KFREE = 4096, PERF_EVENT_KFREE = 4096,
PERF_EVENT_PAGE_FAULT = 8192, PERF_EVENT_PAGE_FAULT = 8192,
PERF_EVENT_SYSCALL = 16384,
}; };
#define WNOHANG 1 #define WNOHANG 1

View file

@ -112,6 +112,7 @@ enum {
PERF_EVENT_KMALLOC = 2048, PERF_EVENT_KMALLOC = 2048,
PERF_EVENT_KFREE = 4096, PERF_EVENT_KFREE = 4096,
PERF_EVENT_PAGE_FAULT = 8192, PERF_EVENT_PAGE_FAULT = 8192,
PERF_EVENT_SYSCALL = 16384,
}; };
#define PERF_EVENT_MASK_ALL (~0ull) #define PERF_EVENT_MASK_ALL (~0ull)

View file

@ -45,6 +45,8 @@ int main(int argc, char** argv)
event_mask |= PERF_EVENT_KFREE; event_mask |= PERF_EVENT_KFREE;
else if (event_type == "page_fault") else if (event_type == "page_fault")
event_mask |= PERF_EVENT_PAGE_FAULT; event_mask |= PERF_EVENT_PAGE_FAULT;
else if (event_type == "syscall")
event_mask |= PERF_EVENT_SYSCALL;
else { else {
warnln("Unknown event type '{}' specified.", event_type); warnln("Unknown event type '{}' specified.", event_type);
exit(1); exit(1);
@ -54,7 +56,7 @@ int main(int argc, char** argv)
auto print_types = [] { auto print_types = [] {
outln(); outln();
outln("Event type can be one of: sample, context_switch, page_fault, kmalloc and kfree."); outln("Event type can be one of: sample, context_switch, page_fault, syscall, kmalloc and kfree.");
}; };
if (!args_parser.parse(argc, argv, Core::ArgsParser::FailureBehavior::PrintUsage)) { if (!args_parser.parse(argc, argv, Core::ArgsParser::FailureBehavior::PrintUsage)) {