summaryrefslogtreecommitdiffstats
path: root/hw/intc/s390_flic_kvm.c
diff options
context:
space:
mode:
authorFei Li2017-02-17 07:23:44 +0100
committerChristian Borntraeger2017-07-14 12:29:47 +0200
commit6c1dd652a606f4446cdb8883ac68d6fb54b02e5c (patch)
tree61060303f62a2f00b14a10c4d97a0c05c509f22e /hw/intc/s390_flic_kvm.c
parents390x: add flags field for registering I/O adapter (diff)
downloadqemu-6c1dd652a606f4446cdb8883ac68d6fb54b02e5c.tar.gz
qemu-6c1dd652a606f4446cdb8883ac68d6fb54b02e5c.tar.xz
qemu-6c1dd652a606f4446cdb8883ac68d6fb54b02e5c.zip
s390x/flic: introduce modify_ais_mode callback
In order to emulate the adapter interruption suppression (AIS) facility properly, the guest needs to be able to modify the AIS mask. Interrupt suppression will be handled via the flic (for kvm, via a recently introduced kernel backend; for !kvm, in the flic code), so let's introduce a method to change the mode via the flic interface. We introduce the 'simm' and 'nimm' fields to QEMUS390FLICState to store interruption modes for each ISC. Each bit in 'simm' and 'nimm' targets one ISC, and collaboratively indicate three modes: ALL-Interruptions, SINGLE-Interruption and NO-Interruptions. This interface can initiate most transitions between the states; transition from SINGLE-Interruption to NO-Interruptions via adapter interrupt injection will be introduced in a following patch. The meaningful combinations are as follows: interruption mode | simm bit | nimm bit ------------------|----------|---------- ALL | 0 | 0 SINGLE | 1 | 0 NO | 1 | 1 Co-authored-by: Yi Min Zhao <zyimin@linux.vnet.ibm.com> Signed-off-by: Yi Min Zhao <zyimin@linux.vnet.ibm.com> Signed-off-by: Fei Li <sherrylf@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'hw/intc/s390_flic_kvm.c')
-rw-r--r--hw/intc/s390_flic_kvm.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index 15ff534fd1..55aa35fc6a 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -20,6 +20,7 @@
#include "sysemu/kvm.h"
#include "hw/s390x/s390_flic.h"
#include "hw/s390x/adapter.h"
+#include "hw/s390x/css.h"
#include "trace.h"
#define FLIC_SAVE_INITIAL_SIZE getpagesize()
@@ -149,6 +150,26 @@ static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
return rc ? -errno : 0;
}
+static int kvm_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc,
+ uint16_t mode)
+{
+ KVMS390FLICState *flic = KVM_S390_FLIC(fs);
+ struct kvm_s390_ais_req req = {
+ .isc = isc,
+ .mode = mode,
+ };
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_AISM,
+ .addr = (uint64_t)&req,
+ };
+
+ if (!fs->ais_supported) {
+ return -ENOSYS;
+ }
+
+ return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
+}
+
/**
* __get_all_irqs - store all pending irqs in buffer
* @flic: pointer to flic device state
@@ -406,6 +427,7 @@ typedef struct KVMS390FLICStateClass {
static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
{
+ S390FLICState *fs = S390_FLIC_COMMON(dev);
KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
struct kvm_create_device cd = {0};
struct kvm_device_attr test_attr = {0};
@@ -438,6 +460,7 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
flic_state->clear_io_supported = !ioctl(flic_state->fd,
KVM_HAS_DEVICE_ATTR, test_attr);
+ fs->ais_supported = false;
return;
fail:
error_propagate(errp, errp_local);
@@ -446,10 +469,12 @@ fail:
static void kvm_s390_flic_reset(DeviceState *dev)
{
KVMS390FLICState *flic = KVM_S390_FLIC(dev);
+ S390FLICState *fs = S390_FLIC_COMMON(dev);
struct kvm_device_attr attr = {
.group = KVM_DEV_FLIC_CLEAR_IRQS,
};
int rc = 0;
+ uint8_t isc;
if (flic->fd == -1) {
return;
@@ -457,6 +482,16 @@ static void kvm_s390_flic_reset(DeviceState *dev)
flic_disable_wait_pfault(flic);
+ if (fs->ais_supported) {
+ for (isc = 0; isc <= MAX_ISC; isc++) {
+ rc = kvm_s390_modify_ais_mode(fs, isc, SIC_IRQ_MODE_ALL);
+ if (rc) {
+ error_report("Failed to reset ais mode for isc %d: %s",
+ isc, strerror(-rc));
+ }
+ }
+ }
+
rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
if (rc) {
trace_flic_reset_failed(errno);
@@ -479,6 +514,7 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
fsc->add_adapter_routes = kvm_s390_add_adapter_routes;
fsc->release_adapter_routes = kvm_s390_release_adapter_routes;
fsc->clear_io_irq = kvm_s390_clear_io_flic;
+ fsc->modify_ais_mode = kvm_s390_modify_ais_mode;
}
static const TypeInfo kvm_s390_flic_info = {