diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/kexec.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/kexec.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c new file mode 100644 index 000000000..145fcfbc0 --- /dev/null +++ b/arch/powerpc/platforms/pseries/kexec.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2006 Michael Ellerman, IBM Corporation + */ + +#include <linux/kernel.h> +#include <linux/interrupt.h> + +#include <asm/machdep.h> +#include <asm/page.h> +#include <asm/firmware.h> +#include <asm/kexec.h> +#include <asm/xics.h> +#include <asm/xive.h> +#include <asm/smp.h> +#include <asm/plpar_wrappers.h> + +#include "pseries.h" + +void pseries_kexec_cpu_down(int crash_shutdown, int secondary) +{ + /* + * Don't risk a hypervisor call if we're crashing + * XXX: Why? The hypervisor is not crashing. It might be better + * to at least attempt unregister to avoid the hypervisor stepping + * on our memory. + */ + if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { + int ret; + int cpu = smp_processor_id(); + int hwcpu = hard_smp_processor_id(); + + if (get_lppaca()->dtl_enable_mask) { + ret = unregister_dtl(hwcpu); + if (ret) { + pr_err("WARNING: DTL deregistration for cpu " + "%d (hw %d) failed with %d\n", + cpu, hwcpu, ret); + } + } + + ret = unregister_slb_shadow(hwcpu); + if (ret) { + pr_err("WARNING: SLB shadow buffer deregistration " + "for cpu %d (hw %d) failed with %d\n", + cpu, hwcpu, ret); + } + + ret = unregister_vpa(hwcpu); + if (ret) { + pr_err("WARNING: VPA deregistration for cpu %d " + "(hw %d) failed with %d\n", cpu, hwcpu, ret); + } + } + + if (xive_enabled()) { + xive_teardown_cpu(); + + if (!secondary) + xive_shutdown(); + } else + xics_kexec_teardown_cpu(secondary); +} |