summaryrefslogtreecommitdiffstats
path: root/hw/s390x/ipl.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/s390x/ipl.c')
-rw-r--r--hw/s390x/ipl.c59
1 files changed, 56 insertions, 3 deletions
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 8c3e019571..ce21494c08 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -1,10 +1,11 @@
/*
* bootloader support
*
- * Copyright IBM, Corp. 2012
+ * Copyright IBM, Corp. 2012, 2020
*
* Authors:
* Christian Borntraeger <borntraeger@de.ibm.com>
+ * Janosch Frank <frankja@linux.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or (at your
* option) any later version. See the COPYING file in the top-level directory.
@@ -27,6 +28,7 @@
#include "hw/s390x/vfio-ccw.h"
#include "hw/s390x/css.h"
#include "hw/s390x/ebcdic.h"
+#include "hw/s390x/pv.h"
#include "ipl.h"
#include "qemu/error-report.h"
#include "qemu/config-file.h"
@@ -566,12 +568,31 @@ void s390_ipl_update_diag308(IplParameterBlock *iplb)
{
S390IPLState *ipl = get_ipl_device();
- ipl->iplb = *iplb;
- ipl->iplb_valid = true;
+ /*
+ * The IPLB set and retrieved by subcodes 8/9 is completely
+ * separate from the one managed via subcodes 5/6.
+ */
+ if (iplb->pbt == S390_IPL_TYPE_PV) {
+ ipl->iplb_pv = *iplb;
+ ipl->iplb_valid_pv = true;
+ } else {
+ ipl->iplb = *iplb;
+ ipl->iplb_valid = true;
+ }
ipl->netboot = is_virtio_net_device(iplb);
update_machine_ipl_properties(iplb);
}
+IplParameterBlock *s390_ipl_get_iplb_pv(void)
+{
+ S390IPLState *ipl = get_ipl_device();
+
+ if (!ipl->iplb_valid_pv) {
+ return NULL;
+ }
+ return &ipl->iplb_pv;
+}
+
IplParameterBlock *s390_ipl_get_iplb(void)
{
S390IPLState *ipl = get_ipl_device();
@@ -660,6 +681,38 @@ static void s390_ipl_prepare_qipl(S390CPU *cpu)
cpu_physical_memory_unmap(addr, len, 1, len);
}
+int s390_ipl_prepare_pv_header(void)
+{
+ IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
+ IPLBlockPV *ipib_pv = &ipib->pv;
+ void *hdr = g_malloc(ipib_pv->pv_header_len);
+ int rc;
+
+ cpu_physical_memory_read(ipib_pv->pv_header_addr, hdr,
+ ipib_pv->pv_header_len);
+ rc = s390_pv_set_sec_parms((uintptr_t)hdr,
+ ipib_pv->pv_header_len);
+ g_free(hdr);
+ return rc;
+}
+
+int s390_ipl_pv_unpack(void)
+{
+ IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
+ IPLBlockPV *ipib_pv = &ipib->pv;
+ int i, rc = 0;
+
+ for (i = 0; i < ipib_pv->num_comp; i++) {
+ rc = s390_pv_unpack(ipib_pv->components[i].addr,
+ TARGET_PAGE_ALIGN(ipib_pv->components[i].size),
+ ipib_pv->components[i].tweak_pref);
+ if (rc) {
+ break;
+ }
+ }
+ return rc;
+}
+
void s390_ipl_prepare_cpu(S390CPU *cpu)
{
S390IPLState *ipl = get_ipl_device();