qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

xics_spapr.c (13755B)


      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 "trace.h"
     30 #include "qemu/timer.h"
     31 #include "hw/ppc/spapr.h"
     32 #include "hw/ppc/spapr_cpu_core.h"
     33 #include "hw/ppc/xics.h"
     34 #include "hw/ppc/xics_spapr.h"
     35 #include "hw/ppc/fdt.h"
     36 #include "qapi/visitor.h"
     37 
     38 /*
     39  * Guest interfaces
     40  */
     41 
     42 static bool check_emulated_xics(SpaprMachineState *spapr, const char *func)
     43 {
     44     if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) ||
     45         kvm_irqchip_in_kernel()) {
     46         error_report("pseries: %s must only be called for emulated XICS",
     47                      func);
     48         return false;
     49     }
     50 
     51     return true;
     52 }
     53 
     54 #define CHECK_EMULATED_XICS_HCALL(spapr)               \
     55     do {                                               \
     56         if (!check_emulated_xics((spapr), __func__)) { \
     57             return H_HARDWARE;                         \
     58         }                                              \
     59     } while (0)
     60 
     61 static target_ulong h_cppr(PowerPCCPU *cpu, SpaprMachineState *spapr,
     62                            target_ulong opcode, target_ulong *args)
     63 {
     64     target_ulong cppr = args[0];
     65 
     66     CHECK_EMULATED_XICS_HCALL(spapr);
     67 
     68     icp_set_cppr(spapr_cpu_state(cpu)->icp, cppr);
     69     return H_SUCCESS;
     70 }
     71 
     72 static target_ulong h_ipi(PowerPCCPU *cpu, SpaprMachineState *spapr,
     73                           target_ulong opcode, target_ulong *args)
     74 {
     75     target_ulong mfrr = args[1];
     76     ICPState *icp = xics_icp_get(XICS_FABRIC(spapr), args[0]);
     77 
     78     CHECK_EMULATED_XICS_HCALL(spapr);
     79 
     80     if (!icp) {
     81         return H_PARAMETER;
     82     }
     83 
     84     icp_set_mfrr(icp, mfrr);
     85     return H_SUCCESS;
     86 }
     87 
     88 static target_ulong h_xirr(PowerPCCPU *cpu, SpaprMachineState *spapr,
     89                            target_ulong opcode, target_ulong *args)
     90 {
     91     uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp);
     92 
     93     CHECK_EMULATED_XICS_HCALL(spapr);
     94 
     95     args[0] = xirr;
     96     return H_SUCCESS;
     97 }
     98 
     99 static target_ulong h_xirr_x(PowerPCCPU *cpu, SpaprMachineState *spapr,
    100                              target_ulong opcode, target_ulong *args)
    101 {
    102     uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp);
    103 
    104     CHECK_EMULATED_XICS_HCALL(spapr);
    105 
    106     args[0] = xirr;
    107     args[1] = cpu_get_host_ticks();
    108     return H_SUCCESS;
    109 }
    110 
    111 static target_ulong h_eoi(PowerPCCPU *cpu, SpaprMachineState *spapr,
    112                           target_ulong opcode, target_ulong *args)
    113 {
    114     target_ulong xirr = args[0];
    115 
    116     CHECK_EMULATED_XICS_HCALL(spapr);
    117 
    118     icp_eoi(spapr_cpu_state(cpu)->icp, xirr);
    119     return H_SUCCESS;
    120 }
    121 
    122 static target_ulong h_ipoll(PowerPCCPU *cpu, SpaprMachineState *spapr,
    123                             target_ulong opcode, target_ulong *args)
    124 {
    125     ICPState *icp = xics_icp_get(XICS_FABRIC(spapr), args[0]);
    126     uint32_t mfrr;
    127     uint32_t xirr;
    128 
    129     CHECK_EMULATED_XICS_HCALL(spapr);
    130 
    131     if (!icp) {
    132         return H_PARAMETER;
    133     }
    134 
    135     xirr = icp_ipoll(icp, &mfrr);
    136 
    137     args[0] = xirr;
    138     args[1] = mfrr;
    139 
    140     return H_SUCCESS;
    141 }
    142 
    143 #define CHECK_EMULATED_XICS_RTAS(spapr, rets)          \
    144     do {                                               \
    145         if (!check_emulated_xics((spapr), __func__)) { \
    146             rtas_st((rets), 0, RTAS_OUT_HW_ERROR);     \
    147             return;                                    \
    148         }                                              \
    149     } while (0)
    150 
    151 static void rtas_set_xive(PowerPCCPU *cpu, SpaprMachineState *spapr,
    152                           uint32_t token,
    153                           uint32_t nargs, target_ulong args,
    154                           uint32_t nret, target_ulong rets)
    155 {
    156     ICSState *ics = spapr->ics;
    157     uint32_t nr, srcno, server, priority;
    158 
    159     CHECK_EMULATED_XICS_RTAS(spapr, rets);
    160 
    161     if ((nargs != 3) || (nret != 1)) {
    162         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    163         return;
    164     }
    165     if (!ics) {
    166         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
    167         return;
    168     }
    169 
    170     nr = rtas_ld(args, 0);
    171     server = rtas_ld(args, 1);
    172     priority = rtas_ld(args, 2);
    173 
    174     if (!ics_valid_irq(ics, nr) || !xics_icp_get(XICS_FABRIC(spapr), server)
    175         || (priority > 0xff)) {
    176         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    177         return;
    178     }
    179 
    180     srcno = nr - ics->offset;
    181     ics_write_xive(ics, srcno, server, priority, priority);
    182 
    183     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    184 }
    185 
    186 static void rtas_get_xive(PowerPCCPU *cpu, SpaprMachineState *spapr,
    187                           uint32_t token,
    188                           uint32_t nargs, target_ulong args,
    189                           uint32_t nret, target_ulong rets)
    190 {
    191     ICSState *ics = spapr->ics;
    192     uint32_t nr, srcno;
    193 
    194     CHECK_EMULATED_XICS_RTAS(spapr, rets);
    195 
    196     if ((nargs != 1) || (nret != 3)) {
    197         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    198         return;
    199     }
    200     if (!ics) {
    201         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
    202         return;
    203     }
    204 
    205     nr = rtas_ld(args, 0);
    206 
    207     if (!ics_valid_irq(ics, nr)) {
    208         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    209         return;
    210     }
    211 
    212     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    213     srcno = nr - ics->offset;
    214     rtas_st(rets, 1, ics->irqs[srcno].server);
    215     rtas_st(rets, 2, ics->irqs[srcno].priority);
    216 }
    217 
    218 static void rtas_int_off(PowerPCCPU *cpu, SpaprMachineState *spapr,
    219                          uint32_t token,
    220                          uint32_t nargs, target_ulong args,
    221                          uint32_t nret, target_ulong rets)
    222 {
    223     ICSState *ics = spapr->ics;
    224     uint32_t nr, srcno;
    225 
    226     CHECK_EMULATED_XICS_RTAS(spapr, rets);
    227 
    228     if ((nargs != 1) || (nret != 1)) {
    229         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    230         return;
    231     }
    232     if (!ics) {
    233         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
    234         return;
    235     }
    236 
    237     nr = rtas_ld(args, 0);
    238 
    239     if (!ics_valid_irq(ics, nr)) {
    240         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    241         return;
    242     }
    243 
    244     srcno = nr - ics->offset;
    245     ics_write_xive(ics, srcno, ics->irqs[srcno].server, 0xff,
    246                    ics->irqs[srcno].priority);
    247 
    248     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    249 }
    250 
    251 static void rtas_int_on(PowerPCCPU *cpu, SpaprMachineState *spapr,
    252                         uint32_t token,
    253                         uint32_t nargs, target_ulong args,
    254                         uint32_t nret, target_ulong rets)
    255 {
    256     ICSState *ics = spapr->ics;
    257     uint32_t nr, srcno;
    258 
    259     CHECK_EMULATED_XICS_RTAS(spapr, rets);
    260 
    261     if ((nargs != 1) || (nret != 1)) {
    262         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    263         return;
    264     }
    265     if (!ics) {
    266         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
    267         return;
    268     }
    269 
    270     nr = rtas_ld(args, 0);
    271 
    272     if (!ics_valid_irq(ics, nr)) {
    273         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    274         return;
    275     }
    276 
    277     srcno = nr - ics->offset;
    278     ics_write_xive(ics, srcno, ics->irqs[srcno].server,
    279                    ics->irqs[srcno].saved_priority,
    280                    ics->irqs[srcno].saved_priority);
    281 
    282     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    283 }
    284 
    285 static void ics_spapr_realize(DeviceState *dev, Error **errp)
    286 {
    287     ICSState *ics = ICS_SPAPR(dev);
    288     ICSStateClass *icsc = ICS_GET_CLASS(ics);
    289     Error *local_err = NULL;
    290 
    291     icsc->parent_realize(dev, &local_err);
    292     if (local_err) {
    293         error_propagate(errp, local_err);
    294         return;
    295     }
    296 
    297     spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive);
    298     spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_get_xive);
    299     spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_int_off);
    300     spapr_rtas_register(RTAS_IBM_INT_ON, "ibm,int-on", rtas_int_on);
    301 
    302     spapr_register_hypercall(H_CPPR, h_cppr);
    303     spapr_register_hypercall(H_IPI, h_ipi);
    304     spapr_register_hypercall(H_XIRR, h_xirr);
    305     spapr_register_hypercall(H_XIRR_X, h_xirr_x);
    306     spapr_register_hypercall(H_EOI, h_eoi);
    307     spapr_register_hypercall(H_IPOLL, h_ipoll);
    308 }
    309 
    310 static void xics_spapr_dt(SpaprInterruptController *intc, uint32_t nr_servers,
    311                           void *fdt, uint32_t phandle)
    312 {
    313     uint32_t interrupt_server_ranges_prop[] = {
    314         0, cpu_to_be32(nr_servers),
    315     };
    316     int node;
    317 
    318     _FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller"));
    319 
    320     _FDT(fdt_setprop_string(fdt, node, "device_type",
    321                             "PowerPC-External-Interrupt-Presentation"));
    322     _FDT(fdt_setprop_string(fdt, node, "compatible", "IBM,ppc-xicp"));
    323     _FDT(fdt_setprop(fdt, node, "interrupt-controller", NULL, 0));
    324     _FDT(fdt_setprop(fdt, node, "ibm,interrupt-server-ranges",
    325                      interrupt_server_ranges_prop,
    326                      sizeof(interrupt_server_ranges_prop)));
    327     _FDT(fdt_setprop_cell(fdt, node, "#interrupt-cells", 2));
    328     _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle));
    329     _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
    330 }
    331 
    332 static int xics_spapr_cpu_intc_create(SpaprInterruptController *intc,
    333                                        PowerPCCPU *cpu, Error **errp)
    334 {
    335     ICSState *ics = ICS_SPAPR(intc);
    336     Object *obj;
    337     SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
    338 
    339     obj = icp_create(OBJECT(cpu), TYPE_ICP, ics->xics, errp);
    340     if (!obj) {
    341         return -1;
    342     }
    343 
    344     spapr_cpu->icp = ICP(obj);
    345     return 0;
    346 }
    347 
    348 static void xics_spapr_cpu_intc_reset(SpaprInterruptController *intc,
    349                                      PowerPCCPU *cpu)
    350 {
    351     icp_reset(spapr_cpu_state(cpu)->icp);
    352 }
    353 
    354 static void xics_spapr_cpu_intc_destroy(SpaprInterruptController *intc,
    355                                         PowerPCCPU *cpu)
    356 {
    357     SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
    358 
    359     icp_destroy(spapr_cpu->icp);
    360     spapr_cpu->icp = NULL;
    361 }
    362 
    363 static int xics_spapr_claim_irq(SpaprInterruptController *intc, int irq,
    364                                 bool lsi, Error **errp)
    365 {
    366     ICSState *ics = ICS_SPAPR(intc);
    367 
    368     assert(ics);
    369     assert(ics_valid_irq(ics, irq));
    370 
    371     if (!ics_irq_free(ics, irq - ics->offset)) {
    372         error_setg(errp, "IRQ %d is not free", irq);
    373         return -EBUSY;
    374     }
    375 
    376     ics_set_irq_type(ics, irq - ics->offset, lsi);
    377     return 0;
    378 }
    379 
    380 static void xics_spapr_free_irq(SpaprInterruptController *intc, int irq)
    381 {
    382     ICSState *ics = ICS_SPAPR(intc);
    383     uint32_t srcno = irq - ics->offset;
    384 
    385     assert(ics_valid_irq(ics, irq));
    386 
    387     memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState));
    388 }
    389 
    390 static void xics_spapr_set_irq(SpaprInterruptController *intc, int irq, int val)
    391 {
    392     ICSState *ics = ICS_SPAPR(intc);
    393     uint32_t srcno = irq - ics->offset;
    394 
    395     ics_set_irq(ics, srcno, val);
    396 }
    397 
    398 static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
    399 {
    400     ICSState *ics = ICS_SPAPR(intc);
    401     CPUState *cs;
    402 
    403     CPU_FOREACH(cs) {
    404         PowerPCCPU *cpu = POWERPC_CPU(cs);
    405 
    406         icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon);
    407     }
    408 
    409     ics_pic_print_info(ics, mon);
    410 }
    411 
    412 static int xics_spapr_post_load(SpaprInterruptController *intc, int version_id)
    413 {
    414     if (!kvm_irqchip_in_kernel()) {
    415         CPUState *cs;
    416         CPU_FOREACH(cs) {
    417             PowerPCCPU *cpu = POWERPC_CPU(cs);
    418             icp_resend(spapr_cpu_state(cpu)->icp);
    419         }
    420     }
    421     return 0;
    422 }
    423 
    424 static int xics_spapr_activate(SpaprInterruptController *intc,
    425                                uint32_t nr_servers, Error **errp)
    426 {
    427     if (kvm_enabled()) {
    428         return spapr_irq_init_kvm(xics_kvm_connect, intc, nr_servers, 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)