1 /* 2 * QEMU S390x 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/error-report.h" 15 #include "qemu/main-loop.h" 16 #include "qemu/module.h" 17 #include "hw/sysbus.h" 18 #include "hw/s390x/ioinst.h" 19 #include "hw/s390x/s390_flic.h" 20 #include "hw/qdev-properties.h" 21 #include "hw/s390x/css.h" 22 #include "trace.h" 23 #include "cpu.h" 24 #include "qapi/error.h" 25 #include "hw/s390x/s390-virtio-ccw.h" 26 27 S390FLICStateClass *s390_get_flic_class(S390FLICState *fs) 28 { 29 static S390FLICStateClass *class; 30 31 if (!class) { 32 /* we only have one flic device, so this is fine to cache */ 33 class = S390_FLIC_COMMON_GET_CLASS(fs); 34 } 35 return class; 36 } 37 38 QEMUS390FLICState *s390_get_qemu_flic(S390FLICState *fs) 39 { 40 static QEMUS390FLICState *flic; 41 42 if (!flic) { 43 /* we only have one flic device, so this is fine to cache */ 44 flic = QEMU_S390_FLIC(fs); 45 } 46 return flic; 47 } 48 49 S390FLICState *s390_get_flic(void) 50 { 51 static S390FLICState *fs; 52 53 if (!fs) { 54 fs = S390_FLIC_COMMON(object_resolve_path_type("", 55 TYPE_S390_FLIC_COMMON, 56 NULL)); 57 } 58 return fs; 59 } 60 61 void s390_flic_init(void) 62 { 63 DeviceState *dev; 64 65 if (kvm_enabled()) { 66 dev = qdev_create(NULL, TYPE_KVM_S390_FLIC); 67 object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC, 68 OBJECT(dev), NULL); 69 } else { 70 dev = qdev_create(NULL, TYPE_QEMU_S390_FLIC); 71 object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC, 72 OBJECT(dev), NULL); 73 } 74 qdev_init_nofail(dev); 75 } 76 77 static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id, 78 uint8_t isc, bool swap, 79 bool is_maskable, uint8_t flags) 80 { 81 /* nothing to do */ 82 return 0; 83 } 84 85 static int qemu_s390_io_adapter_map(S390FLICState *fs, uint32_t id, 86 uint64_t map_addr, bool do_map) 87 { 88 /* nothing to do */ 89 return 0; 90 } 91 92 static int qemu_s390_add_adapter_routes(S390FLICState *fs, 93 AdapterRoutes *routes) 94 { 95 return -ENOSYS; 96 } 97 98 static void qemu_s390_release_adapter_routes(S390FLICState *fs, 99 AdapterRoutes *routes) 100 { 101 } 102 103 static int qemu_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id, 104 uint16_t subchannel_nr) 105 { 106 QEMUS390FLICState *flic = s390_get_qemu_flic(fs); 107 QEMUS390FlicIO *cur, *next; 108 uint8_t isc; 109 110 g_assert(qemu_mutex_iothread_locked()); 111 if (!(flic->pending & FLIC_PENDING_IO)) { 112 return 0; 113 } 114 115 /* check all iscs */ 116 for (isc = 0; isc < 8; isc++) { 117 if (QLIST_EMPTY(&flic->io[isc])) { 118 continue; 119 } 120 121 /* search and delete any matching one */ 122 QLIST_FOREACH_SAFE(cur, &flic->io[isc], next, next) { 123 if (cur->id == subchannel_id && cur->nr == subchannel_nr) { 124 QLIST_REMOVE(cur, next); 125 g_free(cur); 126 } 127 } 128 129 /* update our indicator bit */ 130 if (QLIST_EMPTY(&flic->io[isc])) { 131 flic->pending &= ~ISC_TO_PENDING_IO(isc); 132 } 133 } 134 return 0; 135 } 136 137 static int qemu_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc, 138 uint16_t mode) 139 { 140 QEMUS390FLICState *flic = s390_get_qemu_flic(fs); 141 142 switch (mode) { 143 case SIC_IRQ_MODE_ALL: 144 flic->simm &= ~AIS_MODE_MASK(isc); 145 flic->nimm &= ~AIS_MODE_MASK(isc); 146 break; 147 case SIC_IRQ_MODE_SINGLE: 148 flic->simm |= AIS_MODE_MASK(isc); 149 flic->nimm &= ~AIS_MODE_MASK(isc); 150 break; 151 default: 152 return -EINVAL; 153 } 154 155 return 0; 156 } 157 158 static int qemu_s390_inject_airq(S390FLICState *fs, uint8_t type, 159 uint8_t isc, uint8_t flags) 160 { 161 QEMUS390FLICState *flic = s390_get_qemu_flic(fs); 162 S390FLICStateClass *fsc = s390_get_flic_class(fs); 163 bool flag = flags & S390_ADAPTER_SUPPRESSIBLE; 164 uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI; 165 166 if (flag && (flic->nimm & AIS_MODE_MASK(isc))) { 167 trace_qemu_s390_airq_suppressed(type, isc); 168 return 0; 169 } 170 171 fsc->inject_io(fs, 0, 0, 0, io_int_word); 172 173 if (flag && (flic->simm & AIS_MODE_MASK(isc))) { 174 flic->nimm |= AIS_MODE_MASK(isc); 175 trace_qemu_s390_suppress_airq(isc, "Single-Interruption Mode", 176 "NO-Interruptions Mode"); 177 } 178 179 return 0; 180 } 181 182 static void qemu_s390_flic_notify(uint32_t type) 183 { 184 CPUState *cs; 185 186 /* 187 * We have to make all CPUs see CPU_INTERRUPT_HARD, so they might 188 * consider it. We will kick all running CPUs and only relevant 189 * sleeping ones. 190 */ 191 CPU_FOREACH(cs) { 192 S390CPU *cpu = S390_CPU(cs); 193 194 cs->interrupt_request |= CPU_INTERRUPT_HARD; 195 196 /* ignore CPUs that are not sleeping */ 197 if (s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING && 198 s390_cpu_get_state(cpu) != S390_CPU_STATE_LOAD) { 199 continue; 200 } 201 202 /* we always kick running CPUs for now, this is tricky */ 203 if (cs->halted) { 204 /* don't check for subclasses, CPUs double check when waking up */ 205 if (type & FLIC_PENDING_SERVICE) { 206 if (!(cpu->env.psw.mask & PSW_MASK_EXT)) { 207 continue; 208 } 209 } else if (type & FLIC_PENDING_IO) { 210 if (!(cpu->env.psw.mask & PSW_MASK_IO)) { 211 continue; 212 } 213 } else if (type & FLIC_PENDING_MCHK_CR) { 214 if (!(cpu->env.psw.mask & PSW_MASK_MCHECK)) { 215 continue; 216 } 217 } 218 } 219 cpu_interrupt(cs, CPU_INTERRUPT_HARD); 220 } 221 } 222 223 uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState *flic) 224 { 225 uint32_t tmp; 226 227 g_assert(qemu_mutex_iothread_locked()); 228 g_assert(flic->pending & FLIC_PENDING_SERVICE); 229 tmp = flic->service_param; 230 flic->service_param = 0; 231 flic->pending &= ~FLIC_PENDING_SERVICE; 232 233 return tmp; 234 } 235 236 /* caller has to free the returned object */ 237 QEMUS390FlicIO *qemu_s390_flic_dequeue_io(QEMUS390FLICState *flic, uint64_t cr6) 238 { 239 QEMUS390FlicIO *io; 240 uint8_t isc; 241 242 g_assert(qemu_mutex_iothread_locked()); 243 if (!(flic->pending & CR6_TO_PENDING_IO(cr6))) { 244 return NULL; 245 } 246 247 for (isc = 0; isc < 8; isc++) { 248 if (QLIST_EMPTY(&flic->io[isc]) || !(cr6 & ISC_TO_ISC_BITS(isc))) { 249 continue; 250 } 251 io = QLIST_FIRST(&flic->io[isc]); 252 QLIST_REMOVE(io, next); 253 254 /* update our indicator bit */ 255 if (QLIST_EMPTY(&flic->io[isc])) { 256 flic->pending &= ~ISC_TO_PENDING_IO(isc); 257 } 258 return io; 259 } 260 261 return NULL; 262 } 263 264 void qemu_s390_flic_dequeue_crw_mchk(QEMUS390FLICState *flic) 265 { 266 g_assert(qemu_mutex_iothread_locked()); 267 g_assert(flic->pending & FLIC_PENDING_MCHK_CR); 268 flic->pending &= ~FLIC_PENDING_MCHK_CR; 269 } 270 271 static void qemu_s390_inject_service(S390FLICState *fs, uint32_t parm) 272 { 273 QEMUS390FLICState *flic = s390_get_qemu_flic(fs); 274 275 g_assert(qemu_mutex_iothread_locked()); 276 /* multiplexing is good enough for sclp - kvm does it internally as well */ 277 flic->service_param |= parm; 278 flic->pending |= FLIC_PENDING_SERVICE; 279 280 qemu_s390_flic_notify(FLIC_PENDING_SERVICE); 281 } 282 283 static void qemu_s390_inject_io(S390FLICState *fs, uint16_t subchannel_id, 284 uint16_t subchannel_nr, uint32_t io_int_parm, 285 uint32_t io_int_word) 286 { 287 const uint8_t isc = IO_INT_WORD_ISC(io_int_word); 288 QEMUS390FLICState *flic = s390_get_qemu_flic(fs); 289 QEMUS390FlicIO *io; 290 291 g_assert(qemu_mutex_iothread_locked()); 292 io = g_new0(QEMUS390FlicIO, 1); 293 io->id = subchannel_id; 294 io->nr = subchannel_nr; 295 io->parm = io_int_parm; 296 io->word = io_int_word; 297 298 QLIST_INSERT_HEAD(&flic->io[isc], io, next); 299 flic->pending |= ISC_TO_PENDING_IO(isc); 300 301 qemu_s390_flic_notify(ISC_TO_PENDING_IO(isc)); 302 } 303 304 static void qemu_s390_inject_crw_mchk(S390FLICState *fs) 305 { 306 QEMUS390FLICState *flic = s390_get_qemu_flic(fs); 307 308 g_assert(qemu_mutex_iothread_locked()); 309 flic->pending |= FLIC_PENDING_MCHK_CR; 310 311 qemu_s390_flic_notify(FLIC_PENDING_MCHK_CR); 312 } 313 314 bool qemu_s390_flic_has_service(QEMUS390FLICState *flic) 315 { 316 /* called without lock via cc->has_work, will be validated under lock */ 317 return !!(flic->pending & FLIC_PENDING_SERVICE); 318 } 319 320 bool qemu_s390_flic_has_io(QEMUS390FLICState *flic, uint64_t cr6) 321 { 322 /* called without lock via cc->has_work, will be validated under lock */ 323 return !!(flic->pending & CR6_TO_PENDING_IO(cr6)); 324 } 325 326 bool qemu_s390_flic_has_crw_mchk(QEMUS390FLICState *flic) 327 { 328 /* called without lock via cc->has_work, will be validated under lock */ 329 return !!(flic->pending & FLIC_PENDING_MCHK_CR); 330 } 331 332 bool qemu_s390_flic_has_any(QEMUS390FLICState *flic) 333 { 334 g_assert(qemu_mutex_iothread_locked()); 335 return !!flic->pending; 336 } 337 338 static void qemu_s390_flic_reset(DeviceState *dev) 339 { 340 QEMUS390FLICState *flic = QEMU_S390_FLIC(dev); 341 QEMUS390FlicIO *cur, *next; 342 int isc; 343 344 g_assert(qemu_mutex_iothread_locked()); 345 flic->simm = 0; 346 flic->nimm = 0; 347 flic->pending = 0; 348 349 /* remove all pending io interrupts */ 350 for (isc = 0; isc < 8; isc++) { 351 QLIST_FOREACH_SAFE(cur, &flic->io[isc], next, next) { 352 QLIST_REMOVE(cur, next); 353 g_free(cur); 354 } 355 } 356 } 357 358 bool ais_needed(void *opaque) 359 { 360 S390FLICState *s = opaque; 361 362 return s->ais_supported; 363 } 364 365 static const VMStateDescription qemu_s390_flic_vmstate = { 366 .name = "qemu-s390-flic", 367 .version_id = 1, 368 .minimum_version_id = 1, 369 .needed = ais_needed, 370 .fields = (VMStateField[]) { 371 VMSTATE_UINT8(simm, QEMUS390FLICState), 372 VMSTATE_UINT8(nimm, QEMUS390FLICState), 373 VMSTATE_END_OF_LIST() 374 } 375 }; 376 377 static void qemu_s390_flic_instance_init(Object *obj) 378 { 379 QEMUS390FLICState *flic = QEMU_S390_FLIC(obj); 380 int isc; 381 382 for (isc = 0; isc < 8; isc++) { 383 QLIST_INIT(&flic->io[isc]); 384 } 385 } 386 387 static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) 388 { 389 DeviceClass *dc = DEVICE_CLASS(oc); 390 S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); 391 392 dc->reset = qemu_s390_flic_reset; 393 dc->vmsd = &qemu_s390_flic_vmstate; 394 fsc->register_io_adapter = qemu_s390_register_io_adapter; 395 fsc->io_adapter_map = qemu_s390_io_adapter_map; 396 fsc->add_adapter_routes = qemu_s390_add_adapter_routes; 397 fsc->release_adapter_routes = qemu_s390_release_adapter_routes; 398 fsc->clear_io_irq = qemu_s390_clear_io_flic; 399 fsc->modify_ais_mode = qemu_s390_modify_ais_mode; 400 fsc->inject_airq = qemu_s390_inject_airq; 401 fsc->inject_service = qemu_s390_inject_service; 402 fsc->inject_io = qemu_s390_inject_io; 403 fsc->inject_crw_mchk = qemu_s390_inject_crw_mchk; 404 } 405 406 static Property s390_flic_common_properties[] = { 407 DEFINE_PROP_UINT32("adapter_routes_max_batch", S390FLICState, 408 adapter_routes_max_batch, ADAPTER_ROUTES_MAX_GSI), 409 DEFINE_PROP_END_OF_LIST(), 410 }; 411 412 static void s390_flic_common_realize(DeviceState *dev, Error **errp) 413 { 414 S390FLICState *fs = S390_FLIC_COMMON(dev); 415 uint32_t max_batch = fs->adapter_routes_max_batch; 416 417 if (max_batch > ADAPTER_ROUTES_MAX_GSI) { 418 error_setg(errp, "flic property adapter_routes_max_batch too big" 419 " (%d > %d)", max_batch, ADAPTER_ROUTES_MAX_GSI); 420 return; 421 } 422 423 fs->ais_supported = s390_has_feat(S390_FEAT_ADAPTER_INT_SUPPRESSION); 424 } 425 426 static void s390_flic_class_init(ObjectClass *oc, void *data) 427 { 428 DeviceClass *dc = DEVICE_CLASS(oc); 429 430 device_class_set_props(dc, s390_flic_common_properties); 431 dc->realize = s390_flic_common_realize; 432 } 433 434 static const TypeInfo qemu_s390_flic_info = { 435 .name = TYPE_QEMU_S390_FLIC, 436 .parent = TYPE_S390_FLIC_COMMON, 437 .instance_size = sizeof(QEMUS390FLICState), 438 .instance_init = qemu_s390_flic_instance_init, 439 .class_init = qemu_s390_flic_class_init, 440 }; 441 442 443 static const TypeInfo s390_flic_common_info = { 444 .name = TYPE_S390_FLIC_COMMON, 445 .parent = TYPE_SYS_BUS_DEVICE, 446 .instance_size = sizeof(S390FLICState), 447 .class_init = s390_flic_class_init, 448 .class_size = sizeof(S390FLICStateClass), 449 }; 450 451 static void qemu_s390_flic_register_types(void) 452 { 453 type_register_static(&s390_flic_common_info); 454 type_register_static(&qemu_s390_flic_info); 455 } 456 457 type_init(qemu_s390_flic_register_types) 458 459 static bool adapter_info_so_needed(void *opaque) 460 { 461 return css_migration_enabled(); 462 } 463 464 const VMStateDescription vmstate_adapter_info_so = { 465 .name = "s390_adapter_info/summary_offset", 466 .version_id = 1, 467 .minimum_version_id = 1, 468 .needed = adapter_info_so_needed, 469 .fields = (VMStateField[]) { 470 VMSTATE_UINT32(summary_offset, AdapterInfo), 471 VMSTATE_END_OF_LIST() 472 } 473 }; 474 475 const VMStateDescription vmstate_adapter_info = { 476 .name = "s390_adapter_info", 477 .version_id = 1, 478 .minimum_version_id = 1, 479 .fields = (VMStateField[]) { 480 VMSTATE_UINT64(ind_offset, AdapterInfo), 481 /* 482 * We do not have to migrate neither the id nor the addresses. 483 * The id is set by css_register_io_adapter and the addresses 484 * are set based on the IndAddr objects after those get mapped. 485 */ 486 VMSTATE_END_OF_LIST() 487 }, 488 .subsections = (const VMStateDescription * []) { 489 &vmstate_adapter_info_so, 490 NULL 491 } 492 }; 493 494 const VMStateDescription vmstate_adapter_routes = { 495 496 .name = "s390_adapter_routes", 497 .version_id = 1, 498 .minimum_version_id = 1, 499 .fields = (VMStateField[]) { 500 VMSTATE_STRUCT(adapter, AdapterRoutes, 1, vmstate_adapter_info, 501 AdapterInfo), 502 VMSTATE_END_OF_LIST() 503 } 504 }; 505