Pablo Greco e6a3ae
From 8128e12a8cb09bdb6bcb1b5735a9726f689e27c3 Mon Sep 17 00:00:00 2001
Pablo Greco e6a3ae
From: Cornelia Huck <cohuck@redhat.com>
Pablo Greco e6a3ae
Date: Wed, 17 Apr 2019 13:57:18 +0100
Pablo Greco e6a3ae
Subject: [PATCH 01/24] s390x/ipl: Try to detect Linux vs non Linux for initial
Pablo Greco e6a3ae
 IPL PSW
Pablo Greco e6a3ae
Pablo Greco e6a3ae
RH-Author: Cornelia Huck <cohuck@redhat.com>
Pablo Greco e6a3ae
Message-id: <20190417135741.25297-2-cohuck@redhat.com>
Pablo Greco e6a3ae
Patchwork-id: 85783
Pablo Greco e6a3ae
O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 01/24] s390x/ipl: Try to detect Linux vs non Linux for initial IPL PSW
Pablo Greco e6a3ae
Bugzilla: 1699070
Pablo Greco e6a3ae
RH-Acked-by: David Hildenbrand <david@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Thomas Huth <thuth@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Jens Freimann <jfreimann@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
From: Christian Borntraeger <borntraeger@de.ibm.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Right now the IPL device always starts from address 0x10000 (the usual
Pablo Greco e6a3ae
Linux entry point). To run other guests (e.g. test programs) it is
Pablo Greco e6a3ae
useful to use the IPL PSW from address 0. We can use the Linux magic
Pablo Greco e6a3ae
at 0x10008 to decide.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Pablo Greco e6a3ae
Message-Id: <20180612125933.262679-1-borntraeger@de.ibm.com>
Pablo Greco e6a3ae
Reviewed-by: David Hildenbrand <david@redhat.com>
Pablo Greco e6a3ae
Reviewed-by: Thomas Huth <thuth@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Pablo Greco e6a3ae
(cherry picked from commit acd7ef837d8987ad4ef2ab8f8e8c0f13ab413dd5)
Pablo Greco e6a3ae
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
Pablo Greco e6a3ae
---
Pablo Greco e6a3ae
 hw/s390x/ipl.c | 27 ++++++++++++++++++++++-----
Pablo Greco e6a3ae
 1 file changed, 22 insertions(+), 5 deletions(-)
Pablo Greco e6a3ae
Pablo Greco e6a3ae
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
Pablo Greco e6a3ae
index 150f6c0..617ac43 100644
Pablo Greco e6a3ae
--- a/hw/s390x/ipl.c
Pablo Greco e6a3ae
+++ b/hw/s390x/ipl.c
Pablo Greco e6a3ae
@@ -28,6 +28,7 @@
Pablo Greco e6a3ae
 #include "qemu/option.h"
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 #define KERN_IMAGE_START                0x010000UL
Pablo Greco e6a3ae
+#define LINUX_MAGIC_ADDR                0x010008UL
Pablo Greco e6a3ae
 #define KERN_PARM_AREA                  0x010480UL
Pablo Greco e6a3ae
 #define INITRD_START                    0x800000UL
Pablo Greco e6a3ae
 #define INITRD_PARM_START               0x010408UL
Pablo Greco e6a3ae
@@ -104,7 +105,9 @@ static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr)
Pablo Greco e6a3ae
 static void s390_ipl_realize(DeviceState *dev, Error **errp)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
     S390IPLState *ipl = S390_IPL(dev);
Pablo Greco e6a3ae
-    uint64_t pentry = KERN_IMAGE_START;
Pablo Greco e6a3ae
+    uint32_t *ipl_psw;
Pablo Greco e6a3ae
+    uint64_t pentry;
Pablo Greco e6a3ae
+    char *magic;
Pablo Greco e6a3ae
     int kernel_size;
Pablo Greco e6a3ae
     Error *err = NULL;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
@@ -156,10 +159,24 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
Pablo Greco e6a3ae
                                NULL, 1, EM_S390, 0, 0);
Pablo Greco e6a3ae
         if (kernel_size < 0) {
Pablo Greco e6a3ae
             kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
Pablo Greco e6a3ae
-        }
Pablo Greco e6a3ae
-        if (kernel_size < 0) {
Pablo Greco e6a3ae
-            error_setg(&err, "could not load kernel '%s'", ipl->kernel);
Pablo Greco e6a3ae
-            goto error;
Pablo Greco e6a3ae
+            if (kernel_size < 0) {
Pablo Greco e6a3ae
+                error_setg(&err, "could not load kernel '%s'", ipl->kernel);
Pablo Greco e6a3ae
+                goto error;
Pablo Greco e6a3ae
+            }
Pablo Greco e6a3ae
+            /* if this is Linux use KERN_IMAGE_START */
Pablo Greco e6a3ae
+            magic = rom_ptr(LINUX_MAGIC_ADDR);
Pablo Greco e6a3ae
+            if (magic && !memcmp(magic, "S390EP", 6)) {
Pablo Greco e6a3ae
+                pentry = KERN_IMAGE_START;
Pablo Greco e6a3ae
+            } else {
Pablo Greco e6a3ae
+                /* if not Linux load the address of the (short) IPL PSW */
Pablo Greco e6a3ae
+                ipl_psw = rom_ptr(4);
Pablo Greco e6a3ae
+                if (ipl_psw) {
Pablo Greco e6a3ae
+                    pentry = be32_to_cpu(*ipl_psw) & 0x7fffffffUL;
Pablo Greco e6a3ae
+                } else {
Pablo Greco e6a3ae
+                    error_setg(&err, "Could not get IPL PSW");
Pablo Greco e6a3ae
+                    goto error;
Pablo Greco e6a3ae
+                }
Pablo Greco e6a3ae
+            }
Pablo Greco e6a3ae
         }
Pablo Greco e6a3ae
         /*
Pablo Greco e6a3ae
          * Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the
Pablo Greco e6a3ae
-- 
Pablo Greco e6a3ae
1.8.3.1
Pablo Greco e6a3ae