aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/smp.c
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@de.ibm.com>2007-04-27 10:01:49 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-04-27 10:01:44 -0400
commit411ed3225733dbd83b4cbaaa992ef80d6ec1534e (patch)
tree388aeac39e9fad5f7cadcc8fcbf0838811f5829d /arch/s390/kernel/smp.c
parent7039d3a11c4b4b59f9ef933b4b0a28304bdd07d1 (diff)
[S390] zfcpdump support.
s390 machines provide hardware support for creating Linux dumps on SCSI disks. For creating a dump a special purpose dump Linux is used. The first 32 MB of memory are saved by the hardware before the dump Linux is booted. Via an SCLP interface, the saved memory can be accessed from Linux. This patch exports memory and registers of the crashed Linux to userspace via a debugfs file. For more information refer to Documentation/s390/zfcpdump.txt, which is included in this patch. Signed-off-by: Michael Holzheu <holzheu@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r--arch/s390/kernel/smp.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 97764f710bb7..7c0143fdf710 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -31,6 +31,7 @@
31#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/cpu.h> 32#include <linux/cpu.h>
33#include <linux/timex.h> 33#include <linux/timex.h>
34#include <linux/bootmem.h>
34#include <asm/ipl.h> 35#include <asm/ipl.h>
35#include <asm/setup.h> 36#include <asm/setup.h>
36#include <asm/sigp.h> 37#include <asm/sigp.h>
@@ -40,6 +41,7 @@
40#include <asm/cpcmd.h> 41#include <asm/cpcmd.h>
41#include <asm/tlbflush.h> 42#include <asm/tlbflush.h>
42#include <asm/timer.h> 43#include <asm/timer.h>
44#include <asm/lowcore.h>
43 45
44extern volatile int __cpu_logical_map[]; 46extern volatile int __cpu_logical_map[];
45 47
@@ -395,6 +397,65 @@ void smp_ctl_clear_bit(int cr, int bit)
395 on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1); 397 on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
396} 398}
397 399
400#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
401
402/*
403 * zfcpdump_prefix_array holds prefix registers for the following scenario:
404 * 64 bit zfcpdump kernel and 31 bit kernel which is to be dumped. We have to
405 * save its prefix registers, since they get lost, when switching from 31 bit
406 * to 64 bit.
407 */
408unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \
409 __attribute__((__section__(".data")));
410
411static void __init smp_get_save_areas(void)
412{
413 unsigned int cpu, cpu_num, rc;
414 __u16 boot_cpu_addr;
415
416 if (ipl_info.type != IPL_TYPE_FCP_DUMP)
417 return;
418 boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
419 cpu_num = 1;
420 for (cpu = 0; cpu <= 65535; cpu++) {
421 if ((u16) cpu == boot_cpu_addr)
422 continue;
423 __cpu_logical_map[1] = (__u16) cpu;
424 if (signal_processor(1, sigp_sense) == sigp_not_operational)
425 continue;
426 if (cpu_num >= NR_CPUS) {
427 printk("WARNING: Registers for cpu %i are not "
428 "saved, since dump kernel was compiled with"
429 "NR_CPUS=%i!\n", cpu_num, NR_CPUS);
430 continue;
431 }
432 zfcpdump_save_areas[cpu_num] =
433 alloc_bootmem(sizeof(union save_area));
434 while (1) {
435 rc = signal_processor(1, sigp_stop_and_store_status);
436 if (rc != sigp_busy)
437 break;
438 cpu_relax();
439 }
440 memcpy(zfcpdump_save_areas[cpu_num],
441 (void *)(unsigned long) store_prefix() +
442 SAVE_AREA_BASE, SAVE_AREA_SIZE);
443#ifdef __s390x__
444 /* copy original prefix register */
445 zfcpdump_save_areas[cpu_num]->s390x.pref_reg =
446 zfcpdump_prefix_array[cpu_num];
447#endif
448 cpu_num++;
449 }
450}
451
452union save_area *zfcpdump_save_areas[NR_CPUS + 1];
453EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
454
455#else
456#define smp_get_save_areas() do { } while (0)
457#endif
458
398/* 459/*
399 * Lets check how many CPUs we have. 460 * Lets check how many CPUs we have.
400 */ 461 */
@@ -589,6 +650,7 @@ void __init smp_setup_cpu_possible_map(void)
589{ 650{
590 unsigned int phy_cpus, pos_cpus, cpu; 651 unsigned int phy_cpus, pos_cpus, cpu;
591 652
653 smp_get_save_areas();
592 phy_cpus = smp_count_cpus(); 654 phy_cpus = smp_count_cpus();
593 pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS); 655 pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS);
594 656