pc-bios/s390-ccw: Remove panics from DASD IPL path

Remove panic-on-error from DASD IPL specific functions so that error recovery
may be possible in the future.

Functions that would previously panic now provide a return code.

Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20241020012953.1380075-11-jrossi@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Jared Rossi 2024-10-19 21:29:44 -04:00 committed by Thomas Huth
parent facd91ac1a
commit 1d5c7f078e
2 changed files with 37 additions and 31 deletions

View File

@ -111,38 +111,29 @@ static void make_readipl(void)
ccwIplRead->count = 0x18; /* Read 0x18 bytes of data */
}
static void run_readipl(SubChannelId schid, uint16_t cutype)
static int run_readipl(SubChannelId schid, uint16_t cutype)
{
if (do_cio(schid, cutype, 0x00, CCW_FMT0)) {
panic("dasd-ipl: Failed to run Read IPL channel program\n");
}
return do_cio(schid, cutype, 0x00, CCW_FMT0);
}
/*
* The architecture states that IPL1 data should consist of a psw followed by
* format-0 READ and TIC CCWs. Let's sanity check.
*/
static void check_ipl1(void)
static bool check_ipl1(void)
{
Ccw0 *ccwread = (Ccw0 *)0x08;
Ccw0 *ccwtic = (Ccw0 *)0x10;
if (ccwread->cmd_code != CCW_CMD_DASD_READ ||
ccwtic->cmd_code != CCW_CMD_TIC) {
panic("dasd-ipl: IPL1 data invalid. Is this disk really bootable?\n");
}
return (ccwread->cmd_code == CCW_CMD_DASD_READ &&
ccwtic->cmd_code == CCW_CMD_TIC);
}
static void check_ipl2(uint32_t ipl2_addr)
static bool check_ipl2(uint32_t ipl2_addr)
{
Ccw0 *ccw = u32toptr(ipl2_addr);
if (ipl2_addr == 0x00) {
panic("IPL2 address invalid. Is this disk really bootable?\n");
}
if (ccw->cmd_code == 0x00) {
panic("IPL2 ccw data invalid. Is this disk really bootable?\n");
}
return (ipl2_addr != 0x00 && ccw->cmd_code != 0x00);
}
static uint32_t read_ipl2_addr(void)
@ -188,52 +179,67 @@ static void ipl1_fixup(void)
ccwSearchTic->cda = ptr2u32(ccwSearchID);
}
static void run_ipl1(SubChannelId schid, uint16_t cutype)
static int run_ipl1(SubChannelId schid, uint16_t cutype)
{
uint32_t startAddr = 0x08;
if (do_cio(schid, cutype, startAddr, CCW_FMT0)) {
panic("dasd-ipl: Failed to run IPL1 channel program\n");
}
return do_cio(schid, cutype, startAddr, CCW_FMT0);
}
static void run_ipl2(SubChannelId schid, uint16_t cutype, uint32_t addr)
static int run_ipl2(SubChannelId schid, uint16_t cutype, uint32_t addr)
{
if (run_dynamic_ccw_program(schid, cutype, addr)) {
panic("dasd-ipl: Failed to run IPL2 channel program\n");
}
return run_dynamic_ccw_program(schid, cutype, addr);
}
/*
* Limitations in vfio-ccw support complicate the IPL process. Details can
* be found in docs/devel/s390-dasd-ipl.rst
*/
void dasd_ipl(SubChannelId schid, uint16_t cutype)
int dasd_ipl(SubChannelId schid, uint16_t cutype)
{
PSWLegacy *pswl = (PSWLegacy *) 0x00;
uint32_t ipl2_addr;
/* Construct Read IPL CCW and run it to read IPL1 from boot disk */
make_readipl();
run_readipl(schid, cutype);
if (run_readipl(schid, cutype)) {
puts("Failed to run Read IPL channel program");
return -EIO;
}
ipl2_addr = read_ipl2_addr();
check_ipl1();
if (!check_ipl1()) {
puts("IPL1 invalid for DASD-IPL");
return -EINVAL;
}
/*
* Fixup IPL1 channel program to account for vfio-ccw limitations, then run
* it to read IPL2 channel program from boot disk.
*/
ipl1_fixup();
run_ipl1(schid, cutype);
check_ipl2(ipl2_addr);
if (run_ipl1(schid, cutype)) {
puts("Failed to run IPL1 channel program");
return -EIO;
}
if (!check_ipl2(ipl2_addr)) {
puts("IPL2 invalid for DASD-IPL");
return -EINVAL;
}
/*
* Run IPL2 channel program to read operating system code from boot disk
*/
run_ipl2(schid, cutype, ipl2_addr);
if (run_ipl2(schid, cutype, ipl2_addr)) {
puts("Failed to run IPL2 channel program");
return -EIO;
}
/* Transfer control to the guest operating system */
pswl->mask |= PSW_MASK_EAMODE; /* Force z-mode */
pswl->addr |= PSW_MASK_BAMODE; /* ... */
jump_to_low_kernel();
return -1;
}

View File

@ -11,6 +11,6 @@
#ifndef DASD_IPL_H
#define DASD_IPL_H
void dasd_ipl(SubChannelId schid, uint16_t cutype);
int dasd_ipl(SubChannelId schid, uint16_t cutype);
#endif /* DASD_IPL_H */