File 0190-s390x-ipl-always-load-the-bios-for-.patch of Package qemu.8405
From 178c4882efdc1ce4f3301e1353235f4d748f49c7 Mon Sep 17 00:00:00 2001
From: Fan Zhang <zhangfan@linux.vnet.ibm.com>
Date: Thu, 12 Feb 2015 18:02:13 +0100
Subject: [PATCH] s390x/ipl: always load the bios for ccw machine
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We will need bios support in order to be able to support selecting a
different boot device via diagnose 308 in the ccw machine, so let's
make the bios mandatory for the ccw machine.
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: Fan Zhang <zhangfan@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
(cherry picked from commit f0180f913e3bcd04cb132f5f6036e823a78e0673)
[AF: Rebased onto non-QOM-machine args]
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
hw/s390x/ipl.c | 105 +++++++++++++++++++++----------------
hw/s390x/s390-virtio-ccw.c | 2 +-
hw/s390x/s390-virtio.c | 6 ++-
hw/s390x/s390-virtio.h | 3 +-
4 files changed, 66 insertions(+), 50 deletions(-)
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index b94d19f435..8e58838d8c 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -50,6 +50,8 @@ typedef struct S390IPLState {
/*< private >*/
SysBusDevice parent_obj;
uint64_t start_addr;
+ uint64_t bios_start_addr;
+ bool enforce_bios;
/*< public >*/
char *kernel;
@@ -65,11 +67,14 @@ static int s390_ipl_init(SysBusDevice *dev)
uint64_t pentry = KERN_IMAGE_START;
int kernel_size;
- if (!ipl->kernel) {
- int bios_size;
- char *bios_filename;
+ int bios_size;
+ char *bios_filename;
- /* Load zipl bootloader */
+ /*
+ * Always load the bios if it was enforced,
+ * even if an external kernel has been defined.
+ */
+ if (!ipl->kernel || ipl->enforce_bios) {
if (bios_name == NULL) {
bios_name = ipl->firmware;
}
@@ -79,12 +84,12 @@ static int s390_ipl_init(SysBusDevice *dev)
hw_error("could not find stage1 bootloader\n");
}
- bios_size = load_elf(bios_filename, NULL, NULL, &ipl->start_addr, NULL,
- NULL, 1, ELF_MACHINE, 0);
+ bios_size = load_elf(bios_filename, NULL, NULL, &ipl->bios_start_addr,
+ NULL, NULL, 1, ELF_MACHINE, 0);
if (bios_size < 0) {
bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
4096);
- ipl->start_addr = ZIPL_IMAGE_START;
+ ipl->bios_start_addr = ZIPL_IMAGE_START;
if (bios_size > 4096) {
hw_error("stage1 bootloader is > 4k\n");
}
@@ -94,52 +99,59 @@ static int s390_ipl_init(SysBusDevice *dev)
if (bios_size == -1) {
hw_error("could not load bootloader '%s'\n", bios_name);
}
- return 0;
- }
- kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
- NULL, 1, ELF_MACHINE, 0);
- if (kernel_size < 0) {
- kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
- }
- if (kernel_size < 0) {
- fprintf(stderr, "could not load kernel '%s'\n", ipl->kernel);
- return -1;
- }
- /*
- * Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the
- * kernel parameters here as well. Note: For old kernels (up to 3.2)
- * we can not rely on the ELF entry point - it was 0x800 (the SALIPL
- * loader) and it won't work. For this case we force it to 0x10000, too.
- */
- if (pentry == KERN_IMAGE_START || pentry == 0x800) {
- ipl->start_addr = KERN_IMAGE_START;
- /* Overwrite parameters in the kernel image, which are "rom" */
- strcpy(rom_ptr(KERN_PARM_AREA), ipl->cmdline);
- } else {
- ipl->start_addr = pentry;
+ /* default boot target is the bios */
+ ipl->start_addr = ipl->bios_start_addr;
}
- if (ipl->initrd) {
- ram_addr_t initrd_offset;
- int initrd_size;
-
- initrd_offset = INITRD_START;
- while (kernel_size + 0x100000 > initrd_offset) {
- initrd_offset += 0x100000;
+ if (ipl->kernel) {
+ kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
+ NULL, 1, ELF_MACHINE, 0);
+ if (kernel_size < 0) {
+ kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
+ }
+ if (kernel_size < 0) {
+ fprintf(stderr, "could not load kernel '%s'\n", ipl->kernel);
+ return -1;
}
- initrd_size = load_image_targphys(ipl->initrd, initrd_offset,
- ram_size - initrd_offset);
- if (initrd_size == -1) {
- fprintf(stderr, "qemu: could not load initrd '%s'\n", ipl->initrd);
- exit(1);
+ /*
+ * Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the
+ * kernel parameters here as well. Note: For old kernels (up to 3.2)
+ * we can not rely on the ELF entry point - it was 0x800 (the SALIPL
+ * loader) and it won't work. For this case we force it to 0x10000, too.
+ */
+ if (pentry == KERN_IMAGE_START || pentry == 0x800) {
+ ipl->start_addr = KERN_IMAGE_START;
+ /* Overwrite parameters in the kernel image, which are "rom" */
+ strcpy(rom_ptr(KERN_PARM_AREA), ipl->cmdline);
+ } else {
+ ipl->start_addr = pentry;
}
- /* we have to overwrite values in the kernel image, which are "rom" */
- stq_p(rom_ptr(INITRD_PARM_START), initrd_offset);
- stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size);
- }
+ if (ipl->initrd) {
+ ram_addr_t initrd_offset;
+ int initrd_size;
+
+ initrd_offset = INITRD_START;
+ while (kernel_size + 0x100000 > initrd_offset) {
+ initrd_offset += 0x100000;
+ }
+ initrd_size = load_image_targphys(ipl->initrd, initrd_offset,
+ ram_size - initrd_offset);
+ if (initrd_size == -1) {
+ fprintf(stderr, "qemu: could not load initrd '%s'\n",
+ ipl->initrd);
+ exit(1);
+ }
+ /*
+ * we have to overwrite values in the kernel image,
+ * which are "rom"
+ */
+ stq_p(rom_ptr(INITRD_PARM_START), initrd_offset);
+ stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size);
+ }
+ }
return 0;
}
@@ -148,6 +160,7 @@ 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_BOOL("enforce_bios", S390IPLState, enforce_bios, false),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 1b5bf59b3a..8565ce2b17 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -103,7 +103,7 @@ static void ccw_init(QEMUMachineInitArgs *args)
css_bus = virtual_css_bus_init();
s390_sclp_init();
s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline,
- args->initrd_filename, "s390-ccw.img");
+ args->initrd_filename, "s390-ccw.img", true);
s390_flic_init();
/* register hypercalls */
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index 01f89d15d5..17eabf6ab5 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -163,7 +163,8 @@ unsigned s390_del_running_cpu(S390CPU *cpu)
void s390_init_ipl_dev(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
- const char *firmware)
+ const char *firmware,
+ bool enforce_bios)
{
DeviceState *dev;
@@ -176,6 +177,7 @@ 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);
qdev_init_nofail(dev);
}
@@ -254,7 +256,7 @@ static void s390_init(QEMUMachineInitArgs *args)
s390_bus = s390_virtio_bus_init(&my_ram_size);
s390_sclp_init();
s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline,
- args->initrd_filename, ZIPL_FILENAME);
+ args->initrd_filename, ZIPL_FILENAME, false);
s390_flic_init();
/* register hypercalls */
diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h
index 5c405e7755..c98d6ee1d9 100644
--- a/hw/s390x/s390-virtio.h
+++ b/hw/s390x/s390-virtio.h
@@ -24,6 +24,7 @@ void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys);
void s390_init_ipl_dev(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
- const char *firmware);
+ const char *firmware,
+ bool enforce_bios);
void s390_create_virtio_net(BusState *bus, const char *name);
#endif