1 /* 2 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator 3 * 4 * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics 5 * 6 * Copyright (c) 2010,2011 David Gibson, IBM Corporation. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a copy 9 * of this software and associated documentation files (the "Software"), to deal 10 * in the Software without restriction, including without limitation the rights 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 * copies of the Software, and to permit persons to whom the Software is 13 * furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included in 16 * all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 * THE SOFTWARE. 25 * 26 */ 27 28 #include "qemu/osdep.h" 29 #include "cpu.h" 30 #include "trace.h" 31 #include "qemu/timer.h" 32 #include "hw/ppc/spapr.h" 33 #include "hw/ppc/spapr_cpu_core.h" 34 #include "hw/ppc/xics.h" 35 #include "hw/ppc/xics_spapr.h" 36 #include "hw/ppc/fdt.h" 37 #include "qapi/visitor.h" 38 39 /* 40 * Guest interfaces 41 */ 42 43 static bool check_emulated_xics(SpaprMachineState *spapr, const char *func) 44 { 45 if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) || 46 kvm_irqchip_in_kernel()) { 47 error_report("pseries: %s must only be called for emulated XICS", 48 func); 49 return false; 50 } 51 52 return true; 53 } 54 55 #define CHECK_EMULATED_XICS_HCALL(spapr) \ 56 do { \ 57 if (!check_emulated_xics((spapr), __func__)) { \ 58 return H_HARDWARE; \ 59 } \ 60 } while (0) 61 62 static target_ulong h_cppr(PowerPCCPU *cpu, SpaprMachineState *spapr, 63 target_ulong opcode, target_ulong *args) 64 { 65 target_ulong cppr = args[0]; 66 67 CHECK_EMULATED_XICS_HCALL(spapr); 68 69 icp_set_cppr(spapr_cpu_state(cpu)->icp, cppr); 70 return H_SUCCESS; 71 } 72 73 static target_ulong h_ipi(PowerPCCPU *cpu, SpaprMachineState *spapr, 74 target_ulong opcode, target_ulong *args) 75 { 76 target_ulong mfrr = args[1]; 77 ICPState *icp = xics_icp_get(XICS_FABRIC(spapr), args[0]); 78 79 CHECK_EMULATED_XICS_HCALL(spapr); 80 81 if (!icp) { 82 return H_PARAMETER; 83 } 84 85 icp_set_mfrr(icp, mfrr); 86 return H_SUCCESS; 87 } 88 89 static target_ulong h_xirr(PowerPCCPU *cpu, SpaprMachineState *spapr, 90 target_ulong opcode, target_ulong *args) 91 { 92 uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp); 93 94 CHECK_EMULATED_XICS_HCALL(spapr); 95 96 args[0] = xirr; 97 return H_SUCCESS; 98 } 99 100 static target_ulong h_xirr_x(PowerPCCPU *cpu, SpaprMachineState *spapr, 101 target_ulong opcode, target_ulong *args) 102 { 103 uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp); 104 105 CHECK_EMULATED_XICS_HCALL(spapr); 106 107 args[0] = xirr; 108 args[1] = cpu_get_host_ticks(); 109 return H_SUCCESS; 110 } 111 112 static target_ulong h_eoi(PowerPCCPU *cpu, SpaprMachineState *spapr, 113 target_ulong opcode, target_ulong *args) 114 { 115 target_ulong xirr = args[0]; 116 117 CHECK_EMULATED_XICS_HCALL(spapr); 118 119 icp_eoi(spapr_cpu_state(cpu)->icp, xirr); 120 return H_SUCCESS; 121 } 122 123 static target_ulong h_ipoll(PowerPCCPU *cpu, SpaprMachineState *spapr, 124 target_ulong opcode, target_ulong *args) 125 { 126 ICPState *icp = xics_icp_get(XICS_FABRIC(spapr), args[0]); 127 uint32_t mfrr; 128 uint32_t xirr; 129 130 CHECK_EMULATED_XICS_HCALL(spapr); 131 132 if (!icp) { 133 return H_PARAMETER; 134 } 135 136 xirr = icp_ipoll(icp, &mfrr); 137 138 args[0] = xirr; 139 args[1] = mfrr; 140 141 return H_SUCCESS; 142 } 143 144 #define CHECK_EMULATED_XICS_RTAS(spapr, rets) \ 145 do { \ 146 if (!check_emulated_xics((spapr), __func__)) { \ 147 rtas_st((rets), 0, RTAS_OUT_HW_ERROR); \ 148 return; \ 149 } \ 150 } while (0) 151 152 static void rtas_set_xive(PowerPCCPU *cpu, SpaprMachineState *spapr, 153 uint32_t token, 154 uint32_t nargs, target_ulong args, 155 uint32_t nret, target_ulong rets) 156 { 157 ICSState *ics = spapr->ics; 158 uint32_t nr, srcno, server, priority; 159 160 CHECK_EMULATED_XICS_RTAS(spapr, rets); 161 162 if ((nargs != 3) || (nret != 1)) { 163 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 164 return; 165 } 166 if (!ics) { 167 rtas_st(rets, 0, RTAS_OUT_HW_ERROR); 168 return; 169 } 170 171 nr = rtas_ld(args, 0); 172 server = rtas_ld(args, 1); 173 priority = rtas_ld(args, 2); 174 175 if (!ics_valid_irq(ics, nr) || !xics_icp_get(XICS_FABRIC(spapr), server) 176 || (priority > 0xff)) { 177 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 178 return; 179 } 180 181 srcno = nr - ics->offset; 182 ics_write_xive(ics, srcno, server, priority, priority); 183 184 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 185 } 186 187 static void rtas_get_xive(PowerPCCPU *cpu, SpaprMachineState *spapr, 188 uint32_t token, 189 uint32_t nargs, target_ulong args, 190 uint32_t nret, target_ulong rets) 191 { 192 ICSState *ics = spapr->ics; 193 uint32_t nr, srcno; 194 195 CHECK_EMULATED_XICS_RTAS(spapr, rets); 196 197 if ((nargs != 1) || (nret != 3)) { 198 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 199 return; 200 } 201 if (!ics) { 202 rtas_st(rets, 0, RTAS_OUT_HW_ERROR); 203 return; 204 } 205 206 nr = rtas_ld(args, 0); 207 208 if (!ics_valid_irq(ics, nr)) { 209 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 210 return; 211 } 212 213 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 214 srcno = nr - ics->offset; 215 rtas_st(rets, 1, ics->irqs[srcno].server); 216 rtas_st(rets, 2, ics->irqs[srcno].priority); 217 } 218 219 static void rtas_int_off(PowerPCCPU *cpu, SpaprMachineState *spapr, 220 uint32_t token, 221 uint32_t nargs, target_ulong args, 222 uint32_t nret, target_ulong rets) 223 { 224 ICSState *ics = spapr->ics; 225 uint32_t nr, srcno; 226 227 CHECK_EMULATED_XICS_RTAS(spapr, rets); 228 229 if ((nargs != 1) || (nret != 1)) { 230 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 231 return; 232 } 233 if (!ics) { 234 rtas_st(rets, 0, RTAS_OUT_HW_ERROR); 235 return; 236 } 237 238 nr = rtas_ld(args, 0); 239 240 if (!ics_valid_irq(ics, nr)) { 241 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 242 return; 243 } 244 245 srcno = nr - ics->offset; 246 ics_write_xive(ics, srcno, ics->irqs[srcno].server, 0xff, 247 ics->irqs[srcno].priority); 248 249 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 250 } 251 252 static void rtas_int_on(PowerPCCPU *cpu, SpaprMachineState *spapr, 253 uint32_t token, 254 uint32_t nargs, target_ulong args, 255 uint32_t nret, target_ulong rets) 256 { 257 ICSState *ics = spapr->ics; 258 uint32_t nr, srcno; 259 260 CHECK_EMULATED_XICS_RTAS(spapr, rets); 261 262 if ((nargs != 1) || (nret != 1)) { 263 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 264 return; 265 } 266 if (!ics) { 267 rtas_st(rets, 0, RTAS_OUT_HW_ERROR); 268 return; 269 } 270 271 nr = rtas_ld(args, 0); 272 273 if (!ics_valid_irq(ics, nr)) { 274 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); 275 return; 276 } 277 278 srcno = nr - ics->offset; 279 ics_write_xive(ics, srcno, ics->irqs[srcno].server, 280 ics->irqs[srcno].saved_priority, 281 ics->irqs[srcno].saved_priority); 282 283 rtas_st(rets, 0, RTAS_OUT_SUCCESS); 284 } 285 286 static void ics_spapr_realize(DeviceState *dev, Error **errp) 287 { 288 ICSState *ics = ICS_SPAPR(dev); 289 ICSStateClass *icsc = ICS_GET_CLASS(ics); 290 Error *local_err = NULL; 291 292 icsc->parent_realize(dev, &local_err); 293 if (local_err) { 294 error_propagate(errp, local_err); 295 return; 296 } 297 298 spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive); 299 spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_get_xive); 300 spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_int_off); 301 spapr_rtas_register(RTAS_IBM_INT_ON, "ibm,int-on", rtas_int_on); 302 303 spapr_register_hypercall(H_CPPR, h_cppr); 304 spapr_register_hypercall(H_IPI, h_ipi); 305 spapr_register_hypercall(H_XIRR, h_xirr); 306 spapr_register_hypercall(H_XIRR_X, h_xirr_x); 307 spapr_register_hypercall(H_EOI, h_eoi); 308 spapr_register_hypercall(H_IPOLL, h_ipoll); 309 } 310 311 static void xics_spapr_dt(SpaprInterruptController *intc, uint32_t nr_servers, 312 void *fdt, uint32_t phandle) 313 { 314 uint32_t interrupt_server_ranges_prop[] = { 315 0, cpu_to_be32(nr_servers), 316 }; 317 int node; 318 319 _FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller")); 320 321 _FDT(fdt_setprop_string(fdt, node, "device_type", 322 "PowerPC-External-Interrupt-Presentation")); 323 _FDT(fdt_setprop_string(fdt, node, "compatible", "IBM,ppc-xicp")); 324 _FDT(fdt_setprop(fdt, node, "interrupt-controller", NULL, 0)); 325 _FDT(fdt_setprop(fdt, node, "ibm,interrupt-server-ranges", 326 interrupt_server_ranges_prop, 327 sizeof(interrupt_server_ranges_prop))); 328 _FDT(fdt_setprop_cell(fdt, node, "#interrupt-cells", 2)); 329 _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle)); 330 _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle)); 331 } 332 333 static int xics_spapr_cpu_intc_create(SpaprInterruptController *intc, 334 PowerPCCPU *cpu, Error **errp) 335 { 336 ICSState *ics = ICS_SPAPR(intc); 337 Object *obj; 338 SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 339 340 obj = icp_create(OBJECT(cpu), TYPE_ICP, ics->xics, errp); 341 if (!obj) { 342 return -1; 343 } 344 345 spapr_cpu->icp = ICP(obj); 346 return 0; 347 } 348 349 static void xics_spapr_cpu_intc_reset(SpaprInterruptController *intc, 350 PowerPCCPU *cpu) 351 { 352 icp_reset(spapr_cpu_state(cpu)->icp); 353 } 354 355 static void xics_spapr_cpu_intc_destroy(SpaprInterruptController *intc, 356 PowerPCCPU *cpu) 357 { 358 SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); 359 360 icp_destroy(spapr_cpu->icp); 361 spapr_cpu->icp = NULL; 362 } 363 364 static int xics_spapr_claim_irq(SpaprInterruptController *intc, int irq, 365 bool lsi, Error **errp) 366 { 367 ICSState *ics = ICS_SPAPR(intc); 368 369 assert(ics); 370 assert(ics_valid_irq(ics, irq)); 371 372 if (!ics_irq_free(ics, irq - ics->offset)) { 373 error_setg(errp, "IRQ %d is not free", irq); 374 return -EBUSY; 375 } 376 377 ics_set_irq_type(ics, irq - ics->offset, lsi); 378 return 0; 379 } 380 381 static void xics_spapr_free_irq(SpaprInterruptController *intc, int irq) 382 { 383 ICSState *ics = ICS_SPAPR(intc); 384 uint32_t srcno = irq - ics->offset; 385 386 assert(ics_valid_irq(ics, irq)); 387 388 memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState)); 389 } 390 391 static void xics_spapr_set_irq(SpaprInterruptController *intc, int irq, int val) 392 { 393 ICSState *ics = ICS_SPAPR(intc); 394 uint32_t srcno = irq - ics->offset; 395 396 ics_set_irq(ics, srcno, val); 397 } 398 399 static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon) 400 { 401 ICSState *ics = ICS_SPAPR(intc); 402 CPUState *cs; 403 404 CPU_FOREACH(cs) { 405 PowerPCCPU *cpu = POWERPC_CPU(cs); 406 407 icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon); 408 } 409 410 ics_pic_print_info(ics, mon); 411 } 412 413 static int xics_spapr_post_load(SpaprInterruptController *intc, int version_id) 414 { 415 if (!kvm_irqchip_in_kernel()) { 416 CPUState *cs; 417 CPU_FOREACH(cs) { 418 PowerPCCPU *cpu = POWERPC_CPU(cs); 419 icp_resend(spapr_cpu_state(cpu)->icp); 420 } 421 } 422 return 0; 423 } 424 425 static int xics_spapr_activate(SpaprInterruptController *intc, Error **errp) 426 { 427 if (kvm_enabled()) { 428 return spapr_irq_init_kvm(xics_kvm_connect, intc, errp); 429 } 430 return 0; 431 } 432 433 static void xics_spapr_deactivate(SpaprInterruptController *intc) 434 { 435 if (kvm_irqchip_in_kernel()) { 436 xics_kvm_disconnect(intc); 437 } 438 } 439 440 static void ics_spapr_class_init(ObjectClass *klass, void *data) 441 { 442 DeviceClass *dc = DEVICE_CLASS(klass); 443 ICSStateClass *isc = ICS_CLASS(klass); 444 SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass); 445 446 device_class_set_parent_realize(dc, ics_spapr_realize, 447 &isc->parent_realize); 448 sicc->activate = xics_spapr_activate; 449 sicc->deactivate = xics_spapr_deactivate; 450 sicc->cpu_intc_create = xics_spapr_cpu_intc_create; 451 sicc->cpu_intc_reset = xics_spapr_cpu_intc_reset; 452 sicc->cpu_intc_destroy = xics_spapr_cpu_intc_destroy; 453 sicc->claim_irq = xics_spapr_claim_irq; 454 sicc->free_irq = xics_spapr_free_irq; 455 sicc->set_irq = xics_spapr_set_irq; 456 sicc->print_info = xics_spapr_print_info; 457 sicc->dt = xics_spapr_dt; 458 sicc->post_load = xics_spapr_post_load; 459 } 460 461 static const TypeInfo ics_spapr_info = { 462 .name = TYPE_ICS_SPAPR, 463 .parent = TYPE_ICS, 464 .class_init = ics_spapr_class_init, 465 .interfaces = (InterfaceInfo[]) { 466 { TYPE_SPAPR_INTC }, 467 { } 468 }, 469 }; 470 471 static void xics_spapr_register_types(void) 472 { 473 type_register_static(&ics_spapr_info); 474 } 475 476 type_init(xics_spapr_register_types) 477