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 S390FLICStateClass
*s390_get_flic_class(S390FLICState
*fs
)
27 static S390FLICStateClass
*class;
30 /* we only have one flic device, so this is fine to cache */
31 class = S390_FLIC_COMMON_GET_CLASS(fs
);
36 QEMUS390FLICState
*s390_get_qemu_flic(S390FLICState
*fs
)
38 static QEMUS390FLICState
*flic
;
41 /* we only have one flic device, so this is fine to cache */
42 flic
= QEMU_S390_FLIC(fs
);
47 S390FLICState
*s390_get_flic(void)
49 static S390FLICState
*fs
;
52 fs
= S390_FLIC_COMMON(object_resolve_path_type("",
53 TYPE_S390_FLIC_COMMON
,
59 void s390_flic_init(void)
64 dev
= qdev_create(NULL
, TYPE_KVM_S390_FLIC
);
65 object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC
,
68 dev
= qdev_create(NULL
, TYPE_QEMU_S390_FLIC
);
69 object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC
,
72 qdev_init_nofail(dev
);
75 static int qemu_s390_register_io_adapter(S390FLICState
*fs
, uint32_t id
,
76 uint8_t isc
, bool swap
,
77 bool is_maskable
, uint8_t flags
)
83 static int qemu_s390_io_adapter_map(S390FLICState
*fs
, uint32_t id
,
84 uint64_t map_addr
, bool do_map
)
90 static int qemu_s390_add_adapter_routes(S390FLICState
*fs
,
91 AdapterRoutes
*routes
)
96 static void qemu_s390_release_adapter_routes(S390FLICState
*fs
,
97 AdapterRoutes
*routes
)
101 static int qemu_s390_clear_io_flic(S390FLICState
*fs
, uint16_t subchannel_id
,
102 uint16_t subchannel_nr
)
104 QEMUS390FLICState
*flic
= s390_get_qemu_flic(fs
);
105 QEMUS390FlicIO
*cur
, *next
;
108 g_assert(qemu_mutex_iothread_locked());
109 if (!(flic
->pending
& FLIC_PENDING_IO
)) {
114 for (isc
= 0; isc
< 8; isc
++) {
115 if (QLIST_EMPTY(&flic
->io
[isc
])) {
119 /* search and delete any matching one */
120 QLIST_FOREACH_SAFE(cur
, &flic
->io
[isc
], next
, next
) {
121 if (cur
->id
== subchannel_id
&& cur
->nr
== subchannel_nr
) {
122 QLIST_REMOVE(cur
, next
);
127 /* update our indicator bit */
128 if (QLIST_EMPTY(&flic
->io
[isc
])) {
129 flic
->pending
&= ~ISC_TO_PENDING_IO(isc
);
135 static int qemu_s390_modify_ais_mode(S390FLICState
*fs
, uint8_t isc
,
138 QEMUS390FLICState
*flic
= s390_get_qemu_flic(fs
);
141 case SIC_IRQ_MODE_ALL
:
142 flic
->simm
&= ~AIS_MODE_MASK(isc
);
143 flic
->nimm
&= ~AIS_MODE_MASK(isc
);
145 case SIC_IRQ_MODE_SINGLE
:
146 flic
->simm
|= AIS_MODE_MASK(isc
);
147 flic
->nimm
&= ~AIS_MODE_MASK(isc
);
156 static int qemu_s390_inject_airq(S390FLICState
*fs
, uint8_t type
,
157 uint8_t isc
, uint8_t flags
)
159 QEMUS390FLICState
*flic
= s390_get_qemu_flic(fs
);
160 S390FLICStateClass
*fsc
= s390_get_flic_class(fs
);
161 bool flag
= flags
& S390_ADAPTER_SUPPRESSIBLE
;
162 uint32_t io_int_word
= (isc
<< 27) | IO_INT_WORD_AI
;
164 if (flag
&& (flic
->nimm
& AIS_MODE_MASK(isc
))) {
165 trace_qemu_s390_airq_suppressed(type
, isc
);
169 fsc
->inject_io(fs
, 0, 0, 0, io_int_word
);
171 if (flag
&& (flic
->simm
& AIS_MODE_MASK(isc
))) {
172 flic
->nimm
|= AIS_MODE_MASK(isc
);
173 trace_qemu_s390_suppress_airq(isc
, "Single-Interruption Mode",
174 "NO-Interruptions Mode");
180 static void qemu_s390_flic_notify(uint32_t type
)
185 * We have to make all CPUs see CPU_INTERRUPT_HARD, so they might
186 * consider it. We will kick all running CPUs and only relevant
190 S390CPU
*cpu
= S390_CPU(cs
);
192 cs
->interrupt_request
|= CPU_INTERRUPT_HARD
;
194 /* ignore CPUs that are not sleeping */
195 if (s390_cpu_get_state(cpu
) != S390_CPU_STATE_OPERATING
&&
196 s390_cpu_get_state(cpu
) != S390_CPU_STATE_LOAD
) {
200 /* we always kick running CPUs for now, this is tricky */
202 /* don't check for subclasses, CPUs double check when waking up */
203 if (type
& FLIC_PENDING_SERVICE
) {
204 if (!(cpu
->env
.psw
.mask
& PSW_MASK_EXT
)) {
207 } else if (type
& FLIC_PENDING_IO
) {
208 if (!(cpu
->env
.psw
.mask
& PSW_MASK_IO
)) {
211 } else if (type
& FLIC_PENDING_MCHK_CR
) {
212 if (!(cpu
->env
.psw
.mask
& PSW_MASK_MCHECK
)) {
217 cpu_interrupt(cs
, CPU_INTERRUPT_HARD
);
221 uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState
*flic
)
225 g_assert(qemu_mutex_iothread_locked());
226 g_assert(flic
->pending
& FLIC_PENDING_SERVICE
);
227 tmp
= flic
->service_param
;
228 flic
->service_param
= 0;
229 flic
->pending
&= ~FLIC_PENDING_SERVICE
;
234 /* caller has to free the returned object */
235 QEMUS390FlicIO
*qemu_s390_flic_dequeue_io(QEMUS390FLICState
*flic
, uint64_t cr6
)
240 g_assert(qemu_mutex_iothread_locked());
241 if (!(flic
->pending
& CR6_TO_PENDING_IO(cr6
))) {
245 for (isc
= 0; isc
< 8; isc
++) {
246 if (QLIST_EMPTY(&flic
->io
[isc
]) || !(cr6
& ISC_TO_ISC_BITS(isc
))) {
249 io
= QLIST_FIRST(&flic
->io
[isc
]);
250 QLIST_REMOVE(io
, next
);
252 /* update our indicator bit */
253 if (QLIST_EMPTY(&flic
->io
[isc
])) {
254 flic
->pending
&= ~ISC_TO_PENDING_IO(isc
);
262 void qemu_s390_flic_dequeue_crw_mchk(QEMUS390FLICState
*flic
)
264 g_assert(qemu_mutex_iothread_locked());
265 g_assert(flic
->pending
& FLIC_PENDING_MCHK_CR
);
266 flic
->pending
&= ~FLIC_PENDING_MCHK_CR
;
269 static void qemu_s390_inject_service(S390FLICState
*fs
, uint32_t parm
)
271 QEMUS390FLICState
*flic
= s390_get_qemu_flic(fs
);
273 g_assert(qemu_mutex_iothread_locked());
274 /* multiplexing is good enough for sclp - kvm does it internally as well */
275 flic
->service_param
|= parm
;
276 flic
->pending
|= FLIC_PENDING_SERVICE
;
278 qemu_s390_flic_notify(FLIC_PENDING_SERVICE
);
281 static void qemu_s390_inject_io(S390FLICState
*fs
, uint16_t subchannel_id
,
282 uint16_t subchannel_nr
, uint32_t io_int_parm
,
283 uint32_t io_int_word
)
285 const uint8_t isc
= IO_INT_WORD_ISC(io_int_word
);
286 QEMUS390FLICState
*flic
= s390_get_qemu_flic(fs
);
289 g_assert(qemu_mutex_iothread_locked());
290 io
= g_new0(QEMUS390FlicIO
, 1);
291 io
->id
= subchannel_id
;
292 io
->nr
= subchannel_nr
;
293 io
->parm
= io_int_parm
;
294 io
->word
= io_int_word
;
296 QLIST_INSERT_HEAD(&flic
->io
[isc
], io
, next
);
297 flic
->pending
|= ISC_TO_PENDING_IO(isc
);
299 qemu_s390_flic_notify(ISC_TO_PENDING_IO(isc
));
302 static void qemu_s390_inject_crw_mchk(S390FLICState
*fs
)
304 QEMUS390FLICState
*flic
= s390_get_qemu_flic(fs
);
306 g_assert(qemu_mutex_iothread_locked());
307 flic
->pending
|= FLIC_PENDING_MCHK_CR
;
309 qemu_s390_flic_notify(FLIC_PENDING_MCHK_CR
);
312 bool qemu_s390_flic_has_service(QEMUS390FLICState
*flic
)
314 /* called without lock via cc->has_work, will be validated under lock */
315 return !!(flic
->pending
& FLIC_PENDING_SERVICE
);
318 bool qemu_s390_flic_has_io(QEMUS390FLICState
*flic
, uint64_t cr6
)
320 /* called without lock via cc->has_work, will be validated under lock */
321 return !!(flic
->pending
& CR6_TO_PENDING_IO(cr6
));
324 bool qemu_s390_flic_has_crw_mchk(QEMUS390FLICState
*flic
)
326 /* called without lock via cc->has_work, will be validated under lock */
327 return !!(flic
->pending
& FLIC_PENDING_MCHK_CR
);
330 bool qemu_s390_flic_has_any(QEMUS390FLICState
*flic
)
332 g_assert(qemu_mutex_iothread_locked());
333 return !!flic
->pending
;
336 static void qemu_s390_flic_reset(DeviceState
*dev
)
338 QEMUS390FLICState
*flic
= QEMU_S390_FLIC(dev
);
339 QEMUS390FlicIO
*cur
, *next
;
342 g_assert(qemu_mutex_iothread_locked());
347 /* remove all pending io interrupts */
348 for (isc
= 0; isc
< 8; isc
++) {
349 QLIST_FOREACH_SAFE(cur
, &flic
->io
[isc
], next
, next
) {
350 QLIST_REMOVE(cur
, next
);
356 bool ais_needed(void *opaque
)
358 S390FLICState
*s
= opaque
;
360 return s
->ais_supported
;
363 static const VMStateDescription qemu_s390_flic_vmstate
= {
364 .name
= "qemu-s390-flic",
366 .minimum_version_id
= 1,
367 .needed
= ais_needed
,
368 .fields
= (VMStateField
[]) {
369 VMSTATE_UINT8(simm
, QEMUS390FLICState
),
370 VMSTATE_UINT8(nimm
, QEMUS390FLICState
),
371 VMSTATE_END_OF_LIST()
375 static void qemu_s390_flic_instance_init(Object
*obj
)
377 QEMUS390FLICState
*flic
= QEMU_S390_FLIC(obj
);
380 for (isc
= 0; isc
< 8; isc
++) {
381 QLIST_INIT(&flic
->io
[isc
]);
385 static void qemu_s390_flic_class_init(ObjectClass
*oc
, void *data
)
387 DeviceClass
*dc
= DEVICE_CLASS(oc
);
388 S390FLICStateClass
*fsc
= S390_FLIC_COMMON_CLASS(oc
);
390 dc
->reset
= qemu_s390_flic_reset
;
391 dc
->vmsd
= &qemu_s390_flic_vmstate
;
392 fsc
->register_io_adapter
= qemu_s390_register_io_adapter
;
393 fsc
->io_adapter_map
= qemu_s390_io_adapter_map
;
394 fsc
->add_adapter_routes
= qemu_s390_add_adapter_routes
;
395 fsc
->release_adapter_routes
= qemu_s390_release_adapter_routes
;
396 fsc
->clear_io_irq
= qemu_s390_clear_io_flic
;
397 fsc
->modify_ais_mode
= qemu_s390_modify_ais_mode
;
398 fsc
->inject_airq
= qemu_s390_inject_airq
;
399 fsc
->inject_service
= qemu_s390_inject_service
;
400 fsc
->inject_io
= qemu_s390_inject_io
;
401 fsc
->inject_crw_mchk
= qemu_s390_inject_crw_mchk
;
404 static Property s390_flic_common_properties
[] = {
405 DEFINE_PROP_UINT32("adapter_routes_max_batch", S390FLICState
,
406 adapter_routes_max_batch
, ADAPTER_ROUTES_MAX_GSI
),
407 DEFINE_PROP_END_OF_LIST(),
410 static void s390_flic_common_realize(DeviceState
*dev
, Error
**errp
)
412 S390FLICState
*fs
= S390_FLIC_COMMON(dev
);
413 uint32_t max_batch
= fs
->adapter_routes_max_batch
;
415 if (max_batch
> ADAPTER_ROUTES_MAX_GSI
) {
416 error_setg(errp
, "flic property adapter_routes_max_batch too big"
417 " (%d > %d)", max_batch
, ADAPTER_ROUTES_MAX_GSI
);
421 fs
->ais_supported
= s390_has_feat(S390_FEAT_ADAPTER_INT_SUPPRESSION
);
424 static void s390_flic_class_init(ObjectClass
*oc
, void *data
)
426 DeviceClass
*dc
= DEVICE_CLASS(oc
);
428 dc
->props
= s390_flic_common_properties
;
429 dc
->realize
= s390_flic_common_realize
;
432 static const TypeInfo qemu_s390_flic_info
= {
433 .name
= TYPE_QEMU_S390_FLIC
,
434 .parent
= TYPE_S390_FLIC_COMMON
,
435 .instance_size
= sizeof(QEMUS390FLICState
),
436 .instance_init
= qemu_s390_flic_instance_init
,
437 .class_init
= qemu_s390_flic_class_init
,
441 static const TypeInfo s390_flic_common_info
= {
442 .name
= TYPE_S390_FLIC_COMMON
,
443 .parent
= TYPE_SYS_BUS_DEVICE
,
444 .instance_size
= sizeof(S390FLICState
),
445 .class_init
= s390_flic_class_init
,
446 .class_size
= sizeof(S390FLICStateClass
),
449 static void qemu_s390_flic_register_types(void)
451 type_register_static(&s390_flic_common_info
);
452 type_register_static(&qemu_s390_flic_info
);
455 type_init(qemu_s390_flic_register_types
)
457 static bool adapter_info_so_needed(void *opaque
)
459 return css_migration_enabled();
462 const VMStateDescription vmstate_adapter_info_so
= {
463 .name
= "s390_adapter_info/summary_offset",
465 .minimum_version_id
= 1,
466 .needed
= adapter_info_so_needed
,
467 .fields
= (VMStateField
[]) {
468 VMSTATE_UINT32(summary_offset
, AdapterInfo
),
469 VMSTATE_END_OF_LIST()
473 const VMStateDescription vmstate_adapter_info
= {
474 .name
= "s390_adapter_info",
476 .minimum_version_id
= 1,
477 .fields
= (VMStateField
[]) {
478 VMSTATE_UINT64(ind_offset
, AdapterInfo
),
480 * We do not have to migrate neither the id nor the addresses.
481 * The id is set by css_register_io_adapter and the addresses
482 * are set based on the IndAddr objects after those get mapped.
484 VMSTATE_END_OF_LIST()
486 .subsections
= (const VMStateDescription
* []) {
487 &vmstate_adapter_info_so
,
492 const VMStateDescription vmstate_adapter_routes
= {
494 .name
= "s390_adapter_routes",
496 .minimum_version_id
= 1,
497 .fields
= (VMStateField
[]) {
498 VMSTATE_STRUCT(adapter
, AdapterRoutes
, 1, vmstate_adapter_info
,
500 VMSTATE_END_OF_LIST()