xref: /linux/arch/powerpc/platforms/pseries/kexec.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright 2006 Michael Ellerman, IBM Corporation
4  */
5 
6 #include <linux/kernel.h>
7 #include <linux/interrupt.h>
8 
9 #include <asm/setup.h>
10 #include <asm/page.h>
11 #include <asm/firmware.h>
12 #include <asm/kexec.h>
13 #include <asm/xics.h>
14 #include <asm/xive.h>
15 #include <asm/smp.h>
16 #include <asm/plpar_wrappers.h>
17 
18 #include "pseries.h"
19 
20 void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
21 {
22 	/*
23 	 * Ensure vpa/slb_shadow/dtl cleanup even while we are crashing.
24 	 * Why? The hypervisor is not crashing so at least attempt unregister to
25 	 * avoid the hypervisor stepping on our memory. If hypervisor or kexec
26 	 * kernel steps on the old memory allocated to these areas before the
27 	 * new kexec-kernel happens to allocate and register new areas,
28 	 * the hypervisor will see invalid content which may cause
29 	 * unexpected behavior.
30 	 */
31 	if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
32 		int ret;
33 		int cpu = smp_processor_id();
34 		int hwcpu = hard_smp_processor_id();
35 
36 		if (get_lppaca()->dtl_enable_mask) {
37 			ret = unregister_dtl(hwcpu);
38 			if (ret) {
39 				pr_err("WARNING: DTL deregistration for cpu "
40 				       "%d (hw %d) failed with %d\n",
41 				       cpu, hwcpu, ret);
42 			}
43 		}
44 
45 		ret = unregister_slb_shadow(hwcpu);
46 		if (ret) {
47 			pr_err("WARNING: SLB shadow buffer deregistration "
48 			       "for cpu %d (hw %d) failed with %d\n",
49 			       cpu, hwcpu, ret);
50 		}
51 
52 		ret = unregister_vpa(hwcpu);
53 		if (ret) {
54 			pr_err("WARNING: VPA deregistration for cpu %d "
55 			       "(hw %d) failed with %d\n", cpu, hwcpu, ret);
56 		}
57 	}
58 
59 	if (xive_enabled()) {
60 		xive_teardown_cpu();
61 
62 		if (!secondary)
63 			xive_shutdown();
64 	} else
65 		xics_kexec_teardown_cpu(secondary);
66 }
67