|
|
016a62 |
From 2f0454ccd0dd12429e8c204933cafe71a248d4eb Mon Sep 17 00:00:00 2001
|
|
|
016a62 |
From: Thomas Huth <thuth@redhat.com>
|
|
|
016a62 |
Date: Mon, 14 Oct 2019 10:06:30 +0100
|
|
|
016a62 |
Subject: [PATCH 05/21] pc-bios/s390-ccw/net: Use diag308 to reset machine
|
|
|
016a62 |
before jumping to the OS
|
|
|
016a62 |
|
|
|
016a62 |
RH-Author: Thomas Huth <thuth@redhat.com>
|
|
|
016a62 |
Message-id: <20191014100645.22862-3-thuth@redhat.com>
|
|
|
016a62 |
Patchwork-id: 91777
|
|
|
016a62 |
O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 02/17] pc-bios/s390-ccw/net: Use diag308 to reset machine before jumping to the OS
|
|
|
016a62 |
Bugzilla: 1664376
|
|
|
016a62 |
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
|
|
016a62 |
RH-Acked-by: David Hildenbrand <david@redhat.com>
|
|
|
016a62 |
RH-Acked-by: Jens Freimann <jfreimann@redhat.com>
|
|
|
016a62 |
|
|
|
016a62 |
The netboot firmware so far simply jumped directly into the OS kernel
|
|
|
016a62 |
after the download has been completed. This, however, bears the risk
|
|
|
016a62 |
that the virtio-net device still might be active in the background and
|
|
|
016a62 |
incoming packets are still placed into the buffers - which could destroy
|
|
|
016a62 |
memory of the now-running Linux kernel in case it did not take over the
|
|
|
016a62 |
device fast enough. Also the SCLP console is not put into a well-defined
|
|
|
016a62 |
state here. We should hand over the system in a clean state when jumping
|
|
|
016a62 |
into the kernel, so let's use the same mechanism as it's done in the
|
|
|
016a62 |
main s390-ccw firmware and reset the machine with diag308 into a clean
|
|
|
016a62 |
state before jumping into the OS kernel code. To be able to share the
|
|
|
016a62 |
code with the main s390-ccw firmware, the related functions are now
|
|
|
016a62 |
extracted from bootmap.c into a new file called jump2ipl.c.
|
|
|
016a62 |
|
|
|
016a62 |
Since we now also set the boot device schid at address 184 for the network
|
|
|
016a62 |
boot device, this patch also slightly changes the way how we detect the
|
|
|
016a62 |
entry points for non-ELF binary images: The code now looks for the "S390EP"
|
|
|
016a62 |
magic first and then jumps to 0x10000 in case it has been found. This is
|
|
|
016a62 |
necessary for booting from network devices, since the normal kernel code
|
|
|
016a62 |
(where the PSW at ddress 0 points to) tries to do a block load from the
|
|
|
016a62 |
boot device. This of course fails for a virtio-net device and causes the
|
|
|
016a62 |
kernel to abort with a panic-PSW silently.
|
|
|
016a62 |
|
|
|
016a62 |
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
|
|
|
016a62 |
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
|
|
016a62 |
(cherry picked from commit 9a848adf45d6732e62551decb3c0255173090767)
|
|
|
016a62 |
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
|
|
016a62 |
---
|
|
|
016a62 |
pc-bios/s390-ccw/Makefile | 4 +-
|
|
|
016a62 |
pc-bios/s390-ccw/bootmap.c | 63 +-----------------------------
|
|
|
016a62 |
pc-bios/s390-ccw/bootmap.h | 4 --
|
|
|
016a62 |
pc-bios/s390-ccw/jump2ipl.c | 91 ++++++++++++++++++++++++++++++++++++++++++++
|
|
|
016a62 |
pc-bios/s390-ccw/netboot.mak | 3 +-
|
|
|
016a62 |
pc-bios/s390-ccw/netmain.c | 11 +++++-
|
|
|
016a62 |
pc-bios/s390-ccw/s390-ccw.h | 4 ++
|
|
|
016a62 |
7 files changed, 111 insertions(+), 69 deletions(-)
|
|
|
016a62 |
create mode 100644 pc-bios/s390-ccw/jump2ipl.c
|
|
|
016a62 |
|
|
|
016a62 |
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
|
|
|
016a62 |
index 1712c2d..439e3cc 100644
|
|
|
016a62 |
--- a/pc-bios/s390-ccw/Makefile
|
|
|
016a62 |
+++ b/pc-bios/s390-ccw/Makefile
|
|
|
016a62 |
@@ -9,7 +9,9 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
|
|
|
016a62 |
|
|
|
016a62 |
.PHONY : all clean build-all
|
|
|
016a62 |
|
|
|
016a62 |
-OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blkdev.o libc.o menu.o
|
|
|
016a62 |
+OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \
|
|
|
016a62 |
+ virtio.o virtio-scsi.o virtio-blkdev.o libc.o
|
|
|
016a62 |
+
|
|
|
016a62 |
QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
|
|
|
016a62 |
QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
|
|
|
016a62 |
QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing
|
|
|
016a62 |
diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
|
|
|
016a62 |
index ffbf671..d13b7cb 100644
|
|
|
016a62 |
--- a/pc-bios/s390-ccw/bootmap.c
|
|
|
016a62 |
+++ b/pc-bios/s390-ccw/bootmap.c
|
|
|
016a62 |
@@ -29,14 +29,6 @@
|
|
|
016a62 |
/* Scratch space */
|
|
|
016a62 |
static uint8_t sec[MAX_SECTOR_SIZE*4] __attribute__((__aligned__(PAGE_SIZE)));
|
|
|
016a62 |
|
|
|
016a62 |
-typedef struct ResetInfo {
|
|
|
016a62 |
- uint32_t ipl_mask;
|
|
|
016a62 |
- uint32_t ipl_addr;
|
|
|
016a62 |
- uint32_t ipl_continue;
|
|
|
016a62 |
-} ResetInfo;
|
|
|
016a62 |
-
|
|
|
016a62 |
-static ResetInfo save;
|
|
|
016a62 |
-
|
|
|
016a62 |
const uint8_t el_torito_magic[] = "EL TORITO SPECIFICATION"
|
|
|
016a62 |
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
|
|
016a62 |
|
|
|
016a62 |
@@ -57,53 +49,6 @@ static inline bool is_iso_vd_valid(IsoVolDesc *vd)
|
|
|
016a62 |
vd->type <= VOL_DESC_TYPE_PARTITION;
|
|
|
016a62 |
}
|
|
|
016a62 |
|
|
|
016a62 |
-static void jump_to_IPL_2(void)
|
|
|
016a62 |
-{
|
|
|
016a62 |
- ResetInfo *current = 0;
|
|
|
016a62 |
-
|
|
|
016a62 |
- void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue;
|
|
|
016a62 |
- *current = save;
|
|
|
016a62 |
- ipl(); /* should not return */
|
|
|
016a62 |
-}
|
|
|
016a62 |
-
|
|
|
016a62 |
-static void jump_to_IPL_code(uint64_t address)
|
|
|
016a62 |
-{
|
|
|
016a62 |
- /* store the subsystem information _after_ the bootmap was loaded */
|
|
|
016a62 |
- write_subsystem_identification();
|
|
|
016a62 |
-
|
|
|
016a62 |
- /* prevent unknown IPL types in the guest */
|
|
|
016a62 |
- if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) {
|
|
|
016a62 |
- iplb.pbt = S390_IPL_TYPE_CCW;
|
|
|
016a62 |
- set_iplb(&iplb);
|
|
|
016a62 |
- }
|
|
|
016a62 |
-
|
|
|
016a62 |
- /*
|
|
|
016a62 |
- * The IPL PSW is at address 0. We also must not overwrite the
|
|
|
016a62 |
- * content of non-BIOS memory after we loaded the guest, so we
|
|
|
016a62 |
- * save the original content and restore it in jump_to_IPL_2.
|
|
|
016a62 |
- */
|
|
|
016a62 |
- ResetInfo *current = 0;
|
|
|
016a62 |
-
|
|
|
016a62 |
- save = *current;
|
|
|
016a62 |
- current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2;
|
|
|
016a62 |
- current->ipl_continue = address & 0x7fffffff;
|
|
|
016a62 |
-
|
|
|
016a62 |
- debug_print_int("set IPL addr to", current->ipl_continue);
|
|
|
016a62 |
-
|
|
|
016a62 |
- /* Ensure the guest output starts fresh */
|
|
|
016a62 |
- sclp_print("\n");
|
|
|
016a62 |
-
|
|
|
016a62 |
- /*
|
|
|
016a62 |
- * HACK ALERT.
|
|
|
016a62 |
- * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2
|
|
|
016a62 |
- * can then use r15 as its stack pointer.
|
|
|
016a62 |
- */
|
|
|
016a62 |
- asm volatile("lghi 1,1\n\t"
|
|
|
016a62 |
- "diag 1,1,0x308\n\t"
|
|
|
016a62 |
- : : : "1", "memory");
|
|
|
016a62 |
- panic("\n! IPL returns !\n");
|
|
|
016a62 |
-}
|
|
|
016a62 |
-
|
|
|
016a62 |
/***********************************************************************
|
|
|
016a62 |
* IPL an ECKD DASD (CDL or LDL/CMS format)
|
|
|
016a62 |
*/
|
|
|
016a62 |
@@ -744,13 +689,7 @@ static void load_iso_bc_entry(IsoBcSection *load)
|
|
|
016a62 |
(void *)((uint64_t)bswap16(s.load_segment)),
|
|
|
016a62 |
blks_to_load);
|
|
|
016a62 |
|
|
|
016a62 |
- /* Trying to get PSW at zero address */
|
|
|
016a62 |
- if (*((uint64_t *)0) & IPL_PSW_MASK) {
|
|
|
016a62 |
- jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff);
|
|
|
016a62 |
- }
|
|
|
016a62 |
-
|
|
|
016a62 |
- /* Try default linux start address */
|
|
|
016a62 |
- jump_to_IPL_code(KERN_IMAGE_START);
|
|
|
016a62 |
+ jump_to_low_kernel();
|
|
|
016a62 |
}
|
|
|
016a62 |
|
|
|
016a62 |
static uint32_t find_iso_bc(void)
|
|
|
016a62 |
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
|
|
|
016a62 |
index f1ce423..94f53a5 100644
|
|
|
016a62 |
--- a/pc-bios/s390-ccw/bootmap.h
|
|
|
016a62 |
+++ b/pc-bios/s390-ccw/bootmap.h
|
|
|
016a62 |
@@ -355,10 +355,6 @@ static inline uint32_t iso_733_to_u32(uint64_t x)
|
|
|
016a62 |
#define ISO_SECTOR_SIZE 2048
|
|
|
016a62 |
/* El Torito specifies boot image size in 512 byte blocks */
|
|
|
016a62 |
#define ET_SECTOR_SHIFT 2
|
|
|
016a62 |
-#define KERN_IMAGE_START 0x010000UL
|
|
|
016a62 |
-#define PSW_MASK_64 0x0000000100000000ULL
|
|
|
016a62 |
-#define PSW_MASK_32 0x0000000080000000ULL
|
|
|
016a62 |
-#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
|
|
|
016a62 |
|
|
|
016a62 |
#define ISO_PRIMARY_VD_SECTOR 16
|
|
|
016a62 |
|
|
|
016a62 |
diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c
|
|
|
016a62 |
new file mode 100644
|
|
|
016a62 |
index 0000000..266f150
|
|
|
016a62 |
--- /dev/null
|
|
|
016a62 |
+++ b/pc-bios/s390-ccw/jump2ipl.c
|
|
|
016a62 |
@@ -0,0 +1,91 @@
|
|
|
016a62 |
+/*
|
|
|
016a62 |
+ * QEMU s390-ccw firmware - jump to IPL code
|
|
|
016a62 |
+ *
|
|
|
016a62 |
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
|
|
|
016a62 |
+ * your option) any later version. See the COPYING file in the top-level
|
|
|
016a62 |
+ * directory.
|
|
|
016a62 |
+ */
|
|
|
016a62 |
+
|
|
|
016a62 |
+#include "libc.h"
|
|
|
016a62 |
+#include "s390-ccw.h"
|
|
|
016a62 |
+
|
|
|
016a62 |
+#define KERN_IMAGE_START 0x010000UL
|
|
|
016a62 |
+#define PSW_MASK_64 0x0000000100000000ULL
|
|
|
016a62 |
+#define PSW_MASK_32 0x0000000080000000ULL
|
|
|
016a62 |
+#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
|
|
|
016a62 |
+
|
|
|
016a62 |
+typedef struct ResetInfo {
|
|
|
016a62 |
+ uint32_t ipl_mask;
|
|
|
016a62 |
+ uint32_t ipl_addr;
|
|
|
016a62 |
+ uint32_t ipl_continue;
|
|
|
016a62 |
+} ResetInfo;
|
|
|
016a62 |
+
|
|
|
016a62 |
+static ResetInfo save;
|
|
|
016a62 |
+
|
|
|
016a62 |
+static void jump_to_IPL_2(void)
|
|
|
016a62 |
+{
|
|
|
016a62 |
+ ResetInfo *current = 0;
|
|
|
016a62 |
+
|
|
|
016a62 |
+ void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue;
|
|
|
016a62 |
+ *current = save;
|
|
|
016a62 |
+ ipl(); /* should not return */
|
|
|
016a62 |
+}
|
|
|
016a62 |
+
|
|
|
016a62 |
+void jump_to_IPL_code(uint64_t address)
|
|
|
016a62 |
+{
|
|
|
016a62 |
+ /* store the subsystem information _after_ the bootmap was loaded */
|
|
|
016a62 |
+ write_subsystem_identification();
|
|
|
016a62 |
+
|
|
|
016a62 |
+ /* prevent unknown IPL types in the guest */
|
|
|
016a62 |
+ if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) {
|
|
|
016a62 |
+ iplb.pbt = S390_IPL_TYPE_CCW;
|
|
|
016a62 |
+ set_iplb(&iplb);
|
|
|
016a62 |
+ }
|
|
|
016a62 |
+
|
|
|
016a62 |
+ /*
|
|
|
016a62 |
+ * The IPL PSW is at address 0. We also must not overwrite the
|
|
|
016a62 |
+ * content of non-BIOS memory after we loaded the guest, so we
|
|
|
016a62 |
+ * save the original content and restore it in jump_to_IPL_2.
|
|
|
016a62 |
+ */
|
|
|
016a62 |
+ ResetInfo *current = 0;
|
|
|
016a62 |
+
|
|
|
016a62 |
+ save = *current;
|
|
|
016a62 |
+ current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2;
|
|
|
016a62 |
+ current->ipl_continue = address & 0x7fffffff;
|
|
|
016a62 |
+
|
|
|
016a62 |
+ debug_print_int("set IPL addr to", current->ipl_continue);
|
|
|
016a62 |
+
|
|
|
016a62 |
+ /* Ensure the guest output starts fresh */
|
|
|
016a62 |
+ sclp_print("\n");
|
|
|
016a62 |
+
|
|
|
016a62 |
+ /*
|
|
|
016a62 |
+ * HACK ALERT.
|
|
|
016a62 |
+ * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2
|
|
|
016a62 |
+ * can then use r15 as its stack pointer.
|
|
|
016a62 |
+ */
|
|
|
016a62 |
+ asm volatile("lghi 1,1\n\t"
|
|
|
016a62 |
+ "diag 1,1,0x308\n\t"
|
|
|
016a62 |
+ : : : "1", "memory");
|
|
|
016a62 |
+ panic("\n! IPL returns !\n");
|
|
|
016a62 |
+}
|
|
|
016a62 |
+
|
|
|
016a62 |
+void jump_to_low_kernel(void)
|
|
|
016a62 |
+{
|
|
|
016a62 |
+ /*
|
|
|
016a62 |
+ * If it looks like a Linux binary, i.e. there is the "S390EP" magic from
|
|
|
016a62 |
+ * arch/s390/kernel/head.S here, then let's jump to the well-known Linux
|
|
|
016a62 |
+ * kernel start address (when jumping to the PSW-at-zero address instead,
|
|
|
016a62 |
+ * the kernel startup code fails when we booted from a network device).
|
|
|
016a62 |
+ */
|
|
|
016a62 |
+ if (!memcmp((char *)0x10008, "S390EP", 6)) {
|
|
|
016a62 |
+ jump_to_IPL_code(KERN_IMAGE_START);
|
|
|
016a62 |
+ }
|
|
|
016a62 |
+
|
|
|
016a62 |
+ /* Trying to get PSW at zero address */
|
|
|
016a62 |
+ if (*((uint64_t *)0) & IPL_PSW_MASK) {
|
|
|
016a62 |
+ jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff);
|
|
|
016a62 |
+ }
|
|
|
016a62 |
+
|
|
|
016a62 |
+ /* No other option left, so use the Linux kernel start address */
|
|
|
016a62 |
+ jump_to_IPL_code(KERN_IMAGE_START);
|
|
|
016a62 |
+}
|
|
|
016a62 |
diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak
|
|
|
016a62 |
index a25d238..4f64128 100644
|
|
|
016a62 |
--- a/pc-bios/s390-ccw/netboot.mak
|
|
|
016a62 |
+++ b/pc-bios/s390-ccw/netboot.mak
|
|
|
016a62 |
@@ -1,7 +1,8 @@
|
|
|
016a62 |
|
|
|
016a62 |
SLOF_DIR := $(SRC_PATH)/roms/SLOF
|
|
|
016a62 |
|
|
|
016a62 |
-NETOBJS := start.o sclp.o virtio.o virtio-net.o netmain.o libnet.a libc.a
|
|
|
016a62 |
+NETOBJS := start.o sclp.o virtio.o virtio-net.o jump2ipl.o netmain.o \
|
|
|
016a62 |
+ libnet.a libc.a
|
|
|
016a62 |
|
|
|
016a62 |
LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include
|
|
|
016a62 |
LIBNET_INC := -I$(SLOF_DIR)/lib/libnet
|
|
|
016a62 |
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
|
|
|
016a62 |
index d86d46b..d60e84f 100644
|
|
|
016a62 |
--- a/pc-bios/s390-ccw/netmain.c
|
|
|
016a62 |
+++ b/pc-bios/s390-ccw/netmain.c
|
|
|
016a62 |
@@ -281,6 +281,15 @@ void panic(const char *string)
|
|
|
016a62 |
}
|
|
|
016a62 |
}
|
|
|
016a62 |
|
|
|
016a62 |
+void write_subsystem_identification(void)
|
|
|
016a62 |
+{
|
|
|
016a62 |
+ SubChannelId *schid = (SubChannelId *) 184;
|
|
|
016a62 |
+ uint32_t *zeroes = (uint32_t *) 188;
|
|
|
016a62 |
+
|
|
|
016a62 |
+ *schid = net_schid;
|
|
|
016a62 |
+ *zeroes = 0;
|
|
|
016a62 |
+}
|
|
|
016a62 |
+
|
|
|
016a62 |
static bool find_net_dev(Schib *schib, int dev_no)
|
|
|
016a62 |
{
|
|
|
016a62 |
int i, r;
|
|
|
016a62 |
@@ -354,7 +363,7 @@ void main(void)
|
|
|
016a62 |
rc = net_load(NULL, (long)_start);
|
|
|
016a62 |
if (rc > 0) {
|
|
|
016a62 |
sclp_print("Network loading done, starting kernel...\n");
|
|
|
016a62 |
- asm volatile (" lpsw 0(%0) " : : "r"(0) : "memory");
|
|
|
016a62 |
+ jump_to_low_kernel();
|
|
|
016a62 |
}
|
|
|
016a62 |
|
|
|
016a62 |
panic("Failed to load OS from network\n");
|
|
|
016a62 |
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
|
|
|
016a62 |
index a1bdb4c..9828aa2 100644
|
|
|
016a62 |
--- a/pc-bios/s390-ccw/s390-ccw.h
|
|
|
016a62 |
+++ b/pc-bios/s390-ccw/s390-ccw.h
|
|
|
016a62 |
@@ -87,6 +87,10 @@ ulong get_second(void);
|
|
|
016a62 |
/* bootmap.c */
|
|
|
016a62 |
void zipl_load(void);
|
|
|
016a62 |
|
|
|
016a62 |
+/* jump2ipl.c */
|
|
|
016a62 |
+void jump_to_IPL_code(uint64_t address);
|
|
|
016a62 |
+void jump_to_low_kernel(void);
|
|
|
016a62 |
+
|
|
|
016a62 |
/* menu.c */
|
|
|
016a62 |
void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout);
|
|
|
016a62 |
int menu_get_zipl_boot_index(const char *menu_data);
|
|
|
016a62 |
--
|
|
|
016a62 |
1.8.3.1
|
|
|
016a62 |
|