Files
s390-tools/zipl/boot/kdump3.c
Mikhail Zaslonko eb06ebe245 include/boot: Move zipl/boot/error.h to include/boot
- Move zipl/boot/error.h to include/boot
- Adjust include statements in zipb/boot and genprotimg/boot
- Remove error.h from tunedasd/src/tunedasd.c as not needed
- Fix tunedasd/src/Makefile

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>
2023-07-20 21:45:27 +02:00

115 lines
3.2 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 "kdump.h"
#include "libc.h"
#include "sclp_stage3.h"
#include "stage3.h"
#include "boot/error.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;
}