xref: /openbmc/qemu/hw/intc/s390_flic.c (revision f68ecdd4f3584130cf0cb8f545b7359fae150fe0)
1 /*
2  * QEMU S390x floating interrupt controller (flic)
3  *
4  * Copyright 2014 IBM Corp.
5  * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
6  *            Cornelia Huck <cornelia.huck@de.ibm.com>
7  *
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
10  * directory.
11  */
12 
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"
19 #include "trace.h"
20 #include "cpu.h"
21 #include "hw/qdev.h"
22 #include "qapi/error.h"
23 #include "hw/s390x/s390-virtio-ccw.h"
24 
25 QEMUS390FLICState *s390_get_qemu_flic(S390FLICState *fs)
26 {
27     static QEMUS390FLICState *flic;
28 
29     if (!flic) {
30         /* we only have one flic device, so this is fine to cache */
31         flic = QEMU_S390_FLIC(fs);
32     }
33     return flic;
34 }
35 
36 S390FLICState *s390_get_flic(void)
37 {
38     static S390FLICState *fs;
39 
40     if (!fs) {
41         fs = S390_FLIC_COMMON(object_resolve_path_type("",
42                                                        TYPE_S390_FLIC_COMMON,
43                                                        NULL));
44     }
45     return fs;
46 }
47 
48 void s390_flic_init(void)
49 {
50     DeviceState *dev;
51 
52     if (kvm_enabled()) {
53         dev = qdev_create(NULL, TYPE_KVM_S390_FLIC);
54         object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC,
55                                   OBJECT(dev), NULL);
56     } else {
57         dev = qdev_create(NULL, TYPE_QEMU_S390_FLIC);
58         object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC,
59                                   OBJECT(dev), NULL);
60     }
61     qdev_init_nofail(dev);
62 }
63 
64 static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
65                                          uint8_t isc, bool swap,
66                                          bool is_maskable, uint8_t flags)
67 {
68     /* nothing to do */
69     return 0;
70 }
71 
72 static int qemu_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
73                                     uint64_t map_addr, bool do_map)
74 {
75     /* nothing to do */
76     return 0;
77 }
78 
79 static int qemu_s390_add_adapter_routes(S390FLICState *fs,
80                                         AdapterRoutes *routes)
81 {
82     return -ENOSYS;
83 }
84 
85 static void qemu_s390_release_adapter_routes(S390FLICState *fs,
86                                              AdapterRoutes *routes)
87 {
88 }
89 
90 static int qemu_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
91                            uint16_t subchannel_nr)
92 {
93     QEMUS390FLICState *flic  = s390_get_qemu_flic(fs);
94     QEMUS390FlicIO *cur, *next;
95     uint8_t isc;
96 
97     g_assert(qemu_mutex_iothread_locked());
98     if (!(flic->pending & FLIC_PENDING_IO)) {
99         return 0;
100     }
101 
102     /* check all iscs */
103     for (isc = 0; isc < 8; isc++) {
104         if (QLIST_EMPTY(&flic->io[isc])) {
105             continue;
106         }
107 
108         /* search and delete any matching one */
109         QLIST_FOREACH_SAFE(cur, &flic->io[isc], next, next) {
110             if (cur->id == subchannel_id && cur->nr == subchannel_nr) {
111                 QLIST_REMOVE(cur, next);
112                 g_free(cur);
113             }
114         }
115 
116         /* update our indicator bit */
117         if (QLIST_EMPTY(&flic->io[isc])) {
118             flic->pending &= ~ISC_TO_PENDING_IO(isc);
119         }
120     }
121     return 0;
122 }
123 
124 static int qemu_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc,
125                                      uint16_t mode)
126 {
127     QEMUS390FLICState *flic  = s390_get_qemu_flic(fs);
128 
129     switch (mode) {
130     case SIC_IRQ_MODE_ALL:
131         flic->simm &= ~AIS_MODE_MASK(isc);
132         flic->nimm &= ~AIS_MODE_MASK(isc);
133         break;
134     case SIC_IRQ_MODE_SINGLE:
135         flic->simm |= AIS_MODE_MASK(isc);
136         flic->nimm &= ~AIS_MODE_MASK(isc);
137         break;
138     default:
139         return -EINVAL;
140     }
141 
142     return 0;
143 }
144 
145 static int qemu_s390_inject_airq(S390FLICState *fs, uint8_t type,
146                                  uint8_t isc, uint8_t flags)
147 {
148     QEMUS390FLICState *flic = s390_get_qemu_flic(fs);
149     S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
150     bool flag = flags & S390_ADAPTER_SUPPRESSIBLE;
151     uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI;
152 
153     if (flag && (flic->nimm & AIS_MODE_MASK(isc))) {
154         trace_qemu_s390_airq_suppressed(type, isc);
155         return 0;
156     }
157 
158     fsc->inject_io(fs, 0, 0, 0, io_int_word);
159 
160     if (flag && (flic->simm & AIS_MODE_MASK(isc))) {
161         flic->nimm |= AIS_MODE_MASK(isc);
162         trace_qemu_s390_suppress_airq(isc, "Single-Interruption Mode",
163                                       "NO-Interruptions Mode");
164     }
165 
166     return 0;
167 }
168 
169 static void qemu_s390_flic_notify(uint32_t type)
170 {
171     CPUState *cs;
172 
173     /*
174      * We have to make all CPUs see CPU_INTERRUPT_HARD, so they might
175      * consider it. We will kick all running CPUs and only relevant
176      * sleeping ones.
177      */
178     CPU_FOREACH(cs) {
179         S390CPU *cpu = S390_CPU(cs);
180 
181         cs->interrupt_request |= CPU_INTERRUPT_HARD;
182 
183         /* ignore CPUs that are not sleeping */
184         if (s390_cpu_get_state(cpu) != CPU_STATE_OPERATING &&
185             s390_cpu_get_state(cpu) != CPU_STATE_LOAD) {
186             continue;
187         }
188 
189         /* we always kick running CPUs for now, this is tricky */
190         if (cs->halted) {
191             /* don't check for subclasses, CPUs double check when waking up */
192             if (type & FLIC_PENDING_SERVICE) {
193                 if (!(cpu->env.psw.mask & PSW_MASK_EXT)) {
194                     continue;
195                 }
196             } else if (type & FLIC_PENDING_IO) {
197                 if (!(cpu->env.psw.mask & PSW_MASK_IO)) {
198                     continue;
199                 }
200             } else if (type & FLIC_PENDING_MCHK_CR) {
201                 if (!(cpu->env.psw.mask & PSW_MASK_MCHECK)) {
202                     continue;
203                 }
204             }
205         }
206         cpu_interrupt(cs, CPU_INTERRUPT_HARD);
207     }
208 }
209 
210 uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState *flic)
211 {
212     uint32_t tmp;
213 
214     g_assert(qemu_mutex_iothread_locked());
215     g_assert(flic->pending & FLIC_PENDING_SERVICE);
216     tmp = flic->service_param;
217     flic->service_param = 0;
218     flic->pending &= ~FLIC_PENDING_SERVICE;
219 
220     return tmp;
221 }
222 
223 /* caller has to free the returned object */
224 QEMUS390FlicIO *qemu_s390_flic_dequeue_io(QEMUS390FLICState *flic, uint64_t cr6)
225 {
226     QEMUS390FlicIO *io;
227     uint8_t isc;
228 
229     g_assert(qemu_mutex_iothread_locked());
230     if (!(flic->pending & CR6_TO_PENDING_IO(cr6))) {
231         return NULL;
232     }
233 
234     for (isc = 0; isc < 8; isc++) {
235         if (QLIST_EMPTY(&flic->io[isc]) || !(cr6 & ISC_TO_ISC_BITS(isc))) {
236             continue;
237         }
238         io = QLIST_FIRST(&flic->io[isc]);
239         QLIST_REMOVE(io, next);
240 
241         /* update our indicator bit */
242         if (QLIST_EMPTY(&flic->io[isc])) {
243             flic->pending &= ~ISC_TO_PENDING_IO(isc);
244         }
245         return io;
246     }
247 
248     return NULL;
249 }
250 
251 void qemu_s390_flic_dequeue_crw_mchk(QEMUS390FLICState *flic)
252 {
253     g_assert(qemu_mutex_iothread_locked());
254     g_assert(flic->pending & FLIC_PENDING_MCHK_CR);
255     flic->pending &= ~FLIC_PENDING_MCHK_CR;
256 }
257 
258 static void qemu_s390_inject_service(S390FLICState *fs, uint32_t parm)
259 {
260     QEMUS390FLICState *flic = s390_get_qemu_flic(fs);
261 
262     g_assert(qemu_mutex_iothread_locked());
263     /* multiplexing is good enough for sclp - kvm does it internally as well */
264     flic->service_param |= parm;
265     flic->pending |= FLIC_PENDING_SERVICE;
266 
267     qemu_s390_flic_notify(FLIC_PENDING_SERVICE);
268 }
269 
270 static void qemu_s390_inject_io(S390FLICState *fs, uint16_t subchannel_id,
271                                 uint16_t subchannel_nr, uint32_t io_int_parm,
272                                 uint32_t io_int_word)
273 {
274     const uint8_t isc = IO_INT_WORD_ISC(io_int_word);
275     QEMUS390FLICState *flic = s390_get_qemu_flic(fs);
276     QEMUS390FlicIO *io;
277 
278     g_assert(qemu_mutex_iothread_locked());
279     io = g_new0(QEMUS390FlicIO, 1);
280     io->id = subchannel_id;
281     io->nr = subchannel_nr;
282     io->parm = io_int_parm;
283     io->word = io_int_word;
284 
285     QLIST_INSERT_HEAD(&flic->io[isc], io, next);
286     flic->pending |= ISC_TO_PENDING_IO(isc);
287 
288     qemu_s390_flic_notify(ISC_TO_PENDING_IO(isc));
289 }
290 
291 static void qemu_s390_inject_crw_mchk(S390FLICState *fs)
292 {
293     QEMUS390FLICState *flic = s390_get_qemu_flic(fs);
294 
295     g_assert(qemu_mutex_iothread_locked());
296     flic->pending |= FLIC_PENDING_MCHK_CR;
297 
298     qemu_s390_flic_notify(FLIC_PENDING_MCHK_CR);
299 }
300 
301 bool qemu_s390_flic_has_service(QEMUS390FLICState *flic)
302 {
303     /* called without lock via cc->has_work, will be validated under lock */
304     return !!(flic->pending & FLIC_PENDING_SERVICE);
305 }
306 
307 bool qemu_s390_flic_has_io(QEMUS390FLICState *flic, uint64_t cr6)
308 {
309     /* called without lock via cc->has_work, will be validated under lock */
310     return !!(flic->pending & CR6_TO_PENDING_IO(cr6));
311 }
312 
313 bool qemu_s390_flic_has_crw_mchk(QEMUS390FLICState *flic)
314 {
315     /* called without lock via cc->has_work, will be validated under lock */
316     return !!(flic->pending & FLIC_PENDING_MCHK_CR);
317 }
318 
319 bool qemu_s390_flic_has_any(QEMUS390FLICState *flic)
320 {
321     g_assert(qemu_mutex_iothread_locked());
322     return !!flic->pending;
323 }
324 
325 static void qemu_s390_flic_reset(DeviceState *dev)
326 {
327     QEMUS390FLICState *flic = QEMU_S390_FLIC(dev);
328     QEMUS390FlicIO *cur, *next;
329     int isc;
330 
331     g_assert(qemu_mutex_iothread_locked());
332     flic->simm = 0;
333     flic->nimm = 0;
334     flic->pending = 0;
335 
336     /* remove all pending io interrupts */
337     for (isc = 0; isc < 8; isc++) {
338         QLIST_FOREACH_SAFE(cur, &flic->io[isc], next, next) {
339             QLIST_REMOVE(cur, next);
340             g_free(cur);
341         }
342     }
343 }
344 
345 bool ais_needed(void *opaque)
346 {
347     S390FLICState *s = opaque;
348 
349     return s->ais_supported;
350 }
351 
352 static const VMStateDescription qemu_s390_flic_vmstate = {
353     .name = "qemu-s390-flic",
354     .version_id = 1,
355     .minimum_version_id = 1,
356     .needed = ais_needed,
357     .fields = (VMStateField[]) {
358         VMSTATE_UINT8(simm, QEMUS390FLICState),
359         VMSTATE_UINT8(nimm, QEMUS390FLICState),
360         VMSTATE_END_OF_LIST()
361     }
362 };
363 
364 static void qemu_s390_flic_instance_init(Object *obj)
365 {
366     QEMUS390FLICState *flic = QEMU_S390_FLIC(obj);
367     int isc;
368 
369     for (isc = 0; isc < 8; isc++) {
370         QLIST_INIT(&flic->io[isc]);
371     }
372 }
373 
374 static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
375 {
376     DeviceClass *dc = DEVICE_CLASS(oc);
377     S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);
378 
379     dc->reset = qemu_s390_flic_reset;
380     dc->vmsd = &qemu_s390_flic_vmstate;
381     fsc->register_io_adapter = qemu_s390_register_io_adapter;
382     fsc->io_adapter_map = qemu_s390_io_adapter_map;
383     fsc->add_adapter_routes = qemu_s390_add_adapter_routes;
384     fsc->release_adapter_routes = qemu_s390_release_adapter_routes;
385     fsc->clear_io_irq = qemu_s390_clear_io_flic;
386     fsc->modify_ais_mode = qemu_s390_modify_ais_mode;
387     fsc->inject_airq = qemu_s390_inject_airq;
388     fsc->inject_service = qemu_s390_inject_service;
389     fsc->inject_io = qemu_s390_inject_io;
390     fsc->inject_crw_mchk = qemu_s390_inject_crw_mchk;
391 }
392 
393 static Property s390_flic_common_properties[] = {
394     DEFINE_PROP_UINT32("adapter_routes_max_batch", S390FLICState,
395                        adapter_routes_max_batch, ADAPTER_ROUTES_MAX_GSI),
396     DEFINE_PROP_END_OF_LIST(),
397 };
398 
399 static void s390_flic_common_realize(DeviceState *dev, Error **errp)
400 {
401     S390FLICState *fs = S390_FLIC_COMMON(dev);
402     uint32_t max_batch = fs->adapter_routes_max_batch;
403 
404     if (max_batch > ADAPTER_ROUTES_MAX_GSI) {
405         error_setg(errp, "flic property adapter_routes_max_batch too big"
406                    " (%d > %d)", max_batch, ADAPTER_ROUTES_MAX_GSI);
407         return;
408     }
409 
410     fs->ais_supported = s390_has_feat(S390_FEAT_ADAPTER_INT_SUPPRESSION);
411 }
412 
413 static void s390_flic_class_init(ObjectClass *oc, void *data)
414 {
415     DeviceClass *dc = DEVICE_CLASS(oc);
416 
417     dc->props = s390_flic_common_properties;
418     dc->realize = s390_flic_common_realize;
419 }
420 
421 static const TypeInfo qemu_s390_flic_info = {
422     .name          = TYPE_QEMU_S390_FLIC,
423     .parent        = TYPE_S390_FLIC_COMMON,
424     .instance_size = sizeof(QEMUS390FLICState),
425     .instance_init = qemu_s390_flic_instance_init,
426     .class_init    = qemu_s390_flic_class_init,
427 };
428 
429 
430 static const TypeInfo s390_flic_common_info = {
431     .name          = TYPE_S390_FLIC_COMMON,
432     .parent        = TYPE_SYS_BUS_DEVICE,
433     .instance_size = sizeof(S390FLICState),
434     .class_init    = s390_flic_class_init,
435     .class_size    = sizeof(S390FLICStateClass),
436 };
437 
438 static void qemu_s390_flic_register_types(void)
439 {
440     type_register_static(&s390_flic_common_info);
441     type_register_static(&qemu_s390_flic_info);
442 }
443 
444 type_init(qemu_s390_flic_register_types)
445 
446 static bool adapter_info_so_needed(void *opaque)
447 {
448     return css_migration_enabled();
449 }
450 
451 const VMStateDescription vmstate_adapter_info_so = {
452     .name = "s390_adapter_info/summary_offset",
453     .version_id = 1,
454     .minimum_version_id = 1,
455     .needed = adapter_info_so_needed,
456     .fields = (VMStateField[]) {
457         VMSTATE_UINT32(summary_offset, AdapterInfo),
458         VMSTATE_END_OF_LIST()
459     }
460 };
461 
462 const VMStateDescription vmstate_adapter_info = {
463     .name = "s390_adapter_info",
464     .version_id = 1,
465     .minimum_version_id = 1,
466     .fields = (VMStateField[]) {
467         VMSTATE_UINT64(ind_offset, AdapterInfo),
468         /*
469          * We do not have to migrate neither the id nor the addresses.
470          * The id is set by css_register_io_adapter and the addresses
471          * are set based on the IndAddr objects after those get mapped.
472          */
473         VMSTATE_END_OF_LIST()
474     },
475     .subsections = (const VMStateDescription * []) {
476         &vmstate_adapter_info_so,
477         NULL
478     }
479 };
480 
481 const VMStateDescription vmstate_adapter_routes = {
482 
483     .name = "s390_adapter_routes",
484     .version_id = 1,
485     .minimum_version_id = 1,
486     .fields = (VMStateField[]) {
487         VMSTATE_STRUCT(adapter, AdapterRoutes, 1, vmstate_adapter_info,
488                        AdapterInfo),
489         VMSTATE_END_OF_LIST()
490     }
491 };
492