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