aboutsummaryrefslogtreecommitdiff
path: root/hw/s390x
diff options
context:
space:
mode:
Diffstat (limited to 'hw/s390x')
-rw-r--r--hw/s390x/s390-pci-bus.c22
-rw-r--r--hw/s390x/sclp.c18
2 files changed, 31 insertions, 9 deletions
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index f87d274..5282089 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -652,7 +652,16 @@ static const PCIIOMMUOps s390_iommu_ops = {
.get_address_space = s390_pci_dma_iommu,
};
-static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set)
+/**
+ * set_ind_bit_atomic - Atomically set a bit in an indicator
+ *
+ * @ind_loc: Address of the indicator
+ * @to_be_set: Bit to set
+ *
+ * Returns true if the bit was set by this function, false if it was
+ * already set or mapping failed.
+ */
+static bool set_ind_bit_atomic(uint64_t ind_loc, uint8_t to_be_set)
{
uint8_t expected, actual;
hwaddr len = 1;
@@ -662,7 +671,7 @@ static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set)
ind_addr = cpu_physical_memory_map(ind_loc, &len, true);
if (!ind_addr) {
s390_pci_generate_error_event(ERR_EVENT_AIRERR, 0, 0, 0, 0);
- return -1;
+ return false;
}
actual = *ind_addr;
do {
@@ -671,7 +680,7 @@ static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set)
} while (actual != expected);
cpu_physical_memory_unmap((void *)ind_addr, len, 1, len);
- return actual;
+ return (actual & to_be_set) ? false : true;
}
static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data,
@@ -693,10 +702,10 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data,
ind_bit = pbdev->routes.adapter.ind_offset;
sum_bit = pbdev->routes.adapter.summary_offset;
- set_ind_atomic(pbdev->routes.adapter.ind_addr + (ind_bit + vec) / 8,
+ set_ind_bit_atomic(pbdev->routes.adapter.ind_addr + (ind_bit + vec) / 8,
0x80 >> ((ind_bit + vec) % 8));
- if (!set_ind_atomic(pbdev->routes.adapter.summary_addr + sum_bit / 8,
- 0x80 >> (sum_bit % 8))) {
+ if (set_ind_bit_atomic(pbdev->routes.adapter.summary_addr + sum_bit / 8,
+ 0x80 >> (sum_bit % 8))) {
css_adapter_interrupt(CSS_IO_ADAPTER_PCI, pbdev->isc);
}
}
@@ -891,6 +900,7 @@ static void s390_pcihost_realize(DeviceState *dev, Error **errp)
s390_pci_init_default_group();
css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false,
S390_ADAPTER_SUPPRESSIBLE, errp);
+ s390_pcihost_kvm_realize();
}
static void s390_pcihost_unrealize(DeviceState *dev)
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 51e88ba..8602a56 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -306,6 +306,7 @@ int sclp_service_call(S390CPU *cpu, uint64_t sccb, uint32_t code)
g_autofree SCCB *work_sccb = NULL;
AddressSpace *as = CPU(cpu)->as;
const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
+ MemTxResult ret;
/* first some basic checks on program checks */
if (env->psw.mask & PSW_MASK_PSTATE) {
@@ -320,7 +321,10 @@ int sclp_service_call(S390CPU *cpu, uint64_t sccb, uint32_t code)
}
/* the header contains the actual length of the sccb */
- address_space_read(as, sccb, attrs, &header, sizeof(SCCBHeader));
+ ret = address_space_read(as, sccb, attrs, &header, sizeof(SCCBHeader));
+ if (ret != MEMTX_OK) {
+ return -PGM_ADDRESSING;
+ }
/* Valid sccb sizes */
if (be16_to_cpu(header.length) < sizeof(SCCBHeader)) {
@@ -333,7 +337,11 @@ int sclp_service_call(S390CPU *cpu, uint64_t sccb, uint32_t code)
* the host has checked the values
*/
work_sccb = g_malloc0(be16_to_cpu(header.length));
- address_space_read(as, sccb, attrs, work_sccb, be16_to_cpu(header.length));
+ ret = address_space_read(as, sccb, attrs,
+ work_sccb, be16_to_cpu(header.length));
+ if (ret != MEMTX_OK) {
+ return -PGM_ADDRESSING;
+ }
if (!sclp_command_code_valid(code)) {
work_sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
@@ -347,7 +355,11 @@ int sclp_service_call(S390CPU *cpu, uint64_t sccb, uint32_t code)
sclp_c->execute(sclp, work_sccb, code);
out_write:
- address_space_write(as, sccb, attrs, work_sccb, be16_to_cpu(header.length));
+ ret = address_space_write(as, sccb, attrs,
+ work_sccb, be16_to_cpu(header.length));
+ if (ret != MEMTX_OK) {
+ return -PGM_PROTECTION;
+ }
sclp_c->service_interrupt(sclp, sccb);