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

View File

@ -11,6 +11,6 @@
#ifndef DASD_IPL_H #ifndef DASD_IPL_H
#define 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 */ #endif /* DASD_IPL_H */