Commit a0e45d40 authored by Heiko Carstens's avatar Heiko Carstens

s390/crash_dump: fix virtual vs physical address handling

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: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 39d02827
...@@ -60,7 +60,7 @@ struct save_area * __init save_area_alloc(bool is_boot_cpu) ...@@ -60,7 +60,7 @@ struct save_area * __init save_area_alloc(bool is_boot_cpu)
{ {
struct save_area *sa; struct save_area *sa;
sa = (void *) memblock_phys_alloc(sizeof(*sa), 8); sa = memblock_alloc(sizeof(*sa), 8);
if (!sa) if (!sa)
panic("Failed to allocate save area\n"); panic("Failed to allocate save area\n");
......
...@@ -658,26 +658,22 @@ int smp_store_status(int cpu) ...@@ -658,26 +658,22 @@ int smp_store_status(int cpu)
* deactivates the elfcorehdr= kernel parameter * deactivates the elfcorehdr= kernel parameter
*/ */
static __init void smp_save_cpu_vxrs(struct save_area *sa, u16 addr, 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) if (is_boot_cpu)
vxrs = boot_cpu_vector_save_area; vxrs = boot_cpu_vector_save_area;
else 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); save_area_add_vxrs(sa, vxrs);
} }
static __init void smp_save_cpu_regs(struct save_area *sa, u16 addr, 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) if (is_boot_cpu)
copy_oldmem_kernel(regs, (void *) __LC_FPREGS_SAVE_AREA, 512); copy_oldmem_kernel(regs, (void *) __LC_FPREGS_SAVE_AREA, 512);
else 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); save_area_add_regs(sa, regs);
} }
...@@ -685,14 +681,14 @@ void __init smp_save_dump_cpus(void) ...@@ -685,14 +681,14 @@ void __init smp_save_dump_cpus(void)
{ {
int addr, boot_cpu_addr, max_cpu_addr; int addr, boot_cpu_addr, max_cpu_addr;
struct save_area *sa; struct save_area *sa;
unsigned long page;
bool is_boot_cpu; bool is_boot_cpu;
void *page;
if (!(oldmem_data.start || is_ipl_type_dump())) if (!(oldmem_data.start || is_ipl_type_dump()))
/* No previous system present, normal boot. */ /* No previous system present, normal boot. */
return; return;
/* Allocate a page as dumping area for the store status sigps */ /* 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) if (!page)
panic("ERROR: Failed to allocate %lx bytes below %lx\n", panic("ERROR: Failed to allocate %lx bytes below %lx\n",
PAGE_SIZE, 1UL << 31); PAGE_SIZE, 1UL << 31);
...@@ -723,7 +719,7 @@ void __init smp_save_dump_cpus(void) ...@@ -723,7 +719,7 @@ void __init smp_save_dump_cpus(void)
/* Get the CPU registers */ /* Get the CPU registers */
smp_save_cpu_regs(sa, addr, is_boot_cpu, page); 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(); diag_amode31_ops.diag308_reset();
pcpu_set_smt(0); pcpu_set_smt(0);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment