aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2005-11-11 08:06:05 -0500
committerPaul Mackerras <paulus@samba.org>2005-11-14 00:33:09 -0500
commitc5e24354efae9f962e0e369d875d45f47e0bb9aa (patch)
tree9a92ab7168cd45eb5104ce662e82626b62609aa4 /arch
parent5cd16ee934eafca74a6bb790328950cec68a8b78 (diff)
[PATCH] powerpc: Turn cpu_irq_down into kexec_cpu_down
We currently have a ppc_md member called cpu_irq_down, which disables IRQs for the cpu in question. The only caller of cpu_irq_down is the kexec code. On pSeries we need to do more than just teardown IRQs at kexec time, so rename the ppc_md member to kexec_cpu_down and expand it. The pSeries code needs to know, and other platforms might too, whether we're doing a crash shutdown (ie. panicking) or a regular kexec, so add a flag for that. The pSeries implementation of kexec_cpu_down does an unregister VPA call, which tells the Hypervisor to stop writing stuff into our pacas. Without this we can get weird memory corruption bugs when we kexec, caused by the Hypervisor writing into the first kernel's pacas which happens to be somewhere interesting in the second kernel's memory. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/pseries/setup.c26
-rw-r--r--arch/ppc64/kernel/machine_kexec.c12
2 files changed, 30 insertions, 8 deletions
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 31990829310c..b9d9732b2e06 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -200,14 +200,12 @@ static void __init pSeries_setup_arch(void)
200 if (ppc64_interrupt_controller == IC_OPEN_PIC) { 200 if (ppc64_interrupt_controller == IC_OPEN_PIC) {
201 ppc_md.init_IRQ = pSeries_init_mpic; 201 ppc_md.init_IRQ = pSeries_init_mpic;
202 ppc_md.get_irq = mpic_get_irq; 202 ppc_md.get_irq = mpic_get_irq;
203 ppc_md.cpu_irq_down = mpic_teardown_this_cpu;
204 /* Allocate the mpic now, so that find_and_init_phbs() can 203 /* Allocate the mpic now, so that find_and_init_phbs() can
205 * fill the ISUs */ 204 * fill the ISUs */
206 pSeries_setup_mpic(); 205 pSeries_setup_mpic();
207 } else { 206 } else {
208 ppc_md.init_IRQ = xics_init_IRQ; 207 ppc_md.init_IRQ = xics_init_IRQ;
209 ppc_md.get_irq = xics_get_irq; 208 ppc_md.get_irq = xics_get_irq;
210 ppc_md.cpu_irq_down = xics_teardown_cpu;
211 } 209 }
212 210
213#ifdef CONFIG_SMP 211#ifdef CONFIG_SMP
@@ -595,6 +593,27 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
595 return PCI_PROBE_NORMAL; 593 return PCI_PROBE_NORMAL;
596} 594}
597 595
596#ifdef CONFIG_KEXEC
597static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
598{
599 /* Don't risk a hypervisor call if we're crashing */
600 if (!crash_shutdown) {
601 unsigned long vpa = __pa(&get_paca()->lppaca);
602
603 if (unregister_vpa(hard_smp_processor_id(), vpa)) {
604 printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
605 "failed\n", smp_processor_id(),
606 hard_smp_processor_id());
607 }
608 }
609
610 if (ppc64_interrupt_controller == IC_OPEN_PIC)
611 mpic_teardown_this_cpu(secondary);
612 else
613 xics_teardown_cpu(secondary);
614}
615#endif
616
598struct machdep_calls __initdata pSeries_md = { 617struct machdep_calls __initdata pSeries_md = {
599 .probe = pSeries_probe, 618 .probe = pSeries_probe,
600 .setup_arch = pSeries_setup_arch, 619 .setup_arch = pSeries_setup_arch,
@@ -617,4 +636,7 @@ struct machdep_calls __initdata pSeries_md = {
617 .check_legacy_ioport = pSeries_check_legacy_ioport, 636 .check_legacy_ioport = pSeries_check_legacy_ioport,
618 .system_reset_exception = pSeries_system_reset_exception, 637 .system_reset_exception = pSeries_system_reset_exception,
619 .machine_check_exception = pSeries_machine_check_exception, 638 .machine_check_exception = pSeries_machine_check_exception,
639#ifdef CONFIG_KEXEC
640 .kexec_cpu_down = pseries_kexec_cpu_down,
641#endif
620}; 642};
diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c
index 07ea03598c00..203f1d5e6f10 100644
--- a/arch/ppc64/kernel/machine_kexec.c
+++ b/arch/ppc64/kernel/machine_kexec.c
@@ -185,8 +185,8 @@ void kexec_copy_flush(struct kimage *image)
185 */ 185 */
186void kexec_smp_down(void *arg) 186void kexec_smp_down(void *arg)
187{ 187{
188 if (ppc_md.cpu_irq_down) 188 if (ppc_md.kexec_cpu_down)
189 ppc_md.cpu_irq_down(1); 189 ppc_md.kexec_cpu_down(0, 1);
190 190
191 local_irq_disable(); 191 local_irq_disable();
192 kexec_smp_wait(); 192 kexec_smp_wait();
@@ -233,8 +233,8 @@ static void kexec_prepare_cpus(void)
233 } 233 }
234 234
235 /* after we tell the others to go down */ 235 /* after we tell the others to go down */
236 if (ppc_md.cpu_irq_down) 236 if (ppc_md.kexec_cpu_down)
237 ppc_md.cpu_irq_down(0); 237 ppc_md.kexec_cpu_down(0, 0);
238 238
239 put_cpu(); 239 put_cpu();
240 240
@@ -255,8 +255,8 @@ static void kexec_prepare_cpus(void)
255 * UP to an SMP kernel. 255 * UP to an SMP kernel.
256 */ 256 */
257 smp_release_cpus(); 257 smp_release_cpus();
258 if (ppc_md.cpu_irq_down) 258 if (ppc_md.kexec_cpu_down)
259 ppc_md.cpu_irq_down(0); 259 ppc_md.kexec_cpu_down(0, 0);
260 local_irq_disable(); 260 local_irq_disable();
261} 261}
262 262