diff options
author | David S. Miller <davem@davemloft.net> | 2016-01-13 00:21:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-01-13 00:21:27 -0500 |
commit | ddb5388ffd0ad75d07e7b78181a0b579824ba6f0 (patch) | |
tree | be1e2bd103c69d7bbace3fffd97bc3d714bbc3d7 /kernel/kexec_core.c | |
parent | ccdf6ce6a8dba374668ae9b4d763e19903611c38 (diff) | |
parent | 67990608c8b95d2b8ccc29932376ae73d5818727 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
Diffstat (limited to 'kernel/kexec_core.c')
-rw-r--r-- | kernel/kexec_core.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index 11b64a63c0f8..c823f3001e12 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -853,7 +853,12 @@ struct kimage *kexec_image; struct kimage *kexec_crash_image; int kexec_load_disabled; -void crash_kexec(struct pt_regs *regs) +/* + * No panic_cpu check version of crash_kexec(). This function is called + * only when panic_cpu holds the current CPU number; this is the only CPU + * which processes crash_kexec routines. + */ +void __crash_kexec(struct pt_regs *regs) { /* Take the kexec_mutex here to prevent sys_kexec_load * running on one cpu from replacing the crash kernel @@ -876,6 +881,29 @@ void crash_kexec(struct pt_regs *regs) } } +void crash_kexec(struct pt_regs *regs) +{ + int old_cpu, this_cpu; + + /* + * Only one CPU is allowed to execute the crash_kexec() code as with + * panic(). Otherwise parallel calls of panic() and crash_kexec() + * may stop each other. To exclude them, we use panic_cpu here too. + */ + this_cpu = raw_smp_processor_id(); + old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, this_cpu); + if (old_cpu == PANIC_CPU_INVALID) { + /* This is the 1st CPU which comes here, so go ahead. */ + __crash_kexec(regs); + + /* + * Reset panic_cpu to allow another panic()/crash_kexec() + * call. + */ + atomic_set(&panic_cpu, PANIC_CPU_INVALID); + } +} + size_t crash_get_memory_size(void) { size_t size = 0; |