All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/1] RFC: ipl device for s390
@ 2012-05-04 13:43 Christian Borntraeger
  2012-05-04 13:44 ` [Qemu-devel] [PATCH 1/1] s390: IPL " Christian Borntraeger
  0 siblings, 1 reply; 13+ messages in thread
From: Christian Borntraeger @ 2012-05-04 13:43 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Cornelia Huck, Christian Borntraeger, Jens Freimann,
	Heinz Graalfs, qemu-devel

Alex,

while Einar is reworking the block size/geometry patches,
here is the current state of the external loader. While the real firmware
loader only supports fcp, this patch also allows to ipl dasd disks
(the differences in terms of on-disk format are pretty small).
This has the advantage of being able to zipl on LPAR and ipl in KVM and vice
versa for DASD disks.

This patch also contains code to IPL a new dasd bootmap (which is then 
architectured) that will be created by a future zipl version. This zipl
version will then also allow to zipl a dasd/scsi disk under KVM and
create the same bootmap as under LPAR.

I was able to IPL CDL,LDL and FCP disks.
Can you have a look and give some review feedback?

PS: booting from dasd requires the correct geometry and blocksize

Christian Borntraeger (1):
  s390: IPL device for s390

 Makefile.target  |    2 +-
 hw/s390-loader.c |  463 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/s390-loader.h |   81 ++++++++++
 hw/s390-virtio.c |   36 +----
 vl.c             |    7 +
 5 files changed, 554 insertions(+), 35 deletions(-)
 create mode 100644 hw/s390-loader.c
 create mode 100644 hw/s390-loader.h

-- 
1.7.9.6

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-04 13:43 [Qemu-devel] [PATCH 0/1] RFC: ipl device for s390 Christian Borntraeger
@ 2012-05-04 13:44 ` Christian Borntraeger
  2012-05-04 13:53   ` Alexander Graf
  0 siblings, 1 reply; 13+ messages in thread
From: Christian Borntraeger @ 2012-05-04 13:44 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Cornelia Huck, Christian Borntraeger, Jens Freimann,
	Heinz Graalfs, qemu-devel

An IPL (booting) on s390 of SCSI disks is done by a firmware component.
Lets implement this scheme as an qemu device that also allows to
configure the IPL like the HMC. We have a parameter iplid that
refers to a disk device and a load parm that specifies the entry
on the disk to be ipled. We also provide a default device
if no -device s390-ipl statement is given.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 Makefile.target  |    2 +-
 hw/s390-loader.c |  463 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/s390-loader.h |   81 ++++++++++
 hw/s390-virtio.c |   36 +----
 vl.c             |    7 +
 5 files changed, 554 insertions(+), 35 deletions(-)
 create mode 100644 hw/s390-loader.c
 create mode 100644 hw/s390-loader.h

diff --git a/Makefile.target b/Makefile.target
index 1582904..7b8cd84 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -374,7 +374,7 @@ obj-sh4-y += ide/mmio.o
 obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
 obj-m68k-y += m68k-semi.o dummy_m68k.o
 
-obj-s390x-y = s390-virtio-bus.o s390-virtio.o
+obj-s390x-y = s390-virtio-bus.o s390-virtio.o s390-loader.o
 
 obj-alpha-y = mc146818rtc.o
 obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
diff --git a/hw/s390-loader.c b/hw/s390-loader.c
new file mode 100644
index 0000000..2d63ecf
--- /dev/null
+++ b/hw/s390-loader.c
@@ -0,0 +1,463 @@
+/*
+ * bootloader support
+ * Copyright IBM Corp. 2007,2012
+ * Author: Christian Borntraeger <borntraeger@de.ibm.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "cpu.h"
+#include "hw/loader.h"
+#include "hw/s390-loader.h"
+#include "hw/s390-virtio-bus.h"
+#include "hw/sysbus.h"
+
+#define KERN_IMAGE_START                0x010000UL
+
+typedef struct {
+    BlockDriverState *bs;
+    uint64_t (*blockno)(BlockPtr *blockptr);
+    uint64_t (*offset)(BlockPtr *blockptr);
+    uint64_t (*size)(BlockPtr *blockptr);
+    bool     (*empty)(BlockPtr *blockptr);
+    BlockPtr *(*element)(BlockPtr *blockptr, int num);
+    uint32_t (*entries)(void);
+    uint32_t  loadparm;
+    uint8_t  heads;
+    uint8_t  secs;
+    uint16_t blk_size;
+} Loader;
+
+/*
+ * We have one structure that is setup with the right callbacks for the
+ * detected type of boot loader
+ */
+static Loader loader;
+
+/* here are the FCP Callbacks */
+static uint64_t getblockno_fcp(BlockPtr *entry)
+{
+    return be64_to_cpu(entry->u.fcp.blockno);
+}
+
+static uint64_t getoffset_fcp(BlockPtr *entry)
+{
+    return getblockno_fcp(entry) * be16_to_cpu(entry->u.fcp.size);
+}
+
+static uint64_t getsize_fcp(BlockPtr *entry)
+{
+    return loader.blk_size * (be16_to_cpu(entry->u.fcp.blockct) + 1);
+}
+
+static bool getempty_fcp(BlockPtr *entry)
+{
+    return getblockno_fcp(entry) == 0UL;
+}
+
+static BlockPtr *getelement_fcp(BlockPtr *blockptr, int num)
+{
+     FCPBlockPtr *fcp = (FCPBlockPtr *) blockptr;
+
+     return (BlockPtr *) &fcp[num];
+}
+
+static uint32_t entries_fcp(void)
+{
+    return loader.blk_size / sizeof(FCPBlockPtr);
+};
+
+/* and here the callbacks for the new and old eckd map */
+static uint64_t getblockno_eckd(BlockPtr *entry)
+{
+    return 1UL * loader.secs * loader.heads * entry->u.eckd.cyls +
+           1UL * loader.secs * entry->u.eckd.heads +
+           1UL * entry->u.eckd.secs - 1UL;
+}
+
+static uint64_t getoffset_eckd(BlockPtr *entry)
+{
+    return getblockno_eckd(entry) * entry->u.eckd.block_size;
+}
+
+static uint64_t getsize_eckd(BlockPtr *entry)
+{
+    return loader.blk_size * (entry->u.eckd.count + 1);
+}
+
+static bool getempty_eckd(BlockPtr *entry)
+{
+    return getblockno_eckd(entry) == -1UL;
+}
+
+static BlockPtr *getelement_eckd(BlockPtr *blockptr, int num)
+{
+     ECKDBlockPtr *eckd = (ECKDBlockPtr *) blockptr;
+
+     return (BlockPtr *) &eckd[num];
+}
+
+static BlockPtr *getelement_neckd(BlockPtr *blockptr, int num)
+{
+     NECKDBlockPtr *neckd = (NECKDBlockPtr *) blockptr;
+
+     return (BlockPtr *) &neckd[num];
+}
+
+
+static uint32_t entries_eckd(void)
+{
+    return loader.blk_size / sizeof(ECKDBlockPtr);
+};
+
+static uint32_t entries_neckd(void)
+{
+    return loader.blk_size / sizeof(NECKDBlockPtr);
+};
+
+static int magic_ok(void *tmp)
+{
+    return memcmp(tmp, "zIPL", 4) == 0 ? 1 : 0;
+}
+
+static uint64_t parse_segment_elements(BlockPtr *bprs,
+                                       uint64_t *address,
+                                       Loader *loader)
+{
+    unsigned d;
+    int len;
+
+    for (d = 0; d < loader->entries() - 1; d++) {
+        if (*address > ram_size) {
+            error_report("s390-ipl: bootmap points to illegal address");
+            exit(1);
+        }
+        if (loader->empty(loader->element(bprs, d))) {
+            return 0;
+        }
+        len = bdrv_pread(loader->bs,
+                        loader->offset(loader->element(bprs, d)),
+                        (void *) (*address + qemu_get_ram_ptr(0)),
+                        loader->size(loader->element(bprs, d)));
+        if (len != loader->size(loader->element(bprs, d))) {
+            error_report("s390-ipl: error while parsing bootmap\n");
+            exit(1);
+        }
+        *address += len;
+    }
+    return loader->blockno(loader->element(bprs, loader->entries() - 1));
+}
+
+static void parse_segment_table(uint64_t blockno, uint64_t address,
+                                Loader *loader)
+{
+    BlockPtr bprs[loader->entries() + 1];
+
+    do {
+        bdrv_pread(loader->bs, blockno * loader->blk_size, bprs, sizeof(bprs));
+        blockno = parse_segment_elements(bprs, &address, loader);
+    } while (blockno);
+}
+
+static uint64_t parse_program(BlockPtr *blockptr, Loader *loader)
+{
+    ComponentHeader header;
+    ComponentEntry entry;
+    uint64_t offset = loader->offset(blockptr);
+    int ret;
+
+    ret = bdrv_pread(loader->bs, offset, &header, sizeof(header));
+    if (ret != sizeof(header)) {
+        return -1;
+    }
+    if (!magic_ok(&header.magic)) {
+        return -1;
+    }
+
+    if (header.type != component_header_ipl) {
+        error_report("s390-ipl: no IPL header on bootdevice\n");
+        exit(1);
+    }
+
+    offset += sizeof(header);
+    ret = bdrv_pread(loader->bs, offset, &entry, sizeof(entry));
+    if (ret != sizeof(header)) {
+        return -1;
+    }
+
+    while (entry.component_type == component_load) {
+        parse_segment_table(loader->blockno(&entry.blkptr),
+                            entry.address.load_address, loader);
+        offset += sizeof(entry);
+        ret = bdrv_pread(loader->bs, offset, &entry, sizeof(entry));
+        if (ret != sizeof(header)) {
+            return -1;
+        }
+    }
+    if (entry.component_type == component_execute) {
+        return entry.address.load_address;
+    } else {
+        error_report("s390-ipl: no IPL address on bootmap\n");
+        exit(1);
+    }
+}
+
+static uint64_t parse_program_table(BlockPtr *blockptr,
+                                    Loader *loader)
+{
+    BlockPtr entries[loader->entries()];
+    uint32_t n;
+
+    if (bdrv_pread(loader->bs, loader->offset(blockptr),
+                   entries, loader->blk_size) != loader->blk_size) {
+        return -1;
+    }
+
+    /* entry 0, holds the magic */
+    if (!magic_ok(&entries[0])) {
+        return -1;
+    }
+
+    /* Get the number of entries */
+    for (n = 1; n < loader->entries(); n++) {
+        if (loader->empty(loader->element(entries, n))) {
+            break;
+        }
+    }
+
+    /*
+     * on disk: 0 = magic, 1 = default, 2..n = entries
+     * on HMC: 0 = default, 1..m = entries
+     */
+    if (loader->loadparm >= n - 1) {
+        error_report("s390-ipl: Loadparm entry %d does not exists",
+                     loader->loadparm);
+        exit(1);
+    }
+
+    return parse_program(loader->element(entries, loader->loadparm + 1),
+                         loader);
+}
+
+static uint64_t parse_mbr(BlockDriverState *bs, uint8_t loadparm,
+                          uint16_t blk_size)
+{
+    FCPMbr fmbr;
+    NewECKDMbr nembr;
+    ECKDMbr embr;
+
+    int ret;
+
+    loader.bs       = bs;
+    loader.blk_size = be16_to_cpu(fmbr.blockptr.u.fcp.size);
+    loader.loadparm = loadparm;
+    loader.blk_size = blk_size;
+
+
+    /* is this a scsi bootmap ? */
+    bdrv_pread(bs, 0, &fmbr, sizeof(fmbr));
+    if (magic_ok(&fmbr.magic)) {
+        loader.blockno  = getblockno_fcp;
+        loader.offset   = getoffset_fcp;
+        loader.size     = getsize_fcp;
+        loader.empty    = getempty_fcp;
+        loader.element  = getelement_fcp;
+        loader.entries  = entries_fcp;
+        fprintf(stderr, "s390-ipl: detected FCP bootmap\n");
+        return parse_program_table(&fmbr.blockptr, &loader);
+    }
+
+    /* lets try several ECKD bootloader types */
+    loader.heads = bs->heads;
+    loader.secs = bs->secs;
+    loader.blockno  = getblockno_eckd;
+    loader.offset   = getoffset_eckd;
+    loader.size     = getsize_eckd;
+    loader.empty    = getempty_eckd;
+    loader.element  = getelement_neckd;
+    loader.entries  = entries_neckd;
+
+    /* new dasd bootmap for CDL*/
+    bdrv_pread(bs, blk_size + 92, &nembr, sizeof(nembr));
+    if (magic_ok(&nembr.magic)) {
+        if (nembr.dev_type != DEV_TYPE_ECKD) {
+            return -1;
+        }
+        fprintf(stderr, "s390-ipl: detected new CDL bootmap\n");
+        return parse_program_table(&nembr.blockptr, &loader);
+    }
+    /* new dasd bootmap for LDL */
+    bdrv_pread(bs, 112, &nembr, sizeof(nembr));
+    if (magic_ok(&nembr.magic)) {
+        if (nembr.dev_type != DEV_TYPE_ECKD) {
+            return -1;
+        }
+        fprintf(stderr, "s390-ipl: detected new LDL bootmap\n");
+        return parse_program_table(&nembr.blockptr, &loader);
+    }
+
+    /* classic cdl dasd bootmap, unfortunately there is no magic available */
+    loader.element  = getelement_eckd;
+    loader.entries  = entries_eckd;
+
+    bdrv_pread(bs, blk_size + 4, &embr, sizeof(embr));
+    fprintf(stderr, "s390-ipl: trying old CDL bootmap\n");
+    ret = parse_program_table((BlockPtr *) &embr.blockptr, &loader);
+    if (ret == -1) {
+        /* last chance, classic ldl dasd bootmap */
+        bdrv_pread(bs, blk_size, &embr, sizeof(embr));
+        fprintf(stderr, "s390-ipl: CDL failed. trying old LDL bootmap\n");
+        ret = parse_program_table((BlockPtr *) &embr.blockptr, &loader);
+    }
+    return ret;
+}
+
+/*
+ * looks at the program tables written by the boot loader to load
+ * everything which is specified in the bootmap
+ */
+static unsigned long load_from_disk(BlockDriverState *bs, uint32_t loadparm,
+                                    uint32_t blk_size)
+{
+    uint64_t address;
+
+    address = parse_mbr(bs, loadparm, blk_size);
+    if (address == -1) {
+        return -1;
+    }
+    return address & 0x7fffffff;
+}
+
+static void s390_ipl_disk(const char *id, uint32_t loadparm)
+{
+    uint64_t addr = -1UL;
+    DeviceState *dev;
+    VirtIOS390Device *vdev;
+    DriveInfo *drive;
+    CPUS390XState *env;
+
+    /* If no disk is specified, use the first one */
+    if (!id) {
+        /*
+         * libvirt and friends use if=none to create the device itself,
+         * standard command line without an if= will result in virtio.
+         * Lets search both types for a device
+         */
+        drive = drive_get_by_index(IF_NONE, 0);
+        if (!drive) {
+            drive = drive_get_by_index(IF_VIRTIO, 0);
+        }
+        if (drive) {
+            dev = bdrv_get_attached_dev(drive->bdrv);
+            if (!dev) {
+                error_report("s390-ipl: First drive has no attached device");
+                return;
+            }
+        } else {
+            error_report("s390-ipl: No bootable disk found");
+            return;
+        }
+    } else {
+        dev = qdev_find_recursive(sysbus_get_default(), id);
+        if (!dev) {
+            error_report("s390-ipl: Unable to find '%s'", id);
+            return;
+        }
+    }
+
+    vdev = DO_UPCAST(VirtIOS390Device, qdev, dev);
+    if (!vdev->block.bs) {
+        error_report("s390-ipl: '%s' is not a block device", id);
+        return;
+    }
+
+    addr = load_from_disk(vdev->block.bs, loadparm,
+                          vdev->block.logical_block_size);
+    if (addr == -1)  {
+        error_report("s390-ipl: %s id \"%s\" does not contain a valid bootmap",
+                     qdev_fw_name(dev), id ? id : "");
+        return;
+    }
+
+    env = qemu_get_cpu(0);
+    env->psw.addr = addr;
+    env->psw.mask = 0x0000000180000000ULL;
+    s390_add_running_cpu(env);
+}
+
+static void s390_ipl_kernel(void)
+{
+    CPUS390XState *env;
+    env = qemu_get_cpu(0);
+    /*
+     * we can not rely on the ELF entry point, since up to 3.2 this
+     * value was 0x800 (the SALIPL loader) and it wont work. For
+     * all (Linux) cases 0x10000 (KERN_IMAGE_START) should be fine.
+     */
+    env->psw.addr = KERN_IMAGE_START;
+    env->psw.mask = 0x0000000180000000ULL;
+    s390_add_running_cpu(env);
+}
+
+typedef struct {
+    SysBusDevice busdev;
+    uint32_t loadparm;
+    char *iplid;
+} S390IPLState;
+
+static int s390_ipl_init(SysBusDevice *dev)
+{
+    return 0;
+}
+
+static Property s390_ipl_properties[] = {
+        DEFINE_PROP_UINT32("loadparm", S390IPLState, loadparm, 0),
+        DEFINE_PROP_STRING("iplid", S390IPLState, iplid),
+        DEFINE_PROP_END_OF_LIST(),
+};
+
+static void s390_ipl_reset(DeviceState *s390ipl)
+{
+    S390IPLState *iplstate = container_of(s390ipl, S390IPLState, busdev.qdev);
+
+    /* if the user provides a kernel, we dont load from disk */
+    if (rom_ptr(KERN_IMAGE_START)) {
+        s390_ipl_kernel();
+    } else {
+        s390_ipl_disk(iplstate->iplid, iplstate->loadparm);
+    }
+}
+
+static void s390_ipl_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = s390_ipl_init;
+    dc->props = s390_ipl_properties;
+    dc->reset = s390_ipl_reset;
+}
+
+static TypeInfo s390_ipl_info = {
+    .class_init = s390_ipl_class_init,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .name  = "s390-ipl",
+    .instance_size  = sizeof(S390IPLState),
+};
+
+static void s390_register_ipl(void)
+{
+    type_register_static(&s390_ipl_info);
+}
+
+type_init(s390_register_ipl)
diff --git a/hw/s390-loader.h b/hw/s390-loader.h
new file mode 100644
index 0000000..347c07f
--- /dev/null
+++ b/hw/s390-loader.h
@@ -0,0 +1,81 @@
+#include "blockdev.h"
+#include "block_int.h"
+#include "cpu.h"
+
+typedef struct {
+    uint64_t blockno;
+    uint16_t size;
+    uint16_t blockct;
+    uint8_t reserved[4];
+} __attribute__ ((packed)) FCPBlockPtr;
+
+typedef struct {
+    uint16_t cyls;
+    uint16_t heads;
+    uint8_t secs;
+    uint16_t block_size;
+    uint8_t count;
+    uint8_t reserved[8];
+} __attribute__ ((packed)) NECKDBlockPtr;
+
+typedef struct {
+    uint16_t cyls;
+    uint16_t heads;
+    uint8_t secs;
+    uint16_t block_size;
+    uint8_t count;
+} __attribute__ ((packed)) ECKDBlockPtr;
+
+
+typedef struct {
+    union {
+        NECKDBlockPtr neckd;
+        ECKDBlockPtr eckd;
+        FCPBlockPtr  fcp;
+    } u;
+} __attribute__ ((packed)) BlockPtr;
+
+typedef struct {
+    BlockPtr blkptr;
+    uint8_t pad[7];
+    uint8_t component_type;
+    union {
+        uint64_t load_address;
+        uint64_t load_psw;
+    } address;
+} __attribute((packed)) ComponentEntry;
+
+typedef struct {
+    uint8_t magic[4];
+    uint8_t type;
+    uint8_t reserved[27];
+} __attribute((packed)) ComponentHeader;
+
+typedef struct {
+    ECKDBlockPtr blockptr;
+} __attribute__ ((packed)) ECKDMbr;
+
+typedef struct {
+    char    magic[4];
+    uint8_t version;
+    uint8_t bp_type;
+#define DEV_TYPE_ECKD    0x00
+#define DEV_TYPE_FBA     0x01
+    uint8_t dev_type;
+    uint8_t flags;
+    BlockPtr blockptr;
+    uint8_t reserved[8];
+} __attribute__ ((packed)) NewECKDMbr;
+
+typedef struct {
+    char magic[4];
+    uint32_t version_id;
+    uint8_t reserved[8];
+    BlockPtr blockptr;
+} __attribute__ ((packed)) FCPMbr;
+
+#define component_execute 0x01
+#define component_load    0x02
+
+#define component_header_ipl 0x00
+#define component_header_dump 0x01
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 2c5820f..d68e25f 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -20,6 +20,7 @@
 #include "hw.h"
 #include "block.h"
 #include "blockdev.h"
+#include "block_int.h"
 #include "sysemu.h"
 #include "net.h"
 #include "boards.h"
@@ -33,6 +34,7 @@
 
 #include "hw/s390-virtio-bus.h"
 
+#include "hw/s390-loader.h"
 //#define DEBUG_S390
 
 #ifdef DEBUG_S390
@@ -221,11 +223,7 @@ static void s390_init(ram_addr_t my_ram_size,
         tmp_env->storage_keys = storage_keys;
     }
 
-    /* One CPU has to run */
-    s390_add_running_cpu(env);
-
     if (kernel_filename) {
-
         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, NULL,
                                NULL, 1, ELF_MACHINE, 0);
         if (kernel_size == -1UL) {
@@ -236,36 +234,6 @@ static void s390_init(ram_addr_t my_ram_size,
                     kernel_filename);
             exit(1);
         }
-        /*
-         * we can not rely on the ELF entry point, since up to 3.2 this
-         * value was 0x800 (the SALIPL loader) and it wont work. For
-         * all (Linux) cases 0x10000 (KERN_IMAGE_START) should be fine.
-         */
-        env->psw.addr = KERN_IMAGE_START;
-        env->psw.mask = 0x0000000180000000ULL;
-    } else {
-        ram_addr_t bios_size = 0;
-        char *bios_filename;
-
-        /* Load zipl bootloader */
-        if (bios_name == NULL) {
-            bios_name = ZIPL_FILENAME;
-        }
-
-        bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        bios_size = load_image_targphys(bios_filename, ZIPL_LOAD_ADDR, 4096);
-        g_free(bios_filename);
-
-        if ((long)bios_size < 0) {
-            hw_error("could not load bootloader '%s'\n", bios_name);
-        }
-
-        if (bios_size > 4096) {
-            hw_error("stage1 bootloader is > 4k\n");
-        }
-
-        env->psw.addr = ZIPL_START;
-        env->psw.mask = 0x0000000180000000ULL;
     }
 
     if (initrd_filename) {
diff --git a/vl.c b/vl.c
index e724084..f8341c9 100644
--- a/vl.c
+++ b/vl.c
@@ -273,6 +273,7 @@ static int default_monitor = 1;
 static int default_floppy = 1;
 static int default_cdrom = 1;
 static int default_sdcard = 1;
+static int default_loader = 1;
 
 static struct {
     const char *driver;
@@ -288,6 +289,7 @@ static struct {
     { .driver = "virtio-serial-pci",    .flag = &default_virtcon   },
     { .driver = "virtio-serial-s390",   .flag = &default_virtcon   },
     { .driver = "virtio-serial",        .flag = &default_virtcon   },
+    { .driver = "s390-ipl",             .flag = &default_loader    },
 };
 
 static void res_free(void)
@@ -3114,6 +3116,7 @@ int main(int argc, char **argv, char **envp)
                 default_floppy = 0;
                 default_cdrom = 0;
                 default_sdcard = 0;
+                default_loader = 0;
                 vga_model = "none";
                 break;
             case QEMU_OPTION_xen_domid:
@@ -3268,6 +3271,10 @@ int main(int argc, char **argv, char **envp)
     qemu_opts_foreach(qemu_find_opts("device"), default_driver_check, NULL, 0);
     qemu_opts_foreach(qemu_find_opts("global"), default_driver_check, NULL, 0);
 
+    if (default_loader && strcmp(machine->alias, "s390") == 0) {
+        qdev_init_nofail(qdev_create(NULL, "s390-ipl"));
+    }
+
     if (machine->no_serial) {
         default_serial = 0;
     }
-- 
1.7.9.6

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-04 13:44 ` [Qemu-devel] [PATCH 1/1] s390: IPL " Christian Borntraeger
@ 2012-05-04 13:53   ` Alexander Graf
  2012-05-04 14:00     ` Christian Borntraeger
  0 siblings, 1 reply; 13+ messages in thread
