dfee3a7b92
For quite some time there have been problems with memory barriers and various races with NMI on multi processor systems using the kernel debugger. The algorithm for entering the kernel debug core and resuming kernel execution was racy and had several known edge case problems with attempting to debug something on a heavily loaded system using breakpoints that are hit repeatedly and quickly. The prior "locking" design entry worked as follows: * The atomic counter kgdb_active was used with atomic exchange in order to elect a master cpu out of all the cpus that may have taken a debug exception. * The master cpu increments all elements of passive_cpu_wait[]. * The master cpu issues the round up cpus message. * Each "slave cpu" that enters the debug core increments its own element in cpu_in_kgdb[]. * Each "slave cpu" spins on passive_cpu_wait[] until it becomes 0. * The master cpu debugs the system. The new scheme removes the two arrays of atomic counters and replaces them with 2 single counters. One counter is used to count the number of cpus waiting to become a master cpu (because one or more hit an exception). The second counter is use to indicate how many cpus have entered as slave cpus. The new entry logic works as follows: * One or more cpus enters via kgdb_handle_exception() and increments the masters_in_kgdb. Each cpu attempts to get the spin lock called dbg_master_lock. * The master cpu sets kgdb_active to the current cpu. * The master cpu takes the spinlock dbg_slave_lock. * The master cpu asks to round up all the other cpus. * Each slave cpu that is not already in kgdb_handle_exception() will enter and increment slaves_in_kgdb. Each slave will now spin try_locking on dbg_slave_lock. * The master cpu waits for the sum of masters_in_kgdb and slaves_in_kgdb to be equal to the sum of the online cpus. * The master cpu debugs the system. In the new design the kgdb_active can only be changed while holding dbg_master_lock. Stress testing has not turned up any further entry/exit races that existed in the prior locking design. The prior locking design suffered from atomic variables not being truly atomic (in the capacity as used by kgdb) along with memory barrier races. Signed-off-by: Jason Wessel <jason.wessel@windriver.com> Acked-by: Dongdong Deng <dongdong.deng@windriver.com> |
||
---|---|---|
.. | ||
debug | ||
gcov | ||
irq | ||
power | ||
time | ||
trace | ||
.gitignore | ||
acct.c | ||
async.c | ||
audit_tree.c | ||
audit_watch.c | ||
audit.c | ||
audit.h | ||
auditfilter.c | ||
auditsc.c | ||
backtracetest.c | ||
bounds.c | ||
capability.c | ||
cgroup_freezer.c | ||
cgroup.c | ||
compat.c | ||
configs.c | ||
cpu.c | ||
cpuset.c | ||
cred.c | ||
delayacct.c | ||
dma.c | ||
elfcore.c | ||
exec_domain.c | ||
exit.c | ||
extable.c | ||
fork.c | ||
freezer.c | ||
futex_compat.c | ||
futex.c | ||
groups.c | ||
hrtimer.c | ||
hung_task.c | ||
hw_breakpoint.c | ||
irq_work.c | ||
itimer.c | ||
jump_label.c | ||
kallsyms.c | ||
Kconfig.freezer | ||
Kconfig.hz | ||
Kconfig.locks | ||
Kconfig.preempt | ||
kexec.c | ||
kfifo.c | ||
kmod.c | ||
kprobes.c | ||
ksysfs.c | ||
kthread.c | ||
latencytop.c | ||
lockdep_internals.h | ||
lockdep_proc.c | ||
lockdep_states.h | ||
lockdep.c | ||
Makefile | ||
module.c | ||
mutex-debug.c | ||
mutex-debug.h | ||
mutex.c | ||
mutex.h | ||
notifier.c | ||
ns_cgroup.c | ||
nsproxy.c | ||
padata.c | ||
panic.c | ||
params.c | ||
perf_event.c | ||
pid_namespace.c | ||
pid.c | ||
pm_qos_params.c | ||
posix-cpu-timers.c | ||
posix-timers.c | ||
printk.c | ||
profile.c | ||
ptrace.c | ||
range.c | ||
rcupdate.c | ||
rcutiny_plugin.h | ||
rcutiny.c | ||
rcutorture.c | ||
rcutree_plugin.h | ||
rcutree_trace.c | ||
rcutree.c | ||
rcutree.h | ||
relay.c | ||
res_counter.c | ||
resource.c | ||
rtmutex_common.h | ||
rtmutex-debug.c | ||
rtmutex-debug.h | ||
rtmutex-tester.c | ||
rtmutex.c | ||
rtmutex.h | ||
rwsem.c | ||
sched_clock.c | ||
sched_cpupri.c | ||
sched_cpupri.h | ||
sched_debug.c | ||
sched_fair.c | ||
sched_features.h | ||
sched_idletask.c | ||
sched_rt.c | ||
sched_stats.h | ||
sched_stoptask.c | ||
sched.c | ||
seccomp.c | ||
semaphore.c | ||
signal.c | ||
smp.c | ||
softirq.c | ||
spinlock.c | ||
srcu.c | ||
stacktrace.c | ||
stop_machine.c | ||
sys_ni.c | ||
sys.c | ||
sysctl_binary.c | ||
sysctl_check.c | ||
sysctl.c | ||
taskstats.c | ||
test_kprobes.c | ||
time.c | ||
timeconst.pl | ||
timer.c | ||
tracepoint.c | ||
tsacct.c | ||
uid16.c | ||
up.c | ||
user_namespace.c | ||
user-return-notifier.c | ||
user.c | ||
utsname_sysctl.c | ||
utsname.c | ||
wait.c | ||
watchdog.c | ||
workqueue_sched.h | ||
workqueue.c |