xref: /openbmc/qemu/hw/intc/s390_flic_kvm.c (revision a68694cd)
1 /*
2  * QEMU S390x KVM 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 "cpu.h"
15 #include "kvm_s390x.h"
16 #include <sys/ioctl.h>
17 #include "qemu/error-report.h"
18 #include "qemu/module.h"
19 #include "qapi/error.h"
20 #include "hw/sysbus.h"
21 #include "sysemu/kvm.h"
22 #include "hw/s390x/s390_flic.h"
23 #include "hw/s390x/adapter.h"
24 #include "hw/s390x/css.h"
25 #include "migration/qemu-file-types.h"
26 #include "trace.h"
27 #include "qom/object.h"
28 
29 #define FLIC_SAVE_INITIAL_SIZE qemu_real_host_page_size
30 #define FLIC_FAILED (-1UL)
31 #define FLIC_SAVEVM_VERSION 1
32 
33 struct KVMS390FLICState{
34     S390FLICState parent_obj;
35 
36     uint32_t fd;
37     bool clear_io_supported;
38 };
39 
40 static KVMS390FLICState *s390_get_kvm_flic(S390FLICState *fs)
41 {
42     static KVMS390FLICState *flic;
43 
44     if (!flic) {
45         /* we only have one flic device, so this is fine to cache */
46         flic = KVM_S390_FLIC(fs);
47     }
48     return flic;
49 }
50 
51 /**
52  * flic_get_all_irqs - store all pending irqs in buffer
53  * @buf: pointer to buffer which is passed to kernel
54  * @len: length of buffer
55  * @flic: pointer to flic device state
56  *
57  * Returns: -ENOMEM if buffer is too small,
58  * -EINVAL if attr.group is invalid,
59  * -EFAULT if copying to userspace failed,
60  * on success return number of stored interrupts
61  */
62 static int flic_get_all_irqs(KVMS390FLICState *flic,
63                              void *buf, int len)
64 {
65     struct kvm_device_attr attr = {
66         .group = KVM_DEV_FLIC_GET_ALL_IRQS,
67         .addr = (uint64_t) buf,
68         .attr = len,
69     };
70     int rc;
71 
72     rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr);
73 
74     return rc == -1 ? -errno : rc;
75 }
76 
77 static void flic_enable_pfault(KVMS390FLICState *flic)
78 {
79     struct kvm_device_attr attr = {
80         .group = KVM_DEV_FLIC_APF_ENABLE,
81     };
82     int rc;
83 
84     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
85 
86     if (rc) {
87         fprintf(stderr, "flic: couldn't enable pfault\n");
88     }
89 }
90 
91 static void flic_disable_wait_pfault(KVMS390FLICState *flic)
92 {
93     struct kvm_device_attr attr = {
94         .group = KVM_DEV_FLIC_APF_DISABLE_WAIT,
95     };
96     int rc;
97 
98     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
99 
100     if (rc) {
101         fprintf(stderr, "flic: couldn't disable pfault\n");
102     }
103 }
104 
105 /** flic_enqueue_irqs - returns 0 on success
106  * @buf: pointer to buffer which is passed to kernel
107  * @len: length of buffer
108  * @flic: pointer to flic device state
109  *
110  * Returns: -EINVAL if attr.group is unknown
111  */
112 static int flic_enqueue_irqs(void *buf, uint64_t len,
113                             KVMS390FLICState *flic)
114 {
115     int rc;
116     struct kvm_device_attr attr = {
117         .group = KVM_DEV_FLIC_ENQUEUE,
118         .addr = (uint64_t) buf,
119         .attr = len,
120     };
121 
122     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
123 
124     return rc ? -errno : 0;
125 }
126 
127 static void kvm_s390_inject_flic(S390FLICState *fs, struct kvm_s390_irq *irq)
128 {
129     static bool use_flic = true;
130     int r;
131 
132     if (use_flic) {
133         r = flic_enqueue_irqs(irq, sizeof(*irq), s390_get_kvm_flic(fs));
134         if (r == -ENOSYS) {
135             use_flic = false;
136         }
137         if (!r) {
138             return;
139         }
140     }
141     /* fallback to legacy KVM IOCTL in case FLIC fails */
142     kvm_s390_floating_interrupt_legacy(irq);
143 }
144 
145 static void kvm_s390_inject_service(S390FLICState *fs, uint32_t parm)
146 {
147         struct kvm_s390_irq irq = {
148         .type = KVM_S390_INT_SERVICE,
149         .u.ext.ext_params = parm,
150     };
151 
152     kvm_s390_inject_flic(fs, &irq);
153 }
154 
155 static void kvm_s390_inject_io(S390FLICState *fs, uint16_t subchannel_id,
156                                uint16_t subchannel_nr, uint32_t io_int_parm,
157                                uint32_t io_int_word)
158 {
159     struct kvm_s390_irq irq = {
160         .u.io.subchannel_id = subchannel_id,
161         .u.io.subchannel_nr = subchannel_nr,
162         .u.io.io_int_parm = io_int_parm,
163         .u.io.io_int_word = io_int_word,
164     };
165 
166     if (io_int_word & IO_INT_WORD_AI) {
167         irq.type = KVM_S390_INT_IO(1, 0, 0, 0);
168     } else {
169         irq.type = KVM_S390_INT_IO(0, (subchannel_id & 0xff00) >> 8,
170                                       (subchannel_id & 0x0006),
171                                       subchannel_nr);
172     }
173     kvm_s390_inject_flic(fs, &irq);
174 }
175 
176 static void kvm_s390_inject_crw_mchk(S390FLICState *fs)
177 {
178     struct kvm_s390_irq irq = {
179         .type = KVM_S390_MCHK,
180         .u.mchk.cr14 = CR14_CHANNEL_REPORT_SC,
181         .u.mchk.mcic = s390_build_validity_mcic() | MCIC_SC_CP,
182     };
183 
184     kvm_s390_inject_flic(fs, &irq);
185 }
186 
187 static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
188                            uint16_t subchannel_nr)
189 {
190     KVMS390FLICState *flic = s390_get_kvm_flic(fs);
191     int rc;
192     uint32_t sid = subchannel_id << 16 | subchannel_nr;
193     struct kvm_device_attr attr = {
194         .group = KVM_DEV_FLIC_CLEAR_IO_IRQ,
195         .addr = (uint64_t) &sid,
196         .attr = sizeof(sid),
197     };
198     if (unlikely(!flic->clear_io_supported)) {
199         return -ENOSYS;
200     }
201     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
202     return rc ? -errno : 0;
203 }
204 
205 static int kvm_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc,
206                                     uint16_t mode)
207 {
208     KVMS390FLICState *flic = s390_get_kvm_flic(fs);
209     struct kvm_s390_ais_req req = {
210         .isc = isc,
211         .mode = mode,
212     };
213     struct kvm_device_attr attr = {
214         .group = KVM_DEV_FLIC_AISM,
215         .addr = (uint64_t)&req,
216     };
217 
218     if (!fs->ais_supported) {
219         return -ENOSYS;
220     }
221 
222     return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
223 }
224 
225 static int kvm_s390_inject_airq(S390FLICState *fs, uint8_t type,
226                                 uint8_t isc, uint8_t flags)
227 {
228     KVMS390FLICState *flic = s390_get_kvm_flic(fs);
229     uint32_t id = css_get_adapter_id(type, isc);
230     struct kvm_device_attr attr = {
231         .group = KVM_DEV_FLIC_AIRQ_INJECT,
232         .attr = id,
233     };
234 
235     if (!fs->ais_supported) {
236         return -ENOSYS;
237     }
238 
239     return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
240 }
241 
242 /**
243  * __get_all_irqs - store all pending irqs in buffer
244  * @flic: pointer to flic device state
245  * @buf: pointer to pointer to a buffer
246  * @len: length of buffer
247  *
248  * Returns: return value of flic_get_all_irqs
249  * Note: Retry and increase buffer size until flic_get_all_irqs
250  * either returns a value >= 0 or a negative error code.
251  * -ENOMEM is an exception, which means the buffer is too small
252  * and we should try again. Other negative error codes can be
253  * -EFAULT and -EINVAL which we ignore at this point
254  */
255 static int __get_all_irqs(KVMS390FLICState *flic,
256                           void **buf, int len)
257 {
258     int r;
259 
260     do {
261         /* returns -ENOMEM if buffer is too small and number
262          * of queued interrupts on success */
263         r = flic_get_all_irqs(flic, *buf, len);
264         if (r >= 0) {
265             break;
266         }
267         len *= 2;
268         *buf = g_try_realloc(*buf, len);
269         if (!buf) {
270             return -ENOMEM;
271         }
272     } while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER);
273 
274     return r;
275 }
276 
277 static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
278                                         uint8_t isc, bool swap,
279                                         bool is_maskable, uint8_t flags)
280 {
281     struct kvm_s390_io_adapter adapter = {
282         .id = id,
283         .isc = isc,
284         .maskable = is_maskable,
285         .swap = swap,
286         .flags = flags,
287     };
288     KVMS390FLICState *flic = KVM_S390_FLIC(fs);
289     int r;
290     struct kvm_device_attr attr = {
291         .group = KVM_DEV_FLIC_ADAPTER_REGISTER,
292         .addr = (uint64_t)&adapter,
293     };
294 
295     if (!kvm_gsi_routing_enabled()) {
296         /* nothing to do */
297         return 0;
298     }
299 
300     r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
301 
302     return r ? -errno : 0;
303 }
304 
305 static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
306                                    uint64_t map_addr, bool do_map)
307 {
308     struct kvm_s390_io_adapter_req req = {
309         .id = id,
310         .type = do_map ? KVM_S390_IO_ADAPTER_MAP : KVM_S390_IO_ADAPTER_UNMAP,
311         .addr = map_addr,
312     };
313     struct kvm_device_attr attr = {
314         .group = KVM_DEV_FLIC_ADAPTER_MODIFY,
315         .addr = (uint64_t)&req,
316     };
317     KVMS390FLICState *flic = s390_get_kvm_flic(fs);
318     int r;
319 
320     if (!kvm_gsi_routing_enabled()) {
321         /* nothing to do */
322         return 0;
323     }
324 
325     r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
326     return r ? -errno : 0;
327 }
328 
329 static int kvm_s390_add_adapter_routes(S390FLICState *fs,
330                                        AdapterRoutes *routes)
331 {
332     int ret, i;
333     uint64_t ind_offset = routes->adapter.ind_offset;
334 
335     if (!kvm_gsi_routing_enabled()) {
336         return -ENOSYS;
337     }
338 
339     for (i = 0; i < routes->num_routes; i++) {
340         ret = kvm_irqchip_add_adapter_route(kvm_state, &routes->adapter);
341         if (ret < 0) {
342             goto out_undo;
343         }
344         routes->gsi[i] = ret;
345         routes->adapter.ind_offset++;
346     }
347     kvm_irqchip_commit_routes(kvm_state);
348 
349     /* Restore passed-in structure to original state. */
350     routes->adapter.ind_offset = ind_offset;
351     return 0;
352 out_undo:
353     while (--i >= 0) {
354         kvm_irqchip_release_virq(kvm_state, routes->gsi[i]);
355         routes->gsi[i] = -1;
356     }
357     routes->adapter.ind_offset = ind_offset;
358     return ret;
359 }
360 
361 static void kvm_s390_release_adapter_routes(S390FLICState *fs,
362                                             AdapterRoutes *routes)
363 {
364     int i;
365 
366     if (!kvm_gsi_routing_enabled()) {
367         return;
368     }
369 
370     for (i = 0; i < routes->num_routes; i++) {
371         if (routes->gsi[i] >= 0) {
372             kvm_irqchip_release_virq(kvm_state, routes->gsi[i]);
373             routes->gsi[i] = -1;
374         }
375     }
376 }
377 
378 /**
379  * kvm_flic_save - Save pending floating interrupts
380  * @f: QEMUFile containing migration state
381  * @opaque: pointer to flic device state
382  * @size: ignored
383  *
384  * Note: Pass buf and len to kernel. Start with one page and
385  * increase until buffer is sufficient or maxium size is
386  * reached
387  */
388 static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size,
389                          const VMStateField *field, QJSON *vmdesc)
390 {
391     KVMS390FLICState *flic = opaque;
392     int len = FLIC_SAVE_INITIAL_SIZE;
393     void *buf;
394     int count;
395     int r = 0;
396 
397     flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
398 
399     buf = g_try_malloc0(len);
400     if (!buf) {
401         /* Storing FLIC_FAILED into the count field here will cause the
402          * target system to fail when attempting to load irqs from the
403          * migration state */
404         error_report("flic: couldn't allocate memory");
405         qemu_put_be64(f, FLIC_FAILED);
406         return -ENOMEM;
407     }
408 
409     count = __get_all_irqs(flic, &buf, len);
410     if (count < 0) {
411         error_report("flic: couldn't retrieve irqs from kernel, rc %d",
412                      count);
413         /* Storing FLIC_FAILED into the count field here will cause the
414          * target system to fail when attempting to load irqs from the
415          * migration state */
416         qemu_put_be64(f, FLIC_FAILED);
417         r = count;
418     } else {
419         qemu_put_be64(f, count);
420         qemu_put_buffer(f, (uint8_t *) buf,
421                         count * sizeof(struct kvm_s390_irq));
422     }
423     g_free(buf);
424 
425     return r;
426 }
427 
428 /**
429  * kvm_flic_load - Load pending floating interrupts
430  * @f: QEMUFile containing migration state
431  * @opaque: pointer to flic device state
432  * @size: ignored
433  *
434  * Returns: value of flic_enqueue_irqs, -EINVAL on error
435  * Note: Do nothing when no interrupts where stored
436  * in QEMUFile
437  */
438 static int kvm_flic_load(QEMUFile *f, void *opaque, size_t size,
439                          const VMStateField *field)
440 {
441     uint64_t len = 0;
442     uint64_t count = 0;
443     void *buf = NULL;
444     int r = 0;
445 
446     flic_enable_pfault((struct KVMS390FLICState *) opaque);
447 
448     count = qemu_get_be64(f);
449     len = count * sizeof(struct kvm_s390_irq);
450     if (count == FLIC_FAILED) {
451         return -EINVAL;
452     }
453     if (count == 0) {
454         return 0;
455     }
456     buf = g_try_malloc0(len);
457     if (!buf) {
458         return -ENOMEM;
459     }
460 
461     if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) {
462         r = -EINVAL;
463         goto out_free;
464     }
465     r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque);
466 
467 out_free:
468     g_free(buf);
469     return r;
470 }
471 
472 typedef struct KVMS390FLICStateMigTmp {
473     KVMS390FLICState *parent;
474     uint8_t simm;
475     uint8_t nimm;
476 } KVMS390FLICStateMigTmp;
477 
478 static int kvm_flic_ais_pre_save(void *opaque)
479 {
480     KVMS390FLICStateMigTmp *tmp = opaque;
481     KVMS390FLICState *flic = tmp->parent;
482     struct kvm_s390_ais_all ais;
483     struct kvm_device_attr attr = {
484         .group = KVM_DEV_FLIC_AISM_ALL,
485         .addr = (uint64_t)&ais,
486         .attr = sizeof(ais),
487     };
488 
489     if (ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr)) {
490         error_report("Failed to retrieve kvm flic ais states");
491         return -EINVAL;
492     }
493 
494     tmp->simm = ais.simm;
495     tmp->nimm = ais.nimm;
496 
497     return 0;
498 }
499 
500 static int kvm_flic_ais_post_load(void *opaque, int version_id)
501 {
502     KVMS390FLICStateMigTmp *tmp = opaque;
503     KVMS390FLICState *flic = tmp->parent;
504     struct kvm_s390_ais_all ais = {
505         .simm = tmp->simm,
506         .nimm = tmp->nimm,
507     };
508     struct kvm_device_attr attr = {
509         .group = KVM_DEV_FLIC_AISM_ALL,
510         .addr = (uint64_t)&ais,
511     };
512 
513     /* This can happen when the user mis-configures its guests in an
514      * incompatible fashion or without a CPU model. For example using
515      * qemu with -cpu host (which is not migration safe) and do a
516      * migration from a host that has AIS to a host that has no AIS.
517      * In that case the target system will reject the migration here.
518      */
519     if (!ais_needed(flic)) {
520         return -ENOSYS;
521     }
522 
523     return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
524 }
525 
526 static const VMStateDescription kvm_s390_flic_ais_tmp = {
527     .name = "s390-flic-ais-tmp",
528     .pre_save = kvm_flic_ais_pre_save,
529     .post_load = kvm_flic_ais_post_load,
530     .fields = (VMStateField[]) {
531         VMSTATE_UINT8(simm, KVMS390FLICStateMigTmp),
532         VMSTATE_UINT8(nimm, KVMS390FLICStateMigTmp),
533         VMSTATE_END_OF_LIST()
534     }
535 };
536 
537 static const VMStateDescription kvm_s390_flic_vmstate_ais = {
538     .name = "s390-flic/ais",
539     .version_id = 1,
540     .minimum_version_id = 1,
541     .needed = ais_needed,
542     .fields = (VMStateField[]) {
543         VMSTATE_WITH_TMP(KVMS390FLICState, KVMS390FLICStateMigTmp,
544                          kvm_s390_flic_ais_tmp),
545         VMSTATE_END_OF_LIST()
546     }
547 };
548 
549 static const VMStateDescription kvm_s390_flic_vmstate = {
550     /* should have been like kvm-s390-flic,
551      * can't change without breaking compat */
552     .name = "s390-flic",
553     .version_id = FLIC_SAVEVM_VERSION,
554     .minimum_version_id = FLIC_SAVEVM_VERSION,
555     .fields = (VMStateField[]) {
556         {
557             .name = "irqs",
558             .info = &(const VMStateInfo) {
559                 .name = "irqs",
560                 .get = kvm_flic_load,
561                 .put = kvm_flic_save,
562             },
563             .flags = VMS_SINGLE,
564         },
565         VMSTATE_END_OF_LIST()
566     },
567     .subsections = (const VMStateDescription * []) {
568         &kvm_s390_flic_vmstate_ais,
569         NULL
570     }
571 };
572 
573 struct KVMS390FLICStateClass {
574     S390FLICStateClass parent_class;
575     DeviceRealize parent_realize;
576 };
577 typedef struct KVMS390FLICStateClass KVMS390FLICStateClass;
578 
579 DECLARE_CLASS_CHECKERS(KVMS390FLICStateClass, KVM_S390_FLIC,
580                        TYPE_KVM_S390_FLIC)
581 
582 
583 static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
584 {
585     KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
586     struct kvm_create_device cd = {0};
587     struct kvm_device_attr test_attr = {0};
588     int ret;
589     Error *err = NULL;
590 
591     KVM_S390_FLIC_GET_CLASS(dev)->parent_realize(dev, &err);
592     if (err) {
593         error_propagate(errp, err);
594         return;
595     }
596     flic_state->fd = -1;
597 
598     cd.type = KVM_DEV_TYPE_FLIC;
599     ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
600     if (ret < 0) {
601         error_setg_errno(errp, errno, "Creating the KVM device failed");
602         trace_flic_create_device(errno);
603         return;
604     }
605     flic_state->fd = cd.fd;
606 
607     /* Check clear_io_irq support */
608     test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ;
609     flic_state->clear_io_supported = !ioctl(flic_state->fd,
610                                             KVM_HAS_DEVICE_ATTR, test_attr);
611 }
612 
613 static void kvm_s390_flic_reset(DeviceState *dev)
614 {
615     KVMS390FLICState *flic = KVM_S390_FLIC(dev);
616     S390FLICState *fs = S390_FLIC_COMMON(dev);
617     struct kvm_device_attr attr = {
618         .group = KVM_DEV_FLIC_CLEAR_IRQS,
619     };
620     int rc = 0;
621     uint8_t isc;
622 
623     if (flic->fd == -1) {
624         return;
625     }
626 
627     flic_disable_wait_pfault(flic);
628 
629     if (fs->ais_supported) {
630         for (isc = 0; isc <= MAX_ISC; isc++) {
631             rc = kvm_s390_modify_ais_mode(fs, isc, SIC_IRQ_MODE_ALL);
632             if (rc) {
633                 error_report("Failed to reset ais mode for isc %d: %s",
634                              isc, strerror(-rc));
635             }
636         }
637     }
638 
639     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
640     if (rc) {
641         trace_flic_reset_failed(errno);
642     }
643 
644     flic_enable_pfault(flic);
645 }
646 
647 static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
648 {
649     DeviceClass *dc = DEVICE_CLASS(oc);
650     S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);
651 
652     KVM_S390_FLIC_CLASS(oc)->parent_realize = dc->realize;
653     dc->realize = kvm_s390_flic_realize;
654     dc->vmsd = &kvm_s390_flic_vmstate;
655     dc->reset = kvm_s390_flic_reset;
656     fsc->register_io_adapter = kvm_s390_register_io_adapter;
657     fsc->io_adapter_map = kvm_s390_io_adapter_map;
658     fsc->add_adapter_routes = kvm_s390_add_adapter_routes;
659     fsc->release_adapter_routes = kvm_s390_release_adapter_routes;
660     fsc->clear_io_irq = kvm_s390_clear_io_flic;
661     fsc->modify_ais_mode = kvm_s390_modify_ais_mode;
662     fsc->inject_airq = kvm_s390_inject_airq;
663     fsc->inject_service = kvm_s390_inject_service;
664     fsc->inject_io = kvm_s390_inject_io;
665     fsc->inject_crw_mchk = kvm_s390_inject_crw_mchk;
666 }
667 
668 static const TypeInfo kvm_s390_flic_info = {
669     .name          = TYPE_KVM_S390_FLIC,
670     .parent        = TYPE_S390_FLIC_COMMON,
671     .instance_size = sizeof(KVMS390FLICState),
672     .class_size    = sizeof(KVMS390FLICStateClass),
673     .class_init    = kvm_s390_flic_class_init,
674 };
675 
676 static void kvm_s390_flic_register_types(void)
677 {
678     type_register_static(&kvm_s390_flic_info);
679 }
680 
681 type_init(kvm_s390_flic_register_types)
682