diff options
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/rv/Kconfig | 3 | ||||
| -rw-r--r-- | kernel/trace/rv/monitors/pagefault/pagefault.c | 2 | ||||
| -rw-r--r-- | kernel/trace/rv/monitors/sleep/sleep.c | 26 | ||||
| -rw-r--r-- | kernel/trace/rv/rv.c | 26 | ||||
| -rw-r--r-- | kernel/trace/rv/rv_monitors_test.c | 1 |
5 files changed, 44 insertions, 14 deletions
diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index 5608314de06b..efa930f94ea4 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -122,4 +122,7 @@ config RV_MONITORS_KUNIT_TEST These tests verify that monitors correctly detect violations by triggering fake events and validating the expected reactions. + Enabling this may slightly increase overhead of some monitors if any + unrelated KUnit test is running. + If unsure, say N. diff --git a/kernel/trace/rv/monitors/pagefault/pagefault.c b/kernel/trace/rv/monitors/pagefault/pagefault.c index 5e1a2a606783..e52500fd2de0 100644 --- a/kernel/trace/rv/monitors/pagefault/pagefault.c +++ b/kernel/trace/rv/monitors/pagefault/pagefault.c @@ -38,7 +38,7 @@ static void ltl_atoms_init(struct task_struct *task, struct ltl_monitor *mon, bo static void handle_page_fault(void *data, unsigned long address, struct pt_regs *regs, unsigned long error_code) { - ltl_atom_pulse(current, LTL_PAGEFAULT, true); + ltl_atom_pulse(rv_get_current(), LTL_PAGEFAULT, true); } static int enable_pagefault(void) diff --git a/kernel/trace/rv/monitors/sleep/sleep.c b/kernel/trace/rv/monitors/sleep/sleep.c index 4fd5e20151a8..a1b569a4b183 100644 --- a/kernel/trace/rv/monitors/sleep/sleep.c +++ b/kernel/trace/rv/monitors/sleep/sleep.c @@ -65,7 +65,7 @@ static void handle_sched_set_state(void *data, struct task_struct *task, int sta static void handle_sched_exit(void *data, bool is_switch) { - ltl_atom_pulse(current, LTL_SCHEDULE_IN, true); + ltl_atom_pulse(rv_get_current(), LTL_SCHEDULE_IN, true); } static void handle_sched_waking(void *data, struct task_struct *task) @@ -73,7 +73,7 @@ static void handle_sched_waking(void *data, struct task_struct *task) if (in_hardirq()) { ltl_atom_pulse(task, LTL_WOKEN_BY_HARDIRQ, true); } else if (in_task()) { - if (current->prio <= task->prio) + if (rv_get_current()->prio <= task->prio) ltl_atom_pulse(task, LTL_WOKEN_BY_EQUAL_OR_HIGHER_PRIO, true); } else if (in_nmi()) { ltl_atom_pulse(task, LTL_WOKEN_BY_NMI, true); @@ -83,12 +83,12 @@ static void handle_sched_waking(void *data, struct task_struct *task) static void handle_contention_begin(void *data, void *lock, unsigned int flags) { if (flags & LCB_F_RT) - ltl_atom_update(current, LTL_BLOCK_ON_RT_MUTEX, true); + ltl_atom_update(rv_get_current(), LTL_BLOCK_ON_RT_MUTEX, true); } static void handle_contention_end(void *data, void *lock, int ret) { - ltl_atom_update(current, LTL_BLOCK_ON_RT_MUTEX, false); + ltl_atom_update(rv_get_current(), LTL_BLOCK_ON_RT_MUTEX, false); } static void handle_sys_enter(void *data, struct pt_regs *regs, long id) @@ -97,7 +97,7 @@ static void handle_sys_enter(void *data, struct pt_regs *regs, long id) unsigned long args[6]; int op, cmd; - mon = ltl_get_monitor(current); + mon = ltl_get_monitor(rv_get_current()); switch (id) { #ifdef __NR_clock_nanosleep @@ -106,10 +106,10 @@ static void handle_sys_enter(void *data, struct pt_regs *regs, long id) #ifdef __NR_clock_nanosleep_time64 case __NR_clock_nanosleep_time64: #endif - syscall_get_arguments(current, regs, args); + syscall_get_arguments(rv_get_current(), regs, args); ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_REALTIME, args[0] == CLOCK_REALTIME); ltl_atom_set(mon, LTL_NANOSLEEP_TIMER_ABSTIME, args[1] == TIMER_ABSTIME); - ltl_atom_update(current, LTL_CLOCK_NANOSLEEP, true); + ltl_atom_update(rv_get_current(), LTL_CLOCK_NANOSLEEP, true); break; #ifdef __NR_futex @@ -118,25 +118,25 @@ static void handle_sys_enter(void *data, struct pt_regs *regs, long id) #ifdef __NR_futex_time64 case __NR_futex_time64: #endif - syscall_get_arguments(current, regs, args); + syscall_get_arguments(rv_get_current(), regs, args); op = args[1]; cmd = op & FUTEX_CMD_MASK; switch (cmd) { case FUTEX_LOCK_PI: case FUTEX_LOCK_PI2: - ltl_atom_update(current, LTL_FUTEX_LOCK_PI, true); + ltl_atom_update(rv_get_current(), LTL_FUTEX_LOCK_PI, true); break; case FUTEX_WAIT: case FUTEX_WAIT_BITSET: case FUTEX_WAIT_REQUEUE_PI: - ltl_atom_update(current, LTL_FUTEX_WAIT, true); + ltl_atom_update(rv_get_current(), LTL_FUTEX_WAIT, true); break; } break; #ifdef __NR_epoll_wait case __NR_epoll_wait: - ltl_atom_update(current, LTL_EPOLL_WAIT, true); + ltl_atom_update(rv_get_current(), LTL_EPOLL_WAIT, true); break; #endif } @@ -144,14 +144,14 @@ static void handle_sys_enter(void *data, struct pt_regs *regs, long id) static void handle_sys_exit(void *data, struct pt_regs *regs, long ret) { - struct ltl_monitor *mon = ltl_get_monitor(current); + struct ltl_monitor *mon = ltl_get_monitor(rv_get_current()); ltl_atom_set(mon, LTL_FUTEX_LOCK_PI, false); ltl_atom_set(mon, LTL_FUTEX_WAIT, false); ltl_atom_set(mon, LTL_NANOSLEEP_CLOCK_REALTIME, false); ltl_atom_set(mon, LTL_NANOSLEEP_TIMER_ABSTIME, false); ltl_atom_set(mon, LTL_EPOLL_WAIT, false); - ltl_atom_update(current, LTL_CLOCK_NANOSLEEP, false); + ltl_atom_update(rv_get_current(), LTL_CLOCK_NANOSLEEP, false); } static int enable_sleep(void) diff --git a/kernel/trace/rv/rv.c b/kernel/trace/rv/rv.c index 4f577d9b5ba8..29f155c6968b 100644 --- a/kernel/trace/rv/rv.c +++ b/kernel/trace/rv/rv.c @@ -885,4 +885,30 @@ void rv_clear_testing(struct kunit_suite *suite) mutex_unlock(&rv_interface_lock); } EXPORT_SYMBOL_IF_KUNIT(rv_clear_testing); + +/* + * rv_get_mock_current() is called only if we are running from a KUnit test. + * This can occur from a legitimate RV test or any unrelated test running when + * a real RV monitor is active and triggering events. + * We assume the former case is the only one where mock_current is not NULL and + * can occur only sequentially (KUnit doesn't run tests in parallel). + * We cannot rely on the test's context because there is no way to safely + * understand from which test we are running and KUnit utilities require + * locking, which is unsafe from NMI or scheduling context. + * Note that it is not possible for a real RV monitor to run when the RV KUnit + * tests are running (see rv_set_testing()). + */ +static struct task_struct *mock_current; + +void rv_mock_current(struct task_struct *tsk) +{ + mock_current = tsk; +} +EXPORT_SYMBOL_IF_KUNIT(rv_mock_current); + +struct task_struct *rv_get_mock_current(void) +{ + return mock_current ?: current; +} +EXPORT_SYMBOL_GPL(rv_get_mock_current); #endif diff --git a/kernel/trace/rv/rv_monitors_test.c b/kernel/trace/rv/rv_monitors_test.c index be440bf4b4a7..e58bd677ae0b 100644 --- a/kernel/trace/rv/rv_monitors_test.c +++ b/kernel/trace/rv/rv_monitors_test.c @@ -57,6 +57,7 @@ void teardown_test(void *arg) else mon->rv_this->react = NULL; active_ctx = NULL; + rv_mock_current(NULL); if (mon->is_per_task) *mon->task_slot = RV_PER_TASK_MONITOR_INIT; |
