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