s390x: Rebuild IPLB for SCSI device directly from DIAG308

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 <jrossi@linux.ibm.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20241020012953.1380075-17-jrossi@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Jared Rossi 2024-10-19 21:29:50 -04:00 committed by Thomas Huth
parent 0927875e70
commit 455e3bc3f7
5 changed files with 38 additions and 70 deletions

View file

@ -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);
}
}
if (reset_type == S390_RESET_MODIFIED_CLEAR ||
reset_type == S390_RESET_LOAD_NORMAL ||
reset_type == S390_RESET_PV) {