target/sparc/translate: silence the compiler warnings
[qemu/ar7.git] / hw / intc / s390_flic_kvm.c
blob35d91afa557259b32b4ebf6293499792bf8e7342
1 /*
2 * QEMU S390x KVM floating interrupt controller (flic)
4 * Copyright 2014 IBM Corp.
5 * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
6 * Cornelia Huck <cornelia.huck@de.ibm.com>
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.
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"
29 #define FLIC_SAVE_INITIAL_SIZE qemu_real_host_page_size
30 #define FLIC_FAILED (-1UL)
31 #define FLIC_SAVEVM_VERSION 1
33 struct KVMS390FLICState{
34 S390FLICState parent_obj;
36 uint32_t fd;
37 bool clear_io_supported;
40 static KVMS390FLICState *s390_get_kvm_flic(S390FLICState *fs)
42 static KVMS390FLICState *flic;
44 if (!flic) {
45 /* we only have one flic device, so this is fine to cache */
46 flic = KVM_S390_FLIC(fs);
48 return flic;
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
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
62 static int flic_get_all_irqs(KVMS390FLICState *flic,
63 void *buf, int len)
65 struct kvm_device_attr attr = {
66 .group = KVM_DEV_FLIC_GET_ALL_IRQS,
67 .addr = (uint64_t) buf,
68 .attr = len,
70 int rc;
72 rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr);
74 return rc == -1 ? -errno : rc;
77 static void flic_enable_pfault(KVMS390FLICState *flic)
79 struct kvm_device_attr attr = {
80 .group = KVM_DEV_FLIC_APF_ENABLE,
82 int rc;
84 rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
86 if (rc) {
87 fprintf(stderr, "flic: couldn't enable pfault\n");
91 static void flic_disable_wait_pfault(KVMS390FLICState *flic)
93 struct kvm_device_attr attr = {
94 .group = KVM_DEV_FLIC_APF_DISABLE_WAIT,
96 int rc;
98 rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
100 if (rc) {
101 fprintf(stderr, "flic: couldn't disable pfault\n");
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
110 * Returns: -EINVAL if attr.group is unknown
112 static int flic_enqueue_irqs(void *buf, uint64_t len,
113 KVMS390FLICState *flic)
115 int rc;
116 struct kvm_device_attr attr = {
117 .group = KVM_DEV_FLIC_ENQUEUE,
118 .addr = (uint64_t) buf,
119 .attr = len,
122 rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
124 return rc ? -errno : 0;
127 static void kvm_s390_inject_flic(S390FLICState *fs, struct kvm_s390_irq *irq)
129 static bool use_flic = true;
130 int r;
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;
137 if (!r) {
138 return;
141 /* fallback to legacy KVM IOCTL in case FLIC fails */
142 kvm_s390_floating_interrupt_legacy(irq);
145 static void kvm_s390_inject_service(S390FLICState *fs, uint32_t parm)
147 struct kvm_s390_irq irq = {
148 .type = KVM_S390_INT_SERVICE,
149 .u.ext.ext_params = parm,
152 kvm_s390_inject_flic(fs, &irq);
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)
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,
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);
173 kvm_s390_inject_flic(fs, &irq);
176 static void kvm_s390_inject_crw_mchk(S390FLICState *fs)
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,
184 kvm_s390_inject_flic(fs, &irq);
187 static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
188 uint16_t subchannel_nr)
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),
198 if (unlikely(!flic->clear_io_supported)) {
199 return -ENOSYS;
201 rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
202 return rc ? -errno : 0;
205 static int kvm_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc,
206 uint16_t mode)
208 KVMS390FLICState *flic = s390_get_kvm_flic(fs);
209 struct kvm_s390_ais_req req = {
210 .isc = isc,
211 .mode = mode,
213 struct kvm_device_attr attr = {
214 .group = KVM_DEV_FLIC_AISM,
215 .addr = (uint64_t)&req,
218 if (!fs->ais_supported) {
219 return -ENOSYS;
222 return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
225 static int kvm_s390_inject_airq(S390FLICState *fs, uint8_t type,
226 uint8_t isc, uint8_t flags)
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,
235 if (!fs->ais_supported) {
236 return -ENOSYS;
239 return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
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
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
255 static int __get_all_irqs(KVMS390FLICState *flic,
256 void **buf, int len)
258 int r;
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;
267 len *= 2;
268 *buf = g_try_realloc(*buf, len);
269 if (!buf) {
270 return -ENOMEM;
272 } while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER);
274 return r;
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)
281 struct kvm_s390_io_adapter adapter = {
282 .id = id,
283 .isc = isc,
284 .maskable = is_maskable,
285 .swap = swap,
286 .flags = flags,
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,
295 if (!kvm_gsi_routing_enabled()) {
296 /* nothing to do */
297 return 0;
300 r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
302 return r ? -errno : 0;
305 static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
306 uint64_t map_addr, bool do_map)
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,
313 struct kvm_device_attr attr = {
314 .group = KVM_DEV_FLIC_ADAPTER_MODIFY,
315 .addr = (uint64_t)&req,
317 KVMS390FLICState *flic = s390_get_kvm_flic(fs);
318 int r;
320 if (!kvm_gsi_routing_enabled()) {
321 /* nothing to do */
322 return 0;
325 r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
326 return r ? -errno : 0;
329 static int kvm_s390_add_adapter_routes(S390FLICState *fs,
330 AdapterRoutes *routes)
332 int ret, i;
333 uint64_t ind_offset = routes->adapter.ind_offset;
335 if (!kvm_gsi_routing_enabled()) {
336 return -ENOSYS;
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;
344 routes->gsi[i] = ret;
345 routes->adapter.ind_offset++;
347 kvm_irqchip_commit_routes(kvm_state);
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;
357 routes->adapter.ind_offset = ind_offset;
358 return ret;
361 static void kvm_s390_release_adapter_routes(S390FLICState *fs,
362 AdapterRoutes *routes)
364 int i;
366 if (!kvm_gsi_routing_enabled()) {
367 return;
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;
379 * kvm_flic_save - Save pending floating interrupts
380 * @f: QEMUFile containing migration state
381 * @opaque: pointer to flic device state
382 * @size: ignored
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
388 static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size,
389 const VMStateField *field, QJSON *vmdesc)
391 KVMS390FLICState *flic = opaque;
392 int len = FLIC_SAVE_INITIAL_SIZE;
393 void *buf;
394 int count;
395 int r = 0;
397 flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
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;
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));
423 g_free(buf);
425 return r;
429 * kvm_flic_load - Load pending floating interrupts
430 * @f: QEMUFile containing migration state
431 * @opaque: pointer to flic device state
432 * @size: ignored
434 * Returns: value of flic_enqueue_irqs, -EINVAL on error
435 * Note: Do nothing when no interrupts where stored
436 * in QEMUFile
438 static int kvm_flic_load(QEMUFile *f, void *opaque, size_t size,
439 const VMStateField *field)
441 uint64_t len = 0;
442 uint64_t count = 0;
443 void *buf = NULL;
444 int r = 0;
446 flic_enable_pfault((struct KVMS390FLICState *) opaque);
448 count = qemu_get_be64(f);
449 len = count * sizeof(struct kvm_s390_irq);
450 if (count == FLIC_FAILED) {
451 return -EINVAL;
453 if (count == 0) {
454 return 0;
456 buf = g_try_malloc0(len);
457 if (!buf) {
458 return -ENOMEM;
461 if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) {
462 r = -EINVAL;
463 goto out_free;
465 r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque);
467 out_free:
468 g_free(buf);
469 return r;
472 typedef struct KVMS390FLICStateMigTmp {
473 KVMS390FLICState *parent;
474 uint8_t simm;
475 uint8_t nimm;
476 } KVMS390FLICStateMigTmp;
478 static int kvm_flic_ais_pre_save(void *opaque)
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),
489 if (ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr)) {
490 error_report("Failed to retrieve kvm flic ais states");
491 return -EINVAL;
494 tmp->simm = ais.simm;
495 tmp->nimm = ais.nimm;
497 return 0;
500 static int kvm_flic_ais_post_load(void *opaque, int version_id)
502 KVMS390FLICStateMigTmp *tmp = opaque;
503 KVMS390FLICState *flic = tmp->parent;
504 struct kvm_s390_ais_all ais = {
505 .simm = tmp->simm,
506 .nimm = tmp->nimm,
508 struct kvm_device_attr attr = {
509 .group = KVM_DEV_FLIC_AISM_ALL,
510 .addr = (uint64_t)&ais,
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.
519 if (!ais_needed(flic)) {
520 return -ENOSYS;
523 return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
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()
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()
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[]) {
557 .name = "irqs",
558 .info = &(const VMStateInfo) {
559 .name = "irqs",
560 .get = kvm_flic_load,
561 .put = kvm_flic_save,
563 .flags = VMS_SINGLE,
565 VMSTATE_END_OF_LIST()
567 .subsections = (const VMStateDescription * []) {
568 &kvm_s390_flic_vmstate_ais,
569 NULL
573 struct KVMS390FLICStateClass {
574 S390FLICStateClass parent_class;
575 DeviceRealize parent_realize;
577 typedef struct KVMS390FLICStateClass KVMS390FLICStateClass;
579 DECLARE_CLASS_CHECKERS(KVMS390FLICStateClass, KVM_S390_FLIC,
580 TYPE_KVM_S390_FLIC)
583 static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
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;
591 KVM_S390_FLIC_GET_CLASS(dev)->parent_realize(dev, &err);
592 if (err) {
593 error_propagate(errp, err);
594 return;
596 flic_state->fd = -1;
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;
605 flic_state->fd = cd.fd;
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);
613 static void kvm_s390_flic_reset(DeviceState *dev)
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,
620 int rc = 0;
621 uint8_t isc;
623 if (flic->fd == -1) {
624 return;
627 flic_disable_wait_pfault(flic);
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));
639 rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
640 if (rc) {
641 trace_flic_reset_failed(errno);
644 flic_enable_pfault(flic);
647 static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
649 DeviceClass *dc = DEVICE_CLASS(oc);
650 S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);
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;
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,
676 static void kvm_s390_flic_register_types(void)
678 type_register_static(&kvm_s390_flic_info);
681 type_init(kvm_s390_flic_register_types)