]> git.proxmox.com Git - mirror_qemu.git/blob - hw/intc/s390_flic_kvm.c
Use DECLARE_*CHECKER* macros
[mirror_qemu.git] / hw / intc / s390_flic_kvm.c
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)