228 lines
6.8 KiB
Diff
228 lines
6.8 KiB
Diff
|
From 4fcfb2ccd90ffc1e0b121b3e5dbab1cdcba8ce4e Mon Sep 17 00:00:00 2001
|
||
|
From: Jared Rossi <jrossi@linux.ibm.com>
|
||
|
Date: Sat, 19 Oct 2024 21:29:51 -0400
|
||
|
Subject: [PATCH 18/27] pc-bios/s390x: Enable multi-device boot loop
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
RH-Author: Thomas Huth <thuth@redhat.com>
|
||
|
RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9]
|
||
|
RH-Jira: RHEL-11424
|
||
|
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||
|
RH-Commit: [18/23] 2aa3154bfb1c73a6054b1161ae284925e6069c48 (thuth/qemu-kvm-cs9)
|
||
|
|
||
|
Allow attempts to boot from multiple IPL devices. If the first device fails to
|
||
|
IPL, select the pre-built IPLB for the next device in the boot order and attempt
|
||
|
to IPL from it. Continue this process until IPL is successful or there are no
|
||
|
devices left to try.
|
||
|
|
||
|
Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>
|
||
|
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
||
|
Message-ID: <20241020012953.1380075-18-jrossi@linux.ibm.com>
|
||
|
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||
|
(cherry picked from commit f697bed22f58eff9b2893ac2fe3d511847398400)
|
||
|
---
|
||
|
pc-bios/s390-ccw/iplb.h | 24 ++++++++++++++++++++
|
||
|
pc-bios/s390-ccw/jump2ipl.c | 7 +++---
|
||
|
pc-bios/s390-ccw/main.c | 45 +++++++++++++++++++++++--------------
|
||
|
pc-bios/s390-ccw/netmain.c | 2 +-
|
||
|
4 files changed, 57 insertions(+), 21 deletions(-)
|
||
|
|
||
|
diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h
|
||
|
index 16643f5879..08f259ff31 100644
|
||
|
--- a/pc-bios/s390-ccw/iplb.h
|
||
|
+++ b/pc-bios/s390-ccw/iplb.h
|
||
|
@@ -17,9 +17,11 @@
|
||
|
#endif
|
||
|
|
||
|
#include <qipl.h>
|
||
|
+#include <string.h>
|
||
|
|
||
|
extern QemuIplParameters qipl;
|
||
|
extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
|
||
|
+extern bool have_iplb;
|
||
|
|
||
|
#define S390_IPL_TYPE_FCP 0x00
|
||
|
#define S390_IPL_TYPE_CCW 0x02
|
||
|
@@ -49,4 +51,26 @@ static inline bool set_iplb(IplParameterBlock *iplb)
|
||
|
return manage_iplb(iplb, false);
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * The IPL started on the device, but failed in some way. If the IPLB chain
|
||
|
+ * still has more devices left to try, use the next device in order.
|
||
|
+ */
|
||
|
+static inline bool load_next_iplb(void)
|
||
|
+{
|
||
|
+ IplParameterBlock *next_iplb;
|
||
|
+
|
||
|
+ if (qipl.chain_len < 1) {
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ qipl.index++;
|
||
|
+ next_iplb = (IplParameterBlock *) qipl.next_iplb;
|
||
|
+ memcpy(&iplb, next_iplb, sizeof(IplParameterBlock));
|
||
|
+
|
||
|
+ qipl.chain_len--;
|
||
|
+ qipl.next_iplb = qipl.next_iplb + sizeof(IplParameterBlock);
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
#endif /* IPLB_H */
|
||
|
diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c
|
||
|
index 99d18947d1..86321d0f46 100644
|
||
|
--- a/pc-bios/s390-ccw/jump2ipl.c
|
||
|
+++ b/pc-bios/s390-ccw/jump2ipl.c
|
||
|
@@ -45,9 +45,10 @@ int jump_to_IPL_code(uint64_t address)
|
||
|
*/
|
||
|
if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) {
|
||
|
iplb.devno = qipl.index;
|
||
|
- if (!set_iplb(&iplb)) {
|
||
|
- panic("Failed to set IPLB");
|
||
|
- }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (have_iplb && !set_iplb(&iplb)) {
|
||
|
+ panic("Failed to set IPLB");
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
|
||
|
index ab4709e16e..a4d1c05aac 100644
|
||
|
--- a/pc-bios/s390-ccw/main.c
|
||
|
+++ b/pc-bios/s390-ccw/main.c
|
||
|
@@ -23,7 +23,7 @@ static SubChannelId blk_schid = { .one = 1 };
|
||
|
static char loadparm_str[LOADPARM_LEN + 1];
|
||
|
QemuIplParameters qipl;
|
||
|
IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
|
||
|
-static bool have_iplb;
|
||
|
+bool have_iplb;
|
||
|
static uint16_t cutype;
|
||
|
LowCore *lowcore; /* Yes, this *is* a pointer to address 0 */
|
||
|
|
||
|
@@ -55,6 +55,12 @@ void write_iplb_location(void)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+static void copy_qipl(void)
|
||
|
+{
|
||
|
+ QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
|
||
|
+ memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
|
||
|
+}
|
||
|
+
|
||
|
unsigned int get_loadparm_index(void)
|
||
|
{
|
||
|
return atoi(loadparm_str);
|
||
|
@@ -152,6 +158,7 @@ static void menu_setup(void)
|
||
|
|
||
|
/* If loadparm was set to any other value, then do not enable menu */
|
||
|
if (memcmp(loadparm_str, LOADPARM_EMPTY, LOADPARM_LEN) != 0) {
|
||
|
+ menu_set_parms(qipl.qipl_flags & ~BOOT_MENU_FLAG_MASK, 0);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
@@ -183,7 +190,6 @@ static void css_setup(void)
|
||
|
static void boot_setup(void)
|
||
|
{
|
||
|
char lpmsg[] = "LOADPARM=[________]\n";
|
||
|
- have_iplb = store_iplb(&iplb);
|
||
|
|
||
|
if (memcmp(iplb.loadparm, NO_LOADPARM, LOADPARM_LEN) != 0) {
|
||
|
ebcdic_to_ascii((char *) iplb.loadparm, loadparm_str, LOADPARM_LEN);
|
||
|
@@ -191,6 +197,10 @@ static void boot_setup(void)
|
||
|
sclp_get_loadparm_ascii(loadparm_str);
|
||
|
}
|
||
|
|
||
|
+ if (have_iplb) {
|
||
|
+ menu_setup();
|
||
|
+ }
|
||
|
+
|
||
|
memcpy(lpmsg + 10, loadparm_str, 8);
|
||
|
puts(lpmsg);
|
||
|
|
||
|
@@ -208,6 +218,7 @@ static bool find_boot_device(void)
|
||
|
|
||
|
switch (iplb.pbt) {
|
||
|
case S390_IPL_TYPE_CCW:
|
||
|
+ vdev->scsi_device_selected = false;
|
||
|
debug_print_int("device no. ", iplb.ccw.devno);
|
||
|
blk_schid.ssid = iplb.ccw.ssid & 0x3;
|
||
|
debug_print_int("ssid ", blk_schid.ssid);
|
||
|
@@ -231,15 +242,8 @@ static bool find_boot_device(void)
|
||
|
static int virtio_setup(void)
|
||
|
{
|
||
|
VDev *vdev = virtio_get_device();
|
||
|
- QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
|
||
|
int ret;
|
||
|
|
||
|
- memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
|
||
|
-
|
||
|
- if (have_iplb) {
|
||
|
- menu_setup();
|
||
|
- }
|
||
|
-
|
||
|
switch (vdev->senseid.cu_model) {
|
||
|
case VIRTIO_ID_NET:
|
||
|
puts("Network boot device detected");
|
||
|
@@ -271,10 +275,9 @@ static void ipl_boot_device(void)
|
||
|
dasd_ipl(blk_schid, cutype);
|
||
|
break;
|
||
|
case CU_TYPE_VIRTIO:
|
||
|
- if (virtio_setup()) {
|
||
|
- return; /* Only returns in case of errors */
|
||
|
+ if (virtio_setup() == 0) {
|
||
|
+ zipl_load();
|
||
|
}
|
||
|
- zipl_load();
|
||
|
break;
|
||
|
default:
|
||
|
printf("Attempting to boot from unexpected device type 0x%X\n", cutype);
|
||
|
@@ -307,14 +310,22 @@ static void probe_boot_device(void)
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
+ copy_qipl();
|
||
|
sclp_setup();
|
||
|
css_setup();
|
||
|
- boot_setup();
|
||
|
- if (have_iplb && find_boot_device()) {
|
||
|
- ipl_boot_device();
|
||
|
- } else {
|
||
|
+ have_iplb = store_iplb(&iplb);
|
||
|
+ if (!have_iplb) {
|
||
|
probe_boot_device();
|
||
|
}
|
||
|
|
||
|
- panic("Failed to IPL. Halting...");
|
||
|
+ while (have_iplb) {
|
||
|
+ boot_setup();
|
||
|
+ if (have_iplb && find_boot_device()) {
|
||
|
+ ipl_boot_device();
|
||
|
+ }
|
||
|
+ have_iplb = load_next_iplb();
|
||
|
+ }
|
||
|
+
|
||
|
+ panic("No suitable device for IPL. Halting...");
|
||
|
+
|
||
|
}
|
||
|
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
|
||
|
index d1a6c9a91c..e46e470db4 100644
|
||
|
--- a/pc-bios/s390-ccw/netmain.c
|
||
|
+++ b/pc-bios/s390-ccw/netmain.c
|
||
|
@@ -478,7 +478,7 @@ static bool virtio_setup(void)
|
||
|
*/
|
||
|
enable_mss_facility();
|
||
|
|
||
|
- if (store_iplb(&iplb)) {
|
||
|
+ if (have_iplb || store_iplb(&iplb)) {
|
||
|
IPL_assert(iplb.pbt == S390_IPL_TYPE_CCW, "IPL_TYPE_CCW expected");
|
||
|
dev_no = iplb.ccw.devno;
|
||
|
debug_print_int("device no. ", dev_no);
|
||
|
--
|
||
|
2.39.3
|
||
|
|