summaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-02-26 09:08:54 +0000
committerPeter Maydell <peter.maydell@linaro.org>2015-02-26 09:08:54 +0000
commit11d39a131020cc5c54ff9bc86d3259f7d32bf849 (patch)
tree0d2292e475e2e70f25d3b4c917552ff3e08a3026 /hw
parentc5c6d7f81a6950d8e32a3b5a0bafd37bfa5a8e88 (diff)
parente95d24ff40c77fbfd71396834a2eb99375f8bcc4 (diff)
downloadhqemu-11d39a131020cc5c54ff9bc86d3259f7d32bf849.zip
hqemu-11d39a131020cc5c54ff9bc86d3259f7d32bf849.tar.gz
Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20150218' into staging
Features for s390x/kvm 1. guest reIPL changes (Fan Zhang) Implements subcode 5 and 6 of diag 0x308. This allows to use /sys/firmware/[re]ipl/ccw/* and the chreipl and lsreipl tools in Linux. In addition to the normal "change the disk" this also allows to switch from booting an external kernel into rebooting from a disk. 2. Memory page table walking (Thomas Huth) Fix several page table walking functions, used in several places like gdb server and instruction handling. Also use these functions in several I/O related functions. # gpg: Signature made Wed Feb 18 09:13:22 2015 GMT using RSA key ID B5A61C7C # gpg: Good signature from "Christian Borntraeger (IBM) <borntraeger@de.ibm.com>" * remotes/borntraeger/tags/s390x-20150218: (29 commits) s390x/helper: Remove s390_cpu_physical_memory_map s390x/pci: Rework memory access in zpci instruction s390x/ioinst: Rework memory access in TPI instruction s390x/ioinst: Rework memory access in CHSC instruction s390x/ioinst: Rework memory access in STCRW instruction s390x/ioinst: Rework memory access in TSCH instruction s390x/ioinst: Set condition code in ioinst_handle_tsch() handler s390x/ioinst: Rework memory access in STSCH instruction s390x/ioinst: Rework memory access in SSCH instruction s390x/ioinst: Rework memory access in MSCH instruction s390x/css: Make schib parameter of css_do_msch const s390x/mmu: Add function for accessing guest memory s390x/kvm: Add function for injecting pgm access exceptions s390x/mmu: Clean up mmu_translate_asc() s390x/mmu: Check bit 52 in page table entry s390x/mmu: Renaming related to the ASCE confusion s390x/mmu: Add support for read-only regions s390x/mmu: Fix the exception codes for illegal table entries s390x/mmu: Fix exception types when checking the ASCEs s390x/mmu: Fix translation exception code in lowcore ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/s390x/css.c60
-rw-r--r--hw/s390x/ipl.c233
-rw-r--r--hw/s390x/ipl.h25
-rw-r--r--hw/s390x/s390-pci-inst.c37
-rw-r--r--hw/s390x/s390-virtio-ccw.c2
-rw-r--r--hw/s390x/s390-virtio.c8
-rw-r--r--hw/s390x/s390-virtio.h3
7 files changed, 279 insertions, 89 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index d0c5dde..9a13b00 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -584,7 +584,7 @@ static void copy_schib_from_guest(SCHIB *dest, const SCHIB *src)
}
}
-int css_do_msch(SubchDev *sch, SCHIB *orig_schib)
+int css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
{
SCSW *s = &sch->curr_status.scsw;
PMCW *p = &sch->curr_status.pmcw;
@@ -801,7 +801,8 @@ out:
return ret;
}
-static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
+static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw,
+ int *irb_len)
{
int i;
uint16_t stctl = src->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
@@ -815,6 +816,8 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) {
dest->ecw[i] = cpu_to_be32(src->ecw[i]);
}
+ *irb_len = sizeof(*dest) - sizeof(dest->emw);
+
/* extended measurements enabled? */
if ((src->scsw.flags & SCSW_FLAGS_MASK_ESWF) ||
!(pmcw->flags & PMCW_FLAGS_MASK_TF) ||
@@ -832,26 +835,21 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
dest->emw[i] = cpu_to_be32(src->emw[i]);
}
}
+ *irb_len = sizeof(*dest);
}
-int css_do_tsch(SubchDev *sch, IRB *target_irb)
+int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
{
SCSW *s = &sch->curr_status.scsw;
PMCW *p = &sch->curr_status.pmcw;
uint16_t stctl;
- uint16_t fctl;
- uint16_t actl;
IRB irb;
- int ret;
if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
- ret = 3;
- goto out;
+ return 3;
}
stctl = s->ctrl & SCSW_CTRL_MASK_STCTL;
- fctl = s->ctrl & SCSW_CTRL_MASK_FCTL;
- actl = s->ctrl & SCSW_CTRL_MASK_ACTL;
/* Prepare the irb for the guest. */
memset(&irb, 0, sizeof(IRB));
@@ -876,7 +874,22 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb)
}
}
/* Store the irb to the guest. */
- copy_irb_to_guest(target_irb, &irb, p);
+ copy_irb_to_guest(target_irb, &irb, p, irb_len);
+
+ return ((stctl & SCSW_STCTL_STATUS_PEND) == 0);
+}
+
+void css_do_tsch_update_subch(SubchDev *sch)
+{
+ SCSW *s = &sch->curr_status.scsw;
+ PMCW *p = &sch->curr_status.pmcw;
+ uint16_t stctl;
+ uint16_t fctl;
+ uint16_t actl;
+
+ stctl = s->ctrl & SCSW_CTRL_MASK_STCTL;
+ fctl = s->ctrl & SCSW_CTRL_MASK_FCTL;
+ actl = s->ctrl & SCSW_CTRL_MASK_ACTL;
/* Clear conditions on subchannel, if applicable. */
if (stctl & SCSW_STCTL_STATUS_PEND) {
@@ -913,11 +926,6 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb)
memset(sch->sense_data, 0 , sizeof(sch->sense_data));
}
}
-
- ret = ((stctl & SCSW_STCTL_STATUS_PEND) == 0);
-
-out:
- return ret;
}
static void copy_crw_to_guest(CRW *dest, const CRW *src)
@@ -947,6 +955,26 @@ int css_do_stcrw(CRW *crw)
return ret;
}
+static void copy_crw_from_guest(CRW *dest, const CRW *src)
+{
+ dest->flags = be16_to_cpu(src->flags);
+ dest->rsid = be16_to_cpu(src->rsid);
+}
+
+void css_undo_stcrw(CRW *crw)
+{
+ CrwContainer *crw_cont;
+
+ crw_cont = g_try_malloc0(sizeof(CrwContainer));
+ if (!crw_cont) {
+ channel_subsys->crws_lost = true;
+ return;
+ }
+ copy_crw_from_guest(&crw_cont->crw, crw);
+
+ QTAILQ_INSERT_HEAD(&channel_subsys->pending_crws, crw_cont, sibling);
+}
+
int css_do_tpi(IOIntCode *int_code, int lowcore)
{
/* No pending interrupts for !KVM. */
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 4ba8409..b57adbd 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -18,6 +18,7 @@
#include "hw/sysbus.h"
#include "hw/s390x/virtio-ccw.h"
#include "hw/s390x/css.h"
+#include "ipl.h"
#define KERN_IMAGE_START 0x010000UL
#define KERN_PARM_AREA 0x010480UL
@@ -50,14 +51,49 @@ typedef struct S390IPLState {
/*< private >*/
SysBusDevice parent_obj;
uint64_t start_addr;
+ uint64_t bios_start_addr;
+ bool enforce_bios;
+ IplParameterBlock iplb;
+ bool iplb_valid;
+ bool reipl_requested;
/*< public >*/
char *kernel;
char *initrd;
char *cmdline;
char *firmware;
+ uint8_t cssid;
+ uint8_t ssid;
+ uint16_t devno;
} S390IPLState;
+static const VMStateDescription vmstate_iplb = {
+ .name = "ipl/iplb",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8_ARRAY(reserved1, IplParameterBlock, 110),
+ VMSTATE_UINT16(devno, IplParameterBlock),
+ VMSTATE_UINT8_ARRAY(reserved2, IplParameterBlock, 88),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_ipl = {
+ .name = "ipl",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(start_addr, S390IPLState),
+ VMSTATE_UINT64(bios_start_addr, S390IPLState),
+ VMSTATE_STRUCT(iplb, S390IPLState, 0, vmstate_iplb, IplParameterBlock),
+ VMSTATE_BOOL(iplb_valid, S390IPLState),
+ VMSTATE_UINT8(cssid, S390IPLState),
+ VMSTATE_UINT8(ssid, S390IPLState),
+ VMSTATE_UINT16(devno, S390IPLState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int s390_ipl_init(SysBusDevice *dev)
{
@@ -65,11 +101,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 +118,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 +133,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;
+ /* default boot target is the bios */
+ ipl->start_addr = ipl->bios_start_addr;
}
- /*
- * 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;
- }
-
- 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,9 +194,82 @@ 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(),
};
+/*
+ * In addition to updating the iplstate, this function returns:
+ * - 0 if system was ipled with external kernel
+ * - -1 if no valid boot device was found
+ * - ccw id of the boot device otherwise
+ */
+static uint64_t s390_update_iplstate(CPUS390XState *env, S390IPLState *ipl)
+{
+ DeviceState *dev_st;
+
+ if (ipl->iplb_valid) {
+ ipl->cssid = 0;
+ ipl->ssid = 0;
+ ipl->devno = ipl->iplb.devno;
+ goto out;
+ }
+
+ if (ipl->kernel) {
+ return 0;
+ }
+
+ dev_st = get_boot_device(0);
+ if (dev_st) {
+ VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
+ OBJECT(qdev_get_parent_bus(dev_st)->parent),
+ TYPE_VIRTIO_CCW_DEVICE);
+ if (ccw_dev) {
+ ipl->cssid = ccw_dev->sch->cssid;
+ ipl->ssid = ccw_dev->sch->ssid;
+ ipl->devno = ccw_dev->sch->devno;
+ goto out;
+ }
+ }
+
+ return -1;
+out:
+ return ipl->cssid << 24 | ipl->ssid << 16 | ipl->devno;
+}
+
+int s390_ipl_update_diag308(IplParameterBlock *iplb)
+{
+ S390IPLState *ipl;
+
+ ipl = S390_IPL(object_resolve_path(TYPE_S390_IPL, NULL));
+ if (ipl) {
+ ipl->iplb = *iplb;
+ ipl->iplb_valid = true;
+ return 0;
+ }
+ return -1;
+}
+
+IplParameterBlock *s390_ipl_get_iplb(void)
+{
+ S390IPLState *ipl;
+
+ ipl = S390_IPL(object_resolve_path(TYPE_S390_IPL, NULL));
+ if (!ipl || !ipl->iplb_valid) {
+ return NULL;
+ }
+ return &ipl->iplb;
+}
+
+void s390_reipl_request(void)
+{
+ S390IPLState *ipl;
+
+ ipl = S390_IPL(object_resolve_path(TYPE_S390_IPL, NULL));
+ ipl->reipl_requested = true;
+ qemu_system_reset_request();
+}
+
static void s390_ipl_reset(DeviceState *dev)
{
S390IPLState *ipl = S390_IPL(dev);
@@ -160,21 +279,14 @@ static void s390_ipl_reset(DeviceState *dev)
env->psw.addr = ipl->start_addr;
env->psw.mask = IPL_PSW_MASK;
- if (!ipl->kernel) {
- /* Tell firmware, if there is a preferred boot device */
- env->regs[7] = -1;
- DeviceState *dev_st = get_boot_device(0);
- if (dev_st) {
- VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
- OBJECT(qdev_get_parent_bus(dev_st)->parent),
- TYPE_VIRTIO_CCW_DEVICE);
+ if (!ipl->reipl_requested) {
+ ipl->iplb_valid = false;
+ }
+ ipl->reipl_requested = false;
- if (ccw_dev) {
- env->regs[7] = ccw_dev->sch->cssid << 24 |
- ccw_dev->sch->ssid << 16 |
- ccw_dev->sch->devno;
- }
- }
+ if (!ipl->kernel || ipl->iplb_valid) {
+ env->psw.addr = ipl->bios_start_addr;
+ env->regs[7] = s390_update_iplstate(env, ipl);
}
s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
@@ -188,6 +300,7 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data)
k->init = s390_ipl_init;
dc->props = s390_ipl_properties;
dc->reset = s390_ipl_reset;
+ dc->vmsd = &vmstate_ipl;
}
static const TypeInfo s390_ipl_info = {
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
new file mode 100644
index 0000000..70497bc
--- /dev/null
+++ b/hw/s390x/ipl.h
@@ -0,0 +1,25 @@
+/*
+ * s390 IPL device
+ *
+ * Copyright 2015 IBM Corp.
+ * Author(s): Zhang Fan <bjfanzh@cn.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.
+ */
+
+#ifndef HW_S390_IPL_H
+#define HW_S390_IPL_H
+
+typedef struct IplParameterBlock {
+ uint8_t reserved1[110];
+ uint16_t devno;
+ uint8_t reserved2[88];
+} IplParameterBlock;
+
+int s390_ipl_update_diag308(IplParameterBlock *iplb);
+IplParameterBlock *s390_ipl_get_iplb(void);
+void s390_reipl_request(void);
+
+#endif
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 9e5bc5b..08d8aa6 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -155,7 +155,9 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
return 0;
}
- cpu_physical_memory_read(env->regs[r2], buffer, sizeof(*reqh));
+ if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer, sizeof(*reqh))) {
+ return 0;
+ }
reqh = (ClpReqHdr *)buffer;
req_len = lduw_p(&reqh->len);
if (req_len < 16 || req_len > 8184 || (req_len % 8 != 0)) {
@@ -163,7 +165,10 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
return 0;
}
- cpu_physical_memory_read(env->regs[r2], buffer, req_len + sizeof(*resh));
+ if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer,
+ req_len + sizeof(*resh))) {
+ return 0;
+ }
resh = (ClpRspHdr *)(buffer + req_len);
res_len = lduw_p(&resh->len);
if (res_len < 8 || res_len > 8176 || (res_len % 8 != 0)) {
@@ -175,7 +180,10 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
return 0;
}
- cpu_physical_memory_read(env->regs[r2], buffer, req_len + res_len);
+ if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer,
+ req_len + res_len)) {
+ return 0;
+ }
if (req_len != 32) {
stw_p(&resh->rsp, CLP_RC_LEN);
@@ -269,7 +277,10 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
}
out:
- cpu_physical_memory_write(env->regs[r2], buffer, req_len + res_len);
+ if (s390_cpu_virt_mem_write(cpu, env->regs[r2], buffer,
+ req_len + res_len)) {
+ return 0;
+ }
setcc(cpu, cc);
return 0;
}
@@ -539,10 +550,10 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr)
S390PCIBusDevice *pbdev;
MemoryRegion *mr;
int i;
- uint64_t val;
uint32_t fh;
uint8_t pcias;
uint8_t len;
+ uint8_t buffer[128];
if (env->psw.mask & PSW_MASK_PSTATE) {
program_interrupt(env, PGM_PRIVILEGED, 6);
@@ -590,9 +601,12 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr)
return 0;
}
+ if (s390_cpu_virt_mem_read(cpu, gaddr, buffer, len)) {
+ return 0;
+ }
+
for (i = 0; i < len / 8; i++) {
- val = ldq_phys(&address_space_memory, gaddr + i * 8);
- io_mem_write(mr, env->regs[r3] + i * 8, val, 8);
+ io_mem_write(mr, env->regs[r3] + i * 8, ldq_p(buffer + i * 8), 8);
}
setcc(cpu, ZPCI_PCI_LS_OK);
@@ -709,7 +723,9 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba)
return 0;
}
- cpu_physical_memory_read(fiba, (uint8_t *)&fib, sizeof(fib));
+ if (s390_cpu_virt_mem_read(cpu, fiba, (uint8_t *)&fib, sizeof(fib))) {
+ return 0;
+ }
switch (oc) {
case ZPCI_MOD_FC_REG_INT:
@@ -809,7 +825,10 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba)
fib.fc |= 0x10;
}
- cpu_physical_memory_write(fiba, (uint8_t *)&fib, sizeof(fib));
+ if (s390_cpu_virt_mem_write(cpu, fiba, (uint8_t *)&fib, sizeof(fib))) {
+ return 0;
+ }
+
setcc(cpu, cc);
return 0;
}
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 71bafe0..8f0ae59 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -126,7 +126,7 @@ static void ccw_init(MachineState *machine)
css_bus = virtual_css_bus_init();
s390_sclp_init();
s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline,
- machine->initrd_filename, "s390-ccw.img");
+ machine->initrd_filename, "s390-ccw.img", true);
s390_flic_init();
dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE);
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index c215cd8..412e49b 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -128,7 +128,8 @@ static void s390_virtio_register_hcalls(void)
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;
@@ -141,6 +142,9 @@ 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);
+ object_property_add_child(qdev_get_machine(), "s390-ipl",
+ OBJECT(dev), NULL);
qdev_init_nofail(dev);
}
@@ -221,7 +225,7 @@ static void s390_init(MachineState *machine)
s390_bus = s390_virtio_bus_init(&my_ram_size);
s390_sclp_init();
s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline,
- machine->initrd_filename, ZIPL_FILENAME);
+ machine->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 33847ae..75b67ed 100644
--- a/hw/s390x/s390-virtio.h
+++ b/hw/s390x/s390-virtio.h
@@ -26,7 +26,8 @@ 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);
void s390_nmi(NMIState *n, int cpu_index, Error **errp);
#endif
OpenPOWER on IntegriCloud