diff options
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r-- | arch/s390/kernel/smp.c | 62 |
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 | ||
44 | extern volatile int __cpu_logical_map[]; | 46 | extern 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 | */ | ||
408 | unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \ | ||
409 | __attribute__((__section__(".data"))); | ||
410 | |||
411 | static 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 | |||
452 | union save_area *zfcpdump_save_areas[NR_CPUS + 1]; | ||
453 | EXPORT_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 | ||