From: Alexander Graf @ 2012-05-04 13:53 UTC (permalink / raw)
  To: Christian Borntraeger
  Cc: Cornelia Huck, Jens Freimann, Heinz Graalfs, qemu-devel


On 04.05.2012, at 15:44, Christian Borntraeger wrote:

> An IPL (booting) on s390 of SCSI disks is done by a firmware component.
> Lets implement this scheme as an qemu device that also allows to
> configure the IPL like the HMC. We have a parameter iplid that
> refers to a disk device and a load parm that specifies the entry
> on the disk to be ipled. We also provide a default device
> if no -device s390-ipl statement is given.

Any reason we can't do this in guest firmware code?


Alex

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-04 13:53   ` Alexander Graf
@ 2012-05-04 14:00     ` Christian Borntraeger
  2012-05-04 14:02       ` Christian Borntraeger
  0 siblings, 1 reply; 13+ messages in thread
From: Christian Borntraeger @ 2012-05-04 14:00 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Cornelia Huck, Jens Freimann, Heinz Graalfs, qemu-devel

On 04/05/12 15:53, Alexander Graf wrote:
> 
> On 04.05.2012, at 15:44, Christian Borntraeger wrote:
> 
>> An IPL (booting) on s390 of SCSI disks is done by a firmware component.
>> Lets implement this scheme as an qemu device that also allows to
>> configure the IPL like the HMC. We have a parameter iplid that
>> refers to a disk device and a load parm that specifies the entry
>> on the disk to be ipled. We also provide a default device
>> if no -device s390-ipl statement is given.
> 
> Any reason we can't do this in guest firmware code?

Conceptually guest firmware does not exist in the guest address space
on s390. It is separate in a storage area called HSA. 
(you could say the existing hardware is semi-hosted, you cant buy it bare 
metal.
Doing the boot code in guest address space will fail if the guest firmware
address  collides with the addresses specified by a bootmap.

Christian

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-04 14:00     ` Christian Borntraeger
@ 2012-05-04 14:02       ` Christian Borntraeger
  2012-05-04 18:12         ` Alexander Graf
  0 siblings, 1 reply; 13+ messages in thread
From: Christian Borntraeger @ 2012-05-04 14:02 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Cornelia Huck, Jens Freimann, Heinz Graalfs, qemu-devel

On 04/05/12 16:00, Christian Borntraeger wrote:
>>> An IPL (booting) on s390 of SCSI disks is done by a firmware component.
>>> Lets implement this scheme as an qemu device that also allows to
>>> configure the IPL like the HMC. We have a parameter iplid that
>>> refers to a disk device and a load parm that specifies the entry
>>> on the disk to be ipled. We also provide a default device
>>> if no -device s390-ipl statement is given.
>>
>> Any reason we can't do this in guest firmware code?
> 
> Conceptually guest firmware does not exist in the guest address space
> on s390. It is separate in a storage area called HSA. 
> (you could say the existing hardware is semi-hosted, you cant buy it bare 
> metal.
> Doing the boot code in guest address space will fail if the guest firmware
> address  collides with the addresses specified by a bootmap.

Or in other words, this code is closer to the real s390 boxes.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-04 14:02       ` Christian Borntraeger
@ 2012-05-04 18:12         ` Alexander Graf
  2012-05-08 12:32           ` Christian Borntraeger
  0 siblings, 1 reply; 13+ messages in thread
From: Alexander Graf @ 2012-05-04 18:12 UTC (permalink / raw)
  To: Christian Borntraeger
  Cc: Cornelia Huck, Jens Freimann, Anthony Liguori, Heinz Graalfs,
	qemu-devel Developers


On 04.05.2012, at 16:02, Christian Borntraeger wrote:

> On 04/05/12 16:00, Christian Borntraeger wrote:
>>>> An IPL (booting) on s390 of SCSI disks is done by a firmware component.
>>>> Lets implement this scheme as an qemu device that also allows to
>>>> configure the IPL like the HMC. We have a parameter iplid that
>>>> refers to a disk device and a load parm that specifies the entry
>>>> on the disk to be ipled. We also provide a default device
>>>> if no -device s390-ipl statement is given.
>>> 
>>> Any reason we can't do this in guest firmware code?
>> 
>> Conceptually guest firmware does not exist in the guest address space
>> on s390. It is separate in a storage area called HSA. 
>> (you could say the existing hardware is semi-hosted, you cant buy it bare 
>> metal.
>> Doing the boot code in guest address space will fail if the guest firmware
>> address  collides with the addresses specified by a bootmap.
> 
> Or in other words, this code is closer to the real s390 boxes.

Yeah, I see the point. I'd really like to get Anthony's comments on this one first though.


Alex

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-04 18:12         ` Alexander Graf
@ 2012-05-08 12:32           ` Christian Borntraeger
  2012-05-08 12:40             ` Alexander Graf
  2012-05-08 19:16             ` Anthony Liguori
  0 siblings, 2 replies; 13+ messages in thread
From: Christian Borntraeger @ 2012-05-08 12:32 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Cornelia Huck, Jens Freimann, Heinz Graalfs, Alexander Graf,
	qemu-devel Developers

On 04/05/12 20:12, Alexander Graf wrote:
> 
> On 04.05.2012, at 16:02, Christian Borntraeger wrote:
> 
>> On 04/05/12 16:00, Christian Borntraeger wrote:
>>>>> An IPL (booting) on s390 of SCSI disks is done by a firmware component.
>>>>> Lets implement this scheme as an qemu device that also allows to
>>>>> configure the IPL like the HMC. We have a parameter iplid that
>>>>> refers to a disk device and a load parm that specifies the entry
>>>>> on the disk to be ipled. We also provide a default device
>>>>> if no -device s390-ipl statement is given.
>>>>
>>>> Any reason we can't do this in guest firmware code?
>>>
>>> Conceptually guest firmware does not exist in the guest address space
>>> on s390. It is separate in a storage area called HSA. 
>>> (you could say the existing hardware is semi-hosted, you cant buy it bare 
>>> metal.
>>> Doing the boot code in guest address space will fail if the guest firmware
>>> address  collides with the addresses specified by a bootmap.
>>
>> Or in other words, this code is closer to the real s390 boxes.
> 
> Yeah, I see the point. I'd really like to get Anthony's comments on this one first though.

Right.

Anthony, this is the prototype of the IPL device that we have talked about some weeks
ago. Is an external device to do the IPL process for s390 still ok with you?

Christian

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-08 12:32           ` Christian Borntraeger
@ 2012-05-08 12:40             ` Alexander Graf
  2012-05-08 14:43               ` Christian Borntraeger
  2012-05-08 19:16             ` Anthony Liguori
  1 sibling, 1 reply; 13+ messages in thread
From: Alexander Graf @ 2012-05-08 12:40 UTC (permalink / raw)
  To: Christian Borntraeger
  Cc: Cornelia Huck, Anthony Liguori, Heinz Graalfs, Jens Freimann,
	qemu-devel Developers


On 08.05.2012, at 14:32, Christian Borntraeger wrote:

> On 04/05/12 20:12, Alexander Graf wrote:
>> 
>> On 04.05.2012, at 16:02, Christian Borntraeger wrote:
>> 
>>> On 04/05/12 16:00, Christian Borntraeger wrote:
>>>>>> An IPL (booting) on s390 of SCSI disks is done by a firmware component.
>>>>>> Lets implement this scheme as an qemu device that also allows to
>>>>>> configure the IPL like the HMC. We have a parameter iplid that
>>>>>> refers to a disk device and a load parm that specifies the entry
>>>>>> on the disk to be ipled. We also provide a default device
>>>>>> if no -device s390-ipl statement is given.
>>>>> 
>>>>> Any reason we can't do this in guest firmware code?
>>>> 
>>>> Conceptually guest firmware does not exist in the guest address space
>>>> on s390. It is separate in a storage area called HSA. 
>>>> (you could say the existing hardware is semi-hosted, you cant buy it bare 
>>>> metal.
>>>> Doing the boot code in guest address space will fail if the guest firmware
>>>> address  collides with the addresses specified by a bootmap.
>>> 
>>> Or in other words, this code is closer to the real s390 boxes.
>> 
>> Yeah, I see the point. I'd really like to get Anthony's comments on this one first though.
> 
> Right.
> 
> Anthony, this is the prototype of the IPL device that we have talked about some weeks
> ago. Is an external device to do the IPL process for s390 still ok with you?

Even with an external IPL, we should still be able to detect that a guest provides its own virtio-zipl code that contains a boot menu and execute that instead of directly booting into the first entry, right?


Alex

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-08 12:40             ` Alexander Graf
@ 2012-05-08 14:43               ` Christian Borntraeger
  2012-05-08 14:53                 ` Alexander Graf
  0 siblings, 1 reply; 13+ messages in thread
From: Christian Borntraeger @ 2012-05-08 14:43 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Cornelia Huck, Anthony Liguori, Heinz Graalfs, Jens Freimann,
	qemu-devel Developers

>> Anthony, this is the prototype of the IPL device that we have talked about some weeks
>> ago. Is an external device to do the IPL process for s390 still ok with you?
> 
> Even with an external IPL, we should still be able to detect that a guest provides 
> its own virtio-zipl code that contains a boot menu and execute that instead of directly
> booting into the first entry, right?

This is something that we can argue about to find a way to cover all our use cases
Some of my goals are
- make it possible to install the boot loader in lpar/vm and boot in kvm and vice versa
- follow the real HW ipl process (which I do for FCP, but not for dasd/eckd)
- be able to choose a boot device (-boot <x> is not the right thing for s390)
- be able to choose an program (loadparm)
- get a disk booted no matter if FCP, ECKD CDL, ECKD LDL, block size etc as long as this
  configuration can exist with the current tool sets (that includes ipling disks prepared
  with the sles11 tools)
- have some code that can be extended to non-disk boot devices (s390-ipl takes a qdev id
  as parameter)

Can you clarify what you need? the code should be modular enough to add a detection, a switch
or something else to make that possible.

Christian 

PS: long term we probably also want to have real ECKD dasd passthrough as an alternative to 
virtio for dasds. Then the IPL process will also include interpretation of ipl ccws, but this is 
something that wont be ready anytime soon


  

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-08 14:43               ` Christian Borntraeger
@ 2012-05-08 14:53                 ` Alexander Graf
  2012-05-08 18:54                   ` Christian Borntraeger
  0 siblings, 1 reply; 13+ messages in thread
From: Alexander Graf @ 2012-05-08 14:53 UTC (permalink / raw)
  To: Christian Borntraeger
  Cc: Cornelia Huck, Anthony Liguori, Heinz Graalfs, Jens Freimann,
	qemu-devel Developers


On 08.05.2012, at 16:43, Christian Borntraeger wrote:

>>> Anthony, this is the prototype of the IPL device that we have talked about some weeks
>>> ago. Is an external device to do the IPL process for s390 still ok with you?
>> 
>> Even with an external IPL, we should still be able to detect that a guest provides 
>> its own virtio-zipl code that contains a boot menu and execute that instead of directly
>> booting into the first entry, right?
> 
> This is something that we can argue about to find a way to cover all our use cases
> Some of my goals are
> - make it possible to install the boot loader in lpar/vm and boot in kvm and vice versa
> - follow the real HW ipl process (which I do for FCP, but not for dasd/eckd)
> - be able to choose a boot device (-boot <x> is not the right thing for s390)
> - be able to choose an program (loadparm)
> - get a disk booted no matter if FCP, ECKD CDL, ECKD LDL, block size etc as long as this
>  configuration can exist with the current tool sets (that includes ipling disks prepared
>  with the sles11 tools)
> - have some code that can be extended to non-disk boot devices (s390-ipl takes a qdev id
>  as parameter)
> 
> Can you clarify what you need? the code should be modular enough to add a detection, a switch
> or something else to make that possible.

Well, the only shortcomings I'm aware of of the external IPL are:

  * You lose the boot menu. All you get is "entry 0", "entry 1", etc. as the description is not part of the boot map
  * You can't choose different entries during runtime. Doing a reboot of a VM and selecting a different entry won't work.

The former is pretty annoying if you don't know all of your VMs by heart. The latter is an issue when you don't own the qemu process, but do own the VM. Think of a hosted environment.

Issue 1 could be fixed for the future by changing the bootmap format to include the entry description in a well known format.

As for the runtime selection, we can do some small piece of code that runs inside the guest, provides a choice to the user and then issues a call into QEMU to IPL into the "real" image. That way QEMU would still read out the bootmap and all of the guest RAM is available for the IPL'ed program. We would still maintain the ability to interact with the user though.

> Christian 
> 
> PS: long term we probably also want to have real ECKD dasd passthrough as an alternative to 
> virtio for dasds. Then the IPL process will also include interpretation of ipl ccws, but this is 
> something that wont be ready anytime soon

Makes sense. Though it might be useful to be able to run the on-disk code there too.


Alex

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-08 14:53                 ` Alexander Graf
@ 2012-05-08 18:54                   ` Christian Borntraeger
  2012-05-08 19:18                     ` Alexander Graf
  0 siblings, 1 reply; 13+ messages in thread
From: Christian Borntraeger @ 2012-05-08 18:54 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Cornelia Huck, Anthony Liguori, Heinz Graalfs, Jens Freimann,
	qemu-devel Developers

> Well, the only shortcomings I'm aware of of the external IPL are:
> 
>   * You lose the boot menu. All you get is "entry 0", "entry 1", etc. as the description is not part of the boot map
>   * You can't choose different entries during runtime. Doing a reboot of a VM and selecting a different entry won't work.
> 
> The former is pretty annoying if you don't know all of your VMs by heart. The latter is an issue when you don't own the qemu process, 
> but do own the VM. Think of a hosted environment.

Those are valid points. Regarding the former, I see two things that we might do here:
1. have the current zipl-"bios" as a fallback if the user does not specify an s390-ipl device.
That should be pretty easy and might even have the advantage to minimize the surprise to
existing users of kvm on s390(are there any?). If the user provides an s390-ipl device
then this is a conscious decision. (I will move the specific virtio-zipl bios code into
the s390-ipl device nevertheless,see below for rationale)
2. I will check with the zipl maintainer if we could sneak in the necessary information in 
the boot map, the program table or something else (e.g. defining an component_description,
after component_execute). It just have to be compatible with the layout that the firmware
loader expects. Not sure yet, if this will work out


I definitely want to concentrate all booting in this device: kernel, zipl-virtio, firmware
loader and everything else, because on system_reset we have to reset the cpus and set
the PSW accordingly. As a device we are being called during reset at the right time.

Does that make sense? If yes I will try to refresh that patch as outlined above

Christian

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-08 12:32           ` Christian Borntraeger
  2012-05-08 12:40             ` Alexander Graf
@ 2012-05-08 19:16             ` Anthony Liguori
  1 sibling, 0 replies; 13+ messages in thread
From: Anthony Liguori @ 2012-05-08 19:16 UTC (permalink / raw)
  To: Christian Borntraeger
  Cc: Cornelia Huck, Jens Freimann, Heinz Graalfs, Alexander Graf,
	qemu-devel Developers

On 05/08/2012 07:32 AM, Christian Borntraeger wrote:
> On 04/05/12 20:12, Alexander Graf wrote:
>>
>> On 04.05.2012, at 16:02, Christian Borntraeger wrote:
>>
>>> On 04/05/12 16:00, Christian Borntraeger wrote:
>>>>>> An IPL (booting) on s390 of SCSI disks is done by a firmware component.
>>>>>> Lets implement this scheme as an qemu device that also allows to
>>>>>> configure the IPL like the HMC. We have a parameter iplid that
>>>>>> refers to a disk device and a load parm that specifies the entry
>>>>>> on the disk to be ipled. We also provide a default device
>>>>>> if no -device s390-ipl statement is given.
>>>>>
>>>>> Any reason we can't do this in guest firmware code?
>>>>
>>>> Conceptually guest firmware does not exist in the guest address space
>>>> on s390. It is separate in a storage area called HSA.
>>>> (you could say the existing hardware is semi-hosted, you cant buy it bare
>>>> metal.
>>>> Doing the boot code in guest address space will fail if the guest firmware
>>>> address  collides with the addresses specified by a bootmap.
>>>
>>> Or in other words, this code is closer to the real s390 boxes.
>>
>> Yeah, I see the point. I'd really like to get Anthony's comments on this one first though.
>
> Right.
>
> Anthony, this is the prototype of the IPL device that we have talked about some weeks
> ago. Is an external device to do the IPL process for s390 still ok with you?

I don't really understand the point about collision.  If you chain load 
carefully, you ought to be able to relocate or something like that I would imagine.

But at any rate, for these semi-hosted platforms, I don't see a lot better 
choices than doing these things as devices since there's no "real hardware" to 
model.

So doing this as a device and limiting it to s390 seems like the right strategy 
to me.

Regards,

Anthony Liguori

>
> Christian
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] s390: IPL device for s390
  2012-05-08 18:54                   ` Christian Borntraeger
@ 2012-05-08 19:18                     ` Alexander Graf
  0 siblings, 0 replies; 13+ messages in thread
From: Alexander Graf @ 2012-05-08 19:18 UTC (permalink / raw)
  To: Christian Borntraeger
  Cc: Cornelia Huck, Anthony Liguori, Heinz Graalfs, Jens Freimann,
	qemu-devel Developers


On 08.05.2012, at 20:54, Christian Borntraeger wrote:

>> Well, the only shortcomings I'm aware of of the external IPL are:
>> 
>>  * You lose the boot menu. All you get is "entry 0", "entry 1", etc. as the description is not part of the boot map
>>  * You can't choose different entries during runtime. Doing a reboot of a VM and selecting a different entry won't work.
>> 
>> The former is pretty annoying if you don't know all of your VMs by heart. The latter is an issue when you don't own the qemu process, 
>> but do own the VM. Think of a hosted environment.
> 
> Those are valid points. Regarding the former, I see two things that we might do here:
> 1. have the current zipl-"bios" as a fallback if the user does not specify an s390-ipl device.
> That should be pretty easy and might even have the advantage to minimize the surprise to
> existing users of kvm on s390(are there any?). If the user provides an s390-ipl device
> then this is a conscious decision. (I will move the specific virtio-zipl bios code into
> the s390-ipl device nevertheless,see below for rationale)

I would certainly want that, yes.

What I was also envisioning on top was to run a new version of the zipl-"bios" that only communicates with the special bootup device and virtio-console. It could use all the memory it wants, read out the menu from the bootup device and when it's either run into a timeout or the user chose an entry, it could call into the bootup device to IPL the box for real.

On reboot, IPL would happen into this new zipl-"bios", which would then IPL into the default entry or another user give choice if the user wants to choose something different.

This gives us the possibility of the use case where the VMM owner is different from the VM owner. The VM owner only needs access to its console and is still able to boot however he likes.

I don't think at this point that it'd make sense to share any code with zipl though, as we basically moved all zipl functionality into the bootup device. Maybe we could even do all of this in grub2 with a special pseudo-fs for the entries? Then the user could even modify kernel parameters on the fly! Omg :). Usability meets z ;)

Either way, this is just an idea of the direction we should go here, to make sure the code we write today doesn't go against that direction. As long as we can have an "auto" mode that just loads some guest blob and runs that (zipl-bios today), I think we're good for now.

> 2. I will check with the zipl maintainer if we could sneak in the necessary information in 
> the boot map, the program table or something else (e.g. defining an component_description,
> after component_execute). It just have to be compatible with the layout that the firmware
> loader expects. Not sure yet, if this will work out

That'd be great, yes! Worst case we can always add a "special" entry that is invisible in the boot menu, but contains metadata, no? It'd just be a normal IPL entry after all the user defined entries, just that nobody knows it exists ;).

> I definitely want to concentrate all booting in this device: kernel, zipl-virtio, firmware
> loader and everything else, because on system_reset we have to reset the cpus and set
> the PSW accordingly. As a device we are being called during reset at the right time.
> 
> Does that make sense? If yes I will try to refresh that patch as outlined above

Yes, that makes perfect sense :)


Alex

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-05-08 19:18 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-04 13:43 [Qemu-devel] [PATCH 0/1] RFC: ipl device for s390 Christian Borntraeger
2012-05-04 13:44 ` [Qemu-devel] [PATCH 1/1] s390: IPL " Christian Borntraeger
2012-05-04 13:53   ` Alexander Graf
2012-05-04 14:00     ` Christian Borntraeger
2012-05-04 14:02       ` Christian Borntraeger
2012-05-04 18:12         ` Alexander Graf
2012-05-08 12:32           ` Christian Borntraeger
2012-05-08 12:40             ` Alexander Graf
2012-05-08 14:43               ` Christian Borntraeger
2012-05-08 14:53                 ` Alexander Graf
2012-05-08 18:54                   ` Christian Borntraeger
2012-05-08 19:18                     ` Alexander Graf
2012-05-08 19:16             ` Anthony Liguori

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.