]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blobdiff - arch/powerpc/kernel/machine_kexec_64.c
powerpc/kexec: Switch to a static PACA on the way out
[mirror_ubuntu-focal-kernel.git] / arch / powerpc / kernel / machine_kexec_64.c
index ed31a29c4ff772cb22bbf038603b4bbd83731888..022d2f613b7b4794bd2a785003494de5fcb40659 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/sections.h>      /* _end */
 #include <asm/prom.h>
 #include <asm/smp.h>
+#include <asm/hw_breakpoint.h>
 
 int default_machine_kexec_prepare(struct kimage *image)
 {
@@ -165,6 +166,7 @@ static void kexec_smp_down(void *arg)
        while(kexec_all_irq_disabled == 0)
                cpu_relax();
        mb(); /* make sure all irqs are disabled before this */
+       hw_breakpoint_disable();
        /*
         * Now every CPU has IRQs off, we can clear out any pending
         * IPIs and be sure that no more will come in after this.
@@ -180,6 +182,7 @@ static void kexec_prepare_cpus_wait(int wait_state)
 {
        int my_cpu, i, notified=-1;
 
+       hw_breakpoint_disable();
        my_cpu = get_cpu();
        /* Make sure each CPU has atleast made it to the state we need */
        for_each_online_cpu(i) {
@@ -257,6 +260,12 @@ static void kexec_prepare_cpus(void)
 static union thread_union kexec_stack __init_task_data =
        { };
 
+/*
+ * For similar reasons to the stack above, the kexecing CPU needs to be on a
+ * static PACA; we switch to kexec_paca.
+ */
+struct paca_struct kexec_paca;
+
 /* Our assembly helper, in kexec_stub.S */
 extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start,
                                        void *image, void *control,
@@ -284,6 +293,20 @@ void default_machine_kexec(struct kimage *image)
        kexec_stack.thread_info.task = current_thread_info()->task;
        kexec_stack.thread_info.flags = 0;
 
+       /* We need a static PACA, too; copy this CPU's PACA over and switch to
+        * it.  Also poison per_cpu_offset to catch anyone using non-static
+        * data.
+        */
+       memcpy(&kexec_paca, get_paca(), sizeof(struct paca_struct));
+       kexec_paca.data_offset = 0xedeaddeadeeeeeeeUL;
+       paca = (struct paca_struct *)RELOC_HIDE(&kexec_paca, 0) -
+               kexec_paca.paca_index;
+       setup_paca(&kexec_paca);
+
+       /* XXX: If anyone does 'dynamic lppacas' this will also need to be
+        * switched to a static version!
+        */
+
        /* Some things are best done in assembly.  Finding globals with
         * a toc is easier in C, so pass in what we can.
         */