Commit ba664cf2d3 for qemu.org
commit ba664cf2d3de0f2092d5126733a1b10bb86639a5
Author: Jared Rossi <jrossi@linux.ibm.com>
Date: Mon Aug 31 15:49:18 2026 -0400
s390x: Find scsi-pci boot device and build IPLB
Add logic to identify a virtio-pci scsi controller and target lun with
assigned bootindex, then build IPLB for it.
Unfence PCI case for scsi devices in BIOS.
Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>
Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
Tested-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Link: https://lore.kernel.org/qemu-devel/20260831194919.3830270-8-jrossi@linux.ibm.com
Signed-off-by: Eric Farman <farman@linux.ibm.com>
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 4fa8124f92..1add11ad7b 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -402,6 +402,7 @@ static CcwDevice *s390_get_ccw_device(DeviceState *dev_st, int *devtype)
}
#define PCI_DEVTYPE_VIRTIO 0x05
+#define PCI_DEVTYPE_SCSI 0x06
static S390PCIBusDevice *s390_get_pci_device(DeviceState *dev_st, int *devtype)
{
@@ -417,6 +418,26 @@ static S390PCIBusDevice *s390_get_pci_device(DeviceState *dev_st, int *devtype)
if (pbdev) {
tmp_dt = PCI_DEVTYPE_VIRTIO;
}
+ } else {
+ SCSIDevice *sd = (SCSIDevice *)
+ object_dynamic_cast(OBJECT(dev_st), TYPE_SCSI_DEVICE);
+ if (sd) {
+ SCSIBus *sbus = scsi_bus_from_device(sd);
+ VirtIODevice *vdev = (VirtIODevice *)
+ object_dynamic_cast(OBJECT(sbus->qbus.parent),
+ TYPE_VIRTIO_DEVICE);
+ if (vdev) {
+ pci_dev = (PCIDevice *)
+ object_dynamic_cast(OBJECT(qdev_get_parent_bus(DEVICE(vdev))->parent),
+ TYPE_PCI_DEVICE);
+ if (pci_dev) {
+ pbdev = s390_pci_find_dev_by_pci(s390_get_phb(), pci_dev);
+ if (pbdev) {
+ tmp_dt = PCI_DEVTYPE_SCSI;
+ }
+ }
+ }
+ }
}
}
if (devtype) {
@@ -616,6 +637,22 @@ static bool s390_build_iplb(DeviceState *dev_st, IplParameterBlock *iplb)
iplb->pbt = S390_IPL_TYPE_PCI;
iplb->pci.fid = cpu_to_be32(pbdev->fid);
break;
+ case PCI_DEVTYPE_SCSI:
+ sd = SCSI_DEVICE(dev_st);
+ scsi_lp = object_property_get_str(OBJECT(sd), "loadparm", NULL);
+ if (scsi_lp && strlen(scsi_lp) > 0) {
+ lp = scsi_lp;
+ }
+ iplb->len = cpu_to_be32(S390_IPLB_MIN_PCI_LEN);
+ iplb->blk0_len =
+ cpu_to_be32(S390_IPLB_MIN_PCI_LEN - S390_IPLB_HEADER_LEN);
+ 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.bus = S390_IPL_TYPE_PCI;
+ iplb->scsi.fid = cpu_to_be32(pbdev->fid);
+ break;
default:
return false;
}
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index a2a24b024f..d2a2ac3138 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -267,6 +267,9 @@ static bool find_boot_device(void)
blk_schid.ssid = iplb->scsi.ssid & 0x3;
found = find_subch(iplb->scsi.devno);
break;
+ case S390_IPL_TYPE_PCI:
+ found = find_fid(iplb->scsi.fid);
+ break;
default:
puts("Unrecognized SCSI controller");
break;