2 * QEMU S390x floating interrupt controller (flic)
4 * Copyright 2014 IBM Corp.
5 * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
6 * Cornelia Huck <cornelia.huck@de.ibm.com>
8 * This work is licensed under the terms of the GNU GPL, version 2 or (at
9 * your option) any later version. See the COPYING file in the top-level
13 #include "qemu/osdep.h"
14 #include "qemu/error-report.h"
15 #include "hw/sysbus.h"
16 #include "hw/s390x/ioinst.h"
17 #include "hw/s390x/s390_flic.h"
18 #include "hw/s390x/css.h"
22 #include "qapi/error.h"
23 #include "hw/s390x/s390-virtio-ccw.h"
25 S390FLICState
*s390_get_flic(void)
27 static S390FLICState
*fs
;
30 fs
= S390_FLIC_COMMON(object_resolve_path(TYPE_KVM_S390_FLIC
, NULL
));
32 fs
= S390_FLIC_COMMON(object_resolve_path(TYPE_QEMU_S390_FLIC
,
39 void s390_flic_init(void)
43 dev
= s390_flic_kvm_create();
45 dev
= qdev_create(NULL
, TYPE_QEMU_S390_FLIC
);
46 object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC
,
49 qdev_init_nofail(dev
);
52 static int qemu_s390_register_io_adapter(S390FLICState
*fs
, uint32_t id
,
53 uint8_t isc
, bool swap
,
54 bool is_maskable
, uint8_t flags
)
60 static int qemu_s390_io_adapter_map(S390FLICState
*fs
, uint32_t id
,
61 uint64_t map_addr
, bool do_map
)
67 static int qemu_s390_add_adapter_routes(S390FLICState
*fs
,
68 AdapterRoutes
*routes
)
73 static void qemu_s390_release_adapter_routes(S390FLICState
*fs
,
74 AdapterRoutes
*routes
)
78 static int qemu_s390_clear_io_flic(S390FLICState
*fs
, uint16_t subchannel_id
,
79 uint16_t subchannel_nr
)
85 static int qemu_s390_modify_ais_mode(S390FLICState
*fs
, uint8_t isc
,
88 QEMUS390FLICState
*flic
= QEMU_S390_FLIC(fs
);
91 case SIC_IRQ_MODE_ALL
:
92 flic
->simm
&= ~AIS_MODE_MASK(isc
);
93 flic
->nimm
&= ~AIS_MODE_MASK(isc
);
95 case SIC_IRQ_MODE_SINGLE
:
96 flic
->simm
|= AIS_MODE_MASK(isc
);
97 flic
->nimm
&= ~AIS_MODE_MASK(isc
);
106 static int qemu_s390_inject_airq(S390FLICState
*fs
, uint8_t type
,
107 uint8_t isc
, uint8_t flags
)
109 QEMUS390FLICState
*flic
= QEMU_S390_FLIC(fs
);
110 bool flag
= flags
& S390_ADAPTER_SUPPRESSIBLE
;
111 uint32_t io_int_word
= (isc
<< 27) | IO_INT_WORD_AI
;
113 if (flag
&& (flic
->nimm
& AIS_MODE_MASK(isc
))) {
114 trace_qemu_s390_airq_suppressed(type
, isc
);
118 s390_io_interrupt(0, 0, 0, io_int_word
);
120 if (flag
&& (flic
->simm
& AIS_MODE_MASK(isc
))) {
121 flic
->nimm
|= AIS_MODE_MASK(isc
);
122 trace_qemu_s390_suppress_airq(isc
, "Single-Interruption Mode",
123 "NO-Interruptions Mode");
129 static void qemu_s390_flic_reset(DeviceState
*dev
)
131 QEMUS390FLICState
*flic
= QEMU_S390_FLIC(dev
);
137 bool ais_needed(void *opaque
)
139 S390FLICState
*s
= opaque
;
141 return s
->ais_supported
;
144 static const VMStateDescription qemu_s390_flic_vmstate
= {
145 .name
= "qemu-s390-flic",
147 .minimum_version_id
= 1,
148 .needed
= ais_needed
,
149 .fields
= (VMStateField
[]) {
150 VMSTATE_UINT8(simm
, QEMUS390FLICState
),
151 VMSTATE_UINT8(nimm
, QEMUS390FLICState
),
152 VMSTATE_END_OF_LIST()
156 static void qemu_s390_flic_class_init(ObjectClass
*oc
, void *data
)
158 DeviceClass
*dc
= DEVICE_CLASS(oc
);
159 S390FLICStateClass
*fsc
= S390_FLIC_COMMON_CLASS(oc
);
161 dc
->reset
= qemu_s390_flic_reset
;
162 dc
->vmsd
= &qemu_s390_flic_vmstate
;
163 fsc
->register_io_adapter
= qemu_s390_register_io_adapter
;
164 fsc
->io_adapter_map
= qemu_s390_io_adapter_map
;
165 fsc
->add_adapter_routes
= qemu_s390_add_adapter_routes
;
166 fsc
->release_adapter_routes
= qemu_s390_release_adapter_routes
;
167 fsc
->clear_io_irq
= qemu_s390_clear_io_flic
;
168 fsc
->modify_ais_mode
= qemu_s390_modify_ais_mode
;
169 fsc
->inject_airq
= qemu_s390_inject_airq
;
172 static Property s390_flic_common_properties
[] = {
173 DEFINE_PROP_UINT32("adapter_routes_max_batch", S390FLICState
,
174 adapter_routes_max_batch
, ADAPTER_ROUTES_MAX_GSI
),
175 DEFINE_PROP_END_OF_LIST(),
178 static void s390_flic_common_realize(DeviceState
*dev
, Error
**errp
)
180 S390FLICState
*fs
= S390_FLIC_COMMON(dev
);
181 uint32_t max_batch
= fs
->adapter_routes_max_batch
;
183 if (max_batch
> ADAPTER_ROUTES_MAX_GSI
) {
184 error_setg(errp
, "flic property adapter_routes_max_batch too big"
185 " (%d > %d)", max_batch
, ADAPTER_ROUTES_MAX_GSI
);
189 fs
->ais_supported
= s390_has_feat(S390_FEAT_ADAPTER_INT_SUPPRESSION
);
192 static void s390_flic_class_init(ObjectClass
*oc
, void *data
)
194 DeviceClass
*dc
= DEVICE_CLASS(oc
);
196 dc
->props
= s390_flic_common_properties
;
197 dc
->realize
= s390_flic_common_realize
;
200 static const TypeInfo qemu_s390_flic_info
= {
201 .name
= TYPE_QEMU_S390_FLIC
,
202 .parent
= TYPE_S390_FLIC_COMMON
,
203 .instance_size
= sizeof(QEMUS390FLICState
),
204 .class_init
= qemu_s390_flic_class_init
,
208 static const TypeInfo s390_flic_common_info
= {
209 .name
= TYPE_S390_FLIC_COMMON
,
210 .parent
= TYPE_SYS_BUS_DEVICE
,
211 .instance_size
= sizeof(S390FLICState
),
212 .class_init
= s390_flic_class_init
,
213 .class_size
= sizeof(S390FLICStateClass
),
216 static void qemu_s390_flic_register_types(void)
218 type_register_static(&s390_flic_common_info
);
219 type_register_static(&qemu_s390_flic_info
);
222 type_init(qemu_s390_flic_register_types
)
224 static bool adapter_info_so_needed(void *opaque
)
226 return css_migration_enabled();
229 const VMStateDescription vmstate_adapter_info_so
= {
230 .name
= "s390_adapter_info/summary_offset",
232 .minimum_version_id
= 1,
233 .needed
= adapter_info_so_needed
,
234 .fields
= (VMStateField
[]) {
235 VMSTATE_UINT32(summary_offset
, AdapterInfo
),
236 VMSTATE_END_OF_LIST()
240 const VMStateDescription vmstate_adapter_info
= {
241 .name
= "s390_adapter_info",
243 .minimum_version_id
= 1,
244 .fields
= (VMStateField
[]) {
245 VMSTATE_UINT64(ind_offset
, AdapterInfo
),
247 * We do not have to migrate neither the id nor the addresses.
248 * The id is set by css_register_io_adapter and the addresses
249 * are set based on the IndAddr objects after those get mapped.
251 VMSTATE_END_OF_LIST()
253 .subsections
= (const VMStateDescription
* []) {
254 &vmstate_adapter_info_so
,
259 const VMStateDescription vmstate_adapter_routes
= {
261 .name
= "s390_adapter_routes",
263 .minimum_version_id
= 1,
264 .fields
= (VMStateField
[]) {
265 VMSTATE_STRUCT(adapter
, AdapterRoutes
, 1, vmstate_adapter_info
,
267 VMSTATE_END_OF_LIST()