mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-25 05:34:00 +08:00
d8550860d9
When the scheduler sets TIF_NEED_RESCHED & we call into the scheduler
from arch/mips/kernel/entry.S we disable interrupts. This is true
regardless of whether we reach work_resched from syscall_exit_work,
resume_userspace or by looping after calling schedule(). Although we
disable interrupts in these paths we don't call trace_hardirqs_off()
before calling into C code which may acquire locks, and we therefore
leave lockdep with an inconsistent view of whether interrupts are
disabled or not when CONFIG_PROVE_LOCKING & CONFIG_DEBUG_LOCKDEP are
both enabled.
Without tracing this interrupt state lockdep will print warnings such
as the following once a task returns from a syscall via
syscall_exit_partial with TIF_NEED_RESCHED set:
[ 49.927678] ------------[ cut here ]------------
[ 49.934445] WARNING: CPU: 0 PID: 1 at kernel/locking/lockdep.c:3687 check_flags.part.41+0x1dc/0x1e8
[ 49.946031] DEBUG_LOCKS_WARN_ON(current->hardirqs_enabled)
[ 49.946355] CPU: 0 PID: 1 Comm: init Not tainted 4.10.0-00439-gc9fd5d362289-dirty #197
[ 49.963505] Stack : 0000000000000000 ffffffff81bb5d6a 0000000000000006 ffffffff801ce9c4
[ 49.974431] 0000000000000000 0000000000000000 0000000000000000 000000000000004a
[ 49.985300] ffffffff80b7e487 ffffffff80a24498 a8000000ff160000 ffffffff80ede8b8
[ 49.996194] 0000000000000001 0000000000000000 0000000000000000 0000000077c8030c
[ 50.007063] 000000007fd8a510 ffffffff801cd45c 0000000000000000 a8000000ff127c88
[ 50.017945] 0000000000000000 ffffffff801cf928 0000000000000001 ffffffff80a24498
[ 50.028827] 0000000000000000 0000000000000001 0000000000000000 0000000000000000
[ 50.039688] 0000000000000000 a8000000ff127bd0 0000000000000000 ffffffff805509bc
[ 50.050575] 00000000140084e0 0000000000000000 0000000000000000 0000000000040a00
[ 50.061448] 0000000000000000 ffffffff8010e1b0 0000000000000000 ffffffff805509bc
[ 50.072327] ...
[ 50.076087] Call Trace:
[ 50.079869] [<ffffffff8010e1b0>] show_stack+0x80/0xa8
[ 50.086577] [<ffffffff805509bc>] dump_stack+0x10c/0x190
[ 50.093498] [<ffffffff8015dde0>] __warn+0xf0/0x108
[ 50.099889] [<ffffffff8015de34>] warn_slowpath_fmt+0x3c/0x48
[ 50.107241] [<ffffffff801c15b4>] check_flags.part.41+0x1dc/0x1e8
[ 50.114961] [<ffffffff801c239c>] lock_is_held_type+0x8c/0xb0
[ 50.122291] [<ffffffff809461b8>] __schedule+0x8c0/0x10f8
[ 50.129221] [<ffffffff80946a60>] schedule+0x30/0x98
[ 50.135659] [<ffffffff80106278>] work_resched+0x8/0x34
[ 50.142397] ---[ end trace 0cb4f6ef5b99fe21 ]---
[ 50.148405] possible reason: unannotated irqs-off.
[ 50.154600] irq event stamp: 400463
[ 50.159566] hardirqs last enabled at (400463): [<ffffffff8094edc8>] _raw_spin_unlock_irqrestore+0x40/0xa8
[ 50.171981] hardirqs last disabled at (400462): [<ffffffff8094eb98>] _raw_spin_lock_irqsave+0x30/0xb0
[ 50.183897] softirqs last enabled at (400450): [<ffffffff8016580c>] __do_softirq+0x4ac/0x6a8
[ 50.195015] softirqs last disabled at (400425): [<ffffffff80165e78>] irq_exit+0x110/0x128
Fix this by using the TRACE_IRQS_OFF macro to call trace_hardirqs_off()
when CONFIG_TRACE_IRQFLAGS is enabled. This is done before invoking
schedule() following the work_resched label because:
1) Interrupts are disabled regardless of the path we take to reach
work_resched() & schedule().
2) Performing the tracing here avoids the need to do it in paths which
disable interrupts but don't call out to C code before hitting a
path which uses the RESTORE_SOME macro that will call
trace_hardirqs_on() or trace_hardirqs_off() as appropriate.
We call trace_hardirqs_on() using the TRACE_IRQS_ON macro before calling
syscall_trace_leave() for similar reasons, ensuring that lockdep has a
consistent view of state after we re-enable interrupts.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Fixes:
|
||
---|---|---|
.. | ||
.gitignore | ||
8250-platform.c | ||
asm-offsets.c | ||
binfmt_elfn32.c | ||
binfmt_elfo32.c | ||
bmips_5xxx_init.S | ||
bmips_vec.S | ||
branch.c | ||
cacheinfo.c | ||
cevt-bcm1480.c | ||
cevt-ds1287.c | ||
cevt-gt641xx.c | ||
cevt-r4k.c | ||
cevt-sb1250.c | ||
cevt-txx9.c | ||
cps-vec-ns16550.S | ||
cps-vec.S | ||
cpu-bugs64.c | ||
cpu-probe.c | ||
crash_dump.c | ||
crash.c | ||
csrc-bcm1480.c | ||
csrc-ioasic.c | ||
csrc-r4k.c | ||
csrc-sb1250.c | ||
early_printk_8250.c | ||
early_printk.c | ||
elf.c | ||
entry.S | ||
ftrace.c | ||
genex.S | ||
gpio_txx9.c | ||
head.S | ||
i8253.c | ||
idle.c | ||
irq_txx9.c | ||
irq-gt641xx.c | ||
irq-msc01.c | ||
irq-rm7000.c | ||
irq.c | ||
jump_label.c | ||
kgdb.c | ||
kprobes.c | ||
linux32.c | ||
machine_kexec.c | ||
Makefile | ||
mcount.S | ||
mips_machine.c | ||
mips-cm.c | ||
mips-cpc.c | ||
mips-mt-fpaff.c | ||
mips-mt.c | ||
mips-r2-to-r6-emul.c | ||
module-rela.c | ||
module.c | ||
octeon_switch.S | ||
perf_event_mipsxx.c | ||
perf_event.c | ||
pm-cps.c | ||
pm.c | ||
probes-common.h | ||
proc.c | ||
process.c | ||
prom.c | ||
ptrace32.c | ||
ptrace.c | ||
r4k_fpu.S | ||
r4k_switch.S | ||
r2300_fpu.S | ||
r2300_switch.S | ||
r6000_fpu.S | ||
relocate_kernel.S | ||
relocate.c | ||
reset.c | ||
rtlx-cmp.c | ||
rtlx-mt.c | ||
rtlx.c | ||
scall32-o32.S | ||
scall64-64.S | ||
scall64-n32.S | ||
scall64-o32.S | ||
segment.c | ||
setup.c | ||
signal32.c | ||
signal_n32.c | ||
signal_o32.c | ||
signal-common.h | ||
signal.c | ||
smp-bmips.c | ||
smp-cmp.c | ||
smp-cps.c | ||
smp-mt.c | ||
smp-up.c | ||
smp.c | ||
spinlock_test.c | ||
spram.c | ||
stacktrace.c | ||
sync-r4k.c | ||
syscall.c | ||
sysrq.c | ||
time.c | ||
topology.c | ||
traps.c | ||
unaligned.c | ||
uprobes.c | ||
vdso.c | ||
vmlinux.lds.S | ||
vpe-cmp.c | ||
vpe-mt.c | ||
vpe.c | ||
watch.c |