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