mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Make 'struct os_info *os_info' a const to ensure/indicate that no changes are made to the given structure. Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com> Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
115 lines
3.1 KiB
C
115 lines
3.1 KiB
C
/*
|
|
* zipl - zSeries Initial Program Loader tool
|
|
*
|
|
* Stand-alone kdump support (stage 3)
|
|
*
|
|
* Copyright IBM Corp. 2013, 2023
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#include "error.h"
|
|
#include "kdump.h"
|
|
#include "libc.h"
|
|
#include "sclp_stage3.h"
|
|
#include "stage3.h"
|
|
#include "boot/os_info.h"
|
|
|
|
/*
|
|
* Copy memory from HSA and exit in case of an error
|
|
*/
|
|
static void copy_from_hsa(unsigned long dst, unsigned long src, int cnt)
|
|
{
|
|
if (cnt == 0)
|
|
return;
|
|
if (sclp_hsa_copy((void *) dst, 2 + src / PAGE_SIZE, cnt / PAGE_SIZE)) {
|
|
sclp_hsa_copy_exit();
|
|
kdump_failed(EHSA_COPY_FAILED);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Save lower memory to crash kernel memory and get crash base and size
|
|
*/
|
|
static void kdump_stage3_scsi(unsigned long *base, unsigned long *size)
|
|
{
|
|
unsigned long os_info_addr, crash_base, crash_size, crash_end, hsa_page;
|
|
const struct os_info *os_info;
|
|
unsigned long hsa_size;
|
|
|
|
hsa_page = get_zeroed_page();
|
|
sclp_hsa_copy_init((void *) hsa_page);
|
|
if (sclp_hsa_get_size(&hsa_size)) {
|
|
sclp_hsa_copy_exit();
|
|
kdump_failed(EHSA_COPY_FAILED);
|
|
}
|
|
/* Get OS info pointer from HSA lowcore */
|
|
copy_from_hsa(hsa_page, 0, PAGE_SIZE);
|
|
os_info_addr = *((unsigned long *) (hsa_page + __LC_OS_INFO));
|
|
/* If OS info is inside HSA, get it from there */
|
|
if (os_info_addr < hsa_size) {
|
|
copy_from_hsa(hsa_page, os_info_addr, PAGE_SIZE);
|
|
os_info = (void *) hsa_page;
|
|
} else {
|
|
os_info = (void *) os_info_addr;
|
|
}
|
|
kdump_os_info_check(os_info);
|
|
crash_base = os_info->crashkernel_addr;
|
|
crash_size = os_info->crashkernel_size;
|
|
crash_end = crash_base + crash_size;
|
|
/*
|
|
* Copy [0, crash_size] to [crash_base, crash_base + crash_size] and
|
|
* restore 1:1 memory from HSA
|
|
*/
|
|
|
|
/* copy [0, MIN(crash_size, hsa_size)] to [crash base, ...] from HSA */
|
|
copy_from_hsa(crash_base, 0, MIN(crash_size, hsa_size));
|
|
if (crash_size > hsa_size) {
|
|
/* Copy rest of crashkernel from real memory */
|
|
memcpy((void *) crash_base + hsa_size, (void *) hsa_size,
|
|
crash_size - hsa_size);
|
|
} else {
|
|
/* Restore real memory above crash_size 1:1 from HSA */
|
|
copy_from_hsa(crash_size, crash_size,
|
|
MIN(hsa_size, crash_base) - crash_size);
|
|
}
|
|
if (crash_end < hsa_size) {
|
|
/* Restore memory above crash end 1:1 from HSA */
|
|
copy_from_hsa(crash_end, crash_end, hsa_size - crash_end);
|
|
}
|
|
sclp_hsa_copy_exit();
|
|
*base = __pa(crash_base);
|
|
*size = crash_size;
|
|
}
|
|
|
|
/*
|
|
* Get crash base and size from (stage 2 relocated) OS info lowcore pointer
|
|
*/
|
|
static void kdump_stage3_dasd(unsigned long *base, unsigned long *size)
|
|
{
|
|
struct os_info *lc_os_info = (struct os_info *)S390_lowcore.os_info;
|
|
|
|
*base = lc_os_info->crashkernel_addr;
|
|
*size = lc_os_info->crashkernel_size;
|
|
}
|
|
|
|
/*
|
|
* Stage 3 kdump code
|
|
*/
|
|
void kdump_stage3(void)
|
|
{
|
|
unsigned long crash_base, crash_size;
|
|
|
|
if (!(_stage3_parms.flags & STAGE3_FLAG_KDUMP))
|
|
return;
|
|
if (!(_stage3_parms.flags & STAGE3_FLAG_SCSI))
|
|
kdump_stage3_dasd(&crash_base, &crash_size);
|
|
else
|
|
kdump_stage3_scsi(&crash_base, &crash_size);
|
|
|
|
/* Register oldmem in kernel parameter area */
|
|
*((unsigned long *) OLDMEM_BASE) = crash_base;
|
|
*((unsigned long *) OLDMEM_SIZE) = crash_size;
|
|
}
|