zipl/boot: Conditionally clear memory upon reipl at ccw dump end

- Instead of always clearing the memory on reipl after the ccw dump has
  been taken, check for the special OS_INFO_FLAG_REIPL_CLEAR flag in
  os_info flags entry (indicates if sysfs 'clear' attribute has been set
  on the panicked system) and trigger diag308 with a proper subcode.
- Get rid of superfluous ipib_info structure in stage2dump.c.
- Collect ipl_pbt constants in boot/ipl.h header.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Mikhail Zaslonko
2023-04-21 16:54:39 +02:00
committed by Jan Höppner
parent 2b7df1fcac
commit d205b47c08
3 changed files with 45 additions and 21 deletions

View File

@@ -59,7 +59,7 @@ static gint pv_ipib_init(IplParameterBlock *ipib, GSList *comps,
ipib_size = MAX(ipl_pl_hdr_size + blk0_len, (uint32_t)PAGE_SIZE);
g_assert(pv_ipib_get_size(comps_length) == ipib_size);
pv->pbt = IPL_TYPE_PV;
pv->pbt = IPL_PBT_PV;
pv->len = GUINT32_TO_BE(blk0_len);
pv->num_comp = GUINT32_TO_BE(comps_length);
/* both values will be overwritten during the IPL process by

View File

@@ -21,10 +21,6 @@
#define IPL_MAX_SUPPORTED_VERSION 0
#define IPL_PARM_BLOCK_VERSION 0x1
/* IPL Types */
#define IPL_TYPE_PV 0x5
#ifndef __ASSEMBLER__
#include <stdint.h>
@@ -43,6 +39,16 @@ struct ipl_pb_hdr {
uint8_t pbt;
} __packed;
/* IPL Parameter Block types */
enum ipl_pbt {
IPL_PBT_FCP = 0,
IPL_PBT_SCP_DATA = 1,
IPL_PBT_CCW = 2,
IPL_PBT_ECKD = 3,
IPL_PBT_NVME = 4,
IPL_PBT_PV = 5,
};
/* IPL Parameter Block 0 with common fields */
struct ipl_pb0_common {
uint32_t len;

View File

@@ -17,6 +17,8 @@
#include "libc.h"
#include "sclp.h"
#include "stage2dump.h"
#include "boot/ipl.h"
#include "boot/os_info.h"
#define CPU_ADDRESS_MAX 1000
#define MACHINE_HAS_VX machine_has_vx
@@ -26,14 +28,6 @@
*/
static uint8_t machine_has_vx;
/*
* IPL info in lowcore
*/
struct ipib_info {
unsigned long ipib;
uint32_t ipib_csum;
};
/*
* Tail parameters
*/
@@ -395,17 +389,41 @@ static void store_status(void)
*/
static __noreturn void dump_exit(unsigned long code)
{
struct ipib_info *ipib_info = (struct ipib_info *)&S390_lowcore.ipib;
uint32_t ipib_len, csum;
struct ipl_parameter_block *ipib = (struct ipl_parameter_block *)S390_lowcore.ipib;
const struct os_info *os_info = (struct os_info *)S390_lowcore.os_info;
const struct os_info_entry *os_info_entry = NULL;
unsigned long os_info_flags = 0;
uint32_t csum;
if (!ipib_info->ipib)
if (!ipib)
libc_stop(code);
ipib_len = *((uint32_t *) ipib_info->ipib);
csum = csum_partial((void *) ipib_info->ipib, ipib_len, 0);
if (ipib_info->ipib_csum != csum)
csum = csum_partial(ipib, ipib->hdr.len, 0);
/* Verify ipib checksum against the value stored in lowcore */
if (csum != S390_lowcore.ipib_checksum)
libc_stop(code);
diag308(DIAG308_SET, (void *) ipib_info->ipib);
diag308(DIAG308_LOAD_CLEAR, NULL);
diag308(DIAG308_SET, ipib);
/*
* Check os_info flags entry for REIPL_CLEAR flag and make
* diag308 call with a proper subcode.
* Verify the bit flags field size before accessing it.
*/
if (os_info_check(os_info) == 0) {
os_info_entry = &os_info->entry[OS_INFO_FLAGS_ENTRY];
if (os_info_entry_is_valid(os_info_entry) &&
os_info_entry->size >= OS_INFO_FLAGS_ENTRY_SIZE)
os_info_flags = *((unsigned long *)os_info_entry->addr);
else
printf("Warning: os_info flags entry is missing or corrupted");
} else {
printf("Warning: os_info is missing or corrupted");
}
if (os_info_flags & OS_INFO_FLAG_REIPL_CLEAR)
diag308(DIAG308_LOAD_CLEAR, NULL);
/* Use special diag308 subcode for CCW normal ipl */
if (ipib->pb0_hdr.pbt == IPL_PBT_CCW)
diag308(DIAG308_LOAD_NORMAL_DUMP, NULL);
else
diag308(DIAG308_LOAD_NORMAL, NULL);
__builtin_unreachable();
}