return -ENOSYS;
}
+static int qemu_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc,
+ uint16_t mode)
+{
+ QEMUS390FLICState *flic = QEMU_S390_FLIC(fs);
+
+ switch (mode) {
+ case SIC_IRQ_MODE_ALL:
+ flic->simm &= ~AIS_MODE_MASK(isc);
+ flic->nimm &= ~AIS_MODE_MASK(isc);
+ break;
+ case SIC_IRQ_MODE_SINGLE:
+ flic->simm |= AIS_MODE_MASK(isc);
+ flic->nimm &= ~AIS_MODE_MASK(isc);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void qemu_s390_flic_reset(DeviceState *dev)
+{
+ QEMUS390FLICState *flic = QEMU_S390_FLIC(dev);
+
+ flic->simm = 0;
+ flic->nimm = 0;
+}
+
static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
{
+ DeviceClass *dc = DEVICE_CLASS(oc);
S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);
+ dc->reset = qemu_s390_flic_reset;
fsc->register_io_adapter = qemu_s390_register_io_adapter;
fsc->io_adapter_map = qemu_s390_io_adapter_map;
fsc->add_adapter_routes = qemu_s390_add_adapter_routes;
fsc->release_adapter_routes = qemu_s390_release_adapter_routes;
fsc->clear_io_irq = qemu_s390_clear_io_flic;
+ fsc->modify_ais_mode = qemu_s390_modify_ais_mode;
}
static Property s390_flic_common_properties[] = {
static void s390_flic_common_realize(DeviceState *dev, Error **errp)
{
- uint32_t max_batch = S390_FLIC_COMMON(dev)->adapter_routes_max_batch;
+ S390FLICState *fs = S390_FLIC_COMMON(dev);
+ uint32_t max_batch = fs->adapter_routes_max_batch;
if (max_batch > ADAPTER_ROUTES_MAX_GSI) {
error_setg(errp, "flic property adapter_routes_max_batch too big"
" (%d > %d)", max_batch, ADAPTER_ROUTES_MAX_GSI);
}
+
+ fs->ais_supported = true;
}
static void s390_flic_class_init(ObjectClass *oc, void *data)
#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()
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
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};
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);
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;
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);
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 = {
SysBusDevice parent_obj;
/* to limit AdapterRoutes.num_routes for compat */
uint32_t adapter_routes_max_batch;
-
+ bool ais_supported;
} S390FLICState;
#define S390_FLIC_COMMON_CLASS(klass) \
void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes);
int (*clear_io_irq)(S390FLICState *fs, uint16_t subchannel_id,
uint16_t subchannel_nr);
+ int (*modify_ais_mode)(S390FLICState *fs, uint8_t isc, uint16_t mode);
} S390FLICStateClass;
#define TYPE_KVM_S390_FLIC "s390-flic-kvm"
#define QEMU_S390_FLIC(obj) \
OBJECT_CHECK(QEMUS390FLICState, (obj), TYPE_QEMU_S390_FLIC)
+#define SIC_IRQ_MODE_ALL 0
+#define SIC_IRQ_MODE_SINGLE 1
+#define AIS_MODE_MASK(isc) (0x80 >> isc)
+
typedef struct QEMUS390FLICState {
S390FLICState parent_obj;
+ uint8_t simm;
+ uint8_t nimm;
} QEMUS390FLICState;
void s390_flic_init(void);