13aa597f6SCédric Le Goater /* 23aa597f6SCédric Le Goater * QEMU PowerPC sPAPR XIVE interrupt controller model 33aa597f6SCédric Le Goater * 43aa597f6SCédric Le Goater * Copyright (c) 2017-2018, IBM Corporation. 53aa597f6SCédric Le Goater * 63aa597f6SCédric Le Goater * This code is licensed under the GPL version 2 or later. See the 73aa597f6SCédric Le Goater * COPYING file in the top-level directory. 83aa597f6SCédric Le Goater */ 93aa597f6SCédric Le Goater 103aa597f6SCédric Le Goater #include "qemu/osdep.h" 113aa597f6SCédric Le Goater #include "qemu/log.h" 123aa597f6SCédric Le Goater #include "qapi/error.h" 133aa597f6SCédric Le Goater #include "qemu/error-report.h" 143aa597f6SCédric Le Goater #include "target/ppc/cpu.h" 153aa597f6SCédric Le Goater #include "sysemu/cpus.h" 163aa597f6SCédric Le Goater #include "monitor/monitor.h" 173aa597f6SCédric Le Goater #include "hw/ppc/spapr.h" 183aa597f6SCédric Le Goater #include "hw/ppc/spapr_xive.h" 193aa597f6SCédric Le Goater #include "hw/ppc/xive.h" 203aa597f6SCédric Le Goater #include "hw/ppc/xive_regs.h" 213aa597f6SCédric Le Goater 223aa597f6SCédric Le Goater /* 233aa597f6SCédric Le Goater * XIVE Virtualization Controller BAR and Thread Managment BAR that we 243aa597f6SCédric Le Goater * use for the ESB pages and the TIMA pages 253aa597f6SCédric Le Goater */ 263aa597f6SCédric Le Goater #define SPAPR_XIVE_VC_BASE 0x0006010000000000ull 273aa597f6SCédric Le Goater #define SPAPR_XIVE_TM_BASE 0x0006030203180000ull 283aa597f6SCédric Le Goater 293aa597f6SCédric Le Goater /* 30*0cddee8dSCédric Le Goater * The allocation of VP blocks is a complex operation in OPAL and the 31*0cddee8dSCédric Le Goater * VP identifiers have a relation with the number of HW chips, the 32*0cddee8dSCédric Le Goater * size of the VP blocks, VP grouping, etc. The QEMU sPAPR XIVE 33*0cddee8dSCédric Le Goater * controller model does not have the same constraints and can use a 34*0cddee8dSCédric Le Goater * simple mapping scheme of the CPU vcpu_id 35*0cddee8dSCédric Le Goater * 36*0cddee8dSCédric Le Goater * These identifiers are never returned to the OS. 37*0cddee8dSCédric Le Goater */ 38*0cddee8dSCédric Le Goater 39*0cddee8dSCédric Le Goater #define SPAPR_XIVE_NVT_BASE 0x400 40*0cddee8dSCédric Le Goater 41*0cddee8dSCédric Le Goater /* 42*0cddee8dSCédric Le Goater * sPAPR NVT and END indexing helpers 43*0cddee8dSCédric Le Goater */ 44*0cddee8dSCédric Le Goater static uint32_t spapr_xive_nvt_to_target(uint8_t nvt_blk, uint32_t nvt_idx) 45*0cddee8dSCédric Le Goater { 46*0cddee8dSCédric Le Goater return nvt_idx - SPAPR_XIVE_NVT_BASE; 47*0cddee8dSCédric Le Goater } 48*0cddee8dSCédric Le Goater 49*0cddee8dSCédric Le Goater /* 503aa597f6SCédric Le Goater * On sPAPR machines, use a simplified output for the XIVE END 513aa597f6SCédric Le Goater * structure dumping only the information related to the OS EQ. 523aa597f6SCédric Le Goater */ 533aa597f6SCédric Le Goater static void spapr_xive_end_pic_print_info(sPAPRXive *xive, XiveEND *end, 543aa597f6SCédric Le Goater Monitor *mon) 553aa597f6SCédric Le Goater { 563aa597f6SCédric Le Goater uint32_t qindex = xive_get_field32(END_W1_PAGE_OFF, end->w1); 573aa597f6SCédric Le Goater uint32_t qgen = xive_get_field32(END_W1_GENERATION, end->w1); 583aa597f6SCédric Le Goater uint32_t qsize = xive_get_field32(END_W0_QSIZE, end->w0); 593aa597f6SCédric Le Goater uint32_t qentries = 1 << (qsize + 10); 603aa597f6SCédric Le Goater uint32_t nvt = xive_get_field32(END_W6_NVT_INDEX, end->w6); 613aa597f6SCédric Le Goater uint8_t priority = xive_get_field32(END_W7_F0_PRIORITY, end->w7); 623aa597f6SCédric Le Goater 63*0cddee8dSCédric Le Goater monitor_printf(mon, "%3d/%d % 6d/%5d ^%d", 64*0cddee8dSCédric Le Goater spapr_xive_nvt_to_target(0, nvt), 653aa597f6SCédric Le Goater priority, qindex, qentries, qgen); 663aa597f6SCédric Le Goater 673aa597f6SCédric Le Goater xive_end_queue_pic_print_info(end, 6, mon); 683aa597f6SCédric Le Goater monitor_printf(mon, "]"); 693aa597f6SCédric Le Goater } 703aa597f6SCédric Le Goater 713aa597f6SCédric Le Goater void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon) 723aa597f6SCédric Le Goater { 733aa597f6SCédric Le Goater XiveSource *xsrc = &xive->source; 743aa597f6SCédric Le Goater int i; 753aa597f6SCédric Le Goater 763aa597f6SCédric Le Goater monitor_printf(mon, " LSIN PQ EISN CPU/PRIO EQ\n"); 773aa597f6SCédric Le Goater 783aa597f6SCédric Le Goater for (i = 0; i < xive->nr_irqs; i++) { 793aa597f6SCédric Le Goater uint8_t pq = xive_source_esb_get(xsrc, i); 803aa597f6SCédric Le Goater XiveEAS *eas = &xive->eat[i]; 813aa597f6SCédric Le Goater 823aa597f6SCédric Le Goater if (!xive_eas_is_valid(eas)) { 833aa597f6SCédric Le Goater continue; 843aa597f6SCédric Le Goater } 853aa597f6SCédric Le Goater 863aa597f6SCédric Le Goater monitor_printf(mon, " %08x %s %c%c%c %s %08x ", i, 873aa597f6SCédric Le Goater xive_source_irq_is_lsi(xsrc, i) ? "LSI" : "MSI", 883aa597f6SCédric Le Goater pq & XIVE_ESB_VAL_P ? 'P' : '-', 893aa597f6SCédric Le Goater pq & XIVE_ESB_VAL_Q ? 'Q' : '-', 903aa597f6SCédric Le Goater xsrc->status[i] & XIVE_STATUS_ASSERTED ? 'A' : ' ', 913aa597f6SCédric Le Goater xive_eas_is_masked(eas) ? "M" : " ", 923aa597f6SCédric Le Goater (int) xive_get_field64(EAS_END_DATA, eas->w)); 933aa597f6SCédric Le Goater 943aa597f6SCédric Le Goater if (!xive_eas_is_masked(eas)) { 953aa597f6SCédric Le Goater uint32_t end_idx = xive_get_field64(EAS_END_INDEX, eas->w); 963aa597f6SCédric Le Goater XiveEND *end; 973aa597f6SCédric Le Goater 983aa597f6SCédric Le Goater assert(end_idx < xive->nr_ends); 993aa597f6SCédric Le Goater end = &xive->endt[end_idx]; 1003aa597f6SCédric Le Goater 1013aa597f6SCédric Le Goater if (xive_end_is_valid(end)) { 1023aa597f6SCédric Le Goater spapr_xive_end_pic_print_info(xive, end, mon); 1033aa597f6SCédric Le Goater } 1043aa597f6SCédric Le Goater } 1053aa597f6SCédric Le Goater monitor_printf(mon, "\n"); 1063aa597f6SCédric Le Goater } 1073aa597f6SCédric Le Goater } 1083aa597f6SCédric Le Goater 1093aa597f6SCédric Le Goater static void spapr_xive_map_mmio(sPAPRXive *xive) 1103aa597f6SCédric Le Goater { 1113aa597f6SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(xive), 0, xive->vc_base); 1123aa597f6SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(xive), 1, xive->end_base); 1133aa597f6SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(xive), 2, xive->tm_base); 1143aa597f6SCédric Le Goater } 1153aa597f6SCédric Le Goater 1163aa597f6SCédric Le Goater static void spapr_xive_end_reset(XiveEND *end) 1173aa597f6SCédric Le Goater { 1183aa597f6SCédric Le Goater memset(end, 0, sizeof(*end)); 1193aa597f6SCédric Le Goater 1203aa597f6SCédric Le Goater /* switch off the escalation and notification ESBs */ 1213aa597f6SCédric Le Goater end->w1 = cpu_to_be32(END_W1_ESe_Q | END_W1_ESn_Q); 1223aa597f6SCédric Le Goater } 1233aa597f6SCédric Le Goater 1243aa597f6SCédric Le Goater static void spapr_xive_reset(void *dev) 1253aa597f6SCédric Le Goater { 1263aa597f6SCédric Le Goater sPAPRXive *xive = SPAPR_XIVE(dev); 1273aa597f6SCédric Le Goater int i; 1283aa597f6SCédric Le Goater 1293aa597f6SCédric Le Goater /* 1303aa597f6SCédric Le Goater * The XiveSource has its own reset handler, which mask off all 1313aa597f6SCédric Le Goater * IRQs (!P|Q) 1323aa597f6SCédric Le Goater */ 1333aa597f6SCédric Le Goater 1343aa597f6SCédric Le Goater /* Mask all valid EASs in the IRQ number space. */ 1353aa597f6SCédric Le Goater for (i = 0; i < xive->nr_irqs; i++) { 1363aa597f6SCédric Le Goater XiveEAS *eas = &xive->eat[i]; 1373aa597f6SCédric Le Goater if (xive_eas_is_valid(eas)) { 1383aa597f6SCédric Le Goater eas->w = cpu_to_be64(EAS_VALID | EAS_MASKED); 1393aa597f6SCédric Le Goater } else { 1403aa597f6SCédric Le Goater eas->w = 0; 1413aa597f6SCédric Le Goater } 1423aa597f6SCédric Le Goater } 1433aa597f6SCédric Le Goater 1443aa597f6SCédric Le Goater /* Clear all ENDs */ 1453aa597f6SCédric Le Goater for (i = 0; i < xive->nr_ends; i++) { 1463aa597f6SCédric Le Goater spapr_xive_end_reset(&xive->endt[i]); 1473aa597f6SCédric Le Goater } 1483aa597f6SCédric Le Goater } 1493aa597f6SCédric Le Goater 1503aa597f6SCédric Le Goater static void spapr_xive_instance_init(Object *obj) 1513aa597f6SCédric Le Goater { 1523aa597f6SCédric Le Goater sPAPRXive *xive = SPAPR_XIVE(obj); 1533aa597f6SCédric Le Goater 1543aa597f6SCédric Le Goater object_initialize(&xive->source, sizeof(xive->source), TYPE_XIVE_SOURCE); 1553aa597f6SCédric Le Goater object_property_add_child(obj, "source", OBJECT(&xive->source), NULL); 1563aa597f6SCédric Le Goater 1573aa597f6SCédric Le Goater object_initialize(&xive->end_source, sizeof(xive->end_source), 1583aa597f6SCédric Le Goater TYPE_XIVE_END_SOURCE); 1593aa597f6SCédric Le Goater object_property_add_child(obj, "end_source", OBJECT(&xive->end_source), 1603aa597f6SCédric Le Goater NULL); 1613aa597f6SCédric Le Goater } 1623aa597f6SCédric Le Goater 1633aa597f6SCédric Le Goater static void spapr_xive_realize(DeviceState *dev, Error **errp) 1643aa597f6SCédric Le Goater { 1653aa597f6SCédric Le Goater sPAPRXive *xive = SPAPR_XIVE(dev); 1663aa597f6SCédric Le Goater XiveSource *xsrc = &xive->source; 1673aa597f6SCédric Le Goater XiveENDSource *end_xsrc = &xive->end_source; 1683aa597f6SCédric Le Goater Error *local_err = NULL; 1693aa597f6SCédric Le Goater 1703aa597f6SCédric Le Goater if (!xive->nr_irqs) { 1713aa597f6SCédric Le Goater error_setg(errp, "Number of interrupt needs to be greater 0"); 1723aa597f6SCédric Le Goater return; 1733aa597f6SCédric Le Goater } 1743aa597f6SCédric Le Goater 1753aa597f6SCédric Le Goater if (!xive->nr_ends) { 1763aa597f6SCédric Le Goater error_setg(errp, "Number of interrupt needs to be greater 0"); 1773aa597f6SCédric Le Goater return; 1783aa597f6SCédric Le Goater } 1793aa597f6SCédric Le Goater 1803aa597f6SCédric Le Goater /* 1813aa597f6SCédric Le Goater * Initialize the internal sources, for IPIs and virtual devices. 1823aa597f6SCédric Le Goater */ 1833aa597f6SCédric Le Goater object_property_set_int(OBJECT(xsrc), xive->nr_irqs, "nr-irqs", 1843aa597f6SCédric Le Goater &error_fatal); 1853aa597f6SCédric Le Goater object_property_add_const_link(OBJECT(xsrc), "xive", OBJECT(xive), 1863aa597f6SCédric Le Goater &error_fatal); 1873aa597f6SCédric Le Goater object_property_set_bool(OBJECT(xsrc), true, "realized", &local_err); 1883aa597f6SCédric Le Goater if (local_err) { 1893aa597f6SCédric Le Goater error_propagate(errp, local_err); 1903aa597f6SCédric Le Goater return; 1913aa597f6SCédric Le Goater } 1923aa597f6SCédric Le Goater 1933aa597f6SCédric Le Goater /* 1943aa597f6SCédric Le Goater * Initialize the END ESB source 1953aa597f6SCédric Le Goater */ 1963aa597f6SCédric Le Goater object_property_set_int(OBJECT(end_xsrc), xive->nr_irqs, "nr-ends", 1973aa597f6SCédric Le Goater &error_fatal); 1983aa597f6SCédric Le Goater object_property_add_const_link(OBJECT(end_xsrc), "xive", OBJECT(xive), 1993aa597f6SCédric Le Goater &error_fatal); 2003aa597f6SCédric Le Goater object_property_set_bool(OBJECT(end_xsrc), true, "realized", &local_err); 2013aa597f6SCédric Le Goater if (local_err) { 2023aa597f6SCédric Le Goater error_propagate(errp, local_err); 2033aa597f6SCédric Le Goater return; 2043aa597f6SCédric Le Goater } 2053aa597f6SCédric Le Goater 2063aa597f6SCédric Le Goater /* Set the mapping address of the END ESB pages after the source ESBs */ 2073aa597f6SCédric Le Goater xive->end_base = xive->vc_base + (1ull << xsrc->esb_shift) * xsrc->nr_irqs; 2083aa597f6SCédric Le Goater 2093aa597f6SCédric Le Goater /* 2103aa597f6SCédric Le Goater * Allocate the routing tables 2113aa597f6SCédric Le Goater */ 2123aa597f6SCédric Le Goater xive->eat = g_new0(XiveEAS, xive->nr_irqs); 2133aa597f6SCédric Le Goater xive->endt = g_new0(XiveEND, xive->nr_ends); 2143aa597f6SCédric Le Goater 2153aa597f6SCédric Le Goater /* TIMA initialization */ 2163aa597f6SCédric Le Goater memory_region_init_io(&xive->tm_mmio, OBJECT(xive), &xive_tm_ops, xive, 2173aa597f6SCédric Le Goater "xive.tima", 4ull << TM_SHIFT); 2183aa597f6SCédric Le Goater 2193aa597f6SCédric Le Goater /* Define all XIVE MMIO regions on SysBus */ 2203aa597f6SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xsrc->esb_mmio); 2213aa597f6SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(xive), &end_xsrc->esb_mmio); 2223aa597f6SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(xive), &xive->tm_mmio); 2233aa597f6SCédric Le Goater 2243aa597f6SCédric Le Goater /* Map all regions */ 2253aa597f6SCédric Le Goater spapr_xive_map_mmio(xive); 2263aa597f6SCédric Le Goater 2273aa597f6SCédric Le Goater qemu_register_reset(spapr_xive_reset, dev); 2283aa597f6SCédric Le Goater } 2293aa597f6SCédric Le Goater 2303aa597f6SCédric Le Goater static int spapr_xive_get_eas(XiveRouter *xrtr, uint8_t eas_blk, 2313aa597f6SCédric Le Goater uint32_t eas_idx, XiveEAS *eas) 2323aa597f6SCédric Le Goater { 2333aa597f6SCédric Le Goater sPAPRXive *xive = SPAPR_XIVE(xrtr); 2343aa597f6SCédric Le Goater 2353aa597f6SCédric Le Goater if (eas_idx >= xive->nr_irqs) { 2363aa597f6SCédric Le Goater return -1; 2373aa597f6SCédric Le Goater } 2383aa597f6SCédric Le Goater 2393aa597f6SCédric Le Goater *eas = xive->eat[eas_idx]; 2403aa597f6SCédric Le Goater return 0; 2413aa597f6SCédric Le Goater } 2423aa597f6SCédric Le Goater 2433aa597f6SCédric Le Goater static int spapr_xive_get_end(XiveRouter *xrtr, 2443aa597f6SCédric Le Goater uint8_t end_blk, uint32_t end_idx, XiveEND *end) 2453aa597f6SCédric Le Goater { 2463aa597f6SCédric Le Goater sPAPRXive *xive = SPAPR_XIVE(xrtr); 2473aa597f6SCédric Le Goater 2483aa597f6SCédric Le Goater if (end_idx >= xive->nr_ends) { 2493aa597f6SCédric Le Goater return -1; 2503aa597f6SCédric Le Goater } 2513aa597f6SCédric Le Goater 2523aa597f6SCédric Le Goater memcpy(end, &xive->endt[end_idx], sizeof(XiveEND)); 2533aa597f6SCédric Le Goater return 0; 2543aa597f6SCédric Le Goater } 2553aa597f6SCédric Le Goater 2563aa597f6SCédric Le Goater static int spapr_xive_write_end(XiveRouter *xrtr, uint8_t end_blk, 2573aa597f6SCédric Le Goater uint32_t end_idx, XiveEND *end, 2583aa597f6SCédric Le Goater uint8_t word_number) 2593aa597f6SCédric Le Goater { 2603aa597f6SCédric Le Goater sPAPRXive *xive = SPAPR_XIVE(xrtr); 2613aa597f6SCédric Le Goater 2623aa597f6SCédric Le Goater if (end_idx >= xive->nr_ends) { 2633aa597f6SCédric Le Goater return -1; 2643aa597f6SCédric Le Goater } 2653aa597f6SCédric Le Goater 2663aa597f6SCédric Le Goater memcpy(&xive->endt[end_idx], end, sizeof(XiveEND)); 2673aa597f6SCédric Le Goater return 0; 2683aa597f6SCédric Le Goater } 2693aa597f6SCédric Le Goater 270*0cddee8dSCédric Le Goater static int spapr_xive_get_nvt(XiveRouter *xrtr, 271*0cddee8dSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt) 272*0cddee8dSCédric Le Goater { 273*0cddee8dSCédric Le Goater uint32_t vcpu_id = spapr_xive_nvt_to_target(nvt_blk, nvt_idx); 274*0cddee8dSCédric Le Goater PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); 275*0cddee8dSCédric Le Goater 276*0cddee8dSCédric Le Goater if (!cpu) { 277*0cddee8dSCédric Le Goater /* TODO: should we assert() if we can find a NVT ? */ 278*0cddee8dSCédric Le Goater return -1; 279*0cddee8dSCédric Le Goater } 280*0cddee8dSCédric Le Goater 281*0cddee8dSCédric Le Goater /* 282*0cddee8dSCédric Le Goater * sPAPR does not maintain a NVT table. Return that the NVT is 283*0cddee8dSCédric Le Goater * valid if we have found a matching CPU 284*0cddee8dSCédric Le Goater */ 285*0cddee8dSCédric Le Goater nvt->w0 = cpu_to_be32(NVT_W0_VALID); 286*0cddee8dSCédric Le Goater return 0; 287*0cddee8dSCédric Le Goater } 288*0cddee8dSCédric Le Goater 289*0cddee8dSCédric Le Goater static int spapr_xive_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, 290*0cddee8dSCédric Le Goater uint32_t nvt_idx, XiveNVT *nvt, 291*0cddee8dSCédric Le Goater uint8_t word_number) 292*0cddee8dSCédric Le Goater { 293*0cddee8dSCédric Le Goater /* 294*0cddee8dSCédric Le Goater * We don't need to write back to the NVTs because the sPAPR 295*0cddee8dSCédric Le Goater * machine should never hit a non-scheduled NVT. It should never 296*0cddee8dSCédric Le Goater * get called. 297*0cddee8dSCédric Le Goater */ 298*0cddee8dSCédric Le Goater g_assert_not_reached(); 299*0cddee8dSCédric Le Goater } 300*0cddee8dSCédric Le Goater 3013aa597f6SCédric Le Goater static const VMStateDescription vmstate_spapr_xive_end = { 3023aa597f6SCédric Le Goater .name = TYPE_SPAPR_XIVE "/end", 3033aa597f6SCédric Le Goater .version_id = 1, 3043aa597f6SCédric Le Goater .minimum_version_id = 1, 3053aa597f6SCédric Le Goater .fields = (VMStateField []) { 3063aa597f6SCédric Le Goater VMSTATE_UINT32(w0, XiveEND), 3073aa597f6SCédric Le Goater VMSTATE_UINT32(w1, XiveEND), 3083aa597f6SCédric Le Goater VMSTATE_UINT32(w2, XiveEND), 3093aa597f6SCédric Le Goater VMSTATE_UINT32(w3, XiveEND), 3103aa597f6SCédric Le Goater VMSTATE_UINT32(w4, XiveEND), 3113aa597f6SCédric Le Goater VMSTATE_UINT32(w5, XiveEND), 3123aa597f6SCédric Le Goater VMSTATE_UINT32(w6, XiveEND), 3133aa597f6SCédric Le Goater VMSTATE_UINT32(w7, XiveEND), 3143aa597f6SCédric Le Goater VMSTATE_END_OF_LIST() 3153aa597f6SCédric Le Goater }, 3163aa597f6SCédric Le Goater }; 3173aa597f6SCédric Le Goater 3183aa597f6SCédric Le Goater static const VMStateDescription vmstate_spapr_xive_eas = { 3193aa597f6SCédric Le Goater .name = TYPE_SPAPR_XIVE "/eas", 3203aa597f6SCédric Le Goater .version_id = 1, 3213aa597f6SCédric Le Goater .minimum_version_id = 1, 3223aa597f6SCédric Le Goater .fields = (VMStateField []) { 3233aa597f6SCédric Le Goater VMSTATE_UINT64(w, XiveEAS), 3243aa597f6SCédric Le Goater VMSTATE_END_OF_LIST() 3253aa597f6SCédric Le Goater }, 3263aa597f6SCédric Le Goater }; 3273aa597f6SCédric Le Goater 3283aa597f6SCédric Le Goater static const VMStateDescription vmstate_spapr_xive = { 3293aa597f6SCédric Le Goater .name = TYPE_SPAPR_XIVE, 3303aa597f6SCédric Le Goater .version_id = 1, 3313aa597f6SCédric Le Goater .minimum_version_id = 1, 3323aa597f6SCédric Le Goater .fields = (VMStateField[]) { 3333aa597f6SCédric Le Goater VMSTATE_UINT32_EQUAL(nr_irqs, sPAPRXive, NULL), 3343aa597f6SCédric Le Goater VMSTATE_STRUCT_VARRAY_POINTER_UINT32(eat, sPAPRXive, nr_irqs, 3353aa597f6SCédric Le Goater vmstate_spapr_xive_eas, XiveEAS), 3363aa597f6SCédric Le Goater VMSTATE_STRUCT_VARRAY_POINTER_UINT32(endt, sPAPRXive, nr_ends, 3373aa597f6SCédric Le Goater vmstate_spapr_xive_end, XiveEND), 3383aa597f6SCédric Le Goater VMSTATE_END_OF_LIST() 3393aa597f6SCédric Le Goater }, 3403aa597f6SCédric Le Goater }; 3413aa597f6SCédric Le Goater 3423aa597f6SCédric Le Goater static Property spapr_xive_properties[] = { 3433aa597f6SCédric Le Goater DEFINE_PROP_UINT32("nr-irqs", sPAPRXive, nr_irqs, 0), 3443aa597f6SCédric Le Goater DEFINE_PROP_UINT32("nr-ends", sPAPRXive, nr_ends, 0), 3453aa597f6SCédric Le Goater DEFINE_PROP_UINT64("vc-base", sPAPRXive, vc_base, SPAPR_XIVE_VC_BASE), 3463aa597f6SCédric Le Goater DEFINE_PROP_UINT64("tm-base", sPAPRXive, tm_base, SPAPR_XIVE_TM_BASE), 3473aa597f6SCédric Le Goater DEFINE_PROP_END_OF_LIST(), 3483aa597f6SCédric Le Goater }; 3493aa597f6SCédric Le Goater 3503aa597f6SCédric Le Goater static void spapr_xive_class_init(ObjectClass *klass, void *data) 3513aa597f6SCédric Le Goater { 3523aa597f6SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 3533aa597f6SCédric Le Goater XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass); 3543aa597f6SCédric Le Goater 3553aa597f6SCédric Le Goater dc->desc = "sPAPR XIVE Interrupt Controller"; 3563aa597f6SCédric Le Goater dc->props = spapr_xive_properties; 3573aa597f6SCédric Le Goater dc->realize = spapr_xive_realize; 3583aa597f6SCédric Le Goater dc->vmsd = &vmstate_spapr_xive; 3593aa597f6SCédric Le Goater 3603aa597f6SCédric Le Goater xrc->get_eas = spapr_xive_get_eas; 3613aa597f6SCédric Le Goater xrc->get_end = spapr_xive_get_end; 3623aa597f6SCédric Le Goater xrc->write_end = spapr_xive_write_end; 363*0cddee8dSCédric Le Goater xrc->get_nvt = spapr_xive_get_nvt; 364*0cddee8dSCédric Le Goater xrc->write_nvt = spapr_xive_write_nvt; 3653aa597f6SCédric Le Goater } 3663aa597f6SCédric Le Goater 3673aa597f6SCédric Le Goater static const TypeInfo spapr_xive_info = { 3683aa597f6SCédric Le Goater .name = TYPE_SPAPR_XIVE, 3693aa597f6SCédric Le Goater .parent = TYPE_XIVE_ROUTER, 3703aa597f6SCédric Le Goater .instance_init = spapr_xive_instance_init, 3713aa597f6SCédric Le Goater .instance_size = sizeof(sPAPRXive), 3723aa597f6SCédric Le Goater .class_init = spapr_xive_class_init, 3733aa597f6SCédric Le Goater }; 3743aa597f6SCédric Le Goater 3753aa597f6SCédric Le Goater static void spapr_xive_register_types(void) 3763aa597f6SCédric Le Goater { 3773aa597f6SCédric Le Goater type_register_static(&spapr_xive_info); 3783aa597f6SCédric Le Goater } 3793aa597f6SCédric Le Goater 3803aa597f6SCédric Le Goater type_init(spapr_xive_register_types) 3813aa597f6SCédric Le Goater 3823aa597f6SCédric Le Goater bool spapr_xive_irq_claim(sPAPRXive *xive, uint32_t lisn, bool lsi) 3833aa597f6SCédric Le Goater { 3843aa597f6SCédric Le Goater XiveSource *xsrc = &xive->source; 3853aa597f6SCédric Le Goater 3863aa597f6SCédric Le Goater if (lisn >= xive->nr_irqs) { 3873aa597f6SCédric Le Goater return false; 3883aa597f6SCédric Le Goater } 3893aa597f6SCédric Le Goater 3903aa597f6SCédric Le Goater xive->eat[lisn].w |= cpu_to_be64(EAS_VALID); 3913aa597f6SCédric Le Goater xive_source_irq_set(xsrc, lisn, lsi); 3923aa597f6SCédric Le Goater return true; 3933aa597f6SCédric Le Goater } 3943aa597f6SCédric Le Goater 3953aa597f6SCédric Le Goater bool spapr_xive_irq_free(sPAPRXive *xive, uint32_t lisn) 3963aa597f6SCédric Le Goater { 3973aa597f6SCédric Le Goater XiveSource *xsrc = &xive->source; 3983aa597f6SCédric Le Goater 3993aa597f6SCédric Le Goater if (lisn >= xive->nr_irqs) { 4003aa597f6SCédric Le Goater return false; 4013aa597f6SCédric Le Goater } 4023aa597f6SCédric Le Goater 4033aa597f6SCédric Le Goater xive->eat[lisn].w &= cpu_to_be64(~EAS_VALID); 4043aa597f6SCédric Le Goater xive_source_irq_set(xsrc, lisn, false); 4053aa597f6SCédric Le Goater return true; 4063aa597f6SCédric Le Goater } 4073aa597f6SCédric Le Goater 4083aa597f6SCédric Le Goater qemu_irq spapr_xive_qirq(sPAPRXive *xive, uint32_t lisn) 4093aa597f6SCédric Le Goater { 4103aa597f6SCédric Le Goater XiveSource *xsrc = &xive->source; 4113aa597f6SCédric Le Goater 4123aa597f6SCédric Le Goater if (lisn >= xive->nr_irqs) { 4133aa597f6SCédric Le Goater return NULL; 4143aa597f6SCédric Le Goater } 4153aa597f6SCédric Le Goater 4163aa597f6SCédric Le Goater /* The sPAPR machine/device should have claimed the IRQ before */ 4173aa597f6SCédric Le Goater assert(xive_eas_is_valid(&xive->eat[lisn])); 4183aa597f6SCédric Le Goater 4193aa597f6SCédric Le Goater return xive_source_qirq(xsrc, lisn); 4203aa597f6SCédric Le Goater } 421