diff --git a/kvm-docs-system-Update-documentation-for-s390x-IPL.patch b/kvm-docs-system-Update-documentation-for-s390x-IPL.patch new file mode 100644 index 0000000..2b707e6 --- /dev/null +++ b/kvm-docs-system-Update-documentation-for-s390x-IPL.patch @@ -0,0 +1,76 @@ +From 38df1fff536527bf47e190d000d8c05679f0f220 Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:52 -0400 +Subject: [PATCH 19/27] docs/system: Update documentation for s390x IPL +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [19/23] feefab248336e1744eeb6bdf86e9033fe8184b3a (thuth/qemu-kvm-cs9) + +Update docs to show that s390x PC BIOS can support more than one boot device. + +Signed-off-by: Jared Rossi +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-19-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 0bd107138ff0b171e3cd314dbc200950bcab2b05) +--- + docs/system/bootindex.rst | 7 ++++--- + docs/system/s390x/bootdevices.rst | 9 ++++++--- + 2 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/docs/system/bootindex.rst b/docs/system/bootindex.rst +index 8b057f812f..988f7b3beb 100644 +--- a/docs/system/bootindex.rst ++++ b/docs/system/bootindex.rst +@@ -49,10 +49,11 @@ Limitations + ----------- + + Some firmware has limitations on which devices can be considered for +-booting. For instance, the PC BIOS boot specification allows only one +-disk to be bootable. If boot from disk fails for some reason, the BIOS ++booting. For instance, the x86 PC BIOS boot specification allows only one ++disk to be bootable. If boot from disk fails for some reason, the x86 BIOS + won't retry booting from other disk. It can still try to boot from +-floppy or net, though. ++floppy or net, though. In the case of s390x BIOS, the BIOS will try up to ++8 total devices, any number of which may be disks. + + Sometimes, firmware cannot map the device path QEMU wants firmware to + boot from to a boot method. It doesn't happen for devices the firmware +diff --git a/docs/system/s390x/bootdevices.rst b/docs/system/s390x/bootdevices.rst +index c97efb8fc0..1a1a764c1c 100644 +--- a/docs/system/s390x/bootdevices.rst ++++ b/docs/system/s390x/bootdevices.rst +@@ -6,9 +6,7 @@ Booting with bootindex parameter + + For classical mainframe guests (i.e. LPAR or z/VM installations), you always + have to explicitly specify the disk where you want to boot from (or "IPL" from, +-in s390x-speak -- IPL means "Initial Program Load"). In particular, there can +-also be only one boot device according to the architecture specification, thus +-specifying multiple boot devices is not possible (yet). ++in s390x-speak -- IPL means "Initial Program Load"). + + So for booting an s390x guest in QEMU, you should always mark the + device where you want to boot from with the ``bootindex`` property, for +@@ -17,6 +15,11 @@ example:: + qemu-system-s390x -drive if=none,id=dr1,file=guest.qcow2 \ + -device virtio-blk,drive=dr1,bootindex=1 + ++Multiple devices may have a bootindex. The lowest bootindex is assigned to the ++device to IPL first. If the IPL fails for the first, the device with the second ++lowest bootindex will be tried and so on until IPL is successful or there are no ++remaining boot devices to try. ++ + For booting from a CD-ROM ISO image (which needs to include El-Torito boot + information in order to be bootable), it is recommended to specify a ``scsi-cd`` + device, for example like this:: +-- +2.39.3 + diff --git a/kvm-docs-system-s390x-bootdevices-Update-the-documentati.patch b/kvm-docs-system-s390x-bootdevices-Update-the-documentati.patch new file mode 100644 index 0000000..fdc7d4b --- /dev/null +++ b/kvm-docs-system-s390x-bootdevices-Update-the-documentati.patch @@ -0,0 +1,66 @@ +From 63c705bdd8d8f17860988d22aa29a238e9fae631 Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:40 -0400 +Subject: [PATCH 07/27] docs/system/s390x/bootdevices: Update the documentation + about network booting +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [7/23] 31b1f484e98304c385adbefb6eb50b501d179268 (thuth/qemu-kvm-cs9) + +Remove the information about the separate s390-netboot.img from +the documentation. + +Co-authored by: Thomas Huth +Signed-off-by: Jared Rossi +Message-ID: <20241020012953.1380075-7-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit ab2691b6c7ff360875e0af86ff463278f17786f5) +--- + docs/system/s390x/bootdevices.rst | 20 +++++++------------- + 1 file changed, 7 insertions(+), 13 deletions(-) + +diff --git a/docs/system/s390x/bootdevices.rst b/docs/system/s390x/bootdevices.rst +index 1a7a18b43b..c97efb8fc0 100644 +--- a/docs/system/s390x/bootdevices.rst ++++ b/docs/system/s390x/bootdevices.rst +@@ -82,23 +82,17 @@ Note that ``0`` can be used to boot the default entry. + Booting from a network device + ----------------------------- + +-Beside the normal guest firmware (which is loaded from the file ``s390-ccw.img`` +-in the data directory of QEMU, or via the ``-bios`` option), QEMU ships with +-a small TFTP network bootloader firmware for virtio-net-ccw devices, too. This +-firmware is loaded from a file called ``s390-netboot.img`` in the QEMU data +-directory. In case you want to load it from a different filename instead, +-you can specify it via the ``-global s390-ipl.netboot_fw=filename`` +-command line option. +- +-The ``bootindex`` property is especially important for booting via the network. +-If you don't specify the ``bootindex`` property here, the network bootloader +-firmware code won't get loaded into the guest memory so that the network boot +-will fail. For a successful network boot, try something like this:: ++The firmware that ships with QEMU includes a small TFTP network bootloader ++for virtio-net-ccw devices. The ``bootindex`` property is especially ++important for booting via the network. If you don't specify the ``bootindex`` ++property here, the network bootloader won't be taken into consideration and ++the network boot will fail. For a successful network boot, try something ++like this:: + + qemu-system-s390x -netdev user,id=n1,tftp=...,bootfile=... \ + -device virtio-net-ccw,netdev=n1,bootindex=1 + +-The network bootloader firmware also has basic support for pxelinux.cfg-style ++The network bootloader also has basic support for pxelinux.cfg-style + configuration files. See the `PXELINUX Configuration page + `__ + for details how to set up the configuration file on your TFTP server. +-- +2.39.3 + diff --git a/kvm-hw-s390x-Build-an-IPLB-for-each-boot-device.patch b/kvm-hw-s390x-Build-an-IPLB-for-each-boot-device.patch new file mode 100644 index 0000000..2b89353 --- /dev/null +++ b/kvm-hw-s390x-Build-an-IPLB-for-each-boot-device.patch @@ -0,0 +1,270 @@ +From ca648a6167953204a9ec55131e9aa836f63ab7e8 Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:49 -0400 +Subject: [PATCH 16/27] hw/s390x: Build an IPLB for each boot device +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [16/23] 4b87f66a28d9a34b0182e0a2c92af406d2e492a6 (thuth/qemu-kvm-cs9) + +Build an IPLB for any device with a bootindex (up to a maximum of 8 devices). + +The IPLB chain is placed immediately before the BIOS in memory. Because this +is not a fixed address, the location of the next IPLB and number of remaining +boot devices is stored in the QIPL global variable for possible later access by +the guest during IPL. + +Signed-off-by: Jared Rossi +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-16-jrossi@linux.ibm.com> +[thuth: Fix endianness problem when accessing the qipl structure] +Signed-off-by: Thomas Huth +(cherry picked from commit 0927875e704e93ace03bb7533c0877bf97e4bda9) +--- + hw/s390x/ipl.c | 129 ++++++++++++++++++++++++++++-------- + hw/s390x/ipl.h | 1 + + include/hw/s390x/ipl/qipl.h | 4 +- + 3 files changed, 105 insertions(+), 29 deletions(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index d83832d975..f4576f8822 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -56,6 +56,13 @@ static bool iplb_extended_needed(void *opaque) + return ipl->iplbext_migration; + } + ++/* Place the IPLB chain immediately before the BIOS in memory */ ++static uint64_t find_iplb_chain_addr(uint64_t bios_addr, uint16_t count) ++{ ++ return (bios_addr & TARGET_PAGE_MASK) ++ - (count * sizeof(IplParameterBlock)); ++} ++ + static const VMStateDescription vmstate_iplb_extended = { + .name = "ipl/iplb_extended", + .version_id = 0, +@@ -398,6 +405,17 @@ static CcwDevice *s390_get_ccw_device(DeviceState *dev_st, int *devtype) + return ccw_dev; + } + ++static uint64_t s390_ipl_map_iplb_chain(IplParameterBlock *iplb_chain) ++{ ++ S390IPLState *ipl = get_ipl_device(); ++ uint16_t count = be16_to_cpu(ipl->qipl.chain_len); ++ uint64_t len = sizeof(IplParameterBlock) * count; ++ uint64_t chain_addr = find_iplb_chain_addr(ipl->bios_start_addr, count); ++ ++ cpu_physical_memory_write(chain_addr, iplb_chain, len); ++ return chain_addr; ++} ++ + void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp) + { + int i; +@@ -428,54 +446,51 @@ void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp) + } + } + +-static bool s390_gen_initial_iplb(S390IPLState *ipl) ++static bool s390_build_iplb(DeviceState *dev_st, IplParameterBlock *iplb) + { +- DeviceState *dev_st; ++ S390IPLState *ipl = get_ipl_device(); + CcwDevice *ccw_dev = NULL; + SCSIDevice *sd; + int devtype; + uint8_t *lp; + +- dev_st = get_boot_device(0); +- if (dev_st) { +- ccw_dev = s390_get_ccw_device(dev_st, &devtype); +- } +- + /* + * Currently allow IPL only from CCW devices. + */ ++ ccw_dev = s390_get_ccw_device(dev_st, &devtype); + if (ccw_dev) { + lp = ccw_dev->loadparm; + + switch (devtype) { + case CCW_DEVTYPE_SCSI: + sd = SCSI_DEVICE(dev_st); +- ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN); +- ipl->iplb.blk0_len = ++ iplb->len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN); ++ iplb->blk0_len = + cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN); +- ipl->iplb.pbt = S390_IPL_TYPE_QEMU_SCSI; +- ipl->iplb.scsi.lun = cpu_to_be32(sd->lun); +- ipl->iplb.scsi.target = cpu_to_be16(sd->id); +- ipl->iplb.scsi.channel = cpu_to_be16(sd->channel); +- ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno); +- ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3; ++ iplb->pbt = S390_IPL_TYPE_QEMU_SCSI; ++ iplb->scsi.lun = cpu_to_be32(sd->lun); ++ iplb->scsi.target = cpu_to_be16(sd->id); ++ iplb->scsi.channel = cpu_to_be16(sd->channel); ++ iplb->scsi.devno = cpu_to_be16(ccw_dev->sch->devno); ++ iplb->scsi.ssid = ccw_dev->sch->ssid & 3; + break; + case CCW_DEVTYPE_VFIO: +- ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); +- ipl->iplb.pbt = S390_IPL_TYPE_CCW; +- ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); +- ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; ++ iplb->len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); ++ iplb->pbt = S390_IPL_TYPE_CCW; ++ iplb->ccw.devno = cpu_to_be16(ccw_dev->sch->devno); ++ iplb->ccw.ssid = ccw_dev->sch->ssid & 3; + break; + case CCW_DEVTYPE_VIRTIO_NET: ++ /* The S390IPLState netboot is true if ANY IPLB may use netboot */ + ipl->netboot = true; + /* Fall through to CCW_DEVTYPE_VIRTIO case */ + case CCW_DEVTYPE_VIRTIO: +- ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); +- ipl->iplb.blk0_len = ++ iplb->len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); ++ iplb->blk0_len = + cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); +- ipl->iplb.pbt = S390_IPL_TYPE_CCW; +- ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); +- ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; ++ iplb->pbt = S390_IPL_TYPE_CCW; ++ iplb->ccw.devno = cpu_to_be16(ccw_dev->sch->devno); ++ iplb->ccw.ssid = ccw_dev->sch->ssid & 3; + break; + } + +@@ -484,8 +499,8 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl) + lp = S390_CCW_MACHINE(qdev_get_machine())->loadparm; + } + +- s390_ipl_convert_loadparm((char *)lp, ipl->iplb.loadparm); +- ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID; ++ s390_ipl_convert_loadparm((char *)lp, iplb->loadparm); ++ iplb->flags |= DIAG308_FLAGS_LP_VALID; + + return true; + } +@@ -493,6 +508,62 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl) + return false; + } + ++static bool s390_init_all_iplbs(S390IPLState *ipl) ++{ ++ int iplb_num = 0; ++ IplParameterBlock iplb_chain[7]; ++ DeviceState *dev_st = get_boot_device(0); ++ Object *machine = qdev_get_machine(); ++ ++ /* ++ * Parse the boot devices. Generate an IPLB for only the first boot device ++ * which will later be set with DIAG308. ++ */ ++ if (!dev_st) { ++ ipl->qipl.chain_len = 0; ++ return false; ++ } ++ ++ /* If no machine loadparm was defined fill it with spaces */ ++ if (memcmp(S390_CCW_MACHINE(machine)->loadparm, NO_LOADPARM, 8) == 0) { ++ object_property_set_str(machine, "loadparm", " ", NULL); ++ } ++ ++ iplb_num = 1; ++ s390_build_iplb(dev_st, &ipl->iplb); ++ ++ /* Index any fallback boot devices */ ++ while (get_boot_device(iplb_num)) { ++ iplb_num++; ++ } ++ ++ if (iplb_num > MAX_BOOT_DEVS) { ++ warn_report("Excess boot devices defined! %d boot devices found, " ++ "but only the first %d will be considered.", ++ iplb_num, MAX_BOOT_DEVS); ++ ++ iplb_num = MAX_BOOT_DEVS; ++ } ++ ++ ipl->qipl.chain_len = cpu_to_be16(iplb_num - 1); ++ ++ /* ++ * Build fallback IPLBs for any boot devices above index 0, up to a ++ * maximum amount as defined in ipl.h ++ */ ++ if (iplb_num > 1) { ++ /* Start at 1 because the IPLB for boot index 0 is not chained */ ++ for (int i = 1; i < iplb_num; i++) { ++ dev_st = get_boot_device(i); ++ s390_build_iplb(dev_st, &iplb_chain[i - 1]); ++ } ++ ++ ipl->qipl.next_iplb = cpu_to_be64(s390_ipl_map_iplb_chain(iplb_chain)); ++ } ++ ++ return iplb_num; ++} ++ + static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb, + int virtio_id) + { +@@ -620,7 +691,7 @@ void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type) + * this is the original boot device's SCSI + * so restore IPL parameter info from it + */ +- ipl->iplb_valid = s390_gen_initial_iplb(ipl); ++ ipl->iplb_valid = s390_build_iplb(get_boot_device(0), &ipl->iplb); + } + } + if (reset_type == S390_RESET_MODIFIED_CLEAR || +@@ -714,7 +785,9 @@ void s390_ipl_prepare_cpu(S390CPU *cpu) + if (!ipl->kernel || ipl->iplb_valid) { + cpu->env.psw.addr = ipl->bios_start_addr; + if (!ipl->iplb_valid) { +- ipl->iplb_valid = s390_gen_initial_iplb(ipl); ++ ipl->iplb_valid = s390_init_all_iplbs(ipl); ++ } else { ++ ipl->qipl.chain_len = 0; + } + } + s390_ipl_set_boot_menu(ipl); +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index b670bad551..54eb48fd6e 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -20,6 +20,7 @@ + #include "qom/object.h" + + #define DIAG308_FLAGS_LP_VALID 0x80 ++#define MAX_BOOT_DEVS 8 /* Max number of devices that may have a bootindex */ + + void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp); + void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp); +diff --git a/include/hw/s390x/ipl/qipl.h b/include/hw/s390x/ipl/qipl.h +index b67d2ae061..1da4f75aa8 100644 +--- a/include/hw/s390x/ipl/qipl.h ++++ b/include/hw/s390x/ipl/qipl.h +@@ -32,7 +32,9 @@ struct QemuIplParameters { + uint8_t reserved1[3]; + uint64_t reserved2; + uint32_t boot_menu_timeout; +- uint8_t reserved3[12]; ++ uint8_t reserved3[2]; ++ uint16_t chain_len; ++ uint64_t next_iplb; + } QEMU_PACKED; + typedef struct QemuIplParameters QemuIplParameters; + +-- +2.39.3 + diff --git a/kvm-hw-s390x-Remove-the-possibility-to-load-the-s390-net.patch b/kvm-hw-s390x-Remove-the-possibility-to-load-the-s390-net.patch new file mode 100644 index 0000000..b5b820d --- /dev/null +++ b/kvm-hw-s390x-Remove-the-possibility-to-load-the-s390-net.patch @@ -0,0 +1,201 @@ +From 99d6e739324ff1be46ad89a2682978cc1fa3a56c Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Thu, 20 Jun 2024 16:59:28 +0200 +Subject: [PATCH 05/27] hw/s390x: Remove the possibility to load the + s390-netboot.img binary +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [5/23] e4e037f24be08626c02f8e870992e8f0a5ed505e (thuth/qemu-kvm-cs9) + +Since the netboot code has now been merged into the main s390-ccw.img +binary, we don't need the separate s390-netboot.img anymore. Remove +it and the code that was responsible for loading it. + +Message-Id: <20240621082422.136217-6-thuth@redhat.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 188e255bf8ed68fa64bcb63577cb100eeb326254) +--- + hw/s390x/ipl.c | 55 -------------------------------------- + hw/s390x/ipl.h | 12 +++------ + hw/s390x/s390-virtio-ccw.c | 10 ++----- + pc-bios/meson.build | 1 - + 4 files changed, 6 insertions(+), 72 deletions(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index 9362de0b6f..8a0a3e6961 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -288,7 +288,6 @@ static Property s390_ipl_properties[] = { + DEFINE_PROP_STRING("initrd", S390IPLState, initrd), + DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline), + DEFINE_PROP_STRING("firmware", S390IPLState, firmware), +- DEFINE_PROP_STRING("netboot_fw", S390IPLState, netboot_fw), + DEFINE_PROP_BOOL("enforce_bios", S390IPLState, enforce_bios, false), + DEFINE_PROP_BOOL("iplbext_migration", S390IPLState, iplbext_migration, + true), +@@ -480,56 +479,6 @@ int s390_ipl_set_loadparm(uint8_t *loadparm) + return -1; + } + +-static int load_netboot_image(Error **errp) +-{ +- MachineState *ms = MACHINE(qdev_get_machine()); +- S390IPLState *ipl = get_ipl_device(); +- char *netboot_filename; +- MemoryRegion *sysmem = get_system_memory(); +- MemoryRegion *mr = NULL; +- void *ram_ptr = NULL; +- int img_size = -1; +- +- mr = memory_region_find(sysmem, 0, 1).mr; +- if (!mr) { +- error_setg(errp, "Failed to find memory region at address 0"); +- return -1; +- } +- +- ram_ptr = memory_region_get_ram_ptr(mr); +- if (!ram_ptr) { +- error_setg(errp, "No RAM found"); +- goto unref_mr; +- } +- +- netboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->netboot_fw); +- if (netboot_filename == NULL) { +- error_setg(errp, "Could not find network bootloader '%s'", +- ipl->netboot_fw); +- goto unref_mr; +- } +- +- img_size = load_elf_ram(netboot_filename, NULL, NULL, NULL, +- &ipl->start_addr, +- NULL, NULL, NULL, 1, EM_S390, 0, 0, NULL, +- false); +- +- if (img_size < 0) { +- img_size = load_image_size(netboot_filename, ram_ptr, ms->ram_size); +- ipl->start_addr = KERN_IMAGE_START; +- } +- +- if (img_size < 0) { +- error_setg(errp, "Failed to load network bootloader"); +- } +- +- g_free(netboot_filename); +- +-unref_mr: +- memory_region_unref(mr); +- return img_size; +-} +- + static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb, + int virtio_id) + { +@@ -754,10 +703,6 @@ void s390_ipl_prepare_cpu(S390CPU *cpu) + ipl->iplb_valid = s390_gen_initial_iplb(ipl); + } + } +- if (ipl->netboot) { +- load_netboot_image(&error_fatal); +- ipl->qipl.netboot_start_addr = cpu_to_be64(ipl->start_addr); +- } + s390_ipl_set_boot_menu(ipl); + s390_ipl_prepare_qipl(cpu); + } +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index 57cd125769..b2105b616a 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -134,11 +134,8 @@ void s390_ipl_clear_reset_request(void); + /* + * The QEMU IPL Parameters will be stored at absolute address + * 204 (0xcc) which means it is 32-bit word aligned but not +- * double-word aligned. +- * Placement of data fields in this area must account for +- * their alignment needs. E.g., netboot_start_address must +- * have an offset of 4 + n * 8 bytes within the struct in order +- * to keep it double-word aligned. ++ * double-word aligned. Placement of 64-bit data fields in this ++ * area must account for their alignment needs. + * The total size of the struct must never exceed 28 bytes. + * This definition must be kept in sync with the definition + * in pc-bios/s390-ccw/iplb.h. +@@ -146,9 +143,9 @@ void s390_ipl_clear_reset_request(void); + struct QemuIplParameters { + uint8_t qipl_flags; + uint8_t reserved1[3]; +- uint64_t netboot_start_addr; ++ uint64_t reserved2; + uint32_t boot_menu_timeout; +- uint8_t reserved2[12]; ++ uint8_t reserved3[12]; + } QEMU_PACKED; + typedef struct QemuIplParameters QemuIplParameters; + +@@ -178,7 +175,6 @@ struct S390IPLState { + char *initrd; + char *cmdline; + char *firmware; +- char *netboot_fw; + uint8_t cssid; + uint8_t ssid; + uint16_t devno; +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index a4a6ffa053..5113313aa8 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -197,11 +197,10 @@ static void s390_memory_init(MemoryRegion *ram) + static void s390_init_ipl_dev(const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, const char *firmware, +- const char *netboot_fw, bool enforce_bios) ++ bool enforce_bios) + { + Object *new = object_new(TYPE_S390_IPL); + DeviceState *dev = DEVICE(new); +- char *netboot_fw_prop; + + if (kernel_filename) { + qdev_prop_set_string(dev, "kernel", kernel_filename); +@@ -212,11 +211,6 @@ static void s390_init_ipl_dev(const char *kernel_filename, + qdev_prop_set_string(dev, "cmdline", kernel_cmdline); + qdev_prop_set_string(dev, "firmware", firmware); + qdev_prop_set_bit(dev, "enforce_bios", enforce_bios); +- netboot_fw_prop = object_property_get_str(new, "netboot_fw", &error_abort); +- if (!strlen(netboot_fw_prop)) { +- qdev_prop_set_string(dev, "netboot_fw", netboot_fw); +- } +- g_free(netboot_fw_prop); + object_property_add_child(qdev_get_machine(), TYPE_S390_IPL, + new); + object_unref(new); +@@ -284,7 +278,7 @@ static void ccw_init(MachineState *machine) + s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline, + machine->initrd_filename, + machine->firmware ?: "s390-ccw.img", +- "s390-netboot.img", true); ++ true); + + dev = qdev_new(TYPE_S390_PCI_HOST_BRIDGE); + object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE, +diff --git a/pc-bios/meson.build b/pc-bios/meson.build +index 8602b45b9b..ea85c54c86 100644 +--- a/pc-bios/meson.build ++++ b/pc-bios/meson.build +@@ -66,7 +66,6 @@ blobs = [ + 'kvmvapic.bin', + 'pvh.bin', + 's390-ccw.img', +- 's390-netboot.img', + 'slof.bin', + 'skiboot.lid', + 'palcode-clipper', +-- +2.39.3 + diff --git a/kvm-hw-s390x-ipl-Provide-more-memory-to-the-s390-ccw.img.patch b/kvm-hw-s390x-ipl-Provide-more-memory-to-the-s390-ccw.img.patch new file mode 100644 index 0000000..3e333d4 --- /dev/null +++ b/kvm-hw-s390x-ipl-Provide-more-memory-to-the-s390-ccw.img.patch @@ -0,0 +1,61 @@ +From 22693a98eca5872f87249006d873a95e71c448f2 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 21 Jun 2024 10:24:17 +0200 +Subject: [PATCH 01/27] hw/s390x/ipl: Provide more memory to the s390-ccw.img + firmware +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [1/23] b54cc7784876becb9fcec189811f505c22119b72 (thuth/qemu-kvm-cs9) + +We are going to link the SLOF libc into the s390-ccw.img, and this +libc needs more memory for providing space for malloc() and friends. +Thus bump the memory size that we reserve for the bios to 3 MiB +instead of only 2 MiB. While we're at it, add a proper check that +there is really enough memory assigned to the machine before blindly +using it. + +Message-ID: <20240621082422.136217-3-thuth@redhat.com> +Signed-off-by: Thomas Huth +(cherry picked from commit abaabb2e601adfe296a64471746a997eabcc607f) +--- + hw/s390x/ipl.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index e934bf89d1..9362de0b6f 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -45,6 +45,7 @@ + #define INITRD_PARM_START 0x010408UL + #define PARMFILE_START 0x001000UL + #define ZIPL_IMAGE_START 0x009000UL ++#define BIOS_MAX_SIZE 0x300000UL + #define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64) + + static bool iplb_extended_needed(void *opaque) +@@ -144,7 +145,14 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) + * even if an external kernel has been defined. + */ + if (!ipl->kernel || ipl->enforce_bios) { +- uint64_t fwbase = (MIN(ms->ram_size, 0x80000000U) - 0x200000) & ~0xffffUL; ++ uint64_t fwbase; ++ ++ if (ms->ram_size < BIOS_MAX_SIZE) { ++ error_setg(errp, "not enough RAM to load the BIOS file"); ++ return; ++ } ++ ++ fwbase = (MIN(ms->ram_size, 0x80000000U) - BIOS_MAX_SIZE) & ~0xffffUL; + + bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->firmware); + if (bios_filename == NULL) { +-- +2.39.3 + diff --git a/kvm-include-hw-s390x-Add-include-files-for-common-IPL-st.patch b/kvm-include-hw-s390x-Add-include-files-for-common-IPL-st.patch new file mode 100644 index 0000000..944c549 --- /dev/null +++ b/kvm-include-hw-s390x-Add-include-files-for-common-IPL-st.patch @@ -0,0 +1,402 @@ +From 40b5689f28e6fef2dfdd0269639c8556200458a3 Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:47 -0400 +Subject: [PATCH 14/27] include/hw/s390x: Add include files for common IPL + structs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [14/23] 632d18ef238ded324c962855edb77e3d3f0b4eae (thuth/qemu-kvm-cs9) + +Currently, structures defined in both hw/s390x/ipl.h and pc-bios/s390-ccw/iplb.h +must be kept in sync, which is prone to error. Instead, create a new directory +at include/hw/s390x/ipl/ to contain the definitions that must be shared. + +Signed-off-by: Jared Rossi +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-14-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit ba3658adc80a9370257a9c4e114829ec691311e3) +--- + hw/s390x/ipl.h | 104 +----------------------------- + include/hw/s390x/ipl/qipl.h | 123 ++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/Makefile | 2 +- + pc-bios/s390-ccw/iplb.h | 84 ++---------------------- + 4 files changed, 130 insertions(+), 183 deletions(-) + create mode 100644 include/hw/s390x/ipl/qipl.h + +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index b2105b616a..fa394c339d 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -16,95 +16,11 @@ + #include "cpu.h" + #include "exec/address-spaces.h" + #include "hw/qdev-core.h" ++#include "hw/s390x/ipl/qipl.h" + #include "qom/object.h" + +-struct IPLBlockPVComp { +- uint64_t tweak_pref; +- uint64_t addr; +- uint64_t size; +-} QEMU_PACKED; +-typedef struct IPLBlockPVComp IPLBlockPVComp; +- +-struct IPLBlockPV { +- uint8_t reserved18[87]; /* 0x18 */ +- uint8_t version; /* 0x6f */ +- uint32_t reserved70; /* 0x70 */ +- uint32_t num_comp; /* 0x74 */ +- uint64_t pv_header_addr; /* 0x78 */ +- uint64_t pv_header_len; /* 0x80 */ +- struct IPLBlockPVComp components[0]; +-} QEMU_PACKED; +-typedef struct IPLBlockPV IPLBlockPV; +- +-struct IplBlockCcw { +- uint8_t reserved0[85]; +- uint8_t ssid; +- uint16_t devno; +- uint8_t vm_flags; +- uint8_t reserved3[3]; +- uint32_t vm_parm_len; +- uint8_t nss_name[8]; +- uint8_t vm_parm[64]; +- uint8_t reserved4[8]; +-} QEMU_PACKED; +-typedef struct IplBlockCcw IplBlockCcw; +- +-struct IplBlockFcp { +- uint8_t reserved1[305 - 1]; +- uint8_t opt; +- uint8_t reserved2[3]; +- uint16_t reserved3; +- uint16_t devno; +- uint8_t reserved4[4]; +- uint64_t wwpn; +- uint64_t lun; +- uint32_t bootprog; +- uint8_t reserved5[12]; +- uint64_t br_lba; +- uint32_t scp_data_len; +- uint8_t reserved6[260]; +- uint8_t scp_data[0]; +-} QEMU_PACKED; +-typedef struct IplBlockFcp IplBlockFcp; +- +-struct IplBlockQemuScsi { +- uint32_t lun; +- uint16_t target; +- uint16_t channel; +- uint8_t reserved0[77]; +- uint8_t ssid; +- uint16_t devno; +-} QEMU_PACKED; +-typedef struct IplBlockQemuScsi IplBlockQemuScsi; +- + #define DIAG308_FLAGS_LP_VALID 0x80 + +-union IplParameterBlock { +- struct { +- uint32_t len; +- uint8_t reserved0[3]; +- uint8_t version; +- uint32_t blk0_len; +- uint8_t pbt; +- uint8_t flags; +- uint16_t reserved01; +- uint8_t loadparm[8]; +- union { +- IplBlockCcw ccw; +- IplBlockFcp fcp; +- IPLBlockPV pv; +- IplBlockQemuScsi scsi; +- }; +- } QEMU_PACKED; +- struct { +- uint8_t reserved1[110]; +- uint16_t devno; +- uint8_t reserved2[88]; +- uint8_t reserved_ext[4096 - 200]; +- } QEMU_PACKED; +-} QEMU_PACKED; +-typedef union IplParameterBlock IplParameterBlock; +- + int s390_ipl_set_loadparm(uint8_t *loadparm); + void s390_ipl_update_diag308(IplParameterBlock *iplb); + int s390_ipl_prepare_pv_header(Error **errp); +@@ -131,24 +47,6 @@ void s390_ipl_clear_reset_request(void); + #define QIPL_FLAG_BM_OPTS_CMD 0x80 + #define QIPL_FLAG_BM_OPTS_ZIPL 0x40 + +-/* +- * The QEMU IPL Parameters will be stored at absolute address +- * 204 (0xcc) which means it is 32-bit word aligned but not +- * double-word aligned. Placement of 64-bit data fields in this +- * area must account for their alignment needs. +- * The total size of the struct must never exceed 28 bytes. +- * This definition must be kept in sync with the definition +- * in pc-bios/s390-ccw/iplb.h. +- */ +-struct QemuIplParameters { +- uint8_t qipl_flags; +- uint8_t reserved1[3]; +- uint64_t reserved2; +- uint32_t boot_menu_timeout; +- uint8_t reserved3[12]; +-} QEMU_PACKED; +-typedef struct QemuIplParameters QemuIplParameters; +- + #define TYPE_S390_IPL "s390-ipl" + OBJECT_DECLARE_SIMPLE_TYPE(S390IPLState, S390_IPL) + +diff --git a/include/hw/s390x/ipl/qipl.h b/include/hw/s390x/ipl/qipl.h +new file mode 100644 +index 0000000000..0ef04af027 +--- /dev/null ++++ b/include/hw/s390x/ipl/qipl.h +@@ -0,0 +1,123 @@ ++/* ++ * S/390 boot structures ++ * ++ * Copyright 2024 IBM Corp. ++ * Author(s): Jared Rossi ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#ifndef S390X_QIPL_H ++#define S390X_QIPL_H ++ ++/* Boot Menu flags */ ++#define QIPL_FLAG_BM_OPTS_CMD 0x80 ++#define QIPL_FLAG_BM_OPTS_ZIPL 0x40 ++ ++#define QIPL_ADDRESS 0xcc ++#define LOADPARM_LEN 8 ++ ++/* ++ * The QEMU IPL Parameters will be stored at absolute address ++ * 204 (0xcc) which means it is 32-bit word aligned but not ++ * double-word aligned. Placement of 64-bit data fields in this ++ * area must account for their alignment needs. ++ * The total size of the struct must never exceed 28 bytes. ++ */ ++struct QemuIplParameters { ++ uint8_t qipl_flags; ++ uint8_t reserved1[3]; ++ uint64_t reserved2; ++ uint32_t boot_menu_timeout; ++ uint8_t reserved3[12]; ++} QEMU_PACKED; ++typedef struct QemuIplParameters QemuIplParameters; ++ ++struct IPLBlockPVComp { ++ uint64_t tweak_pref; ++ uint64_t addr; ++ uint64_t size; ++} QEMU_PACKED; ++typedef struct IPLBlockPVComp IPLBlockPVComp; ++ ++struct IPLBlockPV { ++ uint8_t reserved18[87]; /* 0x18 */ ++ uint8_t version; /* 0x6f */ ++ uint32_t reserved70; /* 0x70 */ ++ uint32_t num_comp; /* 0x74 */ ++ uint64_t pv_header_addr; /* 0x78 */ ++ uint64_t pv_header_len; /* 0x80 */ ++ struct IPLBlockPVComp components[0]; ++} QEMU_PACKED; ++typedef struct IPLBlockPV IPLBlockPV; ++ ++struct IplBlockCcw { ++ uint8_t reserved0[85]; ++ uint8_t ssid; ++ uint16_t devno; ++ uint8_t vm_flags; ++ uint8_t reserved3[3]; ++ uint32_t vm_parm_len; ++ uint8_t nss_name[8]; ++ uint8_t vm_parm[64]; ++ uint8_t reserved4[8]; ++} QEMU_PACKED; ++typedef struct IplBlockCcw IplBlockCcw; ++ ++struct IplBlockFcp { ++ uint8_t reserved1[305 - 1]; ++ uint8_t opt; ++ uint8_t reserved2[3]; ++ uint16_t reserved3; ++ uint16_t devno; ++ uint8_t reserved4[4]; ++ uint64_t wwpn; ++ uint64_t lun; ++ uint32_t bootprog; ++ uint8_t reserved5[12]; ++ uint64_t br_lba; ++ uint32_t scp_data_len; ++ uint8_t reserved6[260]; ++ uint8_t scp_data[0]; ++} QEMU_PACKED; ++typedef struct IplBlockFcp IplBlockFcp; ++ ++struct IplBlockQemuScsi { ++ uint32_t lun; ++ uint16_t target; ++ uint16_t channel; ++ uint8_t reserved0[77]; ++ uint8_t ssid; ++ uint16_t devno; ++} QEMU_PACKED; ++typedef struct IplBlockQemuScsi IplBlockQemuScsi; ++ ++union IplParameterBlock { ++ struct { ++ uint32_t len; ++ uint8_t reserved0[3]; ++ uint8_t version; ++ uint32_t blk0_len; ++ uint8_t pbt; ++ uint8_t flags; ++ uint16_t reserved01; ++ uint8_t loadparm[LOADPARM_LEN]; ++ union { ++ IplBlockCcw ccw; ++ IplBlockFcp fcp; ++ IPLBlockPV pv; ++ IplBlockQemuScsi scsi; ++ }; ++ } QEMU_PACKED; ++ struct { ++ uint8_t reserved1[110]; ++ uint16_t devno; ++ uint8_t reserved2[88]; ++ uint8_t reserved_ext[4096 - 200]; ++ } QEMU_PACKED; ++} QEMU_PACKED; ++typedef union IplParameterBlock IplParameterBlock; ++ ++#endif +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index 27cbb354af..db9e8f0892 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -3,7 +3,7 @@ all: build-all + @true + + include config-host.mak +-CFLAGS = -O2 -g ++CFLAGS = -O2 -g -I $(SRC_PATH)/../../include/hw/s390x/ipl + MAKEFLAGS += -rR + + GIT_SUBMODULES = roms/SLOF +diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h +index 3758698468..16643f5879 100644 +--- a/pc-bios/s390-ccw/iplb.h ++++ b/pc-bios/s390-ccw/iplb.h +@@ -12,88 +12,14 @@ + #ifndef IPLB_H + #define IPLB_H + +-#define LOADPARM_LEN 8 ++#ifndef QEMU_PACKED ++#define QEMU_PACKED __attribute__((packed)) ++#endif + +-struct IplBlockCcw { +- uint8_t reserved0[85]; +- uint8_t ssid; +- uint16_t devno; +- uint8_t vm_flags; +- uint8_t reserved3[3]; +- uint32_t vm_parm_len; +- uint8_t nss_name[8]; +- uint8_t vm_parm[64]; +- uint8_t reserved4[8]; +-} __attribute__ ((packed)); +-typedef struct IplBlockCcw IplBlockCcw; +- +-struct IplBlockFcp { +- uint8_t reserved1[305 - 1]; +- uint8_t opt; +- uint8_t reserved2[3]; +- uint16_t reserved3; +- uint16_t devno; +- uint8_t reserved4[4]; +- uint64_t wwpn; +- uint64_t lun; +- uint32_t bootprog; +- uint8_t reserved5[12]; +- uint64_t br_lba; +- uint32_t scp_data_len; +- uint8_t reserved6[260]; +- uint8_t scp_data[]; +-} __attribute__ ((packed)); +-typedef struct IplBlockFcp IplBlockFcp; +- +-struct IplBlockQemuScsi { +- uint32_t lun; +- uint16_t target; +- uint16_t channel; +- uint8_t reserved0[77]; +- uint8_t ssid; +- uint16_t devno; +-} __attribute__ ((packed)); +-typedef struct IplBlockQemuScsi IplBlockQemuScsi; +- +-struct IplParameterBlock { +- uint32_t len; +- uint8_t reserved0[3]; +- uint8_t version; +- uint32_t blk0_len; +- uint8_t pbt; +- uint8_t flags; +- uint16_t reserved01; +- uint8_t loadparm[LOADPARM_LEN]; +- union { +- IplBlockCcw ccw; +- IplBlockFcp fcp; +- IplBlockQemuScsi scsi; +- }; +-} __attribute__ ((packed)); +-typedef struct IplParameterBlock IplParameterBlock; +- +-extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); +- +-#define QIPL_ADDRESS 0xcc +- +-/* Boot Menu flags */ +-#define QIPL_FLAG_BM_OPTS_CMD 0x80 +-#define QIPL_FLAG_BM_OPTS_ZIPL 0x40 +- +-/* +- * This definition must be kept in sync with the definition +- * in hw/s390x/ipl.h +- */ +-struct QemuIplParameters { +- uint8_t qipl_flags; +- uint8_t reserved1[3]; +- uint64_t reserved2; +- uint32_t boot_menu_timeout; +- uint8_t reserved3[12]; +-} __attribute__ ((packed)); +-typedef struct QemuIplParameters QemuIplParameters; ++#include + + extern QemuIplParameters qipl; ++extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); + + #define S390_IPL_TYPE_FCP 0x00 + #define S390_IPL_TYPE_CCW 0x02 +-- +2.39.3 + diff --git a/kvm-kvm-Allow-kvm_arch_get-put_registers-to-accept-Error.patch b/kvm-kvm-Allow-kvm_arch_get-put_registers-to-accept-Error.patch new file mode 100644 index 0000000..5432fd3 --- /dev/null +++ b/kvm-kvm-Allow-kvm_arch_get-put_registers-to-accept-Error.patch @@ -0,0 +1,287 @@ +From 07a472e19f11c6364e787e71c95c990b76aaf187 Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Fri, 27 Sep 2024 12:47:40 +0200 +Subject: [PATCH 26/27] kvm: Allow kvm_arch_get/put_registers to accept Error** + +RH-Author: Julia Suvorova +RH-MergeRequest: 286: kvm: Allow kvm_arch_get/put_registers to accept Error** +RH-Jira: RHEL-60914 +RH-Acked-by: Juraj Marcin +RH-Acked-by: Peter Xu +RH-Commit: [1/2] 2ab30f24245a52c4254a5b9238b1b2e966a8c6a2 + +This is necessary to provide discernible error messages to the caller. + +Signed-off-by: Julia Suvorova +Reviewed-by: Peter Xu +Link: https://lore.kernel.org/r/20240927104743.218468-2-jusual@redhat.com +Signed-off-by: Paolo Bonzini +(cherry picked from commit a1676bb3047f28b292ecbce3a378ccc0b4721d47) +--- + accel/kvm/kvm-all.c | 41 +++++++++++++++++++++++++++++--------- + include/sysemu/kvm.h | 4 ++-- + target/arm/kvm.c | 4 ++-- + target/i386/kvm/kvm.c | 4 ++-- + target/loongarch/kvm/kvm.c | 4 ++-- + target/mips/kvm.c | 4 ++-- + target/ppc/kvm.c | 4 ++-- + target/riscv/kvm/kvm-cpu.c | 4 ++-- + target/s390x/kvm/kvm.c | 4 ++-- + 9 files changed, 48 insertions(+), 25 deletions(-) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 75d11a07b2..a220178822 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -2766,9 +2766,15 @@ void kvm_flush_coalesced_mmio_buffer(void) + static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) + { + if (!cpu->vcpu_dirty && !kvm_state->guest_state_protected) { +- int ret = kvm_arch_get_registers(cpu); ++ Error *err = NULL; ++ int ret = kvm_arch_get_registers(cpu, &err); + if (ret) { +- error_report("Failed to get registers: %s", strerror(-ret)); ++ if (err) { ++ error_reportf_err(err, "Failed to synchronize CPU state: "); ++ } else { ++ error_report("Failed to get registers: %s", strerror(-ret)); ++ } ++ + cpu_dump_state(cpu, stderr, CPU_DUMP_CODE); + vm_stop(RUN_STATE_INTERNAL_ERROR); + } +@@ -2786,9 +2792,15 @@ void kvm_cpu_synchronize_state(CPUState *cpu) + + static void do_kvm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) + { +- int ret = kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE); ++ Error *err = NULL; ++ int ret = kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE, &err); + if (ret) { +- error_report("Failed to put registers after reset: %s", strerror(-ret)); ++ if (err) { ++ error_reportf_err(err, "Restoring resisters after reset: "); ++ } else { ++ error_report("Failed to put registers after reset: %s", ++ strerror(-ret)); ++ } + cpu_dump_state(cpu, stderr, CPU_DUMP_CODE); + vm_stop(RUN_STATE_INTERNAL_ERROR); + } +@@ -2803,9 +2815,15 @@ void kvm_cpu_synchronize_post_reset(CPUState *cpu) + + static void do_kvm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) + { +- int ret = kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE); ++ Error *err = NULL; ++ int ret = kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE, &err); + if (ret) { +- error_report("Failed to put registers after init: %s", strerror(-ret)); ++ if (err) { ++ error_reportf_err(err, "Putting registers after init: "); ++ } else { ++ error_report("Failed to put registers after init: %s", ++ strerror(-ret)); ++ } + exit(1); + } + +@@ -2995,10 +3013,15 @@ int kvm_cpu_exec(CPUState *cpu) + MemTxAttrs attrs; + + if (cpu->vcpu_dirty) { +- ret = kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE); ++ Error *err = NULL; ++ ret = kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE, &err); + if (ret) { +- error_report("Failed to put registers after init: %s", +- strerror(-ret)); ++ if (err) { ++ error_reportf_err(err, "Putting registers after init: "); ++ } else { ++ error_report("Failed to put registers after init: %s", ++ strerror(-ret)); ++ } + ret = -1; + break; + } +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 9cf14ca3d5..d9ad723f78 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -359,7 +359,7 @@ int kvm_arch_handle_exit(CPUState *cpu, struct kvm_run *run); + + int kvm_arch_process_async_events(CPUState *cpu); + +-int kvm_arch_get_registers(CPUState *cpu); ++int kvm_arch_get_registers(CPUState *cpu, Error **errp); + + /* state subset only touched by the VCPU itself during runtime */ + #define KVM_PUT_RUNTIME_STATE 1 +@@ -368,7 +368,7 @@ int kvm_arch_get_registers(CPUState *cpu); + /* full state set, modified during initialization or on vmload */ + #define KVM_PUT_FULL_STATE 3 + +-int kvm_arch_put_registers(CPUState *cpu, int level); ++int kvm_arch_put_registers(CPUState *cpu, int level, Error **errp); + + int kvm_arch_get_default_type(MachineState *ms); + +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 849e2e21b3..f1f1b5b375 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -2042,7 +2042,7 @@ static int kvm_arch_put_sve(CPUState *cs) + return 0; + } + +-int kvm_arch_put_registers(CPUState *cs, int level) ++int kvm_arch_put_registers(CPUState *cs, int level, Error **errp) + { + uint64_t val; + uint32_t fpr; +@@ -2226,7 +2226,7 @@ static int kvm_arch_get_sve(CPUState *cs) + return 0; + } + +-int kvm_arch_get_registers(CPUState *cs) ++int kvm_arch_get_registers(CPUState *cs, Error **errp) + { + uint64_t val; + unsigned int el; +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index 2b28c18693..423e6922d8 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -5121,7 +5121,7 @@ static int kvm_get_nested_state(X86CPU *cpu) + return ret; + } + +-int kvm_arch_put_registers(CPUState *cpu, int level) ++int kvm_arch_put_registers(CPUState *cpu, int level, Error **errp) + { + X86CPU *x86_cpu = X86_CPU(cpu); + int ret; +@@ -5209,7 +5209,7 @@ int kvm_arch_put_registers(CPUState *cpu, int level) + return 0; + } + +-int kvm_arch_get_registers(CPUState *cs) ++int kvm_arch_get_registers(CPUState *cs, Error **errp) + { + X86CPU *cpu = X86_CPU(cs); + int ret; +diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c +index e1be6a6959..9204d4295d 100644 +--- a/target/loongarch/kvm/kvm.c ++++ b/target/loongarch/kvm/kvm.c +@@ -585,7 +585,7 @@ static int kvm_loongarch_put_cpucfg(CPUState *cs) + return ret; + } + +-int kvm_arch_get_registers(CPUState *cs) ++int kvm_arch_get_registers(CPUState *cs, Error **errp) + { + int ret; + +@@ -613,7 +613,7 @@ int kvm_arch_get_registers(CPUState *cs) + return ret; + } + +-int kvm_arch_put_registers(CPUState *cs, int level) ++int kvm_arch_put_registers(CPUState *cs, int level, Error **errp) + { + int ret; + +diff --git a/target/mips/kvm.c b/target/mips/kvm.c +index a631ab544f..a98798c669 100644 +--- a/target/mips/kvm.c ++++ b/target/mips/kvm.c +@@ -1172,7 +1172,7 @@ static int kvm_mips_get_cp0_registers(CPUState *cs) + return ret; + } + +-int kvm_arch_put_registers(CPUState *cs, int level) ++int kvm_arch_put_registers(CPUState *cs, int level, Error **errp) + { + CPUMIPSState *env = cpu_env(cs); + struct kvm_regs regs; +@@ -1207,7 +1207,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) + return ret; + } + +-int kvm_arch_get_registers(CPUState *cs) ++int kvm_arch_get_registers(CPUState *cs, Error **errp) + { + CPUMIPSState *env = cpu_env(cs); + int ret = 0; +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index c942ff55b2..7daa097164 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -902,7 +902,7 @@ int kvmppc_put_books_sregs(PowerPCCPU *cpu) + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs); + } + +-int kvm_arch_put_registers(CPUState *cs, int level) ++int kvm_arch_put_registers(CPUState *cs, int level, Error **errp) + { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; +@@ -1207,7 +1207,7 @@ static int kvmppc_get_books_sregs(PowerPCCPU *cpu) + return 0; + } + +-int kvm_arch_get_registers(CPUState *cs) ++int kvm_arch_get_registers(CPUState *cs, Error **errp) + { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; +diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c +index f6e3156b8d..2bfb112be0 100644 +--- a/target/riscv/kvm/kvm-cpu.c ++++ b/target/riscv/kvm/kvm-cpu.c +@@ -1192,7 +1192,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO + }; + +-int kvm_arch_get_registers(CPUState *cs) ++int kvm_arch_get_registers(CPUState *cs, Error **errp) + { + int ret = 0; + +@@ -1237,7 +1237,7 @@ int kvm_riscv_sync_mpstate_to_kvm(RISCVCPU *cpu, int state) + return 0; + } + +-int kvm_arch_put_registers(CPUState *cs, int level) ++int kvm_arch_put_registers(CPUState *cs, int level, Error **errp) + { + int ret = 0; + +diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c +index 45c23758e7..0d51a4ea6b 100644 +--- a/target/s390x/kvm/kvm.c ++++ b/target/s390x/kvm/kvm.c +@@ -472,7 +472,7 @@ static int can_sync_regs(CPUState *cs, int regs) + #define KVM_SYNC_REQUIRED_REGS (KVM_SYNC_GPRS | KVM_SYNC_ACRS | \ + KVM_SYNC_CRS | KVM_SYNC_PREFIX) + +-int kvm_arch_put_registers(CPUState *cs, int level) ++int kvm_arch_put_registers(CPUState *cs, int level, Error **errp) + { + CPUS390XState *env = cpu_env(cs); + struct kvm_fpu fpu = {}; +@@ -598,7 +598,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) + return 0; + } + +-int kvm_arch_get_registers(CPUState *cs) ++int kvm_arch_get_registers(CPUState *cs, Error **errp) + { + CPUS390XState *env = cpu_env(cs); + struct kvm_fpu fpu; +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Clarify-alignment-is-in-bytes.patch b/kvm-pc-bios-s390-ccw-Clarify-alignment-is-in-bytes.patch new file mode 100644 index 0000000..83c0a3c --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Clarify-alignment-is-in-bytes.patch @@ -0,0 +1,60 @@ +From 77dab9f12b3c4cdaacea1dff687cf1c49e95f304 Mon Sep 17 00:00:00 2001 +From: Jens Remus +Date: Tue, 1 Oct 2024 17:36:16 +0200 +Subject: [PATCH 21/27] pc-bios/s390-ccw: Clarify alignment is in bytes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [21/23] d00be9e7c87cb047d20b729f2ac539fe624f5ce0 (thuth/qemu-kvm-cs9) + +The assembler directive .align [1] has architecture-dependent behavior, +which may be ambiguous for the reader. Some architectures perform the +alignment in bytes, others in power of two. s390 does in bytes. + +Use the directive .balign [2] instead, to clarify that the alignment +request is in bytes. No functional change. + +[1] https://sourceware.org/binutils/docs/as/Align.html +[2] https://sourceware.org/binutils/docs/as/Balign.html + +Signed-off-by: Jens Remus +Reviewed-by: Marc Hartmayer +Message-ID: <20241001153618.17791-2-mhartmay@linux.ibm.com> +Reviewed-by: Thomas Huth +Signed-off-by: Thomas Huth +(cherry picked from commit c58df213af7ec8924d219025a593b8f3ac475f16) +--- + pc-bios/s390-ccw/start.S | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S +index 061b06591c..576fc12c06 100644 +--- a/pc-bios/s390-ccw/start.S ++++ b/pc-bios/s390-ccw/start.S +@@ -112,7 +112,7 @@ io_new_code: + lctlg %c6,%c6,0(%r15) + br %r14 + +- .align 8 ++ .balign 8 + bss_start_literal: + .quad __bss_start + disabled_wait_psw: +@@ -125,7 +125,7 @@ io_new_mask: + .quad 0x0000000180000000 + + .bss +- .align 8 ++ .balign 8 + stack: + .space STACK_SIZE + .size stack,STACK_SIZE +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Don-t-generate-TEXTRELs.patch b/kvm-pc-bios-s390-ccw-Don-t-generate-TEXTRELs.patch new file mode 100644 index 0000000..95d42fc --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Don-t-generate-TEXTRELs.patch @@ -0,0 +1,83 @@ +From 7a5f9ea3bb8ff78bd93eb2cee9b8be876e745346 Mon Sep 17 00:00:00 2001 +From: Jens Remus +Date: Tue, 1 Oct 2024 17:36:17 +0200 +Subject: [PATCH 22/27] pc-bios/s390-ccw: Don't generate TEXTRELs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [22/23] 8d8b2959be6c798f24e1991252fe6c680a6c6025 (thuth/qemu-kvm-cs9) + +Commit 7cd50cbe4ca3 ("pc-bios/s390-ccw: Don't use __bss_start with the +"larl" instruction") introduced the address constant bss_start_literal +for __bss_start in the .text section, which introduced a relocation in +code (i.e. TEXTREL). The dedicated constant is required, as __bss_start +may not necessarily be aligned on a 2-byte boundary (see subject commit +for details). + +Move the constant to the .data section to get rid of the relocation in +the .text section. Add the linker option -z text to prevent TEXTRELs to +get introduced in the future. + +Note that the R_390_RELATIVE relocations are taken care of by function +glue() in include/hw/elf_ops.h.inc introduced by commit 5dce07e1cb67 +("elf-loader: Provide the possibility to relocate s390 ELF files"). + +Reported-by: Marc Hartmayer +Signed-off-by: Jens Remus +Reviewed-by: Marc Hartmayer +Message-ID: <20241001153618.17791-3-mhartmay@linux.ibm.com> +Reviewed-by: Thomas Huth +Signed-off-by: Thomas Huth +(cherry picked from commit 3259b4424a85d9cdfd1a33ed6030a6c51c1b9b8b) +--- + pc-bios/s390-ccw/Makefile | 2 +- + pc-bios/s390-ccw/start.S | 7 +++++-- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index db9e8f0892..38254e22df 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -46,7 +46,7 @@ EXTRA_CFLAGS += -fwrapv -fno-strict-aliasing -fno-asynchronous-unwind-tables + EXTRA_CFLAGS += -msoft-float + EXTRA_CFLAGS += -std=gnu99 + EXTRA_CFLAGS += $(LIBC_INC) $(LIBNET_INC) +-LDFLAGS += -Wl,-pie -nostdlib -z noexecstack ++LDFLAGS += -Wl,-pie -nostdlib -z noexecstack -z text + + cc-test = $(CC) -Werror $1 -c -o /dev/null -xc /dev/null >/dev/null 2>/dev/null + cc-option = if $(call cc-test, $1); then \ +diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S +index 576fc12c06..b70213e412 100644 +--- a/pc-bios/s390-ccw/start.S ++++ b/pc-bios/s390-ccw/start.S +@@ -113,8 +113,6 @@ io_new_code: + br %r14 + + .balign 8 +-bss_start_literal: +- .quad __bss_start + disabled_wait_psw: + .quad 0x0002000180000000,0x0000000000000000 + enabled_wait_psw: +@@ -124,6 +122,11 @@ external_new_mask: + io_new_mask: + .quad 0x0000000180000000 + ++.data ++ .balign 8 ++bss_start_literal: ++ .quad __bss_start ++ + .bss + .balign 8 + stack: +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Enable-failed-IPL-to-return-after-e.patch b/kvm-pc-bios-s390-ccw-Enable-failed-IPL-to-return-after-e.patch new file mode 100644 index 0000000..b513e7d --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Enable-failed-IPL-to-return-after-e.patch @@ -0,0 +1,426 @@ +From 41a56360a0f4124252180132e28c166792ee8853 Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:46 -0400 +Subject: [PATCH 13/27] pc-bios/s390-ccw: Enable failed IPL to return after + error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [13/23] c86e8a72a631081348e88ac1df99c2eec8ca27dd (thuth/qemu-kvm-cs9) + +Remove panic-on-error from IPL functions such that a return code is propagated +back to the main IPL calling function (rather than terminating immediately), +which facilitates possible error recovery in the future. + +A select few panics remain, which indicate fatal non-devices errors that must +result in termination. + +Signed-off-by: Jared Rossi +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-13-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 0181e23713114fd4c33326c3372aaf48dcfb412a) +--- + pc-bios/s390-ccw/bootmap.c | 53 ++++++++++++++++++-------- + pc-bios/s390-ccw/cio.c | 3 +- + pc-bios/s390-ccw/jump2ipl.c | 5 ++- + pc-bios/s390-ccw/main.c | 32 +++++++++------- + pc-bios/s390-ccw/s390-ccw.h | 2 +- + pc-bios/s390-ccw/virtio-blkdev.c | 2 +- + pc-bios/s390-ccw/virtio.c | 65 +++++++++++++++++++++----------- + pc-bios/s390-ccw/virtio.h | 2 +- + 8 files changed, 108 insertions(+), 56 deletions(-) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index 95ef9104d0..56f2f75640 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -62,15 +62,34 @@ static void *s2_prev_blk = _s2; + static void *s2_cur_blk = _s2 + MAX_SECTOR_SIZE; + static void *s2_next_blk = _s2 + MAX_SECTOR_SIZE * 2; + +-static inline void verify_boot_info(BootInfo *bip) ++static inline int verify_boot_info(BootInfo *bip) + { +- IPL_assert(magic_match(bip->magic, ZIPL_MAGIC), "No zIPL sig in BootInfo"); +- IPL_assert(bip->version == BOOT_INFO_VERSION, "Wrong zIPL version"); +- IPL_assert(bip->bp_type == BOOT_INFO_BP_TYPE_IPL, "DASD is not for IPL"); +- IPL_assert(bip->dev_type == BOOT_INFO_DEV_TYPE_ECKD, "DASD is not ECKD"); +- IPL_assert(bip->flags == BOOT_INFO_FLAGS_ARCH, "Not for this arch"); +- IPL_assert(block_size_ok(bip->bp.ipl.bm_ptr.eckd.bptr.size), +- "Bad block size in zIPL section of the 1st record."); ++ if (!magic_match(bip->magic, ZIPL_MAGIC)) { ++ puts("No zIPL sig in BootInfo"); ++ return -EINVAL; ++ } ++ if (bip->version != BOOT_INFO_VERSION) { ++ puts("Wrong zIPL version"); ++ return -EINVAL; ++ } ++ if (bip->bp_type != BOOT_INFO_BP_TYPE_IPL) { ++ puts("DASD is not for IPL"); ++ return -ENODEV; ++ } ++ if (bip->dev_type != BOOT_INFO_DEV_TYPE_ECKD) { ++ puts("DASD is not ECKD"); ++ return -ENODEV; ++ } ++ if (bip->flags != BOOT_INFO_FLAGS_ARCH) { ++ puts("Not for this arch"); ++ return -EINVAL; ++ } ++ if (!block_size_ok(bip->bp.ipl.bm_ptr.eckd.bptr.size)) { ++ puts("Bad block size in zIPL section of 1st record"); ++ return -EINVAL; ++ } ++ ++ return 0; + } + + static void eckd_format_chs(ExtEckdBlockPtr *ptr, bool ldipl, +@@ -367,8 +386,8 @@ static int run_eckd_boot_script(block_number_t bmt_block_nr, + puts("Unknown script entry type"); + return -EINVAL; + } +- write_reset_psw(bms->entry[i].address.load_address); /* no return */ +- jump_to_IPL_code(0); /* no return */ ++ write_reset_psw(bms->entry[i].address.load_address); ++ jump_to_IPL_code(0); + return -1; + } + +@@ -1067,16 +1086,19 @@ void zipl_load(void) + + if (vdev->is_cdrom) { + ipl_iso_el_torito(); +- panic("\n! Cannot IPL this ISO image !\n"); ++ puts("Failed to IPL this ISO image!"); ++ return; + } + + if (virtio_get_device_type() == VIRTIO_ID_NET) { + netmain(); +- panic("\n! Cannot IPL from this network !\n"); ++ puts("Failed to IPL from this network!"); ++ return; + } + + if (ipl_scsi()) { +- panic("\n! Cannot IPL this SCSI device !\n"); ++ puts("Failed to IPL from this SCSI device!"); ++ return; + } + + switch (virtio_get_device_type()) { +@@ -1087,8 +1109,9 @@ void zipl_load(void) + zipl_load_vscsi(); + break; + default: +- panic("\n! Unknown IPL device type !\n"); ++ puts("Unknown IPL device type!"); ++ return; + } + +- puts("zIPL load failed."); ++ puts("zIPL load failed!"); + } +diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c +index 7b09a38c96..5d543da73f 100644 +--- a/pc-bios/s390-ccw/cio.c ++++ b/pc-bios/s390-ccw/cio.c +@@ -59,7 +59,8 @@ uint16_t cu_type(SubChannelId schid) + }; + + if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) { +- panic("Failed to run SenseID CCw\n"); ++ puts("Failed to run SenseID CCW"); ++ return CU_TYPE_UNKNOWN; + } + + return sense_data.cu_type; +diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c +index 80b7f6a1f3..8db1764ff3 100644 +--- a/pc-bios/s390-ccw/jump2ipl.c ++++ b/pc-bios/s390-ccw/jump2ipl.c +@@ -33,7 +33,7 @@ static void jump_to_IPL_addr(void) + /* should not return */ + } + +-void jump_to_IPL_code(uint64_t address) ++int jump_to_IPL_code(uint64_t address) + { + /* store the subsystem information _after_ the bootmap was loaded */ + write_subsystem_identification(); +@@ -68,7 +68,8 @@ void jump_to_IPL_code(uint64_t address) + asm volatile("lghi %%r1,1\n\t" + "diag %%r1,%%r1,0x308\n\t" + : : : "1", "memory"); +- panic("\n! IPL returns !\n"); ++ puts("IPL code jump failed"); ++ return -1; + } + + void jump_to_low_kernel(void) +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index fc44da3161..34ef27d7a6 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -77,6 +77,9 @@ static int is_dev_possibly_bootable(int dev_no, int sch_no) + + enable_subchannel(blk_schid); + cutype = cu_type(blk_schid); ++ if (cutype == CU_TYPE_UNKNOWN) { ++ return -EIO; ++ } + + /* + * Note: we always have to run virtio_is_supported() here to make +@@ -194,10 +197,10 @@ static void boot_setup(void) + have_iplb = store_iplb(&iplb); + } + +-static void find_boot_device(void) ++static bool find_boot_device(void) + { + VDev *vdev = virtio_get_device(); +- bool found; ++ bool found = false; + + switch (iplb.pbt) { + case S390_IPL_TYPE_CCW: +@@ -215,10 +218,10 @@ static void find_boot_device(void) + found = find_subch(iplb.scsi.devno); + break; + default: +- panic("List-directed IPL not supported yet!\n"); ++ puts("Unsupported IPLB"); + } + +- IPL_assert(found, "Boot device not found\n"); ++ return found; + } + + static int virtio_setup(void) +@@ -244,11 +247,13 @@ static int virtio_setup(void) + ret = virtio_scsi_setup_device(blk_schid); + break; + default: +- panic("\n! No IPL device available !\n"); ++ puts("\n! No IPL device available !\n"); ++ return -1; + } + +- if (!ret) { +- IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected"); ++ if (!ret && !virtio_ipl_disk_is_valid()) { ++ puts("No valid IPL device detected"); ++ return -ENODEV; + } + + return ret; +@@ -259,16 +264,16 @@ static void ipl_boot_device(void) + switch (cutype) { + case CU_TYPE_DASD_3990: + case CU_TYPE_DASD_2107: +- dasd_ipl(blk_schid, cutype); /* no return */ ++ dasd_ipl(blk_schid, cutype); + break; + case CU_TYPE_VIRTIO: +- if (virtio_setup() == 0) { +- zipl_load(); /* Only returns in case of errors */ ++ if (virtio_setup()) { ++ return; /* Only returns in case of errors */ + } ++ zipl_load(); + break; + default: + printf("Attempting to boot from unexpected device type 0x%X\n", cutype); +- panic("\nBoot failed.\n"); + } + } + +@@ -301,12 +306,11 @@ void main(void) + sclp_setup(); + css_setup(); + boot_setup(); +- if (have_iplb) { +- find_boot_device(); ++ if (have_iplb && find_boot_device()) { + ipl_boot_device(); + } else { + probe_boot_device(); + } + +- panic("Failed to load OS from hard disk\n"); ++ panic("Failed to IPL. Halting..."); + } +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index 344ad15655..6cdce3e5e5 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -78,7 +78,7 @@ void zipl_load(void); + + /* jump2ipl.c */ + void write_reset_psw(uint64_t psw); +-void jump_to_IPL_code(uint64_t address); ++int jump_to_IPL_code(uint64_t address); + void jump_to_low_kernel(void); + + /* menu.c */ +diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c +index 1c585f034b..7b2d1e20f4 100644 +--- a/pc-bios/s390-ccw/virtio-blkdev.c ++++ b/pc-bios/s390-ccw/virtio-blkdev.c +@@ -59,7 +59,7 @@ int virtio_read_many(unsigned long sector, void *load_addr, int sec_num) + case VIRTIO_ID_SCSI: + return virtio_scsi_read_many(vdev, sector, load_addr, sec_num); + } +- panic("\n! No readable IPL device !\n"); ++ + return -1; + } + +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index 8c6b0a8a92..8b5a370bb3 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -217,16 +217,19 @@ int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd) + return 0; + } + +-void virtio_setup_ccw(VDev *vdev) ++int virtio_setup_ccw(VDev *vdev) + { +- int i, rc, cfg_size = 0; ++ int i, cfg_size = 0; + uint8_t status; + struct VirtioFeatureDesc { + uint32_t features; + uint8_t index; + } __attribute__((packed)) feats; + +- IPL_assert(virtio_is_supported(vdev->schid), "PE"); ++ if (!virtio_is_supported(vdev->schid)) { ++ puts("Virtio unsupported for this device ID"); ++ return -ENODEV; ++ } + /* device ID has been established now */ + + vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */ +@@ -235,8 +238,10 @@ void virtio_setup_ccw(VDev *vdev) + run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0, false); + + status = VIRTIO_CONFIG_S_ACKNOWLEDGE; +- rc = run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false); +- IPL_assert(rc == 0, "Could not write ACKNOWLEDGE status to host"); ++ if (run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false)) { ++ puts("Could not write ACKNOWLEDGE status to host"); ++ return -EIO; ++ } + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_NET: +@@ -255,27 +260,37 @@ void virtio_setup_ccw(VDev *vdev) + cfg_size = sizeof(vdev->config.scsi); + break; + default: +- panic("Unsupported virtio device\n"); ++ puts("Unsupported virtio device"); ++ return -ENODEV; + } + + status |= VIRTIO_CONFIG_S_DRIVER; +- rc = run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false); +- IPL_assert(rc == 0, "Could not write DRIVER status to host"); ++ if (run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false)) { ++ puts("Could not write DRIVER status to host"); ++ return -EIO; ++ } + + /* Feature negotiation */ + for (i = 0; i < ARRAY_SIZE(vdev->guest_features); i++) { + feats.features = 0; + feats.index = i; +- rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats), false); +- IPL_assert(rc == 0, "Could not get features bits"); ++ if (run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats), false)) { ++ puts("Could not get features bits"); ++ return -EIO; ++ } ++ + vdev->guest_features[i] &= bswap32(feats.features); + feats.features = bswap32(vdev->guest_features[i]); +- rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats), false); +- IPL_assert(rc == 0, "Could not set features bits"); ++ if (run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats), false)) { ++ puts("Could not set features bits"); ++ return -EIO; ++ } + } + +- rc = run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size, false); +- IPL_assert(rc == 0, "Could not get virtio device configuration"); ++ if (run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size, false)) { ++ puts("Could not get virtio device configuration"); ++ return -EIO; ++ } + + for (i = 0; i < vdev->nr_vqs; i++) { + VqInfo info = { +@@ -289,19 +304,27 @@ void virtio_setup_ccw(VDev *vdev) + .num = 0, + }; + +- rc = run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config), false); +- IPL_assert(rc == 0, "Could not get virtio device VQ configuration"); ++ if (run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config), ++ false)) { ++ puts("Could not get virtio device VQ config"); ++ return -EIO; ++ } + info.num = config.num; + vring_init(&vdev->vrings[i], &info); + vdev->vrings[i].schid = vdev->schid; +- IPL_assert( +- run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info), false) == 0, +- "Cannot set VQ info"); ++ if (run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info), false)) { ++ puts("Cannot set VQ info"); ++ return -EIO; ++ } + } + + status |= VIRTIO_CONFIG_S_DRIVER_OK; +- rc = run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false); +- IPL_assert(rc == 0, "Could not write DRIVER_OK status to host"); ++ if (run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false)) { ++ puts("Could not write DRIVER_OK status to host"); ++ return -EIO; ++ } ++ ++ return 0; + } + + bool virtio_is_supported(SubChannelId schid) +diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h +index 6f9a558ff5..9faf3986b1 100644 +--- a/pc-bios/s390-ccw/virtio.h ++++ b/pc-bios/s390-ccw/virtio.h +@@ -274,7 +274,7 @@ void vring_send_buf(VRing *vr, void *p, int len, int flags); + int vr_poll(VRing *vr); + int vring_wait_reply(void); + int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd); +-void virtio_setup_ccw(VDev *vdev); ++int virtio_setup_ccw(VDev *vdev); + + int virtio_net_init(void *mac_addr); + +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Introduce-EXTRA_LDFLAGS.patch b/kvm-pc-bios-s390-ccw-Introduce-EXTRA_LDFLAGS.patch new file mode 100644 index 0000000..6b5269f --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Introduce-EXTRA_LDFLAGS.patch @@ -0,0 +1,63 @@ +From 499df84ffe62c783d35d5e67cd0d0c35ba6bd44c Mon Sep 17 00:00:00 2001 +From: Marc Hartmayer +Date: Tue, 1 Oct 2024 17:36:18 +0200 +Subject: [PATCH 23/27] pc-bios/s390-ccw: Introduce `EXTRA_LDFLAGS` +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [23/23] e27a9f3997924573bbacc1a7cf48004b2daeaaaa (thuth/qemu-kvm-cs9) + +Some packaging tools want to override `LDFLAGS` when building QEMU, this will +result in a build error as most likely no `-nostdlib` flag is passed. Introduce +`EXTRA_LDFLAGS` so that the packager can override `LDFLAGS` without breaking the +build. + +Signed-off-by: Marc Hartmayer +Message-ID: <20241001153618.17791-4-mhartmay@linux.ibm.com> +Reviewed-by: Thomas Huth +[thuth: Drop the hunk to netbook.mak which is not necessary anymore] +Signed-off-by: Thomas Huth +(cherry picked from commit 694d79ffce996c0993cebccc07c2ab6fc281e7d0) +--- + pc-bios/s390-ccw/Makefile | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index 38254e22df..dc69dd484f 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -4,6 +4,7 @@ all: build-all + + include config-host.mak + CFLAGS = -O2 -g -I $(SRC_PATH)/../../include/hw/s390x/ipl ++LDFLAGS ?= + MAKEFLAGS += -rR + + GIT_SUBMODULES = roms/SLOF +@@ -46,7 +47,7 @@ EXTRA_CFLAGS += -fwrapv -fno-strict-aliasing -fno-asynchronous-unwind-tables + EXTRA_CFLAGS += -msoft-float + EXTRA_CFLAGS += -std=gnu99 + EXTRA_CFLAGS += $(LIBC_INC) $(LIBNET_INC) +-LDFLAGS += -Wl,-pie -nostdlib -z noexecstack -z text ++EXTRA_LDFLAGS += -Wl,-pie -nostdlib -z noexecstack -z text + + cc-test = $(CC) -Werror $1 -c -o /dev/null -xc /dev/null >/dev/null 2>/dev/null + cc-option = if $(call cc-test, $1); then \ +@@ -111,7 +112,7 @@ libnet.a: $(LIBNETOBJS) + build-all: s390-ccw.img + + s390-ccw.elf: $(OBJECTS) libnet.a libc.a +- $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^,Linking) ++ $(call quiet-command,$(CC) $(EXTRA_LDFLAGS) $(LDFLAGS) -o $@ $^,Linking) + + s390-ccw.img: s390-ccw.elf + $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,Stripping $< into) +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Link-the-netboot-code-into-the-main.patch b/kvm-pc-bios-s390-ccw-Link-the-netboot-code-into-the-main.patch new file mode 100644 index 0000000..1b243e5 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Link-the-netboot-code-into-the-main.patch @@ -0,0 +1,263 @@ +From 5dd12012ec95bbac035a7a8b22216082def604f3 Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:37 -0400 +Subject: [PATCH 03/27] pc-bios/s390-ccw: Link the netboot code into the main + s390-ccw.img binary +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [3/23] d369fc67aa9e10ba97618182e8f9681d151bcc49 (thuth/qemu-kvm-cs9) + +We originally built a separate binary for the netboot code since it +was considered as experimental and we could not be sure that the +necessary SLOF module had been checked out. Time passed, the code +proved its usefulness, and the build system nowadays makes sure that +the SLOF module is checked out if you have a s390x compiler available +for building the s390-ccw bios. So there is no real compelling reason +anymore to keep the netboot code in a separate binary. Linking the +code together with the main s390-ccw.img will make future enhancements +much easier, like supporting more than one boot device. + +Co-authored by: Thomas Huth +Signed-off-by: Jared Rossi +Message-ID: <20241020012953.1380075-4-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 8e5739ce4b0b04d7121cb2b29521acde2a8f3a24) +--- + pc-bios/s390-ccw/Makefile | 13 +++++++------ + pc-bios/s390-ccw/bootmap.c | 2 +- + pc-bios/s390-ccw/cio.h | 2 ++ + pc-bios/s390-ccw/iplb.h | 4 ++-- + pc-bios/s390-ccw/main.c | 10 +++++++--- + pc-bios/s390-ccw/netboot.mak | 14 -------------- + pc-bios/s390-ccw/netmain.c | 15 ++------------- + pc-bios/s390-ccw/s390-ccw.h | 3 +++ + pc-bios/s390-ccw/virtio.h | 1 - + 9 files changed, 24 insertions(+), 40 deletions(-) + +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index 3f4232636e..cf6859823a 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -32,19 +32,20 @@ QEMU_DGFLAGS = -MMD -MP -MT $@ -MF $(@D)/$(*F).d + + .PHONY : all clean build-all distclean + +-OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ +- virtio.o virtio-scsi.o virtio-blkdev.o cio.o dasd-ipl.o ++OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o netmain.o \ ++ virtio.o virtio-net.o virtio-scsi.o virtio-blkdev.o cio.o dasd-ipl.o + + SLOF_DIR := $(SRC_PATH)/../../roms/SLOF + + LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include ++LIBNET_INC := -I$(SLOF_DIR)/lib/libnet + + EXTRA_CFLAGS += -Wall + EXTRA_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -fno-common -fPIE + EXTRA_CFLAGS += -fwrapv -fno-strict-aliasing -fno-asynchronous-unwind-tables + EXTRA_CFLAGS += -msoft-float + EXTRA_CFLAGS += -std=gnu99 +-EXTRA_CFLAGS += $(LIBC_INC) ++EXTRA_CFLAGS += $(LIBC_INC) $(LIBNET_INC) + LDFLAGS += -Wl,-pie -nostdlib -z noexecstack + + cc-test = $(CC) -Werror $1 -c -o /dev/null -xc /dev/null >/dev/null 2>/dev/null +@@ -62,9 +63,9 @@ config-cc.mak: Makefile + + include $(SRC_PATH)/netboot.mak + +-build-all: s390-ccw.img s390-netboot.img ++build-all: s390-ccw.img + +-s390-ccw.elf: $(OBJECTS) libc.a ++s390-ccw.elf: $(OBJECTS) libnet.a libc.a + $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^,Linking) + + s390-ccw.img: s390-ccw.elf +@@ -72,7 +73,7 @@ s390-ccw.img: s390-ccw.elf + + $(OBJECTS): Makefile + +-ALL_OBJS = $(sort $(OBJECTS) $(NETOBJS) $(LIBCOBJS) $(LIBNETOBJS)) ++ALL_OBJS = $(sort $(OBJECTS) $(LIBCOBJS) $(LIBNETOBJS)) + -include $(ALL_OBJS:%.o=%.d) + + clean: +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index 3cc79706be..414c3f1b47 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -929,7 +929,7 @@ void zipl_load(void) + } + + if (virtio_get_device_type() == VIRTIO_ID_NET) { +- jump_to_IPL_code(vdev->netboot_start_addr); ++ netmain(); + } + + ipl_scsi(); +diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h +index 8b18153deb..6a5e86ba01 100644 +--- a/pc-bios/s390-ccw/cio.h ++++ b/pc-bios/s390-ccw/cio.h +@@ -361,6 +361,8 @@ typedef struct CcwSearchIdData { + uint8_t record; + } __attribute__((packed)) CcwSearchIdData; + ++extern SubChannelId net_schid; ++ + int enable_mss_facility(void); + void enable_subchannel(SubChannelId schid); + uint16_t cu_type(SubChannelId schid); +diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h +index cb6ac8a880..3758698468 100644 +--- a/pc-bios/s390-ccw/iplb.h ++++ b/pc-bios/s390-ccw/iplb.h +@@ -87,9 +87,9 @@ extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); + struct QemuIplParameters { + uint8_t qipl_flags; + uint8_t reserved1[3]; +- uint64_t netboot_start_addr; ++ uint64_t reserved2; + uint32_t boot_menu_timeout; +- uint8_t reserved2[12]; ++ uint8_t reserved3[12]; + } __attribute__ ((packed)); + typedef struct QemuIplParameters QemuIplParameters; + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 203df20965..fc44da3161 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -38,8 +38,13 @@ LowCore *lowcore; /* Yes, this *is* a pointer to address 0 */ + */ + void write_subsystem_identification(void) + { +- lowcore->subchannel_id = blk_schid.sch_id; +- lowcore->subchannel_nr = blk_schid.sch_no; ++ if (cutype == CU_TYPE_VIRTIO && virtio_get_device_type() == VIRTIO_ID_NET) { ++ lowcore->subchannel_id = net_schid.sch_id; ++ lowcore->subchannel_nr = net_schid.sch_no; ++ } else { ++ lowcore->subchannel_id = blk_schid.sch_id; ++ lowcore->subchannel_nr = blk_schid.sch_no; ++ } + lowcore->io_int_parm = 0; + } + +@@ -231,7 +236,6 @@ static int virtio_setup(void) + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_NET: + puts("Network boot device detected"); +- vdev->netboot_start_addr = qipl.netboot_start_addr; + return 0; + case VIRTIO_ID_BLOCK: + ret = virtio_blk_setup_device(blk_schid); +diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak +index d2b3d8ee74..0a24257ff4 100644 +--- a/pc-bios/s390-ccw/netboot.mak ++++ b/pc-bios/s390-ccw/netboot.mak +@@ -1,18 +1,4 @@ + +-NETOBJS := start.o sclp.o cio.o virtio.o virtio-net.o jump2ipl.o netmain.o +- +-LIBNET_INC := -I$(SLOF_DIR)/lib/libnet +- +-NETLDFLAGS := $(LDFLAGS) -Wl,-Ttext=0x7800000 +- +-$(NETOBJS): EXTRA_CFLAGS += $(LIBC_INC) $(LIBNET_INC) +- +-s390-netboot.elf: $(NETOBJS) libnet.a libc.a +- $(call quiet-command,$(CC) $(NETLDFLAGS) -o $@ $^,Linking) +- +-s390-netboot.img: s390-netboot.elf +- $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,Stripping $< into) +- + # libc files: + + LIBC_CFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ +diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c +index 509119be15..bc6ad8695f 100644 +--- a/pc-bios/s390-ccw/netmain.c ++++ b/pc-bios/s390-ccw/netmain.c +@@ -41,7 +41,6 @@ + #define DEFAULT_TFTP_RETRIES 20 + + extern char _start[]; +-void write_iplb_location(void) {} + + #define KERNEL_ADDR ((void *)0L) + #define KERNEL_MAX_SIZE ((long)_start) +@@ -50,10 +49,9 @@ void write_iplb_location(void) {} + /* STSI 3.2.2 offset of first vmdb + offset of uuid inside vmdb */ + #define STSI322_VMDB_UUID_OFFSET ((8 + 12) * 4) + +-IplParameterBlock iplb __attribute__((aligned(PAGE_SIZE))); + static char cfgbuf[2048]; + +-static SubChannelId net_schid = { .one = 1 }; ++SubChannelId net_schid = { .one = 1 }; + static uint8_t mac[6]; + static uint64_t dest_timer; + +@@ -438,15 +436,6 @@ static int net_try_direct_tftp_load(filename_ip_t *fn_ip) + return rc; + } + +-void write_subsystem_identification(void) +-{ +- SubChannelId *schid = (SubChannelId *) 184; +- uint32_t *zeroes = (uint32_t *) 188; +- +- *schid = net_schid; +- *zeroes = 0; +-} +- + static bool find_net_dev(Schib *schib, int dev_no) + { + int i, r; +@@ -509,7 +498,7 @@ static void virtio_setup(void) + IPL_assert(found, "No virtio net device found"); + } + +-void main(void) ++void netmain(void) + { + filename_ip_t fn_ip; + int rc, fnlen; +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index 6f6d95d170..6abb34e563 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -55,6 +55,9 @@ void write_iplb_location(void); + unsigned int get_loadparm_index(void); + void main(void); + ++/* netmain.c */ ++void netmain(void); ++ + /* sclp.c */ + void sclp_print(const char *string); + void sclp_set_write_mask(uint32_t receive_mask, uint32_t send_mask); +diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h +index 85bd9d1695..6f9a558ff5 100644 +--- a/pc-bios/s390-ccw/virtio.h ++++ b/pc-bios/s390-ccw/virtio.h +@@ -253,7 +253,6 @@ struct VDev { + uint8_t scsi_dev_heads; + bool scsi_device_selected; + ScsiDevice selected_scsi_device; +- uint64_t netboot_start_addr; + uint32_t max_transfer; + uint32_t guest_features[2]; + }; +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Merge-netboot.mak-into-the-main-Mak.patch b/kvm-pc-bios-s390-ccw-Merge-netboot.mak-into-the-main-Mak.patch new file mode 100644 index 0000000..9e35834 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Merge-netboot.mak-into-the-main-Mak.patch @@ -0,0 +1,141 @@ +From 053fe7407d61ea7f885ae3a75b8dff18712e97fc Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 21 Jun 2024 09:40:11 +0200 +Subject: [PATCH 06/27] pc-bios/s390-ccw: Merge netboot.mak into the main + Makefile +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [6/23] a0f3671677000e9bf00557df773fd72d9f9768a7 (thuth/qemu-kvm-cs9) + +Now that the netboot code has been merged into the main s390-ccw.img, +it also does not make sense to keep the build rules in a separate +file. Thus let's merge netboot.mak into the main Makefile. + +Message-Id: <20240621082422.136217-7-thuth@redhat.com> +Signed-off-by: Thomas Huth +(cherry picked from commit f1fdadda36f73c9a4a96f92deb3062528cd12acc) +--- + pc-bios/s390-ccw/Makefile | 47 +++++++++++++++++++++++++++++++++++- + pc-bios/s390-ccw/netboot.mak | 45 ---------------------------------- + 2 files changed, 46 insertions(+), 46 deletions(-) + delete mode 100644 pc-bios/s390-ccw/netboot.mak + +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index cf6859823a..27cbb354af 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -61,7 +61,52 @@ config-cc.mak: Makefile + $(call cc-option,-march=z900,-march=z10)) 3> config-cc.mak + -include config-cc.mak + +-include $(SRC_PATH)/netboot.mak ++# libc files: ++ ++LIBC_CFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ ++ -MMD -MP -MT $@ -MF $(@:%.o=%.d) ++ ++CTYPE_OBJS = isdigit.o isxdigit.o toupper.o ++%.o : $(SLOF_DIR)/lib/libc/ctype/%.c ++ $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) ++ ++STRING_OBJS = strcat.o strchr.o strrchr.o strcpy.o strlen.o strncpy.o \ ++ strcmp.o strncmp.o strcasecmp.o strncasecmp.o strstr.o \ ++ memset.o memcpy.o memmove.o memcmp.o ++%.o : $(SLOF_DIR)/lib/libc/string/%.c ++ $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) ++ ++STDLIB_OBJS = atoi.o atol.o strtoul.o strtol.o rand.o malloc.o free.o ++%.o : $(SLOF_DIR)/lib/libc/stdlib/%.c ++ $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) ++ ++STDIO_OBJS = sprintf.o snprintf.o vfprintf.o vsnprintf.o vsprintf.o fprintf.o \ ++ printf.o putc.o puts.o putchar.o stdchnls.o fileno.o ++%.o : $(SLOF_DIR)/lib/libc/stdio/%.c ++ $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) ++ ++sbrk.o: $(SLOF_DIR)/slof/sbrk.c ++ $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) ++ ++LIBCOBJS := $(STRING_OBJS) $(CTYPE_OBJS) $(STDLIB_OBJS) $(STDIO_OBJS) sbrk.o ++ ++libc.a: $(LIBCOBJS) ++ $(call quiet-command,$(AR) -rc $@ $^,Creating static library) ++ ++# libnet files: ++ ++LIBNETOBJS := args.o dhcp.o dns.o icmpv6.o ipv6.o tcp.o udp.o bootp.o \ ++ dhcpv6.o ethernet.o ipv4.o ndp.o tftp.o pxelinux.o ++LIBNETCFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ ++ -DDHCPARCH=0x1F -MMD -MP -MT $@ -MF $(@:%.o=%.d) ++ ++%.o : $(SLOF_DIR)/lib/libnet/%.c ++ $(call quiet-command,$(CC) $(LIBNETCFLAGS) -c -o $@ $<,Compiling) ++ ++libnet.a: $(LIBNETOBJS) ++ $(call quiet-command,$(AR) -rc $@ $^,Creating static library) ++ ++# Main targets: + + build-all: s390-ccw.img + +diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak +deleted file mode 100644 +index 0a24257ff4..0000000000 +--- a/pc-bios/s390-ccw/netboot.mak ++++ /dev/null +@@ -1,45 +0,0 @@ +- +-# libc files: +- +-LIBC_CFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ +- -MMD -MP -MT $@ -MF $(@:%.o=%.d) +- +-CTYPE_OBJS = isdigit.o isxdigit.o toupper.o +-%.o : $(SLOF_DIR)/lib/libc/ctype/%.c +- $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) +- +-STRING_OBJS = strcat.o strchr.o strrchr.o strcpy.o strlen.o strncpy.o \ +- strcmp.o strncmp.o strcasecmp.o strncasecmp.o strstr.o \ +- memset.o memcpy.o memmove.o memcmp.o +-%.o : $(SLOF_DIR)/lib/libc/string/%.c +- $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) +- +-STDLIB_OBJS = atoi.o atol.o strtoul.o strtol.o rand.o malloc.o free.o +-%.o : $(SLOF_DIR)/lib/libc/stdlib/%.c +- $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) +- +-STDIO_OBJS = sprintf.o snprintf.o vfprintf.o vsnprintf.o vsprintf.o fprintf.o \ +- printf.o putc.o puts.o putchar.o stdchnls.o fileno.o +-%.o : $(SLOF_DIR)/lib/libc/stdio/%.c +- $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) +- +-sbrk.o: $(SLOF_DIR)/slof/sbrk.c +- $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) +- +-LIBCOBJS := $(STRING_OBJS) $(CTYPE_OBJS) $(STDLIB_OBJS) $(STDIO_OBJS) sbrk.o +- +-libc.a: $(LIBCOBJS) +- $(call quiet-command,$(AR) -rc $@ $^,Creating static library) +- +-# libnet files: +- +-LIBNETOBJS := args.o dhcp.o dns.o icmpv6.o ipv6.o tcp.o udp.o bootp.o \ +- dhcpv6.o ethernet.o ipv4.o ndp.o tftp.o pxelinux.o +-LIBNETCFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ +- -DDHCPARCH=0x1F -MMD -MP -MT $@ -MF $(@:%.o=%.d) +- +-%.o : $(SLOF_DIR)/lib/libnet/%.c +- $(call quiet-command,$(CC) $(LIBNETCFLAGS) -c -o $@ $<,Compiling) +- +-libnet.a: $(LIBNETOBJS) +- $(call quiet-command,$(AR) -rc $@ $^,Creating static library) +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Remove-panics-from-DASD-IPL-path.patch b/kvm-pc-bios-s390-ccw-Remove-panics-from-DASD-IPL-path.patch new file mode 100644 index 0000000..5e0fd94 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Remove-panics-from-DASD-IPL-path.patch @@ -0,0 +1,177 @@ +From 032b512a919662ce65b173416815e29e8f5fb904 Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:44 -0400 +Subject: [PATCH 11/27] pc-bios/s390-ccw: Remove panics from DASD IPL path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [11/23] 941e1e76db8d35a6ad6ca2e2a401e2ac122efd09 (thuth/qemu-kvm-cs9) + +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 +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-11-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 1d5c7f078e938e6844f404429dd70bc52b39dac6) +--- + pc-bios/s390-ccw/dasd-ipl.c | 66 ++++++++++++++++++++----------------- + pc-bios/s390-ccw/dasd-ipl.h | 2 +- + 2 files changed, 37 insertions(+), 31 deletions(-) + +diff --git a/pc-bios/s390-ccw/dasd-ipl.c b/pc-bios/s390-ccw/dasd-ipl.c +index ae751adec1..babece95ea 100644 +--- a/pc-bios/s390-ccw/dasd-ipl.c ++++ b/pc-bios/s390-ccw/dasd-ipl.c +@@ -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; + } +diff --git a/pc-bios/s390-ccw/dasd-ipl.h b/pc-bios/s390-ccw/dasd-ipl.h +index c394828906..eb1898c84a 100644 +--- a/pc-bios/s390-ccw/dasd-ipl.h ++++ b/pc-bios/s390-ccw/dasd-ipl.h +@@ -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 */ +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Remove-panics-from-ECKD-IPL-path.patch b/kvm-pc-bios-s390-ccw-Remove-panics-from-ECKD-IPL-path.patch new file mode 100644 index 0000000..fa854a1 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Remove-panics-from-ECKD-IPL-path.patch @@ -0,0 +1,475 @@ +From 237d714205394102a4cd60eeeddc12b98bfbfa3f Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:42 -0400 +Subject: [PATCH 09/27] pc-bios/s390-ccw: Remove panics from ECKD IPL path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [9/23] 1e6ecba95979a5bc12bd74c1b0bc631ccfbd57ec (thuth/qemu-kvm-cs9) + +Remove panic-on-error from ECKD block device 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 +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-9-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 806315279d5c629e1cc3a945bcfba3fe5482d84b) +--- + pc-bios/s390-ccw/bootmap.c | 187 +++++++++++++++++++++++++------------ + pc-bios/s390-ccw/bootmap.h | 1 + + 2 files changed, 130 insertions(+), 58 deletions(-) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index af73254acb..b9596e28c7 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -145,14 +145,17 @@ static block_number_t load_eckd_segments(block_number_t blk, bool ldipl, + bool more_data; + + memset(_bprs, FREE_SPACE_FILLER, sizeof(_bprs)); +- read_block(blk, bprs, "BPRS read failed"); ++ if (virtio_read(blk, bprs)) { ++ puts("BPRS read failed"); ++ return ERROR_BLOCK_NR; ++ } + + do { + more_data = false; + for (j = 0;; j++) { + block_nr = gen_eckd_block_num(&bprs[j].xeckd, ldipl); + if (is_null_block_number(block_nr)) { /* end of chunk */ +- break; ++ return NULL_BLOCK_NR; + } + + /* we need the updated blockno for the next indirect entry +@@ -163,15 +166,20 @@ static block_number_t load_eckd_segments(block_number_t blk, bool ldipl, + } + + /* List directed pointer does not store block size */ +- IPL_assert(ldipl || block_size_ok(bprs[j].xeckd.bptr.size), +- "bad chunk block size"); ++ if (!ldipl && !block_size_ok(bprs[j].xeckd.bptr.size)) { ++ puts("Bad chunk block size"); ++ return ERROR_BLOCK_NR; ++ } + + if (!eckd_valid_address(&bprs[j].xeckd, ldipl)) { + /* + * If an invalid address is found during LD-IPL then break and +- * retry as CCW ++ * retry as CCW-IPL, otherwise abort on error + */ +- IPL_assert(ldipl, "bad chunk ECKD addr"); ++ if (!ldipl) { ++ puts("Bad chunk ECKD address"); ++ return ERROR_BLOCK_NR; ++ } + break; + } + +@@ -189,7 +197,10 @@ static block_number_t load_eckd_segments(block_number_t blk, bool ldipl, + * I.e. the next ptr must point to the unused memory area + */ + memset(_bprs, FREE_SPACE_FILLER, sizeof(_bprs)); +- read_block(block_nr, bprs, "BPRS continuation read failed"); ++ if (virtio_read(block_nr, bprs)) { ++ puts("BPRS continuation read failed"); ++ return ERROR_BLOCK_NR; ++ } + more_data = true; + break; + } +@@ -198,7 +209,10 @@ static block_number_t load_eckd_segments(block_number_t blk, bool ldipl, + * to memory (address). + */ + rc = virtio_read_many(block_nr, (void *)(*address), count + 1); +- IPL_assert(rc == 0, "code chunk read failed"); ++ if (rc != 0) { ++ puts("Code chunk read failed"); ++ return ERROR_BLOCK_NR; ++ } + + *address += (count + 1) * virtio_get_block_size(); + } +@@ -232,7 +246,10 @@ static int eckd_get_boot_menu_index(block_number_t s1b_block_nr) + + /* Get Stage1b data */ + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); +- read_block(s1b_block_nr, s1b, "Cannot read stage1b boot loader"); ++ if (virtio_read(s1b_block_nr, s1b)) { ++ puts("Cannot read stage1b boot loader"); ++ return -EIO; ++ } + + memset(_s2, FREE_SPACE_FILLER, sizeof(_s2)); + +@@ -244,7 +261,10 @@ static int eckd_get_boot_menu_index(block_number_t s1b_block_nr) + break; + } + +- read_block(cur_block_nr, s2_cur_blk, "Cannot read stage2 boot loader"); ++ if (virtio_read(cur_block_nr, s2_cur_blk)) { ++ puts("Cannot read stage2 boot loader"); ++ return -EIO; ++ } + + if (find_zipl_boot_menu_banner(&banner_offset)) { + /* +@@ -252,8 +272,10 @@ static int eckd_get_boot_menu_index(block_number_t s1b_block_nr) + * possibility of menu data spanning multiple blocks. + */ + if (prev_block_nr) { +- read_block(prev_block_nr, s2_prev_blk, +- "Cannot read stage2 boot loader"); ++ if (virtio_read(prev_block_nr, s2_prev_blk)) { ++ puts("Cannot read stage2 boot loader"); ++ return -EIO; ++ } + } + + if (i + 1 < STAGE2_BLK_CNT_MAX) { +@@ -261,8 +283,10 @@ static int eckd_get_boot_menu_index(block_number_t s1b_block_nr) + } + + if (next_block_nr && !is_null_block_number(next_block_nr)) { +- read_block(next_block_nr, s2_next_blk, +- "Cannot read stage2 boot loader"); ++ if (virtio_read(next_block_nr, s2_next_blk)) { ++ puts("Cannot read stage2 boot loader"); ++ return -EIO; ++ } + } + + return menu_get_zipl_boot_index(s2_cur_blk + banner_offset); +@@ -275,7 +299,7 @@ static int eckd_get_boot_menu_index(block_number_t s1b_block_nr) + return 0; + } + +-static void run_eckd_boot_script(block_number_t bmt_block_nr, ++static int run_eckd_boot_script(block_number_t bmt_block_nr, + block_number_t s1b_block_nr) + { + int i; +@@ -292,17 +316,28 @@ static void run_eckd_boot_script(block_number_t bmt_block_nr, + } + + debug_print_int("loadparm", loadparm); +- IPL_assert(loadparm < MAX_BOOT_ENTRIES, "loadparm value greater than" +- " maximum number of boot entries allowed"); ++ if (loadparm >= MAX_BOOT_ENTRIES) { ++ puts("loadparm value greater than max number of boot entries allowed"); ++ return -EINVAL; ++ } + + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); +- read_block(bmt_block_nr, sec, "Cannot read Boot Map Table"); ++ if (virtio_read(bmt_block_nr, sec)) { ++ puts("Cannot read Boot Map Table"); ++ return -EIO; ++ } + + block_nr = gen_eckd_block_num(&bmt->entry[loadparm].xeckd, ldipl); +- IPL_assert(block_nr != -1, "Cannot find Boot Map Table Entry"); ++ if (block_nr == NULL_BLOCK_NR) { ++ puts("Cannot find Boot Map Table Entry"); ++ return -EIO; ++ } + + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); +- read_block(block_nr, sec, "Cannot read Boot Map Script"); ++ if (virtio_read(block_nr, sec)) { ++ puts("Cannot read Boot Map Script"); ++ return -EIO; ++ } + + for (i = 0; bms->entry[i].type == BOOT_SCRIPT_LOAD || + bms->entry[i].type == BOOT_SCRIPT_SIGNATURE; i++) { +@@ -317,21 +352,27 @@ static void run_eckd_boot_script(block_number_t bmt_block_nr, + + do { + block_nr = load_eckd_segments(block_nr, ldipl, &address); +- } while (block_nr != -1); ++ if (block_nr == ERROR_BLOCK_NR) { ++ return ldipl ? 0 : -EIO; ++ } ++ } while (block_nr != NULL_BLOCK_NR); + } + + if (ldipl && bms->entry[i].type != BOOT_SCRIPT_EXEC) { + /* Abort LD-IPL and retry as CCW-IPL */ +- return; ++ return 0; + } + +- IPL_assert(bms->entry[i].type == BOOT_SCRIPT_EXEC, +- "Unknown script entry type"); ++ if (bms->entry[i].type != BOOT_SCRIPT_EXEC) { ++ puts("Unknown script entry type"); ++ return -EINVAL; ++ } + write_reset_psw(bms->entry[i].address.load_address); /* no return */ + jump_to_IPL_code(0); /* no return */ ++ return -1; + } + +-static void ipl_eckd_cdl(void) ++static int ipl_eckd_cdl(void) + { + XEckdMbr *mbr; + EckdCdlIpl2 *ipl2 = (void *)sec; +@@ -342,20 +383,23 @@ static void ipl_eckd_cdl(void) + puts("CDL"); + + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); +- read_block(1, ipl2, "Cannot read IPL2 record at block 1"); ++ if (virtio_read(1, ipl2)) { ++ puts("Cannot read IPL2 record at block 1"); ++ return -EIO; ++ } + + mbr = &ipl2->mbr; + if (!magic_match(mbr, ZIPL_MAGIC)) { + puts("No zIPL section in IPL2 record."); +- return; ++ return 0; + } + if (!block_size_ok(mbr->blockptr.xeckd.bptr.size)) { + puts("Bad block size in zIPL section of IPL2 record."); +- return; ++ return 0; + } + if (mbr->dev_type != DEV_TYPE_ECKD) { + puts("Non-ECKD device type in zIPL section of IPL2 record."); +- return; ++ return 0; + } + + /* save pointer to Boot Map Table */ +@@ -365,19 +409,21 @@ static void ipl_eckd_cdl(void) + s1b_block_nr = eckd_block_num(&ipl2->stage1.seek[0].chs); + + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); +- read_block(2, vlbl, "Cannot read Volume Label at block 2"); ++ if (virtio_read(2, vlbl)) { ++ puts("Cannot read Volume Label at block 2"); ++ return -EIO; ++ } + if (!magic_match(vlbl->key, VOL1_MAGIC)) { + puts("Invalid magic of volume label block."); +- return; ++ return 0; + } + if (!magic_match(vlbl->f.key, VOL1_MAGIC)) { + puts("Invalid magic of volser block."); +- return; ++ return 0; + } + print_volser(vlbl->f.volser); + +- run_eckd_boot_script(bmt_block_nr, s1b_block_nr); +- /* no return */ ++ return run_eckd_boot_script(bmt_block_nr, s1b_block_nr); + } + + static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode) +@@ -403,7 +449,7 @@ static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode) + print_volser(vlbl->volser); + } + +-static void ipl_eckd_ldl(ECKD_IPL_mode_t mode) ++static int ipl_eckd_ldl(ECKD_IPL_mode_t mode) + { + block_number_t bmt_block_nr, s1b_block_nr; + EckdLdlIpl1 *ipl1 = (void *)sec; +@@ -415,10 +461,13 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode) + /* DO NOT read BootMap pointer (only one, xECKD) at block #2 */ + + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); +- read_block(0, sec, "Cannot read block 0 to grab boot info."); ++ if (virtio_read(0, sec)) { ++ puts("Cannot read block 0 to grab boot info."); ++ return -EIO; ++ } + if (mode == ECKD_LDL_UNLABELED) { + if (!magic_match(ipl1->bip.magic, ZIPL_MAGIC)) { +- return; /* not applicable layout */ ++ return 0; /* not applicable layout */ + } + puts("unlabeled LDL."); + } +@@ -430,8 +479,7 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode) + /* save pointer to Stage1b Data */ + s1b_block_nr = eckd_block_num(&ipl1->stage1.seek[0].chs); + +- run_eckd_boot_script(bmt_block_nr, s1b_block_nr); +- /* no return */ ++ return run_eckd_boot_script(bmt_block_nr, s1b_block_nr); + } + + static block_number_t eckd_find_bmt(ExtEckdBlockPtr *ptr) +@@ -441,7 +489,10 @@ static block_number_t eckd_find_bmt(ExtEckdBlockPtr *ptr) + BootRecord *br; + + blockno = gen_eckd_block_num(ptr, 0); +- read_block(blockno, tmp_sec, "Cannot read boot record"); ++ if (virtio_read(blockno, tmp_sec)) { ++ puts("Cannot read boot record"); ++ return ERROR_BLOCK_NR; ++ } + br = (BootRecord *)tmp_sec; + if (!magic_match(br->magic, ZIPL_MAGIC)) { + /* If the boot record is invalid, return and try CCW-IPL instead */ +@@ -470,7 +521,7 @@ static void print_eckd_msg(void) + printf("%s", msg); + } + +-static void ipl_eckd(void) ++static int ipl_eckd(void) + { + IplVolumeLabel *vlbl = (void *)sec; + LDL_VTOC *vtoc = (void *)sec; +@@ -480,7 +531,10 @@ static void ipl_eckd(void) + + /* Block 2 can contain either the CDL VOL1 label or the LDL VTOC */ + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); +- read_block(2, vlbl, "Cannot read block 2"); ++ if (virtio_read(2, vlbl)) { ++ puts("Cannot read block 2"); ++ return -EIO; ++ } + + /* + * First check for a list-directed-format pointer which would +@@ -488,36 +542,53 @@ static void ipl_eckd(void) + */ + if (eckd_valid_address((ExtEckdBlockPtr *)&vlbl->f.br, 0)) { + ldipl_bmt = eckd_find_bmt((ExtEckdBlockPtr *)&vlbl->f.br); +- if (ldipl_bmt) { ++ switch (ldipl_bmt) { ++ case ERROR_BLOCK_NR: ++ return -EIO; ++ case NULL_BLOCK_NR: ++ break; /* Invalid BMT but the device may still boot with CCW-IPL */ ++ default: + puts("List-Directed"); +- /* LD-IPL does not use the S1B bock, just make it NULL */ +- run_eckd_boot_script(ldipl_bmt, NULL_BLOCK_NR); +- /* Only return in error, retry as CCW-IPL */ ++ /* ++ * LD-IPL does not use the S1B bock, just make it NULL_BLOCK_NR. ++ * In some failure cases retry IPL before aborting. ++ */ ++ if (run_eckd_boot_script(ldipl_bmt, NULL_BLOCK_NR)) { ++ return -EIO; ++ } ++ /* Non-fatal error, retry as CCW-IPL */ + printf("Retrying IPL "); + print_eckd_msg(); + } + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); +- read_block(2, vtoc, "Cannot read block 2"); ++ if (virtio_read(2, vtoc)) { ++ puts("Cannot read block 2"); ++ return -EIO; ++ } + } + + /* Not list-directed */ + if (magic_match(vtoc->magic, VOL1_MAGIC)) { +- ipl_eckd_cdl(); /* may return in error */ ++ if (ipl_eckd_cdl()) { ++ return -1; ++ } + } + + if (magic_match(vtoc->magic, CMS1_MAGIC)) { +- ipl_eckd_ldl(ECKD_CMS); /* no return */ ++ return ipl_eckd_ldl(ECKD_CMS); + } + if (magic_match(vtoc->magic, LNX1_MAGIC)) { +- ipl_eckd_ldl(ECKD_LDL); /* no return */ ++ return ipl_eckd_ldl(ECKD_LDL); + } + +- ipl_eckd_ldl(ECKD_LDL_UNLABELED); /* it still may return */ ++ if (ipl_eckd_ldl(ECKD_LDL_UNLABELED)) { ++ return -1; ++ } + /* + * Ok, it is not a LDL by any means. + * It still might be a CDL with zero record keys for IPL1 and IPL2 + */ +- ipl_eckd_cdl(); ++ return ipl_eckd_cdl(); + } + + /*********************************************************************** +@@ -910,7 +981,7 @@ static bool has_iso_signature(void) + * Bus specific IPL sequences + */ + +-static void zipl_load_vblk(void) ++static int zipl_load_vblk(void) + { + int blksize = virtio_get_block_size(); + +@@ -919,7 +990,7 @@ static void zipl_load_vblk(void) + virtio_assume_iso9660(); + } + if (ipl_iso_el_torito()) { +- return; ++ return 0; + } + } + +@@ -927,21 +998,21 @@ static void zipl_load_vblk(void) + puts("Using guessed DASD geometry."); + virtio_assume_eckd(); + } +- ipl_eckd(); ++ return ipl_eckd(); + } + +-static void zipl_load_vscsi(void) ++static int zipl_load_vscsi(void) + { + if (virtio_get_block_size() == VIRTIO_ISO_BLOCK_SIZE) { + /* Is it an ISO image in non-CD drive? */ + if (ipl_iso_el_torito()) { +- return; ++ return 0; + } + } + + puts("Using guessed DASD geometry."); + virtio_assume_eckd(); +- ipl_eckd(); ++ return ipl_eckd(); + } + + /*********************************************************************** +diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h +index 3cb573b86b..95943441d3 100644 +--- a/pc-bios/s390-ccw/bootmap.h ++++ b/pc-bios/s390-ccw/bootmap.h +@@ -16,6 +16,7 @@ + + typedef uint64_t block_number_t; + #define NULL_BLOCK_NR 0xffffffffffffffffULL ++#define ERROR_BLOCK_NR 0xfffffffffffffffeULL + + #define FREE_SPACE_FILLER '\xAA' + +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Remove-panics-from-ISO-IPL-path.patch b/kvm-pc-bios-s390-ccw-Remove-panics-from-ISO-IPL-path.patch new file mode 100644 index 0000000..0304180 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Remove-panics-from-ISO-IPL-path.patch @@ -0,0 +1,269 @@ +From b850578315ad498d581d8f09c9dfcd0d1dea1a5e Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:41 -0400 +Subject: [PATCH 08/27] pc-bios/s390-ccw: Remove panics from ISO IPL path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [8/23] 92ab09f2df4bcdc721aca11c4a75439ebd72212c (thuth/qemu-kvm-cs9) + +Remove panic-on-error from IPL ISO El Torito 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 +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-8-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit bef2b8dd1a36fc79cabcda48e667f2cba476924c) +--- + pc-bios/s390-ccw/bootmap.c | 87 ++++++++++++++++++++++++------------- + pc-bios/s390-ccw/bootmap.h | 15 +++---- + pc-bios/s390-ccw/s390-ccw.h | 1 + + 3 files changed, 65 insertions(+), 38 deletions(-) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index 414c3f1b47..af73254acb 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -678,8 +678,10 @@ static bool is_iso_bc_entry_compatible(IsoBcSection *s) + if (s->unused || !s->sector_count) { + return false; + } +- read_iso_sector(bswap32(s->load_rba), magic_sec, +- "Failed to read image sector 0"); ++ if (virtio_read(bswap32(s->load_rba), magic_sec)) { ++ puts("Failed to read image sector 0"); ++ return false; ++ } + + /* Checking bytes 8 - 32 for S390 Linux magic */ + return !memcmp(magic_sec + 8, linux_s390_magic, 24); +@@ -692,28 +694,35 @@ static uint32_t sec_offset[ISO9660_MAX_DIR_DEPTH]; + /* Remained directory space in bytes */ + static uint32_t dir_rem[ISO9660_MAX_DIR_DEPTH]; + +-static inline uint32_t iso_get_file_size(uint32_t load_rba) ++static inline long iso_get_file_size(uint32_t load_rba) + { + IsoVolDesc *vd = (IsoVolDesc *)sec; + IsoDirHdr *cur_record = &vd->vd.primary.rootdir; + uint8_t *temp = sec + ISO_SECTOR_SIZE; + int level = 0; + +- read_iso_sector(ISO_PRIMARY_VD_SECTOR, sec, +- "Failed to read ISO primary descriptor"); ++ if (virtio_read(ISO_PRIMARY_VD_SECTOR, sec)) { ++ puts("Failed to read ISO primary descriptor"); ++ return -EIO; ++ } ++ + sec_loc[0] = iso_733_to_u32(cur_record->ext_loc); + dir_rem[0] = 0; + sec_offset[0] = 0; + + while (level >= 0) { +- IPL_assert(sec_offset[level] <= ISO_SECTOR_SIZE, +- "Directory tree structure violation"); ++ if (sec_offset[level] > ISO_SECTOR_SIZE) { ++ puts("Directory tree structure violation"); ++ return -EIO; ++ } + + cur_record = (IsoDirHdr *)(temp + sec_offset[level]); + + if (sec_offset[level] == 0) { +- read_iso_sector(sec_loc[level], temp, +- "Failed to read ISO directory"); ++ if (virtio_read(sec_loc[level], temp)) { ++ puts("Failed to read ISO directory"); ++ return -EIO; ++ } + if (dir_rem[level] == 0) { + /* Skip self and parent records */ + dir_rem[level] = iso_733_to_u32(cur_record->data_len) - +@@ -758,8 +767,10 @@ static inline uint32_t iso_get_file_size(uint32_t load_rba) + if (dir_rem[level] == 0) { + /* Nothing remaining */ + level--; +- read_iso_sector(sec_loc[level], temp, +- "Failed to read ISO directory"); ++ if (virtio_read(sec_loc[level], temp)) { ++ puts("Failed to read ISO directory"); ++ return -EIO; ++ } + } + } + +@@ -774,19 +785,24 @@ static void load_iso_bc_entry(IsoBcSection *load) + * is padded and ISO_SECTOR_SIZE bytes aligned + */ + uint32_t blks_to_load = bswap16(s.sector_count) >> ET_SECTOR_SHIFT; +- uint32_t real_size = iso_get_file_size(bswap32(s.load_rba)); ++ long real_size = iso_get_file_size(bswap32(s.load_rba)); + +- if (real_size) { ++ if (real_size > 0) { + /* Round up blocks to load */ + blks_to_load = (real_size + ISO_SECTOR_SIZE - 1) / ISO_SECTOR_SIZE; + puts("ISO boot image size verified"); + } else { + puts("ISO boot image size could not be verified"); ++ if (real_size < 0) { ++ return; ++ } + } + +- read_iso_boot_image(bswap32(s.load_rba), ++ if (read_iso_boot_image(bswap32(s.load_rba), + (void *)((uint64_t)bswap16(s.load_segment)), +- blks_to_load); ++ blks_to_load)) { ++ return; ++ } + + jump_to_low_kernel(); + } +@@ -809,17 +825,18 @@ static uint32_t find_iso_bc(void) + return bswap32(et->bc_offset); + } + } +- read_iso_sector(block_num++, sec, +- "Failed to read ISO volume descriptor"); ++ if (virtio_read(block_num++, sec)) { ++ puts("Failed to read ISO volume descriptor"); ++ return 0; ++ } + } + + return 0; + } + +-static IsoBcSection *find_iso_bc_entry(void) ++static IsoBcSection *find_iso_bc_entry(uint32_t offset) + { + IsoBcEntry *e = (IsoBcEntry *)sec; +- uint32_t offset = find_iso_bc(); + int i; + unsigned int loadparm = get_loadparm_index(); + +@@ -827,11 +844,13 @@ static IsoBcSection *find_iso_bc_entry(void) + return NULL; + } + +- read_iso_sector(offset, sec, "Failed to read El Torito boot catalog"); ++ if (virtio_read(offset, sec)) { ++ puts("Failed to read El Torito boot catalog"); ++ return NULL; ++ } + + if (!is_iso_bc_valid(e)) { + /* The validation entry is mandatory */ +- panic("No valid boot catalog found!\n"); + return NULL; + } + +@@ -851,19 +870,25 @@ static IsoBcSection *find_iso_bc_entry(void) + } + } + +- panic("No suitable boot entry found on ISO-9660 media!\n"); +- + return NULL; + } + +-static void ipl_iso_el_torito(void) ++static int ipl_iso_el_torito(void) + { +- IsoBcSection *s = find_iso_bc_entry(); ++ uint32_t offset = find_iso_bc(); ++ if (!offset) { ++ return 0; ++ } ++ ++ IsoBcSection *s = find_iso_bc_entry(offset); + + if (s) { +- load_iso_bc_entry(s); +- /* no return */ ++ load_iso_bc_entry(s); /* only return in error */ ++ return -1; + } ++ ++ puts("No suitable boot entry found on ISO-9660 media!"); ++ return -EIO; + } + + /** +@@ -893,7 +918,9 @@ static void zipl_load_vblk(void) + if (blksize != VIRTIO_ISO_BLOCK_SIZE) { + virtio_assume_iso9660(); + } +- ipl_iso_el_torito(); ++ if (ipl_iso_el_torito()) { ++ return; ++ } + } + + if (blksize != VIRTIO_DASD_DEFAULT_BLOCK_SIZE) { +@@ -907,7 +934,9 @@ static void zipl_load_vscsi(void) + { + if (virtio_get_block_size() == VIRTIO_ISO_BLOCK_SIZE) { + /* Is it an ISO image in non-CD drive? */ +- ipl_iso_el_torito(); ++ if (ipl_iso_el_torito()) { ++ return; ++ } + } + + puts("Using guessed DASD geometry."); +diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h +index 4a7d8a91f1..3cb573b86b 100644 +--- a/pc-bios/s390-ccw/bootmap.h ++++ b/pc-bios/s390-ccw/bootmap.h +@@ -385,17 +385,14 @@ static inline uint32_t iso_733_to_u32(uint64_t x) + + #define ISO_PRIMARY_VD_SECTOR 16 + +-static inline void read_iso_sector(uint32_t block_offset, void *buf, +- const char *errmsg) +-{ +- IPL_assert(virtio_read_many(block_offset, buf, 1) == 0, errmsg); +-} +- +-static inline void read_iso_boot_image(uint32_t block_offset, void *load_addr, ++static inline int read_iso_boot_image(uint32_t block_offset, void *load_addr, + uint32_t blks_to_load) + { +- IPL_assert(virtio_read_many(block_offset, load_addr, blks_to_load) == 0, +- "Failed to read boot image!"); ++ if (virtio_read_many(block_offset, load_addr, blks_to_load)) { ++ puts("Failed to read boot image!"); ++ return -1; ++ } ++ return 0; + } + + #define ISO9660_MAX_DIR_DEPTH 8 +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index 6abb34e563..3e844abd71 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -30,6 +30,7 @@ typedef unsigned long long u64; + #define EIO 1 + #define EBUSY 2 + #define ENODEV 3 ++#define EINVAL 4 + + #ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Remove-panics-from-Netboot-IPL-path.patch b/kvm-pc-bios-s390-ccw-Remove-panics-from-Netboot-IPL-path.patch new file mode 100644 index 0000000..6507ce1 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Remove-panics-from-Netboot-IPL-path.patch @@ -0,0 +1,130 @@ +From e572d55c45c5c84e386034b0f853476326a08197 Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:45 -0400 +Subject: [PATCH 12/27] pc-bios/s390-ccw: Remove panics from Netboot IPL path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [12/23] dd193b7e37849dc338d66ac40786e22ff050ae20 (thuth/qemu-kvm-cs9) + +Remove panic-on-error from Netboot 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 +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-12-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit f1a2a6e41ef76e02ddc5ede3dd042ef96b4fb8d2) +--- + pc-bios/s390-ccw/bootmap.c | 1 + + pc-bios/s390-ccw/netmain.c | 17 +++++++++++------ + pc-bios/s390-ccw/s390-ccw.h | 2 +- + pc-bios/s390-ccw/virtio-net.c | 7 +++++-- + 4 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index 652807a16a..95ef9104d0 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -1072,6 +1072,7 @@ void zipl_load(void) + + if (virtio_get_device_type() == VIRTIO_ID_NET) { + netmain(); ++ panic("\n! Cannot IPL from this network !\n"); + } + + if (ipl_scsi()) { +diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c +index bc6ad8695f..d1a6c9a91c 100644 +--- a/pc-bios/s390-ccw/netmain.c ++++ b/pc-bios/s390-ccw/netmain.c +@@ -464,7 +464,7 @@ static bool find_net_dev(Schib *schib, int dev_no) + return false; + } + +-static void virtio_setup(void) ++static bool virtio_setup(void) + { + Schib schib; + int ssid; +@@ -495,10 +495,10 @@ static void virtio_setup(void) + } + } + +- IPL_assert(found, "No virtio net device found"); ++ return found; + } + +-void netmain(void) ++int netmain(void) + { + filename_ip_t fn_ip; + int rc, fnlen; +@@ -506,11 +506,15 @@ void netmain(void) + sclp_setup(); + puts("Network boot starting..."); + +- virtio_setup(); ++ if (!virtio_setup()) { ++ puts("No virtio net device found."); ++ return -1; ++ } + + rc = net_init(&fn_ip); + if (rc) { +- panic("Network initialization failed. Halting."); ++ puts("Network initialization failed."); ++ return -1; + } + + fnlen = strlen(fn_ip.filename); +@@ -528,5 +532,6 @@ void netmain(void) + jump_to_low_kernel(); + } + +- panic("Failed to load OS from network."); ++ puts("Failed to load OS from network."); ++ return -1; + } +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index 3e844abd71..344ad15655 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -57,7 +57,7 @@ unsigned int get_loadparm_index(void); + void main(void); + + /* netmain.c */ +-void netmain(void); ++int netmain(void); + + /* sclp.c */ + void sclp_print(const char *string); +diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c +index 2fcb0a58c5..f9854a22c3 100644 +--- a/pc-bios/s390-ccw/virtio-net.c ++++ b/pc-bios/s390-ccw/virtio-net.c +@@ -54,8 +54,11 @@ int virtio_net_init(void *mac_addr) + vdev->guest_features[0] = VIRTIO_NET_F_MAC_BIT; + virtio_setup_ccw(vdev); + +- IPL_assert(vdev->guest_features[0] & VIRTIO_NET_F_MAC_BIT, +- "virtio-net device does not support the MAC address feature"); ++ if (!(vdev->guest_features[0] & VIRTIO_NET_F_MAC_BIT)) { ++ puts("virtio-net device does not support the MAC address feature"); ++ return -1; ++ } ++ + memcpy(mac_addr, vdev->config.net.mac, ETH_ALEN); + + for (i = 0; i < 64; i++) { +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Remove-panics-from-SCSI-IPL-path.patch b/kvm-pc-bios-s390-ccw-Remove-panics-from-SCSI-IPL-path.patch new file mode 100644 index 0000000..2d4fba4 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Remove-panics-from-SCSI-IPL-path.patch @@ -0,0 +1,554 @@ +From 23033a524625ad13448eda28d429d9265b213a7f Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:43 -0400 +Subject: [PATCH 10/27] pc-bios/s390-ccw: Remove panics from SCSI IPL path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [10/23] 4d8c58a0563e8977b045e7990deabe97c0614708 (thuth/qemu-kvm-cs9) + +Remove panic-on-error from virtio-scsi 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 +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-10-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit facd91ac1af75b657fc80189fe9cb026bb1abdbc) +--- + pc-bios/s390-ccw/bootmap.c | 88 ++++++++++++++----- + pc-bios/s390-ccw/virtio-blkdev.c | 4 +- + pc-bios/s390-ccw/virtio-scsi.c | 143 +++++++++++++++++++++---------- + 3 files changed, 164 insertions(+), 71 deletions(-) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index b9596e28c7..652807a16a 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -595,7 +595,7 @@ static int ipl_eckd(void) + * IPL a SCSI disk + */ + +-static void zipl_load_segment(ComponentEntry *entry) ++static int zipl_load_segment(ComponentEntry *entry) + { + const int max_entries = (MAX_SECTOR_SIZE / sizeof(ScsiBlockPtr)); + ScsiBlockPtr *bprs = (void *)sec; +@@ -615,7 +615,10 @@ static void zipl_load_segment(ComponentEntry *entry) + do { + memset(bprs, FREE_SPACE_FILLER, bprs_size); + fill_hex_val(blk_no, &blockno, sizeof(blockno)); +- read_block(blockno, bprs, err_msg); ++ if (virtio_read(blockno, bprs)) { ++ puts(err_msg); ++ return -EIO; ++ } + + for (i = 0;; i++) { + uint64_t *cur_desc = (void *)&bprs[i]; +@@ -643,23 +646,37 @@ static void zipl_load_segment(ComponentEntry *entry) + } + address = virtio_load_direct(cur_desc[0], cur_desc[1], 0, + (void *)address); +- IPL_assert(address != -1, "zIPL load segment failed"); ++ if (!address) { ++ puts("zIPL load segment failed"); ++ return -EIO; ++ } + } + } while (blockno); ++ ++ return 0; + } + + /* Run a zipl program */ +-static void zipl_run(ScsiBlockPtr *pte) ++static int zipl_run(ScsiBlockPtr *pte) + { + ComponentHeader *header; + ComponentEntry *entry; + uint8_t tmp_sec[MAX_SECTOR_SIZE]; + +- read_block(pte->blockno, tmp_sec, "Cannot read header"); ++ if (virtio_read(pte->blockno, tmp_sec)) { ++ puts("Cannot read header"); ++ return -EIO; ++ } + header = (ComponentHeader *)tmp_sec; + +- IPL_assert(magic_match(tmp_sec, ZIPL_MAGIC), "No zIPL magic in header"); +- IPL_assert(header->type == ZIPL_COMP_HEADER_IPL, "Bad header type"); ++ if (!magic_match(tmp_sec, ZIPL_MAGIC)) { ++ puts("No zIPL magic in header"); ++ return -EINVAL; ++ } ++ if (header->type != ZIPL_COMP_HEADER_IPL) { ++ puts("Bad header type"); ++ return -EINVAL; ++ } + + dputs("start loading images\n"); + +@@ -674,22 +691,30 @@ static void zipl_run(ScsiBlockPtr *pte) + continue; + } + +- zipl_load_segment(entry); ++ if (zipl_load_segment(entry)) { ++ return -1; ++ } + + entry++; + +- IPL_assert((uint8_t *)(&entry[1]) <= (tmp_sec + MAX_SECTOR_SIZE), +- "Wrong entry value"); ++ if ((uint8_t *)(&entry[1]) > (tmp_sec + MAX_SECTOR_SIZE)) { ++ puts("Wrong entry value"); ++ return -EINVAL; ++ } + } + +- IPL_assert(entry->component_type == ZIPL_COMP_ENTRY_EXEC, "No EXEC entry"); ++ if (entry->component_type != ZIPL_COMP_ENTRY_EXEC) { ++ puts("No EXEC entry"); ++ return -EINVAL; ++ } + + /* should not return */ + write_reset_psw(entry->compdat.load_psw); + jump_to_IPL_code(0); ++ return -1; + } + +-static void ipl_scsi(void) ++static int ipl_scsi(void) + { + ScsiMbr *mbr = (void *)sec; + int program_table_entries = 0; +@@ -700,10 +725,13 @@ static void ipl_scsi(void) + + /* Grab the MBR */ + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); +- read_block(0, mbr, "Cannot read block 0"); ++ if (virtio_read(0, mbr)) { ++ puts("Cannot read block 0"); ++ return -EIO; ++ } + + if (!magic_match(mbr->magic, ZIPL_MAGIC)) { +- return; ++ return 0; + } + + puts("Using SCSI scheme."); +@@ -711,11 +739,20 @@ static void ipl_scsi(void) + IPL_check(mbr->version_id == 1, + "Unknown MBR layout version, assuming version 1"); + debug_print_int("program table", mbr->pt.blockno); +- IPL_assert(mbr->pt.blockno, "No Program Table"); ++ if (!mbr->pt.blockno) { ++ puts("No Program Table"); ++ return -EINVAL; ++ } + + /* Parse the program table */ +- read_block(mbr->pt.blockno, sec, "Error reading Program Table"); +- IPL_assert(magic_match(sec, ZIPL_MAGIC), "No zIPL magic in PT"); ++ if (virtio_read(mbr->pt.blockno, sec)) { ++ puts("Error reading Program Table"); ++ return -EIO; ++ } ++ if (!magic_match(sec, ZIPL_MAGIC)) { ++ puts("No zIPL magic in Program Table"); ++ return -EINVAL; ++ } + + for (i = 0; i < MAX_BOOT_ENTRIES; i++) { + if (prog_table->entry[i].scsi.blockno) { +@@ -725,17 +762,22 @@ static void ipl_scsi(void) + } + + debug_print_int("program table entries", program_table_entries); +- IPL_assert(program_table_entries != 0, "Empty Program Table"); ++ if (program_table_entries == 0) { ++ puts("Empty Program Table"); ++ return -EINVAL; ++ } + + if (menu_is_enabled_enum()) { + loadparm = menu_get_enum_boot_index(valid_entries); + } + + debug_print_int("loadparm", loadparm); +- IPL_assert(loadparm < MAX_BOOT_ENTRIES, "loadparm value greater than" +- " maximum number of boot entries allowed"); ++ if (loadparm >= MAX_BOOT_ENTRIES) { ++ puts("loadparm value greater than max number of boot entries allowed"); ++ return -EINVAL; ++ } + +- zipl_run(&prog_table->entry[loadparm].scsi); /* no return */ ++ return zipl_run(&prog_table->entry[loadparm].scsi); + } + + /*********************************************************************** +@@ -1032,7 +1074,9 @@ void zipl_load(void) + netmain(); + } + +- ipl_scsi(); ++ if (ipl_scsi()) { ++ panic("\n! Cannot IPL this SCSI device !\n"); ++ } + + switch (virtio_get_device_type()) { + case VIRTIO_ID_BLOCK: +diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c +index 2666326801..1c585f034b 100644 +--- a/pc-bios/s390-ccw/virtio-blkdev.c ++++ b/pc-bios/s390-ccw/virtio-blkdev.c +@@ -73,13 +73,13 @@ unsigned long virtio_load_direct(unsigned long rec_list1, unsigned long rec_list + unsigned long addr = (unsigned long)load_addr; + + if (sec_len != virtio_get_block_size()) { +- return -1; ++ return 0; + } + + printf("."); + status = virtio_read_many(sec, (void *)addr, sec_num); + if (status) { +- panic("I/O Error"); ++ return 0; + } + addr += sec_num * virtio_get_block_size(); + +diff --git a/pc-bios/s390-ccw/virtio-scsi.c b/pc-bios/s390-ccw/virtio-scsi.c +index 6b4a1caf8a..71db75ce7b 100644 +--- a/pc-bios/s390-ccw/virtio-scsi.c ++++ b/pc-bios/s390-ccw/virtio-scsi.c +@@ -26,7 +26,7 @@ static uint8_t scsi_inquiry_std_response[256]; + static ScsiInquiryEvpdPages scsi_inquiry_evpd_pages_response; + static ScsiInquiryEvpdBl scsi_inquiry_evpd_bl_response; + +-static inline void vs_assert(bool term, const char **msgs) ++static inline bool vs_assert(bool term, const char **msgs) + { + if (!term) { + int i = 0; +@@ -35,11 +35,13 @@ static inline void vs_assert(bool term, const char **msgs) + while (msgs[i]) { + printf("%s", msgs[i++]); + } +- panic(" !\n"); ++ puts(" !"); + } ++ ++ return term; + } + +-static void virtio_scsi_verify_response(VirtioScsiCmdResp *resp, ++static bool virtio_scsi_verify_response(VirtioScsiCmdResp *resp, + const char *title) + { + const char *mr[] = { +@@ -56,8 +58,8 @@ static void virtio_scsi_verify_response(VirtioScsiCmdResp *resp, + 0 + }; + +- vs_assert(resp->response == VIRTIO_SCSI_S_OK, mr); +- vs_assert(resp->status == CDB_STATUS_GOOD, ms); ++ return vs_assert(resp->response == VIRTIO_SCSI_S_OK, mr) && ++ vs_assert(resp->status == CDB_STATUS_GOOD, ms); + } + + static void prepare_request(VDev *vdev, const void *cdb, int cdb_size, +@@ -78,24 +80,31 @@ static void prepare_request(VDev *vdev, const void *cdb, int cdb_size, + } + } + +-static inline void vs_io_assert(bool term, const char *msg) ++static inline bool vs_io_assert(bool term, const char *msg) + { +- if (!term) { +- virtio_scsi_verify_response(&resp, msg); ++ if (!term && !virtio_scsi_verify_response(&resp, msg)) { ++ return false; + } ++ ++ return true; + } + +-static void vs_run(const char *title, VirtioCmd *cmd, VDev *vdev, ++static int vs_run(const char *title, VirtioCmd *cmd, VDev *vdev, + const void *cdb, int cdb_size, + void *data, uint32_t data_size) + { + prepare_request(vdev, cdb, cdb_size, data, data_size); +- vs_io_assert(virtio_run(vdev, VR_REQUEST, cmd) == 0, title); ++ if (!vs_io_assert(virtio_run(vdev, VR_REQUEST, cmd) == 0, title)) { ++ puts(title); ++ return -EIO; ++ } ++ ++ return 0; + } + + /* SCSI protocol implementation routines */ + +-static bool scsi_inquiry(VDev *vdev, uint8_t evpd, uint8_t page, ++static int scsi_inquiry(VDev *vdev, uint8_t evpd, uint8_t page, + void *data, uint32_t data_size) + { + ScsiCdbInquiry cdb = { +@@ -110,12 +119,13 @@ static bool scsi_inquiry(VDev *vdev, uint8_t evpd, uint8_t page, + { data, data_size, VRING_DESC_F_WRITE }, + }; + +- vs_run("inquiry", inquiry, vdev, &cdb, sizeof(cdb), data, data_size); ++ int ret = vs_run("inquiry", inquiry, ++ vdev, &cdb, sizeof(cdb), data, data_size); + +- return virtio_scsi_response_ok(&resp); ++ return ret ? ret : virtio_scsi_response_ok(&resp); + } + +-static bool scsi_test_unit_ready(VDev *vdev) ++static int scsi_test_unit_ready(VDev *vdev) + { + ScsiCdbTestUnitReady cdb = { + .command = 0x00, +@@ -131,7 +141,7 @@ static bool scsi_test_unit_ready(VDev *vdev) + return virtio_scsi_response_ok(&resp); + } + +-static bool scsi_report_luns(VDev *vdev, void *data, uint32_t data_size) ++static int scsi_report_luns(VDev *vdev, void *data, uint32_t data_size) + { + ScsiCdbReportLuns cdb = { + .command = 0xa0, +@@ -144,13 +154,13 @@ static bool scsi_report_luns(VDev *vdev, void *data, uint32_t data_size) + { data, data_size, VRING_DESC_F_WRITE }, + }; + +- vs_run("report luns", report_luns, ++ int ret = vs_run("report luns", report_luns, + vdev, &cdb, sizeof(cdb), data, data_size); + +- return virtio_scsi_response_ok(&resp); ++ return ret ? ret : virtio_scsi_response_ok(&resp); + } + +-static bool scsi_read_10(VDev *vdev, ++static int scsi_read_10(VDev *vdev, + unsigned long sector, int sectors, void *data, + unsigned int data_size) + { +@@ -168,12 +178,13 @@ static bool scsi_read_10(VDev *vdev, + debug_print_int("read_10 sector", sector); + debug_print_int("read_10 sectors", sectors); + +- vs_run("read(10)", read_10, vdev, &cdb, sizeof(cdb), data, data_size); ++ int ret = vs_run("read(10)", read_10, ++ vdev, &cdb, sizeof(cdb), data, data_size); + +- return virtio_scsi_response_ok(&resp); ++ return ret ? ret : virtio_scsi_response_ok(&resp); + } + +-static bool scsi_read_capacity(VDev *vdev, ++static int scsi_read_capacity(VDev *vdev, + void *data, uint32_t data_size) + { + ScsiCdbReadCapacity16 cdb = { +@@ -187,10 +198,10 @@ static bool scsi_read_capacity(VDev *vdev, + { data, data_size, VRING_DESC_F_WRITE }, + }; + +- vs_run("read capacity", read_capacity_16, ++ int ret = vs_run("read capacity", read_capacity_16, + vdev, &cdb, sizeof(cdb), data, data_size); + +- return virtio_scsi_response_ok(&resp); ++ return ret ? ret : virtio_scsi_response_ok(&resp); + } + + /* virtio-scsi routines */ +@@ -207,7 +218,7 @@ static int virtio_scsi_locate_device(VDev *vdev) + static uint8_t data[16 + 8 * 63]; + ScsiLunReport *r = (void *) data; + ScsiDevice *sdev = vdev->scsi_device; +- int i, luns; ++ int i, ret, luns; + + /* QEMU has hardcoded channel #0 in many places. + * If this hardcoded value is ever changed, we'll need to add code for +@@ -233,13 +244,21 @@ static int virtio_scsi_locate_device(VDev *vdev) + sdev->channel = channel; + sdev->target = target; + sdev->lun = 0; /* LUN has to be 0 for REPORT LUNS */ +- if (!scsi_report_luns(vdev, data, sizeof(data))) { ++ ret = scsi_report_luns(vdev, data, sizeof(data)); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ else if (ret == 0) { + if (resp.response == VIRTIO_SCSI_S_BAD_TARGET) { + continue; + } + printf("target 0x%X\n", target); +- virtio_scsi_verify_response(&resp, "SCSI cannot report LUNs"); ++ if (!virtio_scsi_verify_response(&resp, "SCSI cannot report LUNs")) { ++ return -EIO; ++ } + } ++ + if (r->lun_list_len == 0) { + printf("no LUNs for target 0x%X\n", target); + continue; +@@ -283,7 +302,9 @@ int virtio_scsi_read_many(VDev *vdev, + data_size = sector_count * virtio_get_block_size() * f; + if (!scsi_read_10(vdev, sector * f, sector_count * f, load_addr, + data_size)) { +- virtio_scsi_verify_response(&resp, "virtio-scsi:read_many"); ++ if (!virtio_scsi_verify_response(&resp, "virtio-scsi:read_many")) { ++ return -1; ++ } + } + load_addr += data_size; + sector += sector_count; +@@ -352,11 +373,16 @@ static int virtio_scsi_setup(VDev *vdev) + uint8_t code = resp.sense[0] & SCSI_SENSE_CODE_MASK; + uint8_t sense_key = resp.sense[2] & SCSI_SENSE_KEY_MASK; + +- IPL_assert(resp.sense_len != 0, "virtio-scsi:setup: no SENSE data"); ++ if (resp.sense_len == 0) { ++ puts("virtio-scsi: setup: no SENSE data"); ++ return -EINVAL; ++ } + +- IPL_assert(retry_test_unit_ready && code == 0x70 && +- sense_key == SCSI_SENSE_KEY_UNIT_ATTENTION, +- "virtio-scsi:setup: cannot retry"); ++ if (!retry_test_unit_ready || code != 0x70 || ++ sense_key != SCSI_SENSE_KEY_UNIT_ATTENTION) { ++ puts("virtio-scsi:setup: cannot retry"); ++ return -EIO; ++ } + + /* retry on CHECK_CONDITION/UNIT_ATTENTION as it + * may not designate a real error, but it may be +@@ -367,16 +393,22 @@ static int virtio_scsi_setup(VDev *vdev) + continue; + } + +- virtio_scsi_verify_response(&resp, "virtio-scsi:setup"); ++ if (!virtio_scsi_verify_response(&resp, "virtio-scsi:setup")) { ++ return -1; ++ } + } + + /* read and cache SCSI INQUIRY response */ +- if (!scsi_inquiry(vdev, ++ ret = scsi_inquiry(vdev, + SCSI_INQUIRY_STANDARD, + SCSI_INQUIRY_STANDARD_NONE, + scsi_inquiry_std_response, +- sizeof(scsi_inquiry_std_response))) { +- virtio_scsi_verify_response(&resp, "virtio-scsi:setup:inquiry"); ++ sizeof(scsi_inquiry_std_response)); ++ if (ret < 1) { ++ if (ret != 0 || !virtio_scsi_verify_response(&resp, ++ "virtio-scsi:setup:inquiry")) { ++ return -1; ++ } + } + + if (virtio_scsi_inquiry_response_is_cdrom(scsi_inquiry_std_response)) { +@@ -385,12 +417,16 @@ static int virtio_scsi_setup(VDev *vdev) + vdev->scsi_block_size = VIRTIO_ISO_BLOCK_SIZE; + } + +- if (!scsi_inquiry(vdev, ++ ret = scsi_inquiry(vdev, + SCSI_INQUIRY_EVPD, + SCSI_INQUIRY_EVPD_SUPPORTED_PAGES, + evpd, +- sizeof(*evpd))) { +- virtio_scsi_verify_response(&resp, "virtio-scsi:setup:supported_pages"); ++ sizeof(*evpd)); ++ if (ret < 1) { ++ if (ret != 0 || !virtio_scsi_verify_response(&resp, ++ "virtio-scsi:setup:supported_pages")) { ++ return -1; ++ } + } + + debug_print_int("EVPD length", evpd->page_length); +@@ -402,12 +438,16 @@ static int virtio_scsi_setup(VDev *vdev) + continue; + } + +- if (!scsi_inquiry(vdev, ++ ret = scsi_inquiry(vdev, + SCSI_INQUIRY_EVPD, + SCSI_INQUIRY_EVPD_BLOCK_LIMITS, + evpd_bl, +- sizeof(*evpd_bl))) { +- virtio_scsi_verify_response(&resp, "virtio-scsi:setup:blocklimits"); ++ sizeof(*evpd_bl)); ++ if (ret < 1) { ++ if (ret != 0 || !virtio_scsi_verify_response(&resp, ++ "virtio-scsi:setup:blocklimits")) { ++ return -1; ++ } + } + + debug_print_int("max transfer", evpd_bl->max_transfer); +@@ -423,8 +463,12 @@ static int virtio_scsi_setup(VDev *vdev) + vdev->max_transfer = MIN_NON_ZERO(VIRTIO_SCSI_MAX_SECTORS, + vdev->max_transfer); + +- if (!scsi_read_capacity(vdev, data, data_size)) { +- virtio_scsi_verify_response(&resp, "virtio-scsi:setup:read_capacity"); ++ ret = scsi_read_capacity(vdev, data, data_size); ++ if (ret < 1) { ++ if (ret != 0 || !virtio_scsi_verify_response(&resp, ++ "virtio-scsi:setup:read_capacity")) { ++ return -1; ++ } + } + scsi_parse_capacity_report(data, &vdev->scsi_last_block, + (uint32_t *) &vdev->scsi_block_size); +@@ -439,10 +483,15 @@ int virtio_scsi_setup_device(SubChannelId schid) + vdev->schid = schid; + virtio_setup_ccw(vdev); + +- IPL_assert(vdev->config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE, +- "Config: sense size mismatch"); +- IPL_assert(vdev->config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE, +- "Config: CDB size mismatch"); ++ if (vdev->config.scsi.sense_size != VIRTIO_SCSI_SENSE_SIZE) { ++ puts("Config: sense size mismatch"); ++ return -EINVAL; ++ } ++ ++ if (vdev->config.scsi.cdb_size != VIRTIO_SCSI_CDB_SIZE) { ++ puts("Config: CDB size mismatch"); ++ return -EINVAL; ++ } + + puts("Using virtio-scsi."); + +-- +2.39.3 + diff --git a/kvm-pc-bios-s390-ccw-Use-the-libc-from-SLOF-and-remove-s.patch b/kvm-pc-bios-s390-ccw-Use-the-libc-from-SLOF-and-remove-s.patch new file mode 100644 index 0000000..037d987 --- /dev/null +++ b/kvm-pc-bios-s390-ccw-Use-the-libc-from-SLOF-and-remove-s.patch @@ -0,0 +1,1208 @@ +From 4207901122ef7ad3f08ed2e387bd133cc4a35baf Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:36 -0400 +Subject: [PATCH 02/27] pc-bios/s390-ccw: Use the libc from SLOF and remove + sclp prints +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [2/23] ee701f93051e2bfb79da5cbbd089b24490bca128 (thuth/qemu-kvm-cs9) + +We are already using the libc from SLOF for the s390-netboot.img, and +this libc implementation is way more complete and accurate than the +simple implementation that we currently use for the s390-ccw.img binary. +Since we are now always assuming that the SLOF submodule is available +when building the s390-ccw bios (see commit bf6903f6944f), we can drop +the simple implementation and use the SLOF libc for the s390-ccw.img +binary, too. + +Additionally replace sclp_print calls with puts/printf now that it is +available. + +Co-authored by: Thomas Huth +Signed-off-by: Jared Rossi +Message-ID: <20241020012953.1380075-3-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 9f4278837dc770266c8a026696dd91a525dd2682) +--- + pc-bios/s390-ccw/Makefile | 15 +++-- + pc-bios/s390-ccw/bootmap.c | 47 ++++++------- + pc-bios/s390-ccw/bootmap.h | 4 +- + pc-bios/s390-ccw/cio.c | 78 ++++++++++------------ + pc-bios/s390-ccw/dasd-ipl.c | 5 +- + pc-bios/s390-ccw/jump2ipl.c | 5 +- + pc-bios/s390-ccw/libc.c | 88 ------------------------ + pc-bios/s390-ccw/libc.h | 89 ------------------------- + pc-bios/s390-ccw/main.c | 14 ++-- + pc-bios/s390-ccw/menu.c | 51 +++++++------- + pc-bios/s390-ccw/netboot.mak | 3 - + pc-bios/s390-ccw/netmain.c | 10 +-- + pc-bios/s390-ccw/s390-ccw.h | 30 +++------ + pc-bios/s390-ccw/sclp.c | 7 +- + pc-bios/s390-ccw/virtio-blkdev.c | 6 +- + pc-bios/s390-ccw/virtio-scsi.c | 17 ++--- + pc-bios/s390-ccw/virtio.c | 2 +- + tests/tcg/s390x/Makefile.softmmu-target | 2 +- + tests/tcg/s390x/console.c | 3 + + 19 files changed, 140 insertions(+), 336 deletions(-) + delete mode 100644 pc-bios/s390-ccw/libc.c + delete mode 100644 pc-bios/s390-ccw/libc.h + +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index 6207911b53..3f4232636e 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -33,13 +33,18 @@ QEMU_DGFLAGS = -MMD -MP -MT $@ -MF $(@D)/$(*F).d + .PHONY : all clean build-all distclean + + OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ +- virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o dasd-ipl.o ++ virtio.o virtio-scsi.o virtio-blkdev.o cio.o dasd-ipl.o ++ ++SLOF_DIR := $(SRC_PATH)/../../roms/SLOF ++ ++LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include + + EXTRA_CFLAGS += -Wall + EXTRA_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -fno-common -fPIE + EXTRA_CFLAGS += -fwrapv -fno-strict-aliasing -fno-asynchronous-unwind-tables + EXTRA_CFLAGS += -msoft-float + EXTRA_CFLAGS += -std=gnu99 ++EXTRA_CFLAGS += $(LIBC_INC) + LDFLAGS += -Wl,-pie -nostdlib -z noexecstack + + cc-test = $(CC) -Werror $1 -c -o /dev/null -xc /dev/null >/dev/null 2>/dev/null +@@ -55,18 +60,18 @@ config-cc.mak: Makefile + $(call cc-option,-march=z900,-march=z10)) 3> config-cc.mak + -include config-cc.mak + ++include $(SRC_PATH)/netboot.mak ++ + build-all: s390-ccw.img s390-netboot.img + +-s390-ccw.elf: $(OBJECTS) +- $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),Linking) ++s390-ccw.elf: $(OBJECTS) libc.a ++ $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $^,Linking) + + s390-ccw.img: s390-ccw.elf + $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,Stripping $< into) + + $(OBJECTS): Makefile + +-include $(SRC_PATH)/netboot.mak +- + ALL_OBJS = $(sort $(OBJECTS) $(NETOBJS) $(LIBCOBJS) $(LIBNETOBJS)) + -include $(ALL_OBJS:%.o=%.d) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index a2137449dc..3cc79706be 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -8,7 +8,8 @@ + * directory. + */ + +-#include "libc.h" ++#include ++#include + #include "s390-ccw.h" + #include "s390-arch.h" + #include "bootmap.h" +@@ -21,7 +22,7 @@ + + #ifdef DEBUG_FALLBACK + #define dputs(txt) \ +- do { sclp_print("zipl: " txt); } while (0) ++ do { printf("zipl: " txt); } while (0) + #else + #define dputs(fmt, ...) \ + do { } while (0) +@@ -270,7 +271,7 @@ static int eckd_get_boot_menu_index(block_number_t s1b_block_nr) + prev_block_nr = cur_block_nr; + } + +- sclp_print("No zipl boot menu data found. Booting default entry."); ++ printf("No zipl boot menu data found. Booting default entry."); + return 0; + } + +@@ -338,22 +339,22 @@ static void ipl_eckd_cdl(void) + block_number_t bmt_block_nr, s1b_block_nr; + + /* we have just read the block #0 and recognized it as "IPL1" */ +- sclp_print("CDL\n"); ++ puts("CDL"); + + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); + read_block(1, ipl2, "Cannot read IPL2 record at block 1"); + + mbr = &ipl2->mbr; + if (!magic_match(mbr, ZIPL_MAGIC)) { +- sclp_print("No zIPL section in IPL2 record.\n"); ++ puts("No zIPL section in IPL2 record."); + return; + } + if (!block_size_ok(mbr->blockptr.xeckd.bptr.size)) { +- sclp_print("Bad block size in zIPL section of IPL2 record.\n"); ++ puts("Bad block size in zIPL section of IPL2 record."); + return; + } + if (mbr->dev_type != DEV_TYPE_ECKD) { +- sclp_print("Non-ECKD device type in zIPL section of IPL2 record.\n"); ++ puts("Non-ECKD device type in zIPL section of IPL2 record."); + return; + } + +@@ -366,11 +367,11 @@ static void ipl_eckd_cdl(void) + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); + read_block(2, vlbl, "Cannot read Volume Label at block 2"); + if (!magic_match(vlbl->key, VOL1_MAGIC)) { +- sclp_print("Invalid magic of volume label block.\n"); ++ puts("Invalid magic of volume label block."); + return; + } + if (!magic_match(vlbl->f.key, VOL1_MAGIC)) { +- sclp_print("Invalid magic of volser block.\n"); ++ puts("Invalid magic of volser block."); + return; + } + print_volser(vlbl->f.volser); +@@ -384,8 +385,8 @@ static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode) + LDL_VTOC *vlbl = (void *)sec; /* already read, 3rd block */ + char msg[4] = { '?', '.', '\n', '\0' }; + +- sclp_print((mode == ECKD_CMS) ? "CMS" : "LDL"); +- sclp_print(" version "); ++ printf((mode == ECKD_CMS) ? "CMS" : "LDL"); ++ printf(" version "); + switch (vlbl->LDL_version) { + case LDL1_VERSION: + msg[0] = '1'; +@@ -398,7 +399,7 @@ static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode) + msg[1] = '?'; + break; + } +- sclp_print(msg); ++ printf("%s", msg); + print_volser(vlbl->volser); + } + +@@ -419,7 +420,7 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode) + if (!magic_match(ipl1->bip.magic, ZIPL_MAGIC)) { + return; /* not applicable layout */ + } +- sclp_print("unlabeled LDL.\n"); ++ puts("unlabeled LDL."); + } + verify_boot_info(&ipl1->bip); + +@@ -466,7 +467,7 @@ static void print_eckd_msg(void) + *p-- = ' '; + } + } +- sclp_print(msg); ++ printf("%s", msg); + } + + static void ipl_eckd(void) +@@ -488,11 +489,11 @@ static void ipl_eckd(void) + if (eckd_valid_address((ExtEckdBlockPtr *)&vlbl->f.br, 0)) { + ldipl_bmt = eckd_find_bmt((ExtEckdBlockPtr *)&vlbl->f.br); + if (ldipl_bmt) { +- sclp_print("List-Directed\n"); ++ puts("List-Directed"); + /* LD-IPL does not use the S1B bock, just make it NULL */ + run_eckd_boot_script(ldipl_bmt, NULL_BLOCK_NR); + /* Only return in error, retry as CCW-IPL */ +- sclp_print("Retrying IPL "); ++ printf("Retrying IPL "); + print_eckd_msg(); + } + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); +@@ -634,7 +635,7 @@ static void ipl_scsi(void) + return; + } + +- sclp_print("Using SCSI scheme.\n"); ++ puts("Using SCSI scheme."); + debug_print_int("MBR Version", mbr->version_id); + IPL_check(mbr->version_id == 1, + "Unknown MBR layout version, assuming version 1"); +@@ -743,7 +744,7 @@ static inline uint32_t iso_get_file_size(uint32_t load_rba) + if (cur_record->file_flags & 0x2) { + /* Subdirectory */ + if (level == ISO9660_MAX_DIR_DEPTH - 1) { +- sclp_print("ISO-9660 directory depth limit exceeded\n"); ++ puts("ISO-9660 directory depth limit exceeded"); + } else { + level++; + sec_loc[level] = iso_733_to_u32(cur_record->ext_loc); +@@ -778,9 +779,9 @@ static void load_iso_bc_entry(IsoBcSection *load) + if (real_size) { + /* Round up blocks to load */ + blks_to_load = (real_size + ISO_SECTOR_SIZE - 1) / ISO_SECTOR_SIZE; +- sclp_print("ISO boot image size verified\n"); ++ puts("ISO boot image size verified"); + } else { +- sclp_print("ISO boot image size could not be verified\n"); ++ puts("ISO boot image size could not be verified"); + } + + read_iso_boot_image(bswap32(s.load_rba), +@@ -896,7 +897,7 @@ static void zipl_load_vblk(void) + } + + if (blksize != VIRTIO_DASD_DEFAULT_BLOCK_SIZE) { +- sclp_print("Using guessed DASD geometry.\n"); ++ puts("Using guessed DASD geometry."); + virtio_assume_eckd(); + } + ipl_eckd(); +@@ -909,7 +910,7 @@ static void zipl_load_vscsi(void) + ipl_iso_el_torito(); + } + +- sclp_print("Using guessed DASD geometry.\n"); ++ puts("Using guessed DASD geometry."); + virtio_assume_eckd(); + ipl_eckd(); + } +@@ -944,5 +945,5 @@ void zipl_load(void) + panic("\n! Unknown IPL device type !\n"); + } + +- sclp_print("zIPL load failed.\n"); ++ puts("zIPL load failed."); + } +diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h +index d4690a88c2..4a7d8a91f1 100644 +--- a/pc-bios/s390-ccw/bootmap.h ++++ b/pc-bios/s390-ccw/bootmap.h +@@ -336,9 +336,7 @@ static inline void print_volser(const void *volser) + + ebcdic_to_ascii((char *)volser, ascii, 6); + ascii[6] = '\0'; +- sclp_print("VOLSER=["); +- sclp_print(ascii); +- sclp_print("]\n"); ++ printf("VOLSER=[%s]\n", ascii); + } + + static inline bool unused_space(const void *p, size_t size) +diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c +index 83ca27ab41..7b09a38c96 100644 +--- a/pc-bios/s390-ccw/cio.c ++++ b/pc-bios/s390-ccw/cio.c +@@ -11,7 +11,8 @@ + * directory. + */ + +-#include "libc.h" ++#include ++#include + #include "s390-ccw.h" + #include "s390-arch.h" + #include "helper.h" +@@ -90,9 +91,9 @@ static void print_eckd_dasd_sense_data(SenseDataEckdDasd *sd) + char msgline[512]; + + if (sd->config_info & 0x8000) { +- sclp_print("Eckd Dasd Sense Data (fmt 24-bytes):\n"); ++ puts("Eckd Dasd Sense Data (fmt 24-bytes):"); + } else { +- sclp_print("Eckd Dasd Sense Data (fmt 32-bytes):\n"); ++ puts("Eckd Dasd Sense Data (fmt 32-bytes):"); + } + + strcat(msgline, " Sense Condition Flags :"); +@@ -158,22 +159,21 @@ static void print_eckd_dasd_sense_data(SenseDataEckdDasd *sd) + if (sd->status[1] & SNS_STAT2_IMPRECISE_END) { + strcat(msgline, " [Imprecise-End]"); + } +- strcat(msgline, "\n"); +- sclp_print(msgline); +- +- print_int(" Residual Count =", sd->res_count); +- print_int(" Phys Drive ID =", sd->phys_drive_id); +- print_int(" low cyl address =", sd->low_cyl_addr); +- print_int(" head addr & hi cyl =", sd->head_high_cyl_addr); +- print_int(" format/message =", sd->fmt_msg); +- print_int(" fmt-dependent[0-7] =", sd->fmt_dependent_info[0]); +- print_int(" fmt-dependent[8-15]=", sd->fmt_dependent_info[1]); +- print_int(" prog action code =", sd->program_action_code); +- print_int(" Configuration info =", sd->config_info); +- print_int(" mcode / hi-cyl =", sd->mcode_hicyl); +- print_int(" cyl & head addr [0]=", sd->cyl_head_addr[0]); +- print_int(" cyl & head addr [1]=", sd->cyl_head_addr[1]); +- print_int(" cyl & head addr [2]=", sd->cyl_head_addr[2]); ++ puts(msgline); ++ ++ printf(" Residual Count = 0x%X\n", sd->res_count); ++ printf(" Phys Drive ID = 0x%X\n", sd->phys_drive_id); ++ printf(" low cyl address = 0x%X\n", sd->low_cyl_addr); ++ printf(" head addr & hi cyl = 0x%X\n", sd->head_high_cyl_addr); ++ printf(" format/message = 0x%X\n", sd->fmt_msg); ++ printf(" fmt-dependent[0-7] = 0x%llX\n", sd->fmt_dependent_info[0]); ++ printf(" fmt-dependent[8-15]= 0x%llX\n", sd->fmt_dependent_info[1]); ++ printf(" prog action code = 0x%X\n", sd->program_action_code); ++ printf(" Configuration info = 0x%X\n", sd->config_info); ++ printf(" mcode / hi-cyl = 0x%X\n", sd->mcode_hicyl); ++ printf(" cyl & head addr [0]= 0x%X\n", sd->cyl_head_addr[0]); ++ printf(" cyl & head addr [1]= 0x%X\n", sd->cyl_head_addr[1]); ++ printf(" cyl & head addr [2]= 0x%X\n", sd->cyl_head_addr[2]); + } + + static void print_irb_err(Irb *irb) +@@ -182,7 +182,7 @@ static void print_irb_err(Irb *irb) + uint64_t prev_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa - 8); + char msgline[256]; + +- sclp_print("Interrupt Response Block Data:\n"); ++ puts("Interrupt Response Block Data:"); + + strcat(msgline, " Function Ctrl :"); + if (irb->scsw.ctrl & SCSW_FCTL_START_FUNC) { +@@ -194,8 +194,7 @@ static void print_irb_err(Irb *irb) + if (irb->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) { + strcat(msgline, " [Clear]"); + } +- strcat(msgline, "\n"); +- sclp_print(msgline); ++ puts(msgline); + + msgline[0] = '\0'; + strcat(msgline, " Activity Ctrl :"); +@@ -220,8 +219,7 @@ static void print_irb_err(Irb *irb) + if (irb->scsw.ctrl & SCSW_ACTL_SUSPENDED) { + strcat(msgline, " [Suspended]"); + } +- strcat(msgline, "\n"); +- sclp_print(msgline); ++ puts(msgline); + + msgline[0] = '\0'; + strcat(msgline, " Status Ctrl :"); +@@ -240,9 +238,7 @@ static void print_irb_err(Irb *irb) + if (irb->scsw.ctrl & SCSW_SCTL_STATUS_PEND) { + strcat(msgline, " [Status-Pending]"); + } +- +- strcat(msgline, "\n"); +- sclp_print(msgline); ++ puts(msgline); + + msgline[0] = '\0'; + strcat(msgline, " Device Status :"); +@@ -270,8 +266,7 @@ static void print_irb_err(Irb *irb) + if (irb->scsw.dstat & SCSW_DSTAT_UEXCP) { + strcat(msgline, " [Unit-Exception]"); + } +- strcat(msgline, "\n"); +- sclp_print(msgline); ++ puts(msgline); + + msgline[0] = '\0'; + strcat(msgline, " Channel Status :"); +@@ -299,12 +294,11 @@ static void print_irb_err(Irb *irb) + if (irb->scsw.cstat & SCSW_CSTAT_CHAINCHK) { + strcat(msgline, " [Chaining-Check]"); + } +- strcat(msgline, "\n"); +- sclp_print(msgline); ++ puts(msgline); + +- print_int(" cpa=", irb->scsw.cpa); +- print_int(" prev_ccw=", prev_ccw); +- print_int(" this_ccw=", this_ccw); ++ printf(" cpa= 0x%X\n", irb->scsw.cpa); ++ printf(" prev_ccw= 0x%llX\n", prev_ccw); ++ printf(" this_ccw= 0x%llX\n", this_ccw); + } + + /* +@@ -341,7 +335,7 @@ static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb) + return -1; + } + if (rc) { +- print_int("ssch failed with cc=", rc); ++ printf("ssch failed with cc= 0x%x\n", rc); + return rc; + } + +@@ -350,7 +344,7 @@ static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb) + /* collect status */ + rc = tsch(schid, irb); + if (rc) { +- print_int("tsch failed with cc=", rc); ++ printf("tsch failed with cc= 0x%X\n", rc); + } + + return rc; +@@ -406,12 +400,12 @@ int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt) + continue; + } + +- sclp_print("cio device error\n"); +- print_int(" ssid ", schid.ssid); +- print_int(" cssid ", schid.cssid); +- print_int(" sch_no", schid.sch_no); +- print_int(" ctrl-unit type", cutype); +- sclp_print("\n"); ++ printf("cio device error\n"); ++ printf(" ssid 0x%X\n", schid.ssid); ++ printf(" cssid 0x%X\n", schid.cssid); ++ printf(" sch_no 0x%X\n", schid.sch_no); ++ printf(" ctrl-unit type 0x%X\n", cutype); ++ printf("\n"); + print_irb_err(&irb); + if (cutype == CU_TYPE_DASD_3990 || cutype == CU_TYPE_DASD_2107 || + cutype == CU_TYPE_UNKNOWN) { +diff --git a/pc-bios/s390-ccw/dasd-ipl.c b/pc-bios/s390-ccw/dasd-ipl.c +index 254bb1a15e..ae751adec1 100644 +--- a/pc-bios/s390-ccw/dasd-ipl.c ++++ b/pc-bios/s390-ccw/dasd-ipl.c +@@ -8,7 +8,8 @@ + * directory. + */ + +-#include "libc.h" ++#include ++#include + #include "s390-ccw.h" + #include "s390-arch.h" + #include "dasd-ipl.h" +@@ -82,7 +83,7 @@ static int run_dynamic_ccw_program(SubChannelId schid, uint16_t cutype, + do { + has_next = dynamic_cp_fixup(cpa, &next_cpa); + +- print_int("executing ccw chain at ", cpa); ++ printf("executing ccw chain at 0x%X\n", cpa); + enable_prefixing(); + rc = do_cio(schid, cutype, cpa, CCW_FMT0); + disable_prefixing(); +diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c +index 78f5f46533..80b7f6a1f3 100644 +--- a/pc-bios/s390-ccw/jump2ipl.c ++++ b/pc-bios/s390-ccw/jump2ipl.c +@@ -6,7 +6,8 @@ + * directory. + */ + +-#include "libc.h" ++#include ++#include + #include "s390-ccw.h" + #include "s390-arch.h" + +@@ -57,7 +58,7 @@ void jump_to_IPL_code(uint64_t address) + debug_print_int("set IPL addr to", address ?: *reset_psw & PSW_MASK_SHORT_ADDR); + + /* Ensure the guest output starts fresh */ +- sclp_print("\n"); ++ printf("\n"); + + /* + * HACK ALERT. +diff --git a/pc-bios/s390-ccw/libc.c b/pc-bios/s390-ccw/libc.c +deleted file mode 100644 +index 3187923950..0000000000 +--- a/pc-bios/s390-ccw/libc.c ++++ /dev/null +@@ -1,88 +0,0 @@ +-/* +- * libc-style definitions and functions +- * +- * Copyright 2018 IBM Corp. +- * Author(s): Collin L. Walling +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- */ +- +-#include "libc.h" +-#include "s390-ccw.h" +- +-/** +- * atoui: +- * @str: the string to be converted. +- * +- * Given a string @str, convert it to an integer. Leading spaces are +- * ignored. Any other non-numerical value will terminate the conversion +- * and return 0. This function only handles numbers between 0 and +- * UINT64_MAX inclusive. +- * +- * Returns: an integer converted from the string @str, or the number 0 +- * if an error occurred. +- */ +-uint64_t atoui(const char *str) +-{ +- int val = 0; +- +- if (!str || !str[0]) { +- return 0; +- } +- +- while (*str == ' ') { +- str++; +- } +- +- while (*str) { +- if (!isdigit(*(unsigned char *)str)) { +- break; +- } +- val = val * 10 + *str - '0'; +- str++; +- } +- +- return val; +-} +- +-/** +- * uitoa: +- * @num: an integer (base 10) to be converted. +- * @str: a pointer to a string to store the conversion. +- * @len: the length of the passed string. +- * +- * Given an integer @num, convert it to a string. The string @str must be +- * allocated beforehand. The resulting string will be null terminated and +- * returned. This function only handles numbers between 0 and UINT64_MAX +- * inclusive. +- * +- * Returns: the string @str of the converted integer @num +- */ +-char *uitoa(uint64_t num, char *str, size_t len) +-{ +- long num_idx = 1; /* account for NUL */ +- uint64_t tmp = num; +- +- IPL_assert(str != NULL, "uitoa: no space allocated to store string"); +- +- /* Count indices of num */ +- while ((tmp /= 10) != 0) { +- num_idx++; +- } +- +- /* Check if we have enough space for num and NUL */ +- IPL_assert(len > num_idx, "uitoa: array too small for conversion"); +- +- str[num_idx--] = '\0'; +- +- /* Convert int to string */ +- while (num_idx >= 0) { +- str[num_idx--] = num % 10 + '0'; +- num /= 10; +- } +- +- return str; +-} +diff --git a/pc-bios/s390-ccw/libc.h b/pc-bios/s390-ccw/libc.h +deleted file mode 100644 +index bcdc45732d..0000000000 +--- a/pc-bios/s390-ccw/libc.h ++++ /dev/null +@@ -1,89 +0,0 @@ +-/* +- * libc-style definitions and functions +- * +- * Copyright (c) 2013 Alexander Graf +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- */ +- +-#ifndef S390_CCW_LIBC_H +-#define S390_CCW_LIBC_H +- +-typedef unsigned long size_t; +-typedef int bool; +-typedef unsigned char uint8_t; +-typedef unsigned short uint16_t; +-typedef unsigned int uint32_t; +-typedef unsigned long long uint64_t; +- +-static inline void *memset(void *s, int c, size_t n) +-{ +- size_t i; +- unsigned char *p = s; +- +- for (i = 0; i < n; i++) { +- p[i] = c; +- } +- +- return s; +-} +- +-static inline void *memcpy(void *s1, const void *s2, size_t n) +-{ +- uint8_t *dest = s1; +- const uint8_t *src = s2; +- size_t i; +- +- for (i = 0; i < n; i++) { +- dest[i] = src[i]; +- } +- +- return s1; +-} +- +-static inline int memcmp(const void *s1, const void *s2, size_t n) +-{ +- size_t i; +- const uint8_t *p1 = s1, *p2 = s2; +- +- for (i = 0; i < n; i++) { +- if (p1[i] != p2[i]) { +- return p1[i] > p2[i] ? 1 : -1; +- } +- } +- +- return 0; +-} +- +-static inline size_t strlen(const char *str) +-{ +- size_t i; +- for (i = 0; *str; i++) { +- str++; +- } +- return i; +-} +- +-static inline char *strcat(char *dest, const char *src) +-{ +- int i; +- char *dest_end = dest + strlen(dest); +- +- for (i = 0; i <= strlen(src); i++) { +- dest_end[i] = src[i]; +- } +- return dest; +-} +- +-static inline int isdigit(int c) +-{ +- return (c >= '0') && (c <= '9'); +-} +- +-uint64_t atoui(const char *str); +-char *uitoa(uint64_t num, char *str, size_t len); +- +-#endif +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 5506798098..203df20965 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -8,7 +8,9 @@ + * directory. + */ + +-#include "libc.h" ++#include ++#include ++#include + #include "helper.h" + #include "s390-arch.h" + #include "s390-ccw.h" +@@ -50,7 +52,7 @@ void write_iplb_location(void) + + unsigned int get_loadparm_index(void) + { +- return atoui(loadparm_str); ++ return atoi(loadparm_str); + } + + static int is_dev_possibly_bootable(int dev_no, int sch_no) +@@ -176,7 +178,7 @@ static void boot_setup(void) + + sclp_get_loadparm_ascii(loadparm_str); + memcpy(lpmsg + 10, loadparm_str, 8); +- sclp_print(lpmsg); ++ puts(lpmsg); + + /* + * Clear out any potential S390EP magic (see jump_to_low_kernel()), +@@ -228,7 +230,7 @@ static int virtio_setup(void) + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_NET: +- sclp_print("Network boot device detected\n"); ++ puts("Network boot device detected"); + vdev->netboot_start_addr = qipl.netboot_start_addr; + return 0; + case VIRTIO_ID_BLOCK: +@@ -261,7 +263,7 @@ static void ipl_boot_device(void) + } + break; + default: +- print_int("Attempting to boot from unexpected device type", cutype); ++ printf("Attempting to boot from unexpected device type 0x%X\n", cutype); + panic("\nBoot failed.\n"); + } + } +@@ -287,7 +289,7 @@ static void probe_boot_device(void) + } + } + +- sclp_print("Could not find a suitable boot device (none specified)\n"); ++ puts("Could not find a suitable boot device (none specified)"); + } + + void main(void) +diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c +index d601952d3e..84062e94af 100644 +--- a/pc-bios/s390-ccw/menu.c ++++ b/pc-bios/s390-ccw/menu.c +@@ -9,7 +9,10 @@ + * directory. + */ + +-#include "libc.h" ++#include ++#include ++#include ++#include + #include "s390-ccw.h" + #include "sclp.h" + #include "s390-time.h" +@@ -93,7 +96,7 @@ static int read_prompt(char *buf, size_t len) + case KEYCODE_BACKSP: + if (idx > 0) { + buf[--idx] = 0; +- sclp_print("\b \b"); ++ printf("\b \b"); + } + continue; + case KEYCODE_ENTER: +@@ -103,7 +106,7 @@ static int read_prompt(char *buf, size_t len) + /* Echo input and add to buffer */ + if (idx < len) { + buf[idx++] = inp[0]; +- sclp_print(inp); ++ printf("%s", inp); + } + } + } +@@ -140,22 +143,19 @@ static int get_index(void) + } + } + +- return atoui(buf); ++ return atoi(buf); + } + + static void boot_menu_prompt(bool retry) + { +- char tmp[11]; +- + if (retry) { +- sclp_print("\nError: undefined configuration" ++ printf("\nError: undefined configuration" + "\nPlease choose:\n"); + } else if (timeout > 0) { +- sclp_print("Please choose (default will boot in "); +- sclp_print(uitoa(timeout / 1000, tmp, sizeof(tmp))); +- sclp_print(" seconds):\n"); ++ printf("Please choose (default will boot in %d seconds):\n", ++ (int)(timeout / 1000)); + } else { +- sclp_print("Please choose:\n"); ++ puts("Please choose:"); + } + } + +@@ -163,7 +163,6 @@ static int get_boot_index(bool *valid_entries) + { + int boot_index; + bool retry = false; +- char tmp[5]; + + do { + boot_menu_prompt(retry); +@@ -172,8 +171,7 @@ static int get_boot_index(bool *valid_entries) + } while (boot_index < 0 || boot_index >= MAX_BOOT_ENTRIES || + !valid_entries[boot_index]); + +- sclp_print("\nBooting entry #"); +- sclp_print(uitoa(boot_index, tmp, sizeof(tmp))); ++ printf("\nBooting entry #%d", boot_index); + + return boot_index; + } +@@ -187,9 +185,9 @@ static int zipl_print_entry(const char *data, size_t len) + buf[len] = '\n'; + buf[len + 1] = '\0'; + +- sclp_print(buf); ++ printf("%s", buf); + +- return buf[0] == ' ' ? atoui(buf + 1) : atoui(buf); ++ return buf[0] == ' ' ? atoi(buf + 1) : atoi(buf); + } + + int menu_get_zipl_boot_index(const char *menu_data) +@@ -209,7 +207,7 @@ int menu_get_zipl_boot_index(const char *menu_data) + } + + /* Print banner */ +- sclp_print("s390-ccw zIPL Boot Menu\n\n"); ++ puts("s390-ccw zIPL Boot Menu\n"); + menu_data += strlen(menu_data) + 1; + + /* Print entries */ +@@ -221,37 +219,34 @@ int menu_get_zipl_boot_index(const char *menu_data) + valid_entries[entry] = true; + + if (entry == 0) { +- sclp_print("\n"); ++ printf("\n"); + } + } + +- sclp_print("\n"); ++ printf("\n"); + return get_boot_index(valid_entries); + } + + int menu_get_enum_boot_index(bool *valid_entries) + { +- char tmp[3]; + int i; + +- sclp_print("s390-ccw Enumerated Boot Menu.\n\n"); ++ puts("s390-ccw Enumerated Boot Menu.\n"); + + for (i = 0; i < MAX_BOOT_ENTRIES; i++) { + if (valid_entries[i]) { + if (i < 10) { +- sclp_print(" "); ++ printf(" "); + } +- sclp_print("["); +- sclp_print(uitoa(i, tmp, sizeof(tmp))); +- sclp_print("]"); ++ printf("[%d]", i); + if (i == 0) { +- sclp_print(" default\n"); ++ printf(" default\n"); + } +- sclp_print("\n"); ++ printf("\n"); + } + } + +- sclp_print("\n"); ++ printf("\n"); + return get_boot_index(valid_entries); + } + +diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak +index 046aa35587..d2b3d8ee74 100644 +--- a/pc-bios/s390-ccw/netboot.mak ++++ b/pc-bios/s390-ccw/netboot.mak +@@ -1,9 +1,6 @@ + +-SLOF_DIR := $(SRC_PATH)/../../roms/SLOF +- + NETOBJS := start.o sclp.o cio.o virtio.o virtio-net.o jump2ipl.o netmain.o + +-LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include + LIBNET_INC := -I$(SLOF_DIR)/lib/libnet + + NETLDFLAGS := $(LDFLAGS) -Wl,-Ttext=0x7800000 +diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c +index 5cd619b2d6..509119be15 100644 +--- a/pc-bios/s390-ccw/netmain.c ++++ b/pc-bios/s390-ccw/netmain.c +@@ -293,7 +293,7 @@ static int load_kernel_with_initrd(filename_ip_t *fn_ip, + printf("Loading pxelinux.cfg entry '%s'\n", entry->label); + + if (!entry->kernel) { +- printf("Kernel entry is missing!\n"); ++ puts("Kernel entry is missing!\n"); + return -1; + } + +@@ -515,13 +515,13 @@ void main(void) + int rc, fnlen; + + sclp_setup(); +- sclp_print("Network boot starting...\n"); ++ puts("Network boot starting..."); + + virtio_setup(); + + rc = net_init(&fn_ip); + if (rc) { +- panic("Network initialization failed. Halting.\n"); ++ panic("Network initialization failed. Halting."); + } + + fnlen = strlen(fn_ip.filename); +@@ -535,9 +535,9 @@ void main(void) + net_release(&fn_ip); + + if (rc > 0) { +- sclp_print("Network loading done, starting kernel...\n"); ++ puts("Network loading done, starting kernel..."); + jump_to_low_kernel(); + } + +- panic("Failed to load OS from network\n"); ++ panic("Failed to load OS from network."); + } +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index c977a52b50..6f6d95d170 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -13,6 +13,11 @@ + + /* #define DEBUG */ + ++#include ++#include ++#include ++#include ++ + typedef unsigned char u8; + typedef unsigned short u16; + typedef unsigned int u32; +@@ -26,9 +31,6 @@ typedef unsigned long long u64; + #define EBUSY 2 + #define ENODEV 3 + +-#ifndef NULL +-#define NULL 0 +-#endif + #ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) + #endif +@@ -87,7 +89,7 @@ bool menu_is_enabled_enum(void); + __attribute__ ((__noreturn__)) + static inline void panic(const char *string) + { +- sclp_print(string); ++ printf("ERROR: %s\n ", string); + disabled_wait(); + } + +@@ -109,20 +111,10 @@ static inline void fill_hex_val(char *out, void *ptr, unsigned size) + } + } + +-static inline void print_int(const char *desc, u64 addr) +-{ +- char out[] = ": 0xffffffffffffffff\n"; +- +- fill_hex_val(&out[4], &addr, sizeof(addr)); +- +- sclp_print(desc); +- sclp_print(out); +-} +- + static inline void debug_print_int(const char *desc, u64 addr) + { + #ifdef DEBUG +- print_int(desc, addr); ++ printf("%s 0x%X\n", desc, addr); + #endif + } + +@@ -147,18 +139,14 @@ static inline void debug_print_addr(const char *desc, void *p) + static inline void IPL_assert(bool term, const char *message) + { + if (!term) { +- sclp_print("\n! "); +- sclp_print(message); +- panic(" !\n"); /* no return */ ++ panic(message); /* no return */ + } + } + + static inline void IPL_check(bool term, const char *message) + { + if (!term) { +- sclp_print("\n! WARNING: "); +- sclp_print(message); +- sclp_print(" !\n"); ++ printf("WARNING: %s\n", message); + } + } + +diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c +index 7251f9af4d..4a07de018d 100644 +--- a/pc-bios/s390-ccw/sclp.c ++++ b/pc-bios/s390-ccw/sclp.c +@@ -8,7 +8,7 @@ + * directory. + */ + +-#include "libc.h" ++#include + #include "s390-ccw.h" + #include "sclp.h" + +@@ -101,11 +101,6 @@ long write(int fd, const void *str, size_t len) + return len; + } + +-void sclp_print(const char *str) +-{ +- write(1, str, strlen(str)); +-} +- + void sclp_get_loadparm_ascii(char *loadparm) + { + +diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c +index a81207b52e..2666326801 100644 +--- a/pc-bios/s390-ccw/virtio-blkdev.c ++++ b/pc-bios/s390-ccw/virtio-blkdev.c +@@ -8,7 +8,7 @@ + * directory. + */ + +-#include "libc.h" ++#include + #include "s390-ccw.h" + #include "virtio.h" + #include "virtio-scsi.h" +@@ -76,7 +76,7 @@ unsigned long virtio_load_direct(unsigned long rec_list1, unsigned long rec_list + return -1; + } + +- sclp_print("."); ++ printf("."); + status = virtio_read_many(sec, (void *)addr, sec_num); + if (status) { + panic("I/O Error"); +@@ -230,7 +230,7 @@ int virtio_blk_setup_device(SubChannelId schid) + vdev->schid = schid; + virtio_setup_ccw(vdev); + +- sclp_print("Using virtio-blk.\n"); ++ puts("Using virtio-blk."); + + return 0; + } +diff --git a/pc-bios/s390-ccw/virtio-scsi.c b/pc-bios/s390-ccw/virtio-scsi.c +index d1a84b937c..6b4a1caf8a 100644 +--- a/pc-bios/s390-ccw/virtio-scsi.c ++++ b/pc-bios/s390-ccw/virtio-scsi.c +@@ -9,7 +9,8 @@ + * directory. + */ + +-#include "libc.h" ++#include ++#include + #include "s390-ccw.h" + #include "virtio.h" + #include "scsi.h" +@@ -30,9 +31,9 @@ static inline void vs_assert(bool term, const char **msgs) + if (!term) { + int i = 0; + +- sclp_print("\n! "); ++ printf("\n! "); + while (msgs[i]) { +- sclp_print(msgs[i++]); ++ printf("%s", msgs[i++]); + } + panic(" !\n"); + } +@@ -236,11 +237,11 @@ static int virtio_scsi_locate_device(VDev *vdev) + if (resp.response == VIRTIO_SCSI_S_BAD_TARGET) { + continue; + } +- print_int("target", target); ++ printf("target 0x%X\n", target); + virtio_scsi_verify_response(&resp, "SCSI cannot report LUNs"); + } + if (r->lun_list_len == 0) { +- print_int("no LUNs for target", target); ++ printf("no LUNs for target 0x%X\n", target); + continue; + } + luns = r->lun_list_len / 8; +@@ -264,7 +265,7 @@ static int virtio_scsi_locate_device(VDev *vdev) + } + } + +- sclp_print("Warning: Could not locate a usable virtio-scsi device\n"); ++ puts("Warning: Could not locate a usable virtio-scsi device"); + return -ENODEV; + } + +@@ -379,7 +380,7 @@ static int virtio_scsi_setup(VDev *vdev) + } + + if (virtio_scsi_inquiry_response_is_cdrom(scsi_inquiry_std_response)) { +- sclp_print("SCSI CD-ROM detected.\n"); ++ puts("SCSI CD-ROM detected."); + vdev->is_cdrom = true; + vdev->scsi_block_size = VIRTIO_ISO_BLOCK_SIZE; + } +@@ -443,7 +444,7 @@ int virtio_scsi_setup_device(SubChannelId schid) + IPL_assert(vdev->config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE, + "Config: CDB size mismatch"); + +- sclp_print("Using virtio-scsi.\n"); ++ puts("Using virtio-scsi."); + + return virtio_scsi_setup(vdev); + } +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index 5edd058d88..8c6b0a8a92 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -8,7 +8,7 @@ + * directory. + */ + +-#include "libc.h" ++#include + #include "s390-ccw.h" + #include "cio.h" + #include "virtio.h" +diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target +index f60f94b090..90964a2ccb 100644 +--- a/tests/tcg/s390x/Makefile.softmmu-target ++++ b/tests/tcg/s390x/Makefile.softmmu-target +@@ -2,7 +2,7 @@ S390X_SRC=$(SRC_PATH)/tests/tcg/s390x + VPATH+=$(S390X_SRC) + QEMU_OPTS+=-action panic=exit-failure -nographic $(EXTFLAGS) -kernel + LINK_SCRIPT=$(S390X_SRC)/softmmu.ld +-CFLAGS+=-ggdb -O0 ++CFLAGS+=-ggdb -O0 -I$(SRC_PATH)/include/hw/s390x/ipl/ + LDFLAGS=-nostdlib -static + + %.o: %.S +diff --git a/tests/tcg/s390x/console.c b/tests/tcg/s390x/console.c +index d43ce3f44b..6c26f04949 100644 +--- a/tests/tcg/s390x/console.c ++++ b/tests/tcg/s390x/console.c +@@ -4,7 +4,10 @@ + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ ++ + #include "../../../pc-bios/s390-ccw/sclp.c" ++#include "../../../roms/SLOF/lib/libc/string/memset.c" ++#include "../../../roms/SLOF/lib/libc/string/memcpy.c" + + void __sys_outc(char c) + { +-- +2.39.3 + diff --git a/kvm-pc-bios-s390x-Enable-multi-device-boot-loop.patch b/kvm-pc-bios-s390x-Enable-multi-device-boot-loop.patch new file mode 100644 index 0000000..80006bf --- /dev/null +++ b/kvm-pc-bios-s390x-Enable-multi-device-boot-loop.patch @@ -0,0 +1,227 @@ +From 4fcfb2ccd90ffc1e0b121b3e5dbab1cdcba8ce4e Mon Sep 17 00:00:00 2001 +From: Jared Rossi +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 +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +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 +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-18-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(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 ++#include + + 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 + diff --git a/kvm-s390x-Add-individual-loadparm-assignment-to-CCW-devi.patch b/kvm-s390x-Add-individual-loadparm-assignment-to-CCW-devi.patch new file mode 100644 index 0000000..3440acb --- /dev/null +++ b/kvm-s390x-Add-individual-loadparm-assignment-to-CCW-devi.patch @@ -0,0 +1,362 @@ +From 20a4a01fde02a619cee994af92721592e7d91716 Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:48 -0400 +Subject: [PATCH 15/27] s390x: Add individual loadparm assignment to CCW device +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [15/23] c4eaab72e6246db7295593b86f097773aa4f49b7 (thuth/qemu-kvm-cs9) + +Add a loadparm property to the VirtioCcwDevice object so that different +loadparms can be defined on a per-device basis for CCW boot devices. + +The machine/global loadparm is still supported. If both a global and per-device +loadparm are defined, the per-device value will override the global value for +that device, but any other devices that do not specify a per-device loadparm +will still use the global loadparm. + +It is invalid to assign a loadparm to a non-boot device. + +Signed-off-by: Jared Rossi +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-15-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit bb185de42339025db9bbd5aa11f3f644c2a077f8) +--- + hw/s390x/ccw-device.c | 46 +++++++++++++++++++++++++ + hw/s390x/ccw-device.h | 2 ++ + hw/s390x/ipl.c | 68 ++++++++++++++++++++++--------------- + hw/s390x/ipl.h | 3 +- + hw/s390x/s390-virtio-ccw.c | 18 +--------- + hw/s390x/sclp.c | 9 ++--- + include/hw/s390x/ipl/qipl.h | 1 + + pc-bios/s390-ccw/main.c | 10 ++++-- + 8 files changed, 102 insertions(+), 55 deletions(-) + +diff --git a/hw/s390x/ccw-device.c b/hw/s390x/ccw-device.c +index a7d682e5af..4e54f34b1c 100644 +--- a/hw/s390x/ccw-device.c ++++ b/hw/s390x/ccw-device.c +@@ -13,6 +13,10 @@ + #include "ccw-device.h" + #include "hw/qdev-properties.h" + #include "qemu/module.h" ++#include "ipl.h" ++#include "qapi/visitor.h" ++#include "qemu/ctype.h" ++#include "qapi/error.h" + + static void ccw_device_refill_ids(CcwDevice *dev) + { +@@ -37,10 +41,52 @@ static bool ccw_device_realize(CcwDevice *dev, Error **errp) + return true; + } + ++static void ccw_device_get_loadparm(Object *obj, Visitor *v, ++ const char *name, void *opaque, ++ Error **errp) ++{ ++ CcwDevice *dev = CCW_DEVICE(obj); ++ char *str = g_strndup((char *) dev->loadparm, sizeof(dev->loadparm)); ++ ++ visit_type_str(v, name, &str, errp); ++ g_free(str); ++} ++ ++static void ccw_device_set_loadparm(Object *obj, Visitor *v, ++ const char *name, void *opaque, ++ Error **errp) ++{ ++ CcwDevice *dev = CCW_DEVICE(obj); ++ char *val; ++ int index; ++ ++ index = object_property_get_int(obj, "bootindex", NULL); ++ ++ if (index < 0) { ++ error_setg(errp, "LOADPARM is only valid for boot devices!"); ++ } ++ ++ if (!visit_type_str(v, name, &val, errp)) { ++ return; ++ } ++ ++ s390_ipl_fmt_loadparm(dev->loadparm, val, errp); ++} ++ ++static const PropertyInfo ccw_loadparm = { ++ .name = "ccw_loadparm", ++ .description = "Up to 8 chars in set of [A-Za-z0-9. ] to pass" ++ " to the guest loader/kernel", ++ .get = ccw_device_get_loadparm, ++ .set = ccw_device_set_loadparm, ++}; ++ + static Property ccw_device_properties[] = { + DEFINE_PROP_CSS_DEV_ID("devno", CcwDevice, devno), + DEFINE_PROP_CSS_DEV_ID_RO("dev_id", CcwDevice, dev_id), + DEFINE_PROP_CSS_DEV_ID_RO("subch_id", CcwDevice, subch_id), ++ DEFINE_PROP("loadparm", CcwDevice, loadparm, ccw_loadparm, ++ typeof(uint8_t[8])), + DEFINE_PROP_END_OF_LIST(), + }; + +diff --git a/hw/s390x/ccw-device.h b/hw/s390x/ccw-device.h +index 5feeb0ee7a..1e1737c0f3 100644 +--- a/hw/s390x/ccw-device.h ++++ b/hw/s390x/ccw-device.h +@@ -26,6 +26,8 @@ struct CcwDevice { + CssDevId dev_id; + /* The actual busid of the virtual subchannel. */ + CssDevId subch_id; ++ /* If set, use this loadparm value when device is boot target */ ++ uint8_t loadparm[8]; + }; + typedef struct CcwDevice CcwDevice; + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index 8a0a3e6961..d83832d975 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -34,6 +34,7 @@ + #include "qemu/config-file.h" + #include "qemu/cutils.h" + #include "qemu/option.h" ++#include "qemu/ctype.h" + #include "standard-headers/linux/virtio_ids.h" + + #define KERN_IMAGE_START 0x010000UL +@@ -397,12 +398,43 @@ static CcwDevice *s390_get_ccw_device(DeviceState *dev_st, int *devtype) + return ccw_dev; + } + ++void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp) ++{ ++ int i; ++ ++ /* Initialize the loadparm with spaces */ ++ memset(loadparm, ' ', LOADPARM_LEN); ++ for (i = 0; i < LOADPARM_LEN && str[i]; i++) { ++ uint8_t c = qemu_toupper(str[i]); /* mimic HMC */ ++ ++ if (qemu_isalnum(c) || c == '.' || c == ' ') { ++ loadparm[i] = c; ++ } else { ++ error_setg(errp, "LOADPARM: invalid character '%c' (ASCII 0x%02x)", ++ c, c); ++ return; ++ } ++ } ++} ++ ++void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp) ++{ ++ int i; ++ ++ /* Initialize the loadparm with EBCDIC spaces (0x40) */ ++ memset(ebcdic_lp, '@', LOADPARM_LEN); ++ for (i = 0; i < LOADPARM_LEN && ascii_lp[i]; i++) { ++ ebcdic_lp[i] = ascii2ebcdic[(uint8_t) ascii_lp[i]]; ++ } ++} ++ + static bool s390_gen_initial_iplb(S390IPLState *ipl) + { + DeviceState *dev_st; + CcwDevice *ccw_dev = NULL; + SCSIDevice *sd; + int devtype; ++ uint8_t *lp; + + dev_st = get_boot_device(0); + if (dev_st) { +@@ -413,6 +445,8 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl) + * Currently allow IPL only from CCW devices. + */ + if (ccw_dev) { ++ lp = ccw_dev->loadparm; ++ + switch (devtype) { + case CCW_DEVTYPE_SCSI: + sd = SCSI_DEVICE(dev_st); +@@ -445,40 +479,20 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl) + break; + } + +- if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) { +- ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID; ++ /* If the device loadparm is empty use the global machine loadparm */ ++ if (memcmp(lp, NO_LOADPARM, 8) == 0) { ++ lp = S390_CCW_MACHINE(qdev_get_machine())->loadparm; + } + ++ s390_ipl_convert_loadparm((char *)lp, ipl->iplb.loadparm); ++ ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID; ++ + return true; + } + + return false; + } + +-int s390_ipl_set_loadparm(uint8_t *loadparm) +-{ +- MachineState *machine = MACHINE(qdev_get_machine()); +- char *lp = object_property_get_str(OBJECT(machine), "loadparm", NULL); +- +- if (lp) { +- int i; +- +- /* lp is an uppercase string without leading/embedded spaces */ +- for (i = 0; i < 8 && lp[i]; i++) { +- loadparm[i] = ascii2ebcdic[(uint8_t) lp[i]]; +- } +- +- if (i < 8) { +- memset(loadparm + i, 0x40, 8 - i); /* fill with EBCDIC spaces */ +- } +- +- g_free(lp); +- return 0; +- } +- +- return -1; +-} +- + static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb, + int virtio_id) + { +@@ -534,7 +548,7 @@ static void update_machine_ipl_properties(IplParameterBlock *iplb) + ascii_loadparm[i] = 0; + object_property_set_str(machine, "loadparm", ascii_loadparm, &err); + } else { +- object_property_set_str(machine, "loadparm", "", &err); ++ object_property_set_str(machine, "loadparm", " ", &err); + } + if (err) { + warn_report_err(err); +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index fa394c339d..b670bad551 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -21,7 +21,8 @@ + + #define DIAG308_FLAGS_LP_VALID 0x80 + +-int s390_ipl_set_loadparm(uint8_t *loadparm); ++void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp); ++void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp); + void s390_ipl_update_diag308(IplParameterBlock *iplb); + int s390_ipl_prepare_pv_header(Error **errp); + int s390_ipl_pv_unpack(void); +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 5113313aa8..ef2a9687c7 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -722,28 +722,12 @@ static void machine_set_loadparm(Object *obj, Visitor *v, + { + S390CcwMachineState *ms = S390_CCW_MACHINE(obj); + char *val; +- int i; + + if (!visit_type_str(v, name, &val, errp)) { + return; + } + +- for (i = 0; i < sizeof(ms->loadparm) && val[i]; i++) { +- uint8_t c = qemu_toupper(val[i]); /* mimic HMC */ +- +- if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || (c == '.') || +- (c == ' ')) { +- ms->loadparm[i] = c; +- } else { +- error_setg(errp, "LOADPARM: invalid character '%c' (ASCII 0x%02x)", +- c, c); +- return; +- } +- } +- +- for (; i < sizeof(ms->loadparm); i++) { +- ms->loadparm[i] = ' '; /* pad right with spaces */ +- } ++ s390_ipl_fmt_loadparm(ms->loadparm, val, errp); + } + + static void ccw_machine_class_init(ObjectClass *oc, void *data) +diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c +index e725dcd5fd..8757626b5c 100644 +--- a/hw/s390x/sclp.c ++++ b/hw/s390x/sclp.c +@@ -110,7 +110,6 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb) + MachineState *machine = MACHINE(qdev_get_machine()); + int cpu_count; + int rnsize, rnmax; +- IplParameterBlock *ipib = s390_ipl_get_iplb(); + int required_len = SCCB_REQ_LEN(ReadInfo, machine->possible_cpus->len); + int offset_cpu = s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) ? + offsetof(ReadInfo, entries) : +@@ -171,12 +170,8 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb) + read_info->rnmax2 = cpu_to_be64(rnmax); + } + +- if (ipib && ipib->flags & DIAG308_FLAGS_LP_VALID) { +- memcpy(&read_info->loadparm, &ipib->loadparm, +- sizeof(read_info->loadparm)); +- } else { +- s390_ipl_set_loadparm(read_info->loadparm); +- } ++ s390_ipl_convert_loadparm((char *)S390_CCW_MACHINE(machine)->loadparm, ++ read_info->loadparm); + + sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION); + } +diff --git a/include/hw/s390x/ipl/qipl.h b/include/hw/s390x/ipl/qipl.h +index 0ef04af027..b67d2ae061 100644 +--- a/include/hw/s390x/ipl/qipl.h ++++ b/include/hw/s390x/ipl/qipl.h +@@ -18,6 +18,7 @@ + + #define QIPL_ADDRESS 0xcc + #define LOADPARM_LEN 8 ++#define NO_LOADPARM "\0\0\0\0\0\0\0\0" + + /* + * The QEMU IPL Parameters will be stored at absolute address +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 34ef27d7a6..ab4709e16e 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -183,8 +183,14 @@ 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); ++ } else { ++ sclp_get_loadparm_ascii(loadparm_str); ++ } + +- sclp_get_loadparm_ascii(loadparm_str); + memcpy(lpmsg + 10, loadparm_str, 8); + puts(lpmsg); + +@@ -193,8 +199,6 @@ static void boot_setup(void) + * so we don't taint our decision-making process during a reboot. + */ + memset((char *)S390EP, 0, 6); +- +- have_iplb = store_iplb(&iplb); + } + + static bool find_boot_device(void) +-- +2.39.3 + diff --git a/kvm-s390x-Rebuild-IPLB-for-SCSI-device-directly-from-DIA.patch b/kvm-s390x-Rebuild-IPLB-for-SCSI-device-directly-from-DIA.patch new file mode 100644 index 0000000..059798a --- /dev/null +++ b/kvm-s390x-Rebuild-IPLB-for-SCSI-device-directly-from-DIA.patch @@ -0,0 +1,264 @@ +From 9d333e9e7614676aac3a39b0f4a5f5d67323b23d Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:50 -0400 +Subject: [PATCH 17/27] s390x: Rebuild IPLB for SCSI device directly from + DIAG308 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [17/23] d0326ad7958cc82496bf57fd09bbc877c5b8c0ac (thuth/qemu-kvm-cs9) + +Because virtio-scsi type devices use a non-architected IPLB pbt code they cannot +be set and stored normally. Instead, the IPLB must be rebuilt during re-ipl. + +As s390x does not natively support multiple boot devices, the devno field is +used to store the position in the boot order for the device. + +Handling the rebuild as part of DIAG308 removes the need to check the devices +for invalid IPLBs later in the IPL. + +Signed-off-by: Jared Rossi +Acked-by: Thomas Huth +Message-ID: <20241020012953.1380075-17-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 455e3bc3f74ee76964efec2e0c646db15095d0d2) +--- + hw/s390x/ipl.c | 74 ++++++------------------------------- + hw/s390x/ipl.h | 11 ++++-- + include/hw/s390x/ipl/qipl.h | 3 +- + pc-bios/s390-ccw/jump2ipl.c | 11 ++++-- + target/s390x/diag.c | 9 ++++- + 5 files changed, 38 insertions(+), 70 deletions(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index f4576f8822..5fbd43c346 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -448,7 +448,6 @@ void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp) + + static bool s390_build_iplb(DeviceState *dev_st, IplParameterBlock *iplb) + { +- S390IPLState *ipl = get_ipl_device(); + CcwDevice *ccw_dev = NULL; + SCSIDevice *sd; + int devtype; +@@ -481,9 +480,6 @@ static bool s390_build_iplb(DeviceState *dev_st, IplParameterBlock *iplb) + iplb->ccw.ssid = ccw_dev->sch->ssid & 3; + break; + case CCW_DEVTYPE_VIRTIO_NET: +- /* The S390IPLState netboot is true if ANY IPLB may use netboot */ +- ipl->netboot = true; +- /* Fall through to CCW_DEVTYPE_VIRTIO case */ + case CCW_DEVTYPE_VIRTIO: + iplb->len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); + iplb->blk0_len = +@@ -508,6 +504,16 @@ static bool s390_build_iplb(DeviceState *dev_st, IplParameterBlock *iplb) + return false; + } + ++void s390_rebuild_iplb(uint16_t dev_index, IplParameterBlock *iplb) ++{ ++ S390IPLState *ipl = get_ipl_device(); ++ uint16_t index; ++ index = ipl->rebuilt_iplb ? ipl->iplb_index : dev_index; ++ ++ ipl->rebuilt_iplb = s390_build_iplb(get_boot_device(index), iplb); ++ ipl->iplb_index = index; ++} ++ + static bool s390_init_all_iplbs(S390IPLState *ipl) + { + int iplb_num = 0; +@@ -564,44 +570,6 @@ static bool s390_init_all_iplbs(S390IPLState *ipl) + return iplb_num; + } + +-static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb, +- int virtio_id) +-{ +- uint8_t cssid; +- uint8_t ssid; +- uint16_t devno; +- uint16_t schid; +- SubchDev *sch = NULL; +- +- if (iplb->pbt != S390_IPL_TYPE_CCW) { +- return false; +- } +- +- devno = be16_to_cpu(iplb->ccw.devno); +- ssid = iplb->ccw.ssid & 3; +- +- for (schid = 0; schid < MAX_SCHID; schid++) { +- for (cssid = 0; cssid < MAX_CSSID; cssid++) { +- sch = css_find_subch(1, cssid, ssid, schid); +- +- if (sch && sch->devno == devno) { +- return sch->id.cu_model == virtio_id; +- } +- } +- } +- return false; +-} +- +-static bool is_virtio_net_device(IplParameterBlock *iplb) +-{ +- return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_NET); +-} +- +-static bool is_virtio_scsi_device(IplParameterBlock *iplb) +-{ +- return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_SCSI); +-} +- + static void update_machine_ipl_properties(IplParameterBlock *iplb) + { + Object *machine = qdev_get_machine(); +@@ -641,7 +609,7 @@ void s390_ipl_update_diag308(IplParameterBlock *iplb) + ipl->iplb = *iplb; + ipl->iplb_valid = true; + } +- ipl->netboot = is_virtio_net_device(iplb); ++ + update_machine_ipl_properties(iplb); + } + +@@ -668,32 +636,14 @@ IplParameterBlock *s390_ipl_get_iplb(void) + void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type) + { + S390IPLState *ipl = get_ipl_device(); +- + if (reset_type == S390_RESET_EXTERNAL || reset_type == S390_RESET_REIPL) { + /* use CPU 0 for full resets */ + ipl->reset_cpu_index = 0; + } else { + ipl->reset_cpu_index = cs->cpu_index; + } +- ipl->reset_type = reset_type; + +- if (reset_type == S390_RESET_REIPL && +- ipl->iplb_valid && +- !ipl->netboot && +- ipl->iplb.pbt == S390_IPL_TYPE_CCW && +- is_virtio_scsi_device(&ipl->iplb)) { +- CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0), NULL); +- +- if (ccw_dev && +- cpu_to_be16(ccw_dev->sch->devno) == ipl->iplb.ccw.devno && +- (ccw_dev->sch->ssid & 3) == ipl->iplb.ccw.ssid) { +- /* +- * this is the original boot device's SCSI +- * so restore IPL parameter info from it +- */ +- ipl->iplb_valid = s390_build_iplb(get_boot_device(0), &ipl->iplb); +- } +- } ++ ipl->reset_type = reset_type; + if (reset_type == S390_RESET_MODIFIED_CLEAR || + reset_type == S390_RESET_LOAD_NORMAL || + reset_type == S390_RESET_PV) { +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index 54eb48fd6e..d7d0b7bfd2 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -24,6 +24,7 @@ + + void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp); + void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp); ++void s390_rebuild_iplb(uint16_t index, IplParameterBlock *iplb); + void s390_ipl_update_diag308(IplParameterBlock *iplb); + int s390_ipl_prepare_pv_header(Error **errp); + int s390_ipl_pv_unpack(void); +@@ -65,7 +66,8 @@ struct S390IPLState { + bool enforce_bios; + bool iplb_valid; + bool iplb_valid_pv; +- bool netboot; ++ bool rebuilt_iplb; ++ uint16_t iplb_index; + /* reset related properties don't have to be migrated or reset */ + enum s390_reset reset_type; + int reset_cpu_index; +@@ -172,11 +174,14 @@ static inline bool iplb_valid_pv(IplParameterBlock *iplb) + + static inline bool iplb_valid(IplParameterBlock *iplb) + { ++ uint32_t len = be32_to_cpu(iplb->len); ++ + switch (iplb->pbt) { + case S390_IPL_TYPE_FCP: +- return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_FCP_LEN; ++ return len >= S390_IPLB_MIN_FCP_LEN; + case S390_IPL_TYPE_CCW: +- return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_CCW_LEN; ++ return len >= S390_IPLB_MIN_CCW_LEN; ++ case S390_IPL_TYPE_QEMU_SCSI: + default: + return false; + } +diff --git a/include/hw/s390x/ipl/qipl.h b/include/hw/s390x/ipl/qipl.h +index 1da4f75aa8..6824391111 100644 +--- a/include/hw/s390x/ipl/qipl.h ++++ b/include/hw/s390x/ipl/qipl.h +@@ -29,7 +29,8 @@ + */ + struct QemuIplParameters { + uint8_t qipl_flags; +- uint8_t reserved1[3]; ++ uint8_t index; ++ uint8_t reserved1[2]; + uint64_t reserved2; + uint32_t boot_menu_timeout; + uint8_t reserved3[2]; +diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c +index 8db1764ff3..99d18947d1 100644 +--- a/pc-bios/s390-ccw/jump2ipl.c ++++ b/pc-bios/s390-ccw/jump2ipl.c +@@ -39,10 +39,15 @@ int jump_to_IPL_code(uint64_t address) + write_subsystem_identification(); + write_iplb_location(); + +- /* prevent unknown IPL types in the guest */ ++ /* ++ * The IPLB for QEMU SCSI type devices must be rebuilt during re-ipl. The ++ * iplb.devno is set to the boot position of the target SCSI device. ++ */ + if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) { +- iplb.pbt = S390_IPL_TYPE_CCW; +- set_iplb(&iplb); ++ iplb.devno = qipl.index; ++ if (!set_iplb(&iplb)) { ++ panic("Failed to set IPLB"); ++ } + } + + /* +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 27ffd48576..a1fd54ddac 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -133,7 +133,14 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + + valid = subcode == DIAG308_PV_SET ? iplb_valid_pv(iplb) : iplb_valid(iplb); + if (!valid) { +- env->regs[r1 + 1] = DIAG_308_RC_INVALID; ++ if (subcode == DIAG308_SET && iplb->pbt == S390_IPL_TYPE_QEMU_SCSI) { ++ s390_rebuild_iplb(iplb->devno, iplb); ++ s390_ipl_update_diag308(iplb); ++ env->regs[r1 + 1] = DIAG_308_RC_OK; ++ } else { ++ env->regs[r1 + 1] = DIAG_308_RC_INVALID; ++ } ++ + goto out; + } + +-- +2.39.3 + diff --git a/kvm-target-i386-kvm-Report-which-action-failed-in-kvm_ar.patch b/kvm-target-i386-kvm-Report-which-action-failed-in-kvm_ar.patch new file mode 100644 index 0000000..d67b6f2 --- /dev/null +++ b/kvm-target-i386-kvm-Report-which-action-failed-in-kvm_ar.patch @@ -0,0 +1,176 @@ +From 1ed2fd718be2161f5ad6156dd2311a65b7f3a5e4 Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Fri, 27 Sep 2024 12:47:41 +0200 +Subject: [PATCH 27/27] target/i386/kvm: Report which action failed in + kvm_arch_put/get_registers + +RH-Author: Julia Suvorova +RH-MergeRequest: 286: kvm: Allow kvm_arch_get/put_registers to accept Error** +RH-Jira: RHEL-60914 +RH-Acked-by: Juraj Marcin +RH-Acked-by: Peter Xu +RH-Commit: [2/2] b5d003dc2ccf869d7a810425baf21c783a96dcd1 + +To help debug and triage future failure reports (akin to [1,2]) that +may occur during kvm_arch_put/get_registers, the error path of each +action is accompanied by unique error message. + +[1] https://issues.redhat.com/browse/RHEL-7558 +[2] https://issues.redhat.com/browse/RHEL-21761 + +Signed-off-by: Julia Suvorova +Reviewed-by: Peter Xu +Link: https://lore.kernel.org/r/20240927104743.218468-3-jusual@redhat.com +Signed-off-by: Paolo Bonzini +(cherry picked from commit fc058618d1596d29e89016750a1aaf64c9fe8832) +--- + target/i386/kvm/kvm.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index 423e6922d8..814f93da19 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -5136,6 +5136,7 @@ int kvm_arch_put_registers(CPUState *cpu, int level, Error **errp) + if (level >= KVM_PUT_RESET_STATE) { + ret = kvm_put_msr_feature_control(x86_cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set feature control MSR"); + return ret; + } + } +@@ -5143,12 +5144,14 @@ int kvm_arch_put_registers(CPUState *cpu, int level, Error **errp) + /* must be before kvm_put_nested_state so that EFER.SVME is set */ + ret = has_sregs2 ? kvm_put_sregs2(x86_cpu) : kvm_put_sregs(x86_cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set special registers"); + return ret; + } + + if (level >= KVM_PUT_RESET_STATE) { + ret = kvm_put_nested_state(x86_cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set nested state"); + return ret; + } + } +@@ -5166,6 +5169,7 @@ int kvm_arch_put_registers(CPUState *cpu, int level, Error **errp) + if (xen_mode == XEN_EMULATE && level == KVM_PUT_FULL_STATE) { + ret = kvm_put_xen_state(cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set Xen state"); + return ret; + } + } +@@ -5173,37 +5177,45 @@ int kvm_arch_put_registers(CPUState *cpu, int level, Error **errp) + + ret = kvm_getput_regs(x86_cpu, 1); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set general purpose registers"); + return ret; + } + ret = kvm_put_xsave(x86_cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set XSAVE"); + return ret; + } + ret = kvm_put_xcrs(x86_cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set XCRs"); + return ret; + } + ret = kvm_put_msrs(x86_cpu, level); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set MSRs"); + return ret; + } + ret = kvm_put_vcpu_events(x86_cpu, level); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set vCPU events"); + return ret; + } + if (level >= KVM_PUT_RESET_STATE) { + ret = kvm_put_mp_state(x86_cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set MP state"); + return ret; + } + } + + ret = kvm_put_tscdeadline_msr(x86_cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set TSC deadline MSR"); + return ret; + } + ret = kvm_put_debugregs(x86_cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to set debug registers"); + return ret; + } + return 0; +@@ -5218,6 +5230,7 @@ int kvm_arch_get_registers(CPUState *cs, Error **errp) + + ret = kvm_get_vcpu_events(cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get vCPU events"); + goto out; + } + /* +@@ -5226,44 +5239,54 @@ int kvm_arch_get_registers(CPUState *cs, Error **errp) + */ + ret = kvm_get_mp_state(cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get MP state"); + goto out; + } + ret = kvm_getput_regs(cpu, 0); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get general purpose registers"); + goto out; + } + ret = kvm_get_xsave(cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get XSAVE"); + goto out; + } + ret = kvm_get_xcrs(cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get XCRs"); + goto out; + } + ret = has_sregs2 ? kvm_get_sregs2(cpu) : kvm_get_sregs(cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get special registers"); + goto out; + } + ret = kvm_get_msrs(cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get MSRs"); + goto out; + } + ret = kvm_get_apic(cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get APIC"); + goto out; + } + ret = kvm_get_debugregs(cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get debug registers"); + goto out; + } + ret = kvm_get_nested_state(cpu); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get nested state"); + goto out; + } + #ifdef CONFIG_XEN_EMU + if (xen_mode == XEN_EMULATE) { + ret = kvm_get_xen_state(cs); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Failed to get Xen state"); + goto out; + } + } +-- +2.39.3 + diff --git a/kvm-tests-qtest-Add-s390x-boot-order-tests-to-cdrom-test.patch b/kvm-tests-qtest-Add-s390x-boot-order-tests-to-cdrom-test.patch new file mode 100644 index 0000000..4596afc --- /dev/null +++ b/kvm-tests-qtest-Add-s390x-boot-order-tests-to-cdrom-test.patch @@ -0,0 +1,74 @@ +From 0e5a728c1d46641bbf5c83289df56422efd374c8 Mon Sep 17 00:00:00 2001 +From: Jared Rossi +Date: Sat, 19 Oct 2024 21:29:53 -0400 +Subject: [PATCH 20/27] tests/qtest: Add s390x boot order tests to cdrom-test.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +RH-MergeRequest: 277: Full boot order support for s390x [CentOS 9] +RH-Jira: RHEL-11424 +RH-Acked-by: Cédric Le Goater +RH-Acked-by: Miroslav Rezanina +RH-Commit: [20/23] 6b8769f2fc5f8c8a6345a5961f54e52be62aae49 (thuth/qemu-kvm-cs9) + +Add two new qtests to verify that a valid IPL device can successfully boot after +failed IPL attempts from one or more invalid devices. + +cdrom-test/as-fallback-device: Defines the primary boot target as a device that +is invalid for IPL and a second boot target that is valid for IPL. Ensures that +the valid device will be selected after the initial failed IPL. + +cdrom-test/as-last-option: Defines the maximum number of boot devices (8) +where only the final entry in the boot order is valid. Ensures that a valid +device will be selected even after multiple failed IPL attempts from both +virtio-blk and virtio-scsi device types. + +Signed-off-by: Jared Rossi +Reviewed-by: Thomas Huth +Message-ID: <20241020012953.1380075-20-jrossi@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit f5aa2d9d4c6480fa73b89c935050afe57e5d8bd9) +--- + tests/qtest/cdrom-test.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/tests/qtest/cdrom-test.c b/tests/qtest/cdrom-test.c +index 5d89e62515..ecba648144 100644 +--- a/tests/qtest/cdrom-test.c ++++ b/tests/qtest/cdrom-test.c +@@ -206,6 +206,30 @@ static void add_s390x_tests(void) + "-drive driver=null-co,read-zeroes=on,if=none,id=d1 " + "-device virtio-blk,drive=d2,bootindex=1 " + "-drive if=none,id=d2,media=cdrom,file=", test_cdboot); ++ qtest_add_data_func("cdrom/boot/as-fallback-device", ++ "-device virtio-serial -device virtio-scsi " ++ "-device virtio-blk,drive=d1,bootindex=1 " ++ "-drive driver=null-co,read-zeroes=on,if=none,id=d1 " ++ "-device virtio-blk,drive=d2,bootindex=2 " ++ "-drive if=none,id=d2,media=cdrom,file=", test_cdboot); ++ qtest_add_data_func("cdrom/boot/as-last-option", ++ "-device virtio-serial -device virtio-scsi " ++ "-device virtio-blk,drive=d1,bootindex=1 " ++ "-drive driver=null-co,read-zeroes=on,if=none,id=d1 " ++ "-device virtio-blk,drive=d2,bootindex=2 " ++ "-drive driver=null-co,read-zeroes=on,if=none,id=d2 " ++ "-device virtio-blk,drive=d3,bootindex=3 " ++ "-drive driver=null-co,read-zeroes=on,if=none,id=d3 " ++ "-device scsi-hd,drive=d4,bootindex=4 " ++ "-drive driver=null-co,read-zeroes=on,if=none,id=d4 " ++ "-device scsi-hd,drive=d5,bootindex=5 " ++ "-drive driver=null-co,read-zeroes=on,if=none,id=d5 " ++ "-device virtio-blk,drive=d6,bootindex=6 " ++ "-drive driver=null-co,read-zeroes=on,if=none,id=d6 " ++ "-device scsi-hd,drive=d7,bootindex=7 " ++ "-drive driver=null-co,read-zeroes=on,if=none,id=d7 " ++ "-device scsi-cd,drive=d8,bootindex=8 " ++ "-drive if=none,id=d8,media=cdrom,file=", test_cdboot); + if (qtest_has_device("x-terminal3270")) { + qtest_add_data_func("cdrom/boot/without-bootindex", + "-device virtio-scsi -device virtio-serial " +-- +2.39.3 + diff --git a/kvm-vfio-migration-Change-trace-formats-from-hex-to-deci.patch b/kvm-vfio-migration-Change-trace-formats-from-hex-to-deci.patch new file mode 100644 index 0000000..3dc09cc --- /dev/null +++ b/kvm-vfio-migration-Change-trace-formats-from-hex-to-deci.patch @@ -0,0 +1,70 @@ +From 619ad79630f5ff2c634fa2785acdaa8dc2f66f62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Wed, 6 Nov 2024 17:28:32 +0100 +Subject: [PATCH 25/27] vfio/migration: Change trace formats from hex to + decimal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cédric Le Goater +RH-MergeRequest: 282: vfio/migration: Report only stop-copy size in vfio_state_pending_exact() +RH-Jira: RHEL-64307 +RH-Acked-by: Peter Xu +RH-Acked-by: Alex Williamson +RH-Commit: [2/2] 04c78dea168c6b4edbbf0cbddadb0d760e7afeb5 (clegoate/qemu-kvm-c9s) + +JIRA: https://issues.redhat.com/browse/RHEL-64307 + +commit fa4e20defe239e42af0a1b5c030dec114f799f56 +Author: Avihai Horon +Date: Sun Oct 20 16:01:08 2024 +0300 + + vfio/migration: Change trace formats from hex to decimal + + Data sizes in VFIO migration trace events are printed in hex format + while in migration core trace events they are printed in decimal format. + + This inconsistency makes it less readable when using both trace event + types. Hence, change the data sizes print format to decimal in VFIO + migration trace events. + + Signed-off-by: Avihai Horon + Reviewed-by: Cédric Le Goater + +Signed-off-by: Cédric Le Goater +--- + hw/vfio/trace-events | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events +index 98bd4dccea..3756ff660e 100644 +--- a/hw/vfio/trace-events ++++ b/hw/vfio/trace-events +@@ -151,7 +151,7 @@ vfio_display_edid_write_error(void) "" + vfio_load_cleanup(const char *name) " (%s)" + vfio_load_device_config_state(const char *name) " (%s)" + vfio_load_state(const char *name, uint64_t data) " (%s) data 0x%"PRIx64 +-vfio_load_state_device_data(const char *name, uint64_t data_size, int ret) " (%s) size 0x%"PRIx64" ret %d" ++vfio_load_state_device_data(const char *name, uint64_t data_size, int ret) " (%s) size %"PRIu64" ret %d" + vfio_migration_realize(const char *name) " (%s)" + vfio_migration_set_device_state(const char *name, const char *state) " (%s) state %s" + vfio_migration_set_state(const char *name, const char *new_state, const char *recover_state) " (%s) new state %s, recover state %s" +@@ -160,10 +160,10 @@ vfio_save_block(const char *name, int data_size) " (%s) data_size %d" + vfio_save_cleanup(const char *name) " (%s)" + vfio_save_complete_precopy(const char *name, int ret) " (%s) ret %d" + vfio_save_device_config_state(const char *name) " (%s)" +-vfio_save_iterate(const char *name, uint64_t precopy_init_size, uint64_t precopy_dirty_size) " (%s) precopy initial size 0x%"PRIx64" precopy dirty size 0x%"PRIx64 +-vfio_save_setup(const char *name, uint64_t data_buffer_size) " (%s) data buffer size 0x%"PRIx64 +-vfio_state_pending_estimate(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t precopy_init_size, uint64_t precopy_dirty_size) " (%s) precopy 0x%"PRIx64" postcopy 0x%"PRIx64" precopy initial size 0x%"PRIx64" precopy dirty size 0x%"PRIx64 +-vfio_state_pending_exact(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t stopcopy_size, uint64_t precopy_init_size, uint64_t precopy_dirty_size) " (%s) precopy 0x%"PRIx64" postcopy 0x%"PRIx64" stopcopy size 0x%"PRIx64" precopy initial size 0x%"PRIx64" precopy dirty size 0x%"PRIx64 ++vfio_save_iterate(const char *name, uint64_t precopy_init_size, uint64_t precopy_dirty_size) " (%s) precopy initial size %"PRIu64" precopy dirty size %"PRIu64 ++vfio_save_setup(const char *name, uint64_t data_buffer_size) " (%s) data buffer size %"PRIu64 ++vfio_state_pending_estimate(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t precopy_init_size, uint64_t precopy_dirty_size) " (%s) precopy %"PRIu64" postcopy %"PRIu64" precopy initial size %"PRIu64" precopy dirty size %"PRIu64 ++vfio_state_pending_exact(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t stopcopy_size, uint64_t precopy_init_size, uint64_t precopy_dirty_size) " (%s) precopy %"PRIu64" postcopy %"PRIu64" stopcopy size %"PRIu64" precopy initial size %"PRIu64" precopy dirty size %"PRIu64 + vfio_vmstate_change(const char *name, int running, const char *reason, const char *dev_state) " (%s) running %d reason %s device state %s" + vfio_vmstate_change_prepare(const char *name, int running, const char *reason, const char *dev_state) " (%s) running %d reason %s device state %s" + +-- +2.39.3 + diff --git a/kvm-vfio-migration-Report-only-stop-copy-size-in-vfio_st.patch b/kvm-vfio-migration-Report-only-stop-copy-size-in-vfio_st.patch new file mode 100644 index 0000000..2a2204c --- /dev/null +++ b/kvm-vfio-migration-Report-only-stop-copy-size-in-vfio_st.patch @@ -0,0 +1,66 @@ +From 4d37b5f77a60ea951c33ac715584bb6f5897006a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Wed, 6 Nov 2024 17:28:32 +0100 +Subject: [PATCH 24/27] vfio/migration: Report only stop-copy size in + vfio_state_pending_exact() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cédric Le Goater +RH-MergeRequest: 282: vfio/migration: Report only stop-copy size in vfio_state_pending_exact() +RH-Jira: RHEL-64307 +RH-Acked-by: Peter Xu +RH-Acked-by: Alex Williamson +RH-Commit: [1/2] 5330acbef6f8a8ada56bd4c7f616138df1a94112 (clegoate/qemu-kvm-c9s) + +JIRA: https://issues.redhat.com/browse/RHEL-64307 + +commit 3b5948f808e3b99aedfa0aff45cffbe8b7ec07ed +Author: Avihai Horon +Date: Sun Oct 20 16:01:06 2024 +0300 + + vfio/migration: Report only stop-copy size in vfio_state_pending_exact() + + vfio_state_pending_exact() is used to update migration core how much + device data is left for the device migration. Currently, the sum of + pre-copy and stop-copy sizes of the VFIO device are reported. + + The pre-copy size is obtained via the VFIO_MIG_GET_PRECOPY_INFO ioctl, + which returns the amount of device data available to be transferred + while the device is in the PRE_COPY states. + + The stop-copy size is obtained via the VFIO_DEVICE_FEATURE_MIG_DATA_SIZE + ioctl, which returns the total amount of device data left to be + transferred in order to complete the device migration. + + According to the above, current implementation is wrong -- it reports + extra overlapping data because pre-copy size is already contained in + stop-copy size. Fix it by reporting only stop-copy size. + + Fixes: eda7362af959 ("vfio/migration: Add VFIO migration pre-copy support") + Signed-off-by: Avihai Horon + Reviewed-by: Cédric Le Goater + +Signed-off-by: Cédric Le Goater +--- + hw/vfio/migration.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c +index 262d42a46e..dd717e8d6c 100644 +--- a/hw/vfio/migration.c ++++ b/hw/vfio/migration.c +@@ -576,9 +576,6 @@ static void vfio_state_pending_exact(void *opaque, uint64_t *must_precopy, + + if (vfio_device_state_is_precopy(vbasedev)) { + vfio_query_precopy_size(migration); +- +- *must_precopy += +- migration->precopy_init_size + migration->precopy_dirty_size; + } + + trace_vfio_state_pending_exact(vbasedev->name, *must_precopy, *can_postcopy, +-- +2.39.3 + diff --git a/qemu-kvm.spec b/qemu-kvm.spec index 50358d4..4757186 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -149,7 +149,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \ Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 9.1.0 -Release: 1%{?rcrel}%{?dist}%{?cc_suffix} +Release: 2%{?rcrel}%{?dist}%{?cc_suffix} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped # Epoch 15 used for RHEL 8 # Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5) @@ -200,6 +200,58 @@ Patch0027: 0027-arm-ensure-compatibility-of-virt-rhel9.patch Patch0028: 0028-arm-create-new-virt-machine-type-for-rhel-9.6.patch Patch0029: 0029-x86-create-new-pc-q35-machine-type-for-rhel-9.6.patch Patch0030: 0030-hw-arm-virt-Fix-Manufacturer-and-Product-Name-in-emu.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch31: kvm-hw-s390x-ipl-Provide-more-memory-to-the-s390-ccw.img.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch32: kvm-pc-bios-s390-ccw-Use-the-libc-from-SLOF-and-remove-s.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch33: kvm-pc-bios-s390-ccw-Link-the-netboot-code-into-the-main.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch35: kvm-hw-s390x-Remove-the-possibility-to-load-the-s390-net.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch36: kvm-pc-bios-s390-ccw-Merge-netboot.mak-into-the-main-Mak.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch37: kvm-docs-system-s390x-bootdevices-Update-the-documentati.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch38: kvm-pc-bios-s390-ccw-Remove-panics-from-ISO-IPL-path.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch39: kvm-pc-bios-s390-ccw-Remove-panics-from-ECKD-IPL-path.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch40: kvm-pc-bios-s390-ccw-Remove-panics-from-SCSI-IPL-path.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch41: kvm-pc-bios-s390-ccw-Remove-panics-from-DASD-IPL-path.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch42: kvm-pc-bios-s390-ccw-Remove-panics-from-Netboot-IPL-path.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch43: kvm-pc-bios-s390-ccw-Enable-failed-IPL-to-return-after-e.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch44: kvm-include-hw-s390x-Add-include-files-for-common-IPL-st.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch45: kvm-s390x-Add-individual-loadparm-assignment-to-CCW-devi.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch46: kvm-hw-s390x-Build-an-IPLB-for-each-boot-device.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch47: kvm-s390x-Rebuild-IPLB-for-SCSI-device-directly-from-DIA.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch48: kvm-pc-bios-s390x-Enable-multi-device-boot-loop.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch49: kvm-docs-system-Update-documentation-for-s390x-IPL.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch50: kvm-tests-qtest-Add-s390x-boot-order-tests-to-cdrom-test.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch51: kvm-pc-bios-s390-ccw-Clarify-alignment-is-in-bytes.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch52: kvm-pc-bios-s390-ccw-Don-t-generate-TEXTRELs.patch +# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part +Patch53: kvm-pc-bios-s390-ccw-Introduce-EXTRA_LDFLAGS.patch +# For RHEL-64307 - High threshold value observed in vGPU live migration +Patch54: kvm-vfio-migration-Report-only-stop-copy-size-in-vfio_st.patch +# For RHEL-64307 - High threshold value observed in vGPU live migration +Patch55: kvm-vfio-migration-Change-trace-formats-from-hex-to-deci.patch +# For RHEL-60914 - Fail migration properly when put cpu register fails +Patch56: kvm-kvm-Allow-kvm_arch_get-put_registers-to-accept-Error.patch +# For RHEL-60914 - Fail migration properly when put cpu register fails +Patch57: kvm-target-i386-kvm-Report-which-action-failed-in-kvm_ar.patch %if %{have_clang} BuildRequires: clang @@ -827,7 +879,7 @@ cp -a qemu-system-%{kvm_target} qemu-kvm %ifarch s390x # Copy the built new images into place for "make check": - cp pc-bios/s390-ccw/s390-ccw.img pc-bios/s390-ccw/s390-netboot.img pc-bios/ + cp pc-bios/s390-ccw/s390-ccw.img pc-bios/ %endif popd @@ -966,7 +1018,6 @@ rm -rf %{buildroot}%{_datadir}/%{name}/skiboot.lid rm -rf %{buildroot}%{_datadir}/%{name}/qboot.rom rm -rf %{buildroot}%{_datadir}/%{name}/s390-ccw.img -rm -rf %{buildroot}%{_datadir}/%{name}/s390-netboot.img rm -rf %{buildroot}%{_datadir}/%{name}/hppa-firmware.img rm -rf %{buildroot}%{_datadir}/%{name}/hppa-firmware64.img rm -rf %{buildroot}%{_datadir}/%{name}/canyonlands.dtb @@ -990,9 +1041,8 @@ rm -rf %{buildroot}%{_libexecdir}/virtfs-proxy-helper rm -rf %{buildroot}%{_mandir}/man1/virtfs-proxy-helper* %ifarch s390x - # Use the s390-*.img that we've just built, not the pre-built ones + # Use the s390-ccw.img that we've just built, not the pre-built one install -m 0644 %{qemu_kvm_build}/pc-bios/s390-ccw/s390-ccw.img %{buildroot}%{_datadir}/%{name}/ - install -m 0644 %{qemu_kvm_build}/pc-bios/s390-ccw/s390-netboot.img %{buildroot}%{_datadir}/%{name}/ %else rm -rf %{buildroot}%{_libdir}/%{name}/hw-s390x-virtio-gpu-ccw.so %endif @@ -1183,7 +1233,6 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %endif %ifarch s390x %{_datadir}/%{name}/s390-ccw.img - %{_datadir}/%{name}/s390-netboot.img %endif %{_datadir}/icons/* %{_datadir}/%{name}/linuxboot_dma.bin @@ -1267,6 +1316,41 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %endif %changelog +* Mon Nov 11 2024 Miroslav Rezanina - 9.1.0-2 +- kvm-hw-s390x-ipl-Provide-more-memory-to-the-s390-ccw.img.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Use-the-libc-from-SLOF-and-remove-s.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Link-the-netboot-code-into-the-main.patch [RHEL-11424] +- kvm-redhat-Remove-the-s390-netboot.img-from-the-spec-fil.patch [RHEL-11424] +- kvm-hw-s390x-Remove-the-possibility-to-load-the-s390-net.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Merge-netboot.mak-into-the-main-Mak.patch [RHEL-11424] +- kvm-docs-system-s390x-bootdevices-Update-the-documentati.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Remove-panics-from-ISO-IPL-path.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Remove-panics-from-ECKD-IPL-path.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Remove-panics-from-SCSI-IPL-path.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Remove-panics-from-DASD-IPL-path.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Remove-panics-from-Netboot-IPL-path.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Enable-failed-IPL-to-return-after-e.patch [RHEL-11424] +- kvm-include-hw-s390x-Add-include-files-for-common-IPL-st.patch [RHEL-11424] +- kvm-s390x-Add-individual-loadparm-assignment-to-CCW-devi.patch [RHEL-11424] +- kvm-hw-s390x-Build-an-IPLB-for-each-boot-device.patch [RHEL-11424] +- kvm-s390x-Rebuild-IPLB-for-SCSI-device-directly-from-DIA.patch [RHEL-11424] +- kvm-pc-bios-s390x-Enable-multi-device-boot-loop.patch [RHEL-11424] +- kvm-docs-system-Update-documentation-for-s390x-IPL.patch [RHEL-11424] +- kvm-tests-qtest-Add-s390x-boot-order-tests-to-cdrom-test.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Clarify-alignment-is-in-bytes.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Don-t-generate-TEXTRELs.patch [RHEL-11424] +- kvm-pc-bios-s390-ccw-Introduce-EXTRA_LDFLAGS.patch [RHEL-11424] +- kvm-vfio-migration-Report-only-stop-copy-size-in-vfio_st.patch [RHEL-64307] +- kvm-vfio-migration-Change-trace-formats-from-hex-to-deci.patch [RHEL-64307] +- kvm-kvm-Allow-kvm_arch_get-put_registers-to-accept-Error.patch [RHEL-60914] +- kvm-target-i386-kvm-Report-which-action-failed-in-kvm_ar.patch [RHEL-60914] +- Resolves: RHEL-11424 + ([IBM 9.6 FEAT] KVM: Full boot order support - qemu part) +- Resolves: RHEL-64307 + (High threshold value observed in vGPU live migration) +- Resolves: RHEL-60914 + (Fail migration properly when put cpu register fails) + * Thu Sep 26 2024 Miroslav Rezanina - 9.1.0-1 - Rebase to QEMU 9.1 [RHEL-41247] - Resolves: RHEL-41247