aboutsummaryrefslogtreecommitdiff
path: root/hw/intc/s390_flic_kvm.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-07-14 14:19:35 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-07-14 14:19:35 +0100
commitfbc8ea1ed0704b0cd393e5dc429816a36cb5ed05 (patch)
tree889e3e593b0feb364012d94350b43a130b832d32 /hw/intc/s390_flic_kvm.c
parent6c6076662d98c068059983d411cb2a8987ba5670 (diff)
parent86158a2a2b81f075c84d0b95c6d72b98dbf1dc61 (diff)
Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20170714' into staging
s390x/kvm/migration/cpumodel: fixes, enhancements and cleanups - add a network boot rom for s390 (Thomas Huth) - migration of storage attributes like the CMMA used/unused state - PCI related enhancements - full support for aen, ais and zpci - migration support for css with vmstates (Halil Pasic) - cpu model enhancements for cpu features - guarded storage support # gpg: Signature made Fri 14 Jul 2017 11:33:04 BST # gpg: using RSA key 0x117BBC80B5A61C7C # gpg: Good signature from "Christian Borntraeger (IBM) <borntraeger@de.ibm.com>" # Primary key fingerprint: F922 9381 A334 08F9 DBAB FBCA 117B BC80 B5A6 1C7C * remotes/borntraeger/tags/s390x-20170714: (40 commits) s390x/gdb: add gs registers s390x/arch_dump: also dump guarded storage control block s390x/kvm: enable guarded storage s390x/kvm: Enable KSS facility for nested virtualization s390x/cpumodel: add esop/esop2 to z12 model s390x/cpumodel: we are always in zarchitecture mode s390x/cpumodel: wire up new hardware features s390x/flic: migrate ais states s390x/cpumodel: add zpci, aen and ais facilities s390x: initialize cpu firstly pc-bios/s390: rebuild s390-ccw.img pc-bios/s390: add s390-netboot.img pc-bios/s390-ccw: Link libnet into the netboot image and do the TFTP load pc-bios/s390-ccw: Add virtio-net driver code pc-bios/s390-ccw: Add core files for the network bootloading program roms/SLOF: Update submodule to latest status pc-bios/s390-ccw: Add code for virtio feature negotiation pc-bios/s390-ccw: Remove unused structs from virtio.h pc-bios/s390-ccw: Move byteswap functions to a separate header pc-bios/s390-ccw: Add a write() function for stdio ... Conflicts: target/s390x/kvm.c Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/intc/s390_flic_kvm.c')
-rw-r--r--hw/intc/s390_flic_kvm.c137
1 files changed, 135 insertions, 2 deletions
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index 0bcd49f08b..be3fd00a57 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,43 @@ 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;
+}
+
+static int kvm_s390_inject_airq(S390FLICState *fs, uint8_t type,
+ uint8_t isc, uint8_t flags)
+{
+ KVMS390FLICState *flic = KVM_S390_FLIC(fs);
+ uint32_t id = css_get_adapter_id(type, isc);
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_AIRQ_INJECT,
+ .attr = id,
+ };
+
+ 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
@@ -186,13 +224,14 @@ static int __get_all_irqs(KVMS390FLICState *flic,
static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
uint8_t isc, bool swap,
- bool is_maskable)
+ bool is_maskable, uint8_t flags)
{
struct kvm_s390_io_adapter adapter = {
.id = id,
.isc = isc,
.maskable = is_maskable,
.swap = swap,
+ .flags = flags,
};
KVMS390FLICState *flic = KVM_S390_FLIC(fs);
int r;
@@ -374,7 +413,84 @@ out:
return r;
}
+typedef struct KVMS390FLICStateMigTmp {
+ KVMS390FLICState *parent;
+ uint8_t simm;
+ uint8_t nimm;
+} KVMS390FLICStateMigTmp;
+
+static void kvm_flic_ais_pre_save(void *opaque)
+{
+ KVMS390FLICStateMigTmp *tmp = opaque;
+ KVMS390FLICState *flic = tmp->parent;
+ struct kvm_s390_ais_all ais;
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_AISM_ALL,
+ .addr = (uint64_t)&ais,
+ .attr = sizeof(ais),
+ };
+
+ if (ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr)) {
+ error_report("Failed to retrieve kvm flic ais states");
+ return;
+ }
+
+ tmp->simm = ais.simm;
+ tmp->nimm = ais.nimm;
+}
+
+static int kvm_flic_ais_post_load(void *opaque, int version_id)
+{
+ KVMS390FLICStateMigTmp *tmp = opaque;
+ KVMS390FLICState *flic = tmp->parent;
+ struct kvm_s390_ais_all ais = {
+ .simm = tmp->simm,
+ .nimm = tmp->nimm,
+ };
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_AISM_ALL,
+ .addr = (uint64_t)&ais,
+ };
+
+ /* This can happen when the user mis-configures its guests in an
+ * incompatible fashion or without a CPU model. For example using
+ * qemu with -cpu host (which is not migration safe) and do a
+ * migration from a host that has AIS to a host that has no AIS.
+ * In that case the target system will reject the migration here.
+ */
+ if (!ais_needed(flic)) {
+ return -ENOSYS;
+ }
+
+ return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
+}
+
+static const VMStateDescription kvm_s390_flic_ais_tmp = {
+ .name = "s390-flic-ais-tmp",
+ .pre_save = kvm_flic_ais_pre_save,
+ .post_load = kvm_flic_ais_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(simm, KVMS390FLICStateMigTmp),
+ VMSTATE_UINT8(nimm, KVMS390FLICStateMigTmp),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription kvm_s390_flic_vmstate_ais = {
+ .name = "s390-flic/ais",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = ais_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_WITH_TMP(KVMS390FLICState, KVMS390FLICStateMigTmp,
+ kvm_s390_flic_ais_tmp),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription kvm_s390_flic_vmstate = {
+ /* should have been like kvm-s390-flic,
+ * can't change without breaking compat */
.name = "s390-flic",
.version_id = FLIC_SAVEVM_VERSION,
.minimum_version_id = FLIC_SAVEVM_VERSION,
@@ -389,6 +505,10 @@ static const VMStateDescription kvm_s390_flic_vmstate = {
.flags = VMS_SINGLE,
},
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (const VMStateDescription * []) {
+ &kvm_s390_flic_vmstate_ais,
+ NULL
}
};
@@ -436,7 +556,6 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ;
flic_state->clear_io_supported = !ioctl(flic_state->fd,
KVM_HAS_DEVICE_ATTR, test_attr);
-
return;
fail:
error_propagate(errp, errp_local);
@@ -445,10 +564,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;
@@ -456,6 +577,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);
@@ -478,6 +609,8 @@ 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;
+ fsc->inject_airq = kvm_s390_inject_airq;
}
static const TypeInfo kvm_s390_flic_info = {