s390/crash_dump: fix virtual vs physical address handling
authorHeiko Carstens <hca@linux.ibm.com>
Thu, 16 Dec 2021 12:27:10 +0000 (13:27 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Mon, 20 Dec 2021 09:21:55 +0000 (10:21 +0100)
Signal processor STORE STATUS requires a physical address where register
contents are supposed to be written to, however the kernel must read the
data via the corresponding virtual address.

Also the allocated save_area, where register contents are copied to,
resides in virtual address space.

Fix this by using proper __pa() conversion, or correct memblock_alloc()
invocation.

Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/kernel/crash_dump.c
arch/s390/kernel/smp.c

index 785d54c..af82021 100644 (file)
@@ -60,7 +60,7 @@ struct save_area * __init save_area_alloc(bool is_boot_cpu)
 {
        struct save_area *sa;
 
-       sa = (void *) memblock_phys_alloc(sizeof(*sa), 8);
+       sa = memblock_alloc(sizeof(*sa), 8);
        if (!sa)
                panic("Failed to allocate save area\n");
 
index 1172aaf..2bad902 100644 (file)
@@ -658,26 +658,22 @@ int smp_store_status(int cpu)
  *    deactivates the elfcorehdr= kernel parameter
  */
 static __init void smp_save_cpu_vxrs(struct save_area *sa, u16 addr,
-                                    bool is_boot_cpu, unsigned long page)
+                                    bool is_boot_cpu, __vector128 *vxrs)
 {
-       __vector128 *vxrs = (__vector128 *) page;
-
        if (is_boot_cpu)
                vxrs = boot_cpu_vector_save_area;
        else
-               __pcpu_sigp_relax(addr, SIGP_STORE_ADDITIONAL_STATUS, page);
+               __pcpu_sigp_relax(addr, SIGP_STORE_ADDITIONAL_STATUS, __pa(vxrs));
        save_area_add_vxrs(sa, vxrs);
 }
 
 static __init void smp_save_cpu_regs(struct save_area *sa, u16 addr,
-                                    bool is_boot_cpu, unsigned long page)
+                                    bool is_boot_cpu, void *regs)
 {
-       void *regs = (void *) page;
-
        if (is_boot_cpu)
                copy_oldmem_kernel(regs, (void *) __LC_FPREGS_SAVE_AREA, 512);
        else
-               __pcpu_sigp_relax(addr, SIGP_STORE_STATUS_AT_ADDRESS, page);
+               __pcpu_sigp_relax(addr, SIGP_STORE_STATUS_AT_ADDRESS, __pa(regs));
        save_area_add_regs(sa, regs);
 }
 
@@ -685,14 +681,14 @@ void __init smp_save_dump_cpus(void)
 {
        int addr, boot_cpu_addr, max_cpu_addr;
        struct save_area *sa;
-       unsigned long page;
        bool is_boot_cpu;
+       void *page;
 
        if (!(oldmem_data.start || is_ipl_type_dump()))
                /* No previous system present, normal boot. */
                return;
        /* Allocate a page as dumping area for the store status sigps */
-       page = memblock_phys_alloc_range(PAGE_SIZE, PAGE_SIZE, 0, 1UL << 31);
+       page = memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
        if (!page)
                panic("ERROR: Failed to allocate %lx bytes below %lx\n",
                      PAGE_SIZE, 1UL << 31);
@@ -723,7 +719,7 @@ void __init smp_save_dump_cpus(void)
                        /* Get the CPU registers */
                        smp_save_cpu_regs(sa, addr, is_boot_cpu, page);
        }
-       memblock_phys_free(page, PAGE_SIZE);
+       memblock_free(page, PAGE_SIZE);
        diag_amode31_ops.diag308_reset();
        pcpu_set_smt(0);
 }