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