diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-14 05:00:25 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-14 05:00:25 +0400 |
commit | c206d44ffdd539f5f4553e1a92cc7711084c1d3c (patch) | |
tree | c2bfef721c91c3f468fb9a52bf69a785e4889128 /arch | |
parent | 83ae170092c8ec4d8a268d93438054e32493ee17 (diff) | |
parent | 1d6225e8cc5598f2bc5c992f9c88b1137763e8e1 (diff) | |
download | linux-c206d44ffdd539f5f4553e1a92cc7711084c1d3c.tar.xz |
Merge branch 'x86-uv-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-uv-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86, UV: Make kdump avoid stack dumps - fix !CONFIG_KEXEC breakage
x86, UV: Initialize BAU hub map
x86, UV: Make kdump avoid stack dumps
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/kdebug.h | 6 | ||||
-rw-r--r-- | arch/x86/kernel/apic/x2apic_uv_x.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/crash.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/tlb_uv.c | 26 |
4 files changed, 27 insertions, 12 deletions
diff --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h index fa7c0b974761..5bdfca86581b 100644 --- a/arch/x86/include/asm/kdebug.h +++ b/arch/x86/include/asm/kdebug.h @@ -33,5 +33,11 @@ extern void __show_regs(struct pt_regs *regs, int all); extern void show_regs(struct pt_regs *regs); extern unsigned long oops_begin(void); extern void oops_end(unsigned long, struct pt_regs *, int signr); +#ifdef CONFIG_KEXEC +extern int in_crash_kexec; +#else +/* no crash dump is ever in progress if no crash kernel can be kexec'd */ +#define in_crash_kexec 0 +#endif #endif /* _ASM_X86_KDEBUG_H */ diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index e46f98f36e31..7b598b84c902 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -604,6 +604,10 @@ int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data) { if (reason != DIE_NMI_IPI) return NOTIFY_OK; + + if (in_crash_kexec) + /* do nothing if entering the crash kernel */ + return NOTIFY_OK; /* * Use a lock so only one cpu prints at a time * to prevent intermixed output. diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index ebd4c51d096a..764c7c2b1811 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -28,6 +28,8 @@ #include <asm/reboot.h> #include <asm/virtext.h> +int in_crash_kexec; + #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) static void kdump_nmi_callback(int cpu, struct die_args *args) @@ -61,6 +63,7 @@ static void kdump_nmi_callback(int cpu, struct die_args *args) static void kdump_nmi_shootdown_cpus(void) { + in_crash_kexec = 1; nmi_shootdown_cpus(kdump_nmi_callback); disable_local_APIC(); diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 59efb5390b37..312ef0292815 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c @@ -1484,15 +1484,16 @@ calculate_destination_timeout(void) /* * initialize the bau_control structure for each cpu */ -static void uv_init_per_cpu(int nuvhubs) +static void __init uv_init_per_cpu(int nuvhubs) { int i; int cpu; int pnode; int uvhub; + int have_hmaster; short socket = 0; unsigned short socket_mask; - unsigned int uvhub_mask; + unsigned char *uvhub_mask; struct bau_control *bcp; struct uvhub_desc *bdp; struct socket_desc *sdp; @@ -1516,28 +1517,29 @@ static void uv_init_per_cpu(int nuvhubs) uvhub_descs = (struct uvhub_desc *) kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL); memset(uvhub_descs, 0, nuvhubs * sizeof(struct uvhub_desc)); + uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL); for_each_present_cpu(cpu) { bcp = &per_cpu(bau_control, cpu); memset(bcp, 0, sizeof(struct bau_control)); pnode = uv_cpu_hub_info(cpu)->pnode; uvhub = uv_cpu_hub_info(cpu)->numa_blade_id; - uvhub_mask |= (1 << uvhub); + *(uvhub_mask + (uvhub/8)) |= (1 << (uvhub%8)); bdp = &uvhub_descs[uvhub]; bdp->num_cpus++; bdp->uvhub = uvhub; bdp->pnode = pnode; /* kludge: 'assuming' one node per socket, and assuming that disabling a socket just leaves a gap in node numbers */ - socket = (cpu_to_node(cpu) & 1);; + socket = (cpu_to_node(cpu) & 1); bdp->socket_mask |= (1 << socket); sdp = &bdp->socket[socket]; sdp->cpu_number[sdp->num_cpus] = cpu; sdp->num_cpus++; } - uvhub = 0; - while (uvhub_mask) { - if (!(uvhub_mask & 1)) - goto nexthub; + for (uvhub = 0; uvhub < nuvhubs; uvhub++) { + if (!(*(uvhub_mask + (uvhub/8)) & (1 << (uvhub%8)))) + continue; + have_hmaster = 0; bdp = &uvhub_descs[uvhub]; socket_mask = bdp->socket_mask; socket = 0; @@ -1551,8 +1553,10 @@ static void uv_init_per_cpu(int nuvhubs) bcp->cpu = cpu; if (i == 0) { smaster = bcp; - if (socket == 0) + if (!have_hmaster) { + have_hmaster++; hmaster = bcp; + } } bcp->cpus_in_uvhub = bdp->num_cpus; bcp->cpus_in_socket = sdp->num_cpus; @@ -1566,11 +1570,9 @@ nextsocket: socket++; socket_mask = (socket_mask >> 1); } -nexthub: - uvhub++; - uvhub_mask = (uvhub_mask >> 1); } kfree(uvhub_descs); + kfree(uvhub_mask); for_each_present_cpu(cpu) { bcp = &per_cpu(bau_control, cpu); bcp->baudisabled = 0; |