diff mbox

[PULL,03/25] s390x/ipl: Support IPL from selected SCSI device

Message ID 20160711080912.13947-4-cornelia.huck@de.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Cornelia Huck July 11, 2016, 8:08 a.m. UTC
From: Alexander Yarygin <yarygin@linux.vnet.ibm.com>

If bootindex is specified for a device, we need to IPL from
it. Currently it works for ccw devices, but not for SCSI. To be able to
IPL from the specific device, pc-bios needs to know its address.
For this reason we add special QEMU_SCSI IPL type into the IPLB
structure, that contains the scsi device address.

We enhance the ipl block with a currently qemu-only parameter block
that allows us to specify a concrete scsi device.

Signed-off-by: Alexander Yarygin <yarygin@linux.vnet.ibm.com>
Reviewed-by: Eric Farman <farman@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/s390x/ipl.c | 18 ++++++++++++++++++
 hw/s390x/ipl.h | 13 +++++++++++++
 2 files changed, 31 insertions(+)
diff mbox

Patch

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index e6bf7cf..78998cd 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -217,6 +217,8 @@  static bool s390_gen_initial_iplb(S390IPLState *ipl)
         VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
             OBJECT(qdev_get_parent_bus(dev_st)->parent),
                 TYPE_VIRTIO_CCW_DEVICE);
+        SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
+                                                            TYPE_SCSI_DEVICE);
         if (ccw_dev) {
             ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
             ipl->iplb.blk0_len =
@@ -225,6 +227,22 @@  static bool s390_gen_initial_iplb(S390IPLState *ipl)
             ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
             ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
             return true;
+        } else if (sd) {
+            SCSIBus *bus = scsi_bus_from_device(sd);
+            VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
+            VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev);
+            VirtioCcwDevice *ccw = &scsi_ccw->parent_obj;
+
+            ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
+            ipl->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->sch->devno);
+            ipl->iplb.scsi.ssid = ccw->sch->ssid & 3;
+            return true;
         }
     }
 
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 9aa4d94..ed3f2c8 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -46,6 +46,16 @@  struct IplBlockFcp {
 } 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;
@@ -59,6 +69,7 @@  union IplParameterBlock {
         union {
             IplBlockCcw ccw;
             IplBlockFcp fcp;
+            IplBlockQemuScsi scsi;
         };
     } QEMU_PACKED;
     struct {
@@ -102,10 +113,12 @@  typedef struct S390IPLState S390IPLState;
 
 #define S390_IPL_TYPE_FCP 0x00
 #define S390_IPL_TYPE_CCW 0x02
+#define S390_IPL_TYPE_QEMU_SCSI 0xff
 
 #define S390_IPLB_HEADER_LEN 8
 #define S390_IPLB_MIN_CCW_LEN 200
 #define S390_IPLB_MIN_FCP_LEN 384
+#define S390_IPLB_MIN_QEMU_SCSI_LEN 200
 
 static inline bool iplb_valid_len(IplParameterBlock *iplb)
 {