s390/dump: save IPL CPU registers once DAT is available
authorAlexander Gordeev <agordeev@linux.ibm.com>
Fri, 2 Sep 2022 08:05:08 +0000 (10:05 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Wed, 14 Sep 2022 14:46:00 +0000 (16:46 +0200)
Function smp_save_dump_cpus() collects CPU state of a crashed
system for secondary CPUs and for the IPL CPU very differently.
The Signal Processor stop-and-store-status orders are used for
the former while Hardware System Area requests and memcpy_real()
routine are called for the latter. In addition a system reset is
triggered, which pins smp_save_dump_cpus() function call before
CPU and device initialization.

Move the collection of IPL CPU state to a later stage when DAT
becomes available. That is needed to allow a follow-up rework of
memcpy_real() routine.

Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/include/asm/smp.h
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c

index 59cd27255f38bbb0a6d858ae9e3022e03aac2f36..73ed2781073b260f5621bcb9142d5d2919e518dd 100644 (file)
@@ -30,7 +30,8 @@ extern void smp_emergency_stop(void);
 
 extern int smp_find_processor_id(u16 address);
 extern int smp_store_status(int cpu);
-extern void smp_save_dump_cpus(void);
+extern void smp_save_dump_ipl_cpu(void);
+extern void smp_save_dump_secondary_cpus(void);
 extern void smp_yield_cpu(int cpu);
 extern void smp_cpu_set_polarization(int cpu, int val);
 extern int smp_cpu_get_polarization(int cpu);
index 8d0a670c9f4825fddbc38d14c1916feeebf61ca7..d1390899a8e7e2530c083ec09ce82953aad0d58f 100644 (file)
@@ -1028,10 +1028,10 @@ void __init setup_arch(char **cmdline_p)
        reserve_crashkernel();
 #ifdef CONFIG_CRASH_DUMP
        /*
-        * Be aware that smp_save_dump_cpus() triggers a system reset.
+        * Be aware that smp_save_dump_secondary_cpus() triggers a system reset.
         * Therefore CPU and device initialization should be done afterwards.
         */
-       smp_save_dump_cpus();
+       smp_save_dump_secondary_cpus();
 #endif
 
        setup_resources();
@@ -1056,6 +1056,9 @@ void __init setup_arch(char **cmdline_p)
         * in lowcore can now run with DAT enabled.
         */
        setup_lowcore_dat_on();
+#ifdef CONFIG_CRASH_DUMP
+       smp_save_dump_ipl_cpu();
+#endif
 
         /* Setup default console */
        conmode_default();
index 0f646b568d592981ae740d1cbc55b763900957fb..14601648914ecc1f64a4fc90546cd59796043e0a 100644 (file)
@@ -664,35 +664,36 @@ int smp_store_status(int cpu)
  *    This case does not exist for s390 anymore, setup_arch explicitly
  *    deactivates the elfcorehdr= kernel parameter
  */
-static __init void smp_save_cpu_vxrs(struct save_area *sa, u16 addr,
-                                    bool is_boot_cpu, __vector128 *vxrs)
+static bool dump_available(void)
 {
-       if (is_boot_cpu)
-               vxrs = boot_cpu_vector_save_area;
-       else
-               __pcpu_sigp_relax(addr, SIGP_STORE_ADDITIONAL_STATUS, __pa(vxrs));
-       save_area_add_vxrs(sa, vxrs);
+       return oldmem_data.start || is_ipl_type_dump();
 }
 
-static __init void smp_save_cpu_regs(struct save_area *sa, u16 addr,
-                                    bool is_boot_cpu, void *regs)
+void __init smp_save_dump_ipl_cpu(void)
 {
-       if (is_boot_cpu)
-               copy_oldmem_kernel(regs, __LC_FPREGS_SAVE_AREA, 512);
-       else
-               __pcpu_sigp_relax(addr, SIGP_STORE_STATUS_AT_ADDRESS, __pa(regs));
+       struct save_area *sa;
+       void *regs;
+
+       if (!dump_available())
+               return;
+       sa = save_area_alloc(true);
+       regs = memblock_alloc(512, 8);
+       if (!sa || !regs)
+               panic("could not allocate memory for boot CPU save area\n");
+       copy_oldmem_kernel(regs, __LC_FPREGS_SAVE_AREA, 512);
        save_area_add_regs(sa, regs);
+       memblock_free(regs, 512);
+       if (MACHINE_HAS_VX)
+               save_area_add_vxrs(sa, boot_cpu_vector_save_area);
 }
 
-void __init smp_save_dump_cpus(void)
+void __init smp_save_dump_secondary_cpus(void)
 {
        int addr, boot_cpu_addr, max_cpu_addr;
        struct save_area *sa;
-       bool is_boot_cpu;
        void *page;
 
-       if (!(oldmem_data.start || is_ipl_type_dump()))
-               /* No previous system present, normal boot. */
+       if (!dump_available())
                return;
        /* Allocate a page as dumping area for the store status sigps */
        page = memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
@@ -705,26 +706,20 @@ void __init smp_save_dump_cpus(void)
        boot_cpu_addr = stap();
        max_cpu_addr = SCLP_MAX_CORES << sclp.mtid_prev;
        for (addr = 0; addr <= max_cpu_addr; addr++) {
+               if (addr == boot_cpu_addr)
+                       continue;
                if (__pcpu_sigp_relax(addr, SIGP_SENSE, 0) ==
                    SIGP_CC_NOT_OPERATIONAL)
                        continue;
-               is_boot_cpu = (addr == boot_cpu_addr);
-               /* Allocate save area */
-               sa = save_area_alloc(is_boot_cpu);
+               sa = save_area_alloc(false);
                if (!sa)
                        panic("could not allocate memory for save area\n");
-               if (MACHINE_HAS_VX)
-                       /* Get the vector registers */
-                       smp_save_cpu_vxrs(sa, addr, is_boot_cpu, page);
-               /*
-                * For a zfcp/nvme dump OLDMEM_BASE == NULL and the registers
-                * of the boot CPU are stored in the HSA. To retrieve
-                * these registers an SCLP request is required which is
-                * done by drivers/s390/char/zcore.c:init_cpu_info()
-                */
-               if (!is_boot_cpu || oldmem_data.start)
-                       /* Get the CPU registers */
-                       smp_save_cpu_regs(sa, addr, is_boot_cpu, page);
+               __pcpu_sigp_relax(addr, SIGP_STORE_STATUS_AT_ADDRESS, __pa(page));
+               save_area_add_regs(sa, page);
+               if (MACHINE_HAS_VX) {
+                       __pcpu_sigp_relax(addr, SIGP_STORE_ADDITIONAL_STATUS, __pa(page));
+                       save_area_add_vxrs(sa, page);
+               }
        }
        memblock_free(page, PAGE_SIZE);
        diag_amode31_ops.diag308_reset();