Skip to content

Commit

Permalink
k1c: Add LOCKDEP support
Browse files Browse the repository at this point in the history
Summary:
In order to enable lockdep support, we need a compelte TRACE_IRQFLAGS
support. While enabled previously, there no trace_hardirqs support
leading to various errors when enabling PROVE_LOCKING.
This patch adds necessary calls to trace_hardirqs_on/off in assembly to
correctly track irqs state when entering exceptions.
During testing, a problem arose when calling trace_hardirqs_off
indirectly from module:

```
 ------------[ cut here ]------------
 WARNING: CPU: 0 PID: 59 at kernel/locking/lockdep.c:4329 check_flags.part.23+0x23c/0x240
 DEBUG_LOCKS_WARN_ON(current->hardirqs_enabled)
 Modules linked in: crc32c_generic(+) loop ext4 crc16 mbcache jbd2 crypto_hash crypto_algapi crypto m)
 CPU: 0 PID: 59 Comm: modprobe Tainted: G           O      5.3.0 torvalds#135
 Hardware name: Kalray HAPS prototyping (LS) (DT)
 ...
 Call Trace:
 [<ffffff80007816e8>] dump_stack+0x30/0x50
 [<ffffff8000216c98>] __warn+0x138/0x158
 [<ffffff8000216d10>] warn_slowpath_fmt+0x58/0x78
 [<ffffff800026224c>] check_flags.part.23+0x23c/0x240
 [<ffffff800026649c>] lock_is_held_type+0x1a4/0x1b0
 [<ffffff8000282dd0>] rcu_read_lock_sched_held+0x88/0x90
 [<ffffff80002a2fac>] module_assert_mutex_or_preempt+0x2c/0x98
 [<ffffff80002a3988>] __module_address+0x48/0x150
 [<ffffff80002a3ab0>] __module_text_address+0x20/0xb0
 [<ffffff80002a7900>] is_module_text_address+0x18/0x38
 [<ffffff800023be04>] kernel_text_address+0x8c/0xb8
 [<ffffff800023be50>] __kernel_text_address+0x20/0x90
 [<ffffff800020ded8>] walk_stackframe+0x78/0xe0
 [<ffffff800020e5e8>] return_address+0x58/0x90
 [<ffffff80002c3650>] trace_hardirqs_off+0x68/0x1b8
 [<ffffff800036912c>] kfree+0xe4/0x328
 [<ffffff8040087c3c>] crypto_larval_destroy+0x54/0x78 [crypto]
 [<ffffff8040087464>] crypto_larval_kill+0xd4/0xf8 [crypto]
 [<ffffff804008080c>] crypto_wait_for_test+0x9c/0x108 [crypto_algapi]
 [<ffffff8040080e24>] crypto_register_alg+0xdc/0xe8 [crypto_algapi]
 [<ffffff804008d308>] crypto_register_shash+0x48/0x70 [crypto_hash]
 [<ffffff8040096030>] crc32c_mod_init+0x30/0x4c [crc32c_generic]
 [<ffffff80002099d8>] do_one_initcall+0x70/0x2b0
 [<ffffff80002a7ed4>] do_init_module+0x74/0x270
 [<ffffff80002a6a04>] load_module+0x223c/0x26f0
 [<ffffff80002a70c8>] sys_finit_module+0xb0/0x118
 irq event stamp: 1989
 hardirqs last  enabled at (1989): [<ffffff80007a8854>] _raw_spin_unlock_irqrestore+0x8c/0xa0
 hardirqs last disabled at (1988): [<ffffff80007a861c>] _raw_spin_lock_irqsave+0x34/0x88
 softirqs last  enabled at (1940): [<ffffff80007ab04c>] _etext+0x38c/0x2340
 softirqs last disabled at (1935): [<ffffff800021c754>] irq_exit+0xa4/0xa8
 ---[ end trace f667df957dc78eed ]---
 possible reason: unannotated irqs-off.
```

Problem is due to the fact trace_hardirqs_off used CALLER_ADDR0 and
CALLER_ADDR1. These macros indirectly uses return_addr. Then in
walk_stackframe, address of frame pointer ra is checked to be a kernel
address using __kernel_text_address. In this function, __module_address
take a lock which trigger a hardirqs check that fails. However, since we are
calling it to report that trace_hardirqs are off, this is triggering a check
before even tracking that irqs are off. Remove the call to
__kernel_text_address as it is also not done on arm64.

Ref T10401

Test Plan:
Executed both smp & valid images on FPGA and verified that there are no
signaled lockdep errors. Note that this can't run on debug image since the
overhead to call trace_hardirqs_on in exception does not leave any time for
normal code to execute.

Reviewers: O51 Linux Coolidge, gthouvenin

Reviewed By: O51 Linux Coolidge, gthouvenin

Subscribers: gthouvenin, jcpince, alfred, #linux_coolidge_cc

Maniphest Tasks: T10401

Differential Revision: https://phab.kalray.eu/D2034
  • Loading branch information
clementleger authored and d3athjest3r committed Nov 20, 2023
1 parent 028eece commit a720e36
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 4 deletions.
3 changes: 3 additions & 0 deletions arch/k1c/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ config ZONE_DMA32
config STACKTRACE_SUPPORT
def_bool y

config LOCKDEP_SUPPORT
def_bool y

config TRACE_IRQFLAGS_SUPPORT
def_bool y

Expand Down
37 changes: 36 additions & 1 deletion arch/k1c/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ asn_error_panic_str_label:
.string "ASN mismatch !"
#endif

/**
* call_trace_hardirqs: hardirqs tracing call
* state: State of hardirqs to be reported (on/off)
*/
.macro call_trace_hardirqs state
#ifdef CONFIG_TRACE_IRQFLAGS
call trace_hardirqs_\state
;;
#endif
.endm

/**
* disable_interrupts: Disable interrupts
* tmp_reg: Temporary register to use for interrupt disabling
Expand All @@ -79,6 +90,7 @@ asn_error_panic_str_label:
* call_do_work_pending: Call do_work_pending and set stack argument ($r0)
* NOTE: Since do_work_pending requires thread_flags in $r1, they must
* be provided in $r1 before calling this macro.
* Moreover, do_work_pending expects interrupts to be disabled.
*/
.macro call_do_work_pending
copyd $r0 = $sp
Expand Down Expand Up @@ -221,10 +233,15 @@ asn_error_panic_str_label:
make $fp = 0
/* Reenable hwloop and clear exception taken */
make $r8 = PS_HWLOOP_EN_ET_EN
copyd \pt_regs_sp = $sp
;;
wfxl $ps, $r8
;;
/* When entering exceptions, IRQs are always disabled */
call_trace_hardirqs off
;;
/* Copy regs stack pointer for macro caller */
copyd \pt_regs_sp = $sp
;;
#ifdef CONFIG_DEBUG_EXCEPTION_STACK
addd $sp = $sp, -REG_SIZE
;;
Expand Down Expand Up @@ -289,7 +306,22 @@ _check_ok:
;;
call_do_work_pending
;;
#ifdef CONFIG_TRACE_IRQFLAGS
/* reload sps value from saved registers */
ld $r6 = PT_SPS[$sp]
;;
#endif
_restore_regs:
#ifdef CONFIG_TRACE_IRQFLAGS
/* Check if IRQs are going to be reenable in next context */
andd $r6 = $r6, K1C_SFR_SPS_IE_MASK
;;
cb.deqz $r6? 1f
;;
call trace_hardirqs_on
;;
1:
#endif
lo $r0r1r2r3 = PT_CS_SPC_SPS_ES[$sp]
;;
lo $r4r5r6r7 = PT_LC_LE_LS_RA[$sp]
Expand Down Expand Up @@ -1136,6 +1168,9 @@ call_work_pending:
;;
call_do_work_pending
;;
/* Since we are returning to user, interrupts will be reenabled */
call_trace_hardirqs on
;;
goto ret_to_user
;;

Expand Down
4 changes: 4 additions & 0 deletions arch/k1c/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,13 @@ asmlinkage void do_signal(struct pt_regs *regs)
restore_saved_sigmask();
}


asmlinkage void do_work_pending(struct pt_regs *regs,
unsigned long thread_flags)
{
/* We are called with IRQs disabled */
trace_hardirqs_off();

do {
if (thread_flags & _TIF_NEED_RESCHED) {
schedule();
Expand Down
1 change: 1 addition & 0 deletions arch/k1c/kernel/smpboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ void __init start_kernel_secondary(void)

notify_cpu_starting(cpu);
set_cpu_online(cpu, true);
trace_hardirqs_off();

local_flush_tlb_all();

Expand Down
3 changes: 0 additions & 3 deletions arch/k1c/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ void notrace walk_stackframe(struct task_struct *task, struct stackframe *frame,
while (1) {
addr = frame->ra;

if (unlikely(!__kernel_text_address(addr)))
break;

if (fn(addr, arg))
break;

Expand Down

0 comments on commit a720e36

Please sign in to comment.