1 /* 2 * arch/s390/kernel/machine_kexec.c 3 * 4 * (C) Copyright IBM Corp. 2005 5 * 6 * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com> 7 * 8 */ 9 10 /* 11 * s390_machine_kexec.c - handle the transition of Linux booting another kernel 12 * on the S390 architecture. 13 */ 14 15 #include <linux/device.h> 16 #include <linux/mm.h> 17 #include <linux/kexec.h> 18 #include <linux/delay.h> 19 #include <asm/cio.h> 20 #include <asm/setup.h> 21 #include <asm/pgtable.h> 22 #include <asm/pgalloc.h> 23 #include <asm/system.h> 24 #include <asm/smp.h> 25 26 static void kexec_halt_all_cpus(void *); 27 28 typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long); 29 30 extern const unsigned char relocate_kernel[]; 31 extern const unsigned long long relocate_kernel_len; 32 33 int 34 machine_kexec_prepare(struct kimage *image) 35 { 36 unsigned long reboot_code_buffer; 37 38 /* We don't support anything but the default image type for now. */ 39 if (image->type != KEXEC_TYPE_DEFAULT) 40 return -EINVAL; 41 42 /* Get the destination where the assembler code should be copied to.*/ 43 reboot_code_buffer = page_to_pfn(image->control_code_page)<<PAGE_SHIFT; 44 45 /* Then copy it */ 46 memcpy((void *) reboot_code_buffer, relocate_kernel, 47 relocate_kernel_len); 48 return 0; 49 } 50 51 void 52 machine_kexec_cleanup(struct kimage *image) 53 { 54 } 55 56 void 57 machine_shutdown(void) 58 { 59 printk(KERN_INFO "kexec: machine_shutdown called\n"); 60 } 61 62 NORET_TYPE void 63 machine_kexec(struct kimage *image) 64 { 65 clear_all_subchannels(); 66 67 /* Disable lowcore protection */ 68 ctl_clear_bit(0,28); 69 70 on_each_cpu(kexec_halt_all_cpus, image, 0, 0); 71 for (;;); 72 } 73 74 extern void pfault_fini(void); 75 76 static void 77 kexec_halt_all_cpus(void *kernel_image) 78 { 79 static atomic_t cpuid = ATOMIC_INIT(-1); 80 int cpu; 81 struct kimage *image; 82 relocate_kernel_t data_mover; 83 84 #ifdef CONFIG_PFAULT 85 if (MACHINE_IS_VM) 86 pfault_fini(); 87 #endif 88 89 if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1) 90 signal_processor(smp_processor_id(), sigp_stop); 91 92 /* Wait for all other cpus to enter stopped state */ 93 for_each_online_cpu(cpu) { 94 if (cpu == smp_processor_id()) 95 continue; 96 while (!smp_cpu_not_running(cpu)) 97 cpu_relax(); 98 } 99 100 image = (struct kimage *) kernel_image; 101 data_mover = (relocate_kernel_t) 102 (page_to_pfn(image->control_code_page) << PAGE_SHIFT); 103 104 /* Call the moving routine */ 105 (*data_mover) (&image->head, image->start); 106 } 107