Message ID | 1399554218-8262-3-git-send-email-cornelia.huck@de.ibm.com |
---|---|
State | New |
Headers | show |
On 08/05/14 15:03, Cornelia Huck wrote: > Register an I/O adapter interrupt source for when virtio-ccw devices start > using adapter interrupts. > > Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com> > Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> > --- > hw/intc/s390_flic.c | 16 ++++++++++++++ > hw/intc/s390_flic_kvm.c | 29 ++++++++++++++++++++++++ > hw/s390x/css.c | 50 ++++++++++++++++++++++++++++++++++++++++++ > hw/s390x/css.h | 4 ++++ > hw/s390x/virtio-ccw.c | 4 ++++ > hw/s390x/virtio-ccw.h | 1 + > include/hw/s390x/s390_flic.h | 2 ++ > 7 files changed, 106 insertions(+) > > diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c > index 7dc8c7d..2b56835 100644 > --- a/hw/intc/s390_flic.c > +++ b/hw/intc/s390_flic.c > @@ -44,10 +44,26 @@ void s390_flic_init(void) > } > } > > +static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id, > + uint8_t isc, bool swap, > + bool is_maskable) > +{ > + /* nothing to do */ > + return 0; > +} > + > +static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) > +{ > + S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); > + > + fsc->register_io_adapter = qemu_s390_register_io_adapter; > +} > + > static const TypeInfo qemu_s390_flic_info = { > .name = TYPE_QEMU_S390_FLIC, > .parent = TYPE_S390_FLIC_COMMON, > .instance_size = sizeof(QEMUS390FLICState), > + .class_init = qemu_s390_flic_class_init, > }; > > static const TypeInfo s390_flic_common_info = { > diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c > index 70c1710..cc4072e 100644 > --- a/hw/intc/s390_flic_kvm.c > +++ b/hw/intc/s390_flic_kvm.c > @@ -151,6 +151,33 @@ static int __get_all_irqs(KVMS390FLICState *flic, > return r; > } > > +static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id, > + uint8_t isc, bool swap, > + bool is_maskable) > +{ > + struct kvm_s390_io_adapter adapter = { > + .id = id, > + .isc = isc, > + .maskable = is_maskable, > + .swap = swap, > + }; > + KVMS390FLICState *flic = KVM_S390_FLIC(fs); > + int r, ret; > + 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)) { > + return -ENOSYS; > + } > + > + r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); > + > + ret = r ? -errno : 0; > + return ret; > +} > + > /** > * kvm_flic_save - Save pending floating interrupts > * @f: QEMUFile containing migration state > @@ -304,10 +331,12 @@ static void kvm_s390_flic_reset(DeviceState *dev) > static void kvm_s390_flic_class_init(ObjectClass *oc, void *data) > { > DeviceClass *dc = DEVICE_CLASS(oc); > + S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); > > dc->realize = kvm_s390_flic_realize; > dc->unrealize = kvm_s390_flic_unrealize; > dc->reset = kvm_s390_flic_reset; > + fsc->register_io_adapter = kvm_s390_register_io_adapter; > } > > static const TypeInfo kvm_s390_flic_info = { > diff --git a/hw/s390x/css.c b/hw/s390x/css.c > index 122cc7e..2678e44 100644 > --- a/hw/s390x/css.c > +++ b/hw/s390x/css.c > @@ -16,6 +16,7 @@ > #include "ioinst.h" > #include "css.h" > #include "trace.h" > +#include "hw/s390x/s390_flic.h" > > typedef struct CrwContainer { > CRW crw; > @@ -39,6 +40,13 @@ typedef struct CssImage { > ChpInfo chpids[MAX_CHPID + 1]; > } CssImage; > > +typedef struct IoAdapter { > + uint32_t id; > + uint8_t type; > + uint8_t isc; > + QTAILQ_ENTRY(IoAdapter) sibling; > +} IoAdapter; > + > typedef struct ChannelSubSys { > QTAILQ_HEAD(, CrwContainer) pending_crws; > bool do_crw_mchk; > @@ -49,6 +57,7 @@ typedef struct ChannelSubSys { > uint64_t chnmon_area; > CssImage *css[MAX_CSSID + 1]; > uint8_t default_cssid; > + QTAILQ_HEAD(, IoAdapter) io_adapters; > } ChannelSubSys; > > static ChannelSubSys *channel_subsys; > @@ -69,6 +78,46 @@ int css_create_css_image(uint8_t cssid, bool default_image) > return 0; > } > > +int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap, > + bool maskable, uint32_t *id) > +{ > + IoAdapter *adapter; > + bool found = false; > + int ret; > + S390FLICState *fs = s390_get_flic(); > + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); > + > + *id = 0; > + QTAILQ_FOREACH(adapter, &channel_subsys->io_adapters, sibling) { > + if ((adapter->type == type) && (adapter->isc == isc)) { > + *id = adapter->id; > + found = true; > + ret = 0; > + break; > + } > + if (adapter->id >= *id) { > + *id = adapter->id + 1; > + } > + } > + if (found) { > + goto out; > + } > + adapter = g_new0(IoAdapter, 1); > + ret = fsc->register_io_adapter(fs, *id, isc, swap, maskable); > + if (ret == 0) { > + adapter->id = *id; > + adapter->isc = isc; > + adapter->type = type; > + QTAILQ_INSERT_TAIL(&channel_subsys->io_adapters, adapter, sibling); > + } else { > + g_free(adapter); > + fprintf(stderr, "Unexpected error %d when registering adapter %d\n", > + ret, *id); > + } > +out: > + return ret; > +} > + > uint16_t css_build_subchannel_id(SubchDev *sch) > { > if (channel_subsys->max_cssid > 0) { > @@ -1235,6 +1284,7 @@ static void css_init(void) > channel_subsys->do_crw_mchk = true; > channel_subsys->crws_lost = false; > channel_subsys->chnmon_active = false; > + QTAILQ_INIT(&channel_subsys->io_adapters); > } > machine_init(css_init); > > diff --git a/hw/s390x/css.h b/hw/s390x/css.h > index 220169e..6586106 100644 > --- a/hw/s390x/css.h > +++ b/hw/s390x/css.h > @@ -98,4 +98,8 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, > int hotplugged, int add); > void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); > void css_adapter_interrupt(uint8_t isc); > + > +#define CSS_IO_ADAPTER_VIRTIO 1 > +int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap, > + bool maskable, uint32_t *id); > #endif > diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c > index 1cb4e2c..e3b7120 100644 > --- a/hw/s390x/virtio-ccw.c > +++ b/hw/s390x/virtio-ccw.c > @@ -522,6 +522,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) > dev->thinint_isc = thinint->isc; > dev->ind_bit = thinint->ind_bit; > cpu_physical_memory_unmap(thinint, hw_len, 0, hw_len); > + ret = css_register_io_adapter(CSS_IO_ADAPTER_VIRTIO, > + dev->thinint_isc, true, false, > + &dev->adapter_id); > + assert(ret == 0); > sch->thinint_active = ((dev->indicators != 0) && > (dev->summary_indicator != 0)); > sch->curr_status.scsw.count = ccw.count - len; > diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h > index 4393e44..0b70b91 100644 > --- a/hw/s390x/virtio-ccw.h > +++ b/hw/s390x/virtio-ccw.h > @@ -85,6 +85,7 @@ struct VirtioCcwDevice { > bool ioeventfd_disabled; > uint32_t flags; > uint8_t thinint_isc; > + uint32_t adapter_id; > /* Guest provided values: */ > hwaddr indicators; > hwaddr indicators2; > diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h > index 3bc60fd..83913ec 100644 > --- a/include/hw/s390x/s390_flic.h > +++ b/include/hw/s390x/s390_flic.h > @@ -32,6 +32,8 @@ typedef struct S390FLICState { > typedef struct S390FLICStateClass { > DeviceClass parent_class; > > + int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc, > + bool swap, bool maskable); > } S390FLICStateClass; > > #define TYPE_KVM_S390_FLIC "s390-flic-kvm" >
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index 7dc8c7d..2b56835 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -44,10 +44,26 @@ void s390_flic_init(void) } } +static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id, + uint8_t isc, bool swap, + bool is_maskable) +{ + /* nothing to do */ + return 0; +} + +static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) +{ + S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); + + fsc->register_io_adapter = qemu_s390_register_io_adapter; +} + static const TypeInfo qemu_s390_flic_info = { .name = TYPE_QEMU_S390_FLIC, .parent = TYPE_S390_FLIC_COMMON, .instance_size = sizeof(QEMUS390FLICState), + .class_init = qemu_s390_flic_class_init, }; static const TypeInfo s390_flic_common_info = { diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index 70c1710..cc4072e 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -151,6 +151,33 @@ static int __get_all_irqs(KVMS390FLICState *flic, return r; } +static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id, + uint8_t isc, bool swap, + bool is_maskable) +{ + struct kvm_s390_io_adapter adapter = { + .id = id, + .isc = isc, + .maskable = is_maskable, + .swap = swap, + }; + KVMS390FLICState *flic = KVM_S390_FLIC(fs); + int r, ret; + 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)) { + return -ENOSYS; + } + + r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); + + ret = r ? -errno : 0; + return ret; +} + /** * kvm_flic_save - Save pending floating interrupts * @f: QEMUFile containing migration state @@ -304,10 +331,12 @@ static void kvm_s390_flic_reset(DeviceState *dev) static void kvm_s390_flic_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); dc->realize = kvm_s390_flic_realize; dc->unrealize = kvm_s390_flic_unrealize; dc->reset = kvm_s390_flic_reset; + fsc->register_io_adapter = kvm_s390_register_io_adapter; } static const TypeInfo kvm_s390_flic_info = { diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 122cc7e..2678e44 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -16,6 +16,7 @@ #include "ioinst.h" #include "css.h" #include "trace.h" +#include "hw/s390x/s390_flic.h" typedef struct CrwContainer { CRW crw; @@ -39,6 +40,13 @@ typedef struct CssImage { ChpInfo chpids[MAX_CHPID + 1]; } CssImage; +typedef struct IoAdapter { + uint32_t id; + uint8_t type; + uint8_t isc; + QTAILQ_ENTRY(IoAdapter) sibling; +} IoAdapter; + typedef struct ChannelSubSys { QTAILQ_HEAD(, CrwContainer) pending_crws; bool do_crw_mchk; @@ -49,6 +57,7 @@ typedef struct ChannelSubSys { uint64_t chnmon_area; CssImage *css[MAX_CSSID + 1]; uint8_t default_cssid; + QTAILQ_HEAD(, IoAdapter) io_adapters; } ChannelSubSys; static ChannelSubSys *channel_subsys; @@ -69,6 +78,46 @@ int css_create_css_image(uint8_t cssid, bool default_image) return 0; } +int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap, + bool maskable, uint32_t *id) +{ + IoAdapter *adapter; + bool found = false; + int ret; + S390FLICState *fs = s390_get_flic(); + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); + + *id = 0; + QTAILQ_FOREACH(adapter, &channel_subsys->io_adapters, sibling) { + if ((adapter->type == type) && (adapter->isc == isc)) { + *id = adapter->id; + found = true; + ret = 0; + break; + } + if (adapter->id >= *id) { + *id = adapter->id + 1; + } + } + if (found) { + goto out; + } + adapter = g_new0(IoAdapter, 1); + ret = fsc->register_io_adapter(fs, *id, isc, swap, maskable); + if (ret == 0) { + adapter->id = *id; + adapter->isc = isc; + adapter->type = type; + QTAILQ_INSERT_TAIL(&channel_subsys->io_adapters, adapter, sibling); + } else { + g_free(adapter); + fprintf(stderr, "Unexpected error %d when registering adapter %d\n", + ret, *id); + } +out: + return ret; +} + uint16_t css_build_subchannel_id(SubchDev *sch) { if (channel_subsys->max_cssid > 0) { @@ -1235,6 +1284,7 @@ static void css_init(void) channel_subsys->do_crw_mchk = true; channel_subsys->crws_lost = false; channel_subsys->chnmon_active = false; + QTAILQ_INIT(&channel_subsys->io_adapters); } machine_init(css_init); diff --git a/hw/s390x/css.h b/hw/s390x/css.h index 220169e..6586106 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -98,4 +98,8 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, int hotplugged, int add); void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); void css_adapter_interrupt(uint8_t isc); + +#define CSS_IO_ADAPTER_VIRTIO 1 +int css_register_io_adapter(uint8_t type, uint8_t isc, bool swap, + bool maskable, uint32_t *id); #endif diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 1cb4e2c..e3b7120 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -522,6 +522,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) dev->thinint_isc = thinint->isc; dev->ind_bit = thinint->ind_bit; cpu_physical_memory_unmap(thinint, hw_len, 0, hw_len); + ret = css_register_io_adapter(CSS_IO_ADAPTER_VIRTIO, + dev->thinint_isc, true, false, + &dev->adapter_id); + assert(ret == 0); sch->thinint_active = ((dev->indicators != 0) && (dev->summary_indicator != 0)); sch->curr_status.scsw.count = ccw.count - len; diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index 4393e44..0b70b91 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -85,6 +85,7 @@ struct VirtioCcwDevice { bool ioeventfd_disabled; uint32_t flags; uint8_t thinint_isc; + uint32_t adapter_id; /* Guest provided values: */ hwaddr indicators; hwaddr indicators2; diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index 3bc60fd..83913ec 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -32,6 +32,8 @@ typedef struct S390FLICState { typedef struct S390FLICStateClass { DeviceClass parent_class; + int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc, + bool swap, bool maskable); } S390FLICStateClass; #define TYPE_KVM_S390_FLIC "s390-flic-kvm"