* directory.
*/
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
#include <sys/ioctl.h>
#include "qemu/error-report.h"
#include "hw/sysbus.h"
S390FLICState parent_obj;
uint32_t fd;
+ bool clear_io_supported;
} KVMS390FLICState;
DeviceState *s390_flic_kvm_create(void)
return flic_enqueue_irqs(irq, sizeof(*irq), flic);
}
+static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
+ uint16_t subchannel_nr)
+{
+ KVMS390FLICState *flic = KVM_S390_FLIC(fs);
+ int rc;
+ uint32_t sid = subchannel_id << 16 | subchannel_nr;
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_FLIC_CLEAR_IO_IRQ,
+ .addr = (uint64_t) &sid,
+ .attr = sizeof(sid),
+ };
+ if (unlikely(!flic->clear_io_supported)) {
+ return -ENOSYS;
+ }
+ rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
+ return rc ? -errno : 0;
+}
+
/**
* __get_all_irqs - store all pending irqs in buffer
* @flic: pointer to flic device state
.swap = swap,
};
KVMS390FLICState *flic = KVM_S390_FLIC(fs);
- int r, ret;
+ int r;
struct kvm_device_attr attr = {
.group = KVM_DEV_FLIC_ADAPTER_REGISTER,
.addr = (uint64_t)&adapter,
};
- if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
+ if (!kvm_gsi_routing_enabled()) {
/* nothing to do */
return 0;
}
r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
- ret = r ? -errno : 0;
- return ret;
+ return r ? -errno : 0;
}
static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
KVMS390FLICState *flic = KVM_S390_FLIC(fs);
int r;
- if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
+ if (!kvm_gsi_routing_enabled()) {
/* nothing to do */
return 0;
}
routes->gsi[i] = ret;
routes->adapter.ind_offset++;
}
+ kvm_irqchip_commit_routes(kvm_state);
+
/* Restore passed-in structure to original state. */
routes->adapter.ind_offset = ind_offset;
return 0;
* kvm_flic_save - Save pending floating interrupts
* @f: QEMUFile containing migration state
* @opaque: pointer to flic device state
+ * @size: ignored
*
* Note: Pass buf and len to kernel. Start with one page and
* increase until buffer is sufficient or maxium size is
* reached
*/
-static void kvm_flic_save(QEMUFile *f, void *opaque)
+static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size,
+ VMStateField *field, QJSON *vmdesc)
{
KVMS390FLICState *flic = opaque;
int len = FLIC_SAVE_INITIAL_SIZE;
void *buf;
int count;
+ int r = 0;
flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
* migration state */
error_report("flic: couldn't allocate memory");
qemu_put_be64(f, FLIC_FAILED);
- return;
+ return -ENOMEM;
}
count = __get_all_irqs(flic, &buf, len);
* target system to fail when attempting to load irqs from the
* migration state */
qemu_put_be64(f, FLIC_FAILED);
+ r = count;
} else {
qemu_put_be64(f, count);
qemu_put_buffer(f, (uint8_t *) buf,
count * sizeof(struct kvm_s390_irq));
}
g_free(buf);
+
+ return r;
}
/**
* kvm_flic_load - Load pending floating interrupts
* @f: QEMUFile containing migration state
* @opaque: pointer to flic device state
- * @version_id: version id for migration
+ * @size: ignored
*
* Returns: value of flic_enqueue_irqs, -EINVAL on error
* Note: Do nothing when no interrupts where stored
* in QEMUFile
*/
-static int kvm_flic_load(QEMUFile *f, void *opaque, int version_id)
+static int kvm_flic_load(QEMUFile *f, void *opaque, size_t size,
+ VMStateField *field)
{
uint64_t len = 0;
uint64_t count = 0;
void *buf = NULL;
int r = 0;
- if (version_id != FLIC_SAVEVM_VERSION) {
- r = -EINVAL;
- goto out;
- }
-
flic_enable_pfault((struct KVMS390FLICState *) opaque);
count = qemu_get_be64(f);
return r;
}
+static const VMStateDescription kvm_s390_flic_vmstate = {
+ .name = "s390-flic",
+ .version_id = FLIC_SAVEVM_VERSION,
+ .minimum_version_id = FLIC_SAVEVM_VERSION,
+ .fields = (VMStateField[]) {
+ {
+ .name = "irqs",
+ .info = &(const VMStateInfo) {
+ .name = "irqs",
+ .get = kvm_flic_load,
+ .put = kvm_flic_save,
+ },
+ .flags = VMS_SINGLE,
+ },
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
{
KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
struct kvm_create_device cd = {0};
+ struct kvm_device_attr test_attr = {0};
int ret;
flic_state->fd = -1;
}
flic_state->fd = cd.fd;
- /* Register savevm handler for floating interrupts */
- register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save,
- kvm_flic_load, (void *) flic_state);
-}
-
-static void kvm_s390_flic_unrealize(DeviceState *dev, Error **errp)
-{
- KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
+ /* Check clear_io_irq support */
+ test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ;
+ flic_state->clear_io_supported = !ioctl(flic_state->fd,
+ KVM_HAS_DEVICE_ATTR, test_attr);
- unregister_savevm(DEVICE(flic_state), "s390-flic", flic_state);
}
static void kvm_s390_flic_reset(DeviceState *dev)
S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);
dc->realize = kvm_s390_flic_realize;
- dc->unrealize = kvm_s390_flic_unrealize;
+ dc->vmsd = &kvm_s390_flic_vmstate;
dc->reset = kvm_s390_flic_reset;
fsc->register_io_adapter = kvm_s390_register_io_adapter;
fsc->io_adapter_map = kvm_s390_io_adapter_map;
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;
}
static const TypeInfo kvm_s390_flic_info = {