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