1b5cec4c5SDavid Gibson /* 2b5cec4c5SDavid Gibson * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator 3b5cec4c5SDavid Gibson * 4b5cec4c5SDavid Gibson * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics 5b5cec4c5SDavid Gibson * 6b5cec4c5SDavid Gibson * Copyright (c) 2010,2011 David Gibson, IBM Corporation. 7b5cec4c5SDavid Gibson * 8b5cec4c5SDavid Gibson * Permission is hereby granted, free of charge, to any person obtaining a copy 9b5cec4c5SDavid Gibson * of this software and associated documentation files (the "Software"), to deal 10b5cec4c5SDavid Gibson * in the Software without restriction, including without limitation the rights 11b5cec4c5SDavid Gibson * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12b5cec4c5SDavid Gibson * copies of the Software, and to permit persons to whom the Software is 13b5cec4c5SDavid Gibson * furnished to do so, subject to the following conditions: 14b5cec4c5SDavid Gibson * 15b5cec4c5SDavid Gibson * The above copyright notice and this permission notice shall be included in 16b5cec4c5SDavid Gibson * all copies or substantial portions of the Software. 17b5cec4c5SDavid Gibson * 18b5cec4c5SDavid Gibson * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19b5cec4c5SDavid Gibson * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20b5cec4c5SDavid Gibson * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21b5cec4c5SDavid Gibson * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22b5cec4c5SDavid Gibson * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23b5cec4c5SDavid Gibson * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24b5cec4c5SDavid Gibson * THE SOFTWARE. 25b5cec4c5SDavid Gibson * 26b5cec4c5SDavid Gibson */ 27b5cec4c5SDavid Gibson 280d75590dSPeter Maydell #include "qemu/osdep.h" 29da34e65cSMarkus Armbruster #include "qapi/error.h" 304771d756SPaolo Bonzini #include "qemu-common.h" 314771d756SPaolo Bonzini #include "cpu.h" 3283c9f4caSPaolo Bonzini #include "hw/hw.h" 33500efa23SDavid Gibson #include "trace.h" 345d87e4b7SBenjamin Herrenschmidt #include "qemu/timer.h" 350d09e41aSPaolo Bonzini #include "hw/ppc/xics.h" 369ccff2a4SAlexey Kardashevskiy #include "qemu/error-report.h" 375a3d7b23SAlexey Kardashevskiy #include "qapi/visitor.h" 38b5cec4c5SDavid Gibson 399c7027baSBenjamin Herrenschmidt int xics_get_cpu_index_by_dt_id(int cpu_dt_id) 400f20ba62SAlexey Kardashevskiy { 410f20ba62SAlexey Kardashevskiy PowerPCCPU *cpu = ppc_get_vcpu_by_dt_id(cpu_dt_id); 420f20ba62SAlexey Kardashevskiy 430f20ba62SAlexey Kardashevskiy if (cpu) { 440f20ba62SAlexey Kardashevskiy return cpu->parent_obj.cpu_index; 450f20ba62SAlexey Kardashevskiy } 460f20ba62SAlexey Kardashevskiy 470f20ba62SAlexey Kardashevskiy return -1; 480f20ba62SAlexey Kardashevskiy } 490f20ba62SAlexey Kardashevskiy 5027f24582SBenjamin Herrenschmidt void xics_cpu_destroy(XICSState *xics, PowerPCCPU *cpu) 514a4b344cSBharata B Rao { 524a4b344cSBharata B Rao CPUState *cs = CPU(cpu); 5327f24582SBenjamin Herrenschmidt ICPState *ss = &xics->ss[cs->cpu_index]; 544a4b344cSBharata B Rao 5527f24582SBenjamin Herrenschmidt assert(cs->cpu_index < xics->nr_servers); 564a4b344cSBharata B Rao assert(cs == ss->cs); 574a4b344cSBharata B Rao 584a4b344cSBharata B Rao ss->output = NULL; 594a4b344cSBharata B Rao ss->cs = NULL; 604a4b344cSBharata B Rao } 614a4b344cSBharata B Rao 6227f24582SBenjamin Herrenschmidt void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu) 638ffe04edSAlexey Kardashevskiy { 648ffe04edSAlexey Kardashevskiy CPUState *cs = CPU(cpu); 658ffe04edSAlexey Kardashevskiy CPUPPCState *env = &cpu->env; 6627f24582SBenjamin Herrenschmidt ICPState *ss = &xics->ss[cs->cpu_index]; 6727f24582SBenjamin Herrenschmidt XICSStateClass *info = XICS_COMMON_GET_CLASS(xics); 688ffe04edSAlexey Kardashevskiy 6927f24582SBenjamin Herrenschmidt assert(cs->cpu_index < xics->nr_servers); 708ffe04edSAlexey Kardashevskiy 714a4b344cSBharata B Rao ss->cs = cs; 724a4b344cSBharata B Rao 735eb92cccSAlexey Kardashevskiy if (info->cpu_setup) { 7427f24582SBenjamin Herrenschmidt info->cpu_setup(xics, cpu); 755eb92cccSAlexey Kardashevskiy } 765eb92cccSAlexey Kardashevskiy 778ffe04edSAlexey Kardashevskiy switch (PPC_INPUT(env)) { 788ffe04edSAlexey Kardashevskiy case PPC_FLAGS_INPUT_POWER7: 798ffe04edSAlexey Kardashevskiy ss->output = env->irq_inputs[POWER7_INPUT_INT]; 808ffe04edSAlexey Kardashevskiy break; 818ffe04edSAlexey Kardashevskiy 828ffe04edSAlexey Kardashevskiy case PPC_FLAGS_INPUT_970: 838ffe04edSAlexey Kardashevskiy ss->output = env->irq_inputs[PPC970_INPUT_INT]; 848ffe04edSAlexey Kardashevskiy break; 858ffe04edSAlexey Kardashevskiy 868ffe04edSAlexey Kardashevskiy default: 879ccff2a4SAlexey Kardashevskiy error_report("XICS interrupt controller does not support this CPU " 889ccff2a4SAlexey Kardashevskiy "bus model"); 898ffe04edSAlexey Kardashevskiy abort(); 908ffe04edSAlexey Kardashevskiy } 918ffe04edSAlexey Kardashevskiy } 928ffe04edSAlexey Kardashevskiy 935a3d7b23SAlexey Kardashevskiy /* 945a3d7b23SAlexey Kardashevskiy * XICS Common class - parent for emulated XICS and KVM-XICS 955a3d7b23SAlexey Kardashevskiy */ 965a3d7b23SAlexey Kardashevskiy static void xics_common_reset(DeviceState *d) 978ffe04edSAlexey Kardashevskiy { 9827f24582SBenjamin Herrenschmidt XICSState *xics = XICS_COMMON(d); 99*cc706a53SBenjamin Herrenschmidt ICSState *ics; 1008ffe04edSAlexey Kardashevskiy int i; 1018ffe04edSAlexey Kardashevskiy 10227f24582SBenjamin Herrenschmidt for (i = 0; i < xics->nr_servers; i++) { 10327f24582SBenjamin Herrenschmidt device_reset(DEVICE(&xics->ss[i])); 1048ffe04edSAlexey Kardashevskiy } 1058ffe04edSAlexey Kardashevskiy 106*cc706a53SBenjamin Herrenschmidt QLIST_FOREACH(ics, &xics->ics, list) { 107*cc706a53SBenjamin Herrenschmidt device_reset(DEVICE(ics)); 108*cc706a53SBenjamin Herrenschmidt } 1098ffe04edSAlexey Kardashevskiy } 1108ffe04edSAlexey Kardashevskiy 111d7bce999SEric Blake static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name, 112d7bce999SEric Blake void *opaque, Error **errp) 1135a3d7b23SAlexey Kardashevskiy { 11427f24582SBenjamin Herrenschmidt XICSState *xics = XICS_COMMON(obj); 11527f24582SBenjamin Herrenschmidt int64_t value = xics->nr_irqs; 1165a3d7b23SAlexey Kardashevskiy 11751e72bc1SEric Blake visit_type_int(v, name, &value, errp); 1185a3d7b23SAlexey Kardashevskiy } 1195a3d7b23SAlexey Kardashevskiy 120d7bce999SEric Blake static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name, 121d7bce999SEric Blake void *opaque, Error **errp) 1225a3d7b23SAlexey Kardashevskiy { 12327f24582SBenjamin Herrenschmidt XICSState *xics = XICS_COMMON(obj); 12427f24582SBenjamin Herrenschmidt XICSStateClass *info = XICS_COMMON_GET_CLASS(xics); 1255a3d7b23SAlexey Kardashevskiy Error *error = NULL; 1265a3d7b23SAlexey Kardashevskiy int64_t value; 1275a3d7b23SAlexey Kardashevskiy 12851e72bc1SEric Blake visit_type_int(v, name, &value, &error); 1295a3d7b23SAlexey Kardashevskiy if (error) { 1305a3d7b23SAlexey Kardashevskiy error_propagate(errp, error); 1315a3d7b23SAlexey Kardashevskiy return; 1325a3d7b23SAlexey Kardashevskiy } 13327f24582SBenjamin Herrenschmidt if (xics->nr_irqs) { 1345a3d7b23SAlexey Kardashevskiy error_setg(errp, "Number of interrupts is already set to %u", 13527f24582SBenjamin Herrenschmidt xics->nr_irqs); 1365a3d7b23SAlexey Kardashevskiy return; 1375a3d7b23SAlexey Kardashevskiy } 1385a3d7b23SAlexey Kardashevskiy 1395a3d7b23SAlexey Kardashevskiy assert(info->set_nr_irqs); 14027f24582SBenjamin Herrenschmidt info->set_nr_irqs(xics, value, errp); 1415a3d7b23SAlexey Kardashevskiy } 1425a3d7b23SAlexey Kardashevskiy 1435a3d7b23SAlexey Kardashevskiy static void xics_prop_get_nr_servers(Object *obj, Visitor *v, 144d7bce999SEric Blake const char *name, void *opaque, 1455a3d7b23SAlexey Kardashevskiy Error **errp) 1465a3d7b23SAlexey Kardashevskiy { 14727f24582SBenjamin Herrenschmidt XICSState *xics = XICS_COMMON(obj); 14827f24582SBenjamin Herrenschmidt int64_t value = xics->nr_servers; 1495a3d7b23SAlexey Kardashevskiy 15051e72bc1SEric Blake visit_type_int(v, name, &value, errp); 1515a3d7b23SAlexey Kardashevskiy } 1525a3d7b23SAlexey Kardashevskiy 1535a3d7b23SAlexey Kardashevskiy static void xics_prop_set_nr_servers(Object *obj, Visitor *v, 154d7bce999SEric Blake const char *name, void *opaque, 1555a3d7b23SAlexey Kardashevskiy Error **errp) 1565a3d7b23SAlexey Kardashevskiy { 15727f24582SBenjamin Herrenschmidt XICSState *xics = XICS_COMMON(obj); 15827f24582SBenjamin Herrenschmidt XICSStateClass *info = XICS_COMMON_GET_CLASS(xics); 1595a3d7b23SAlexey Kardashevskiy Error *error = NULL; 1605a3d7b23SAlexey Kardashevskiy int64_t value; 1615a3d7b23SAlexey Kardashevskiy 16251e72bc1SEric Blake visit_type_int(v, name, &value, &error); 1635a3d7b23SAlexey Kardashevskiy if (error) { 1645a3d7b23SAlexey Kardashevskiy error_propagate(errp, error); 1655a3d7b23SAlexey Kardashevskiy return; 1665a3d7b23SAlexey Kardashevskiy } 16727f24582SBenjamin Herrenschmidt if (xics->nr_servers) { 1685a3d7b23SAlexey Kardashevskiy error_setg(errp, "Number of servers is already set to %u", 16927f24582SBenjamin Herrenschmidt xics->nr_servers); 1705a3d7b23SAlexey Kardashevskiy return; 1715a3d7b23SAlexey Kardashevskiy } 1725a3d7b23SAlexey Kardashevskiy 1735a3d7b23SAlexey Kardashevskiy assert(info->set_nr_servers); 17427f24582SBenjamin Herrenschmidt info->set_nr_servers(xics, value, errp); 1755a3d7b23SAlexey Kardashevskiy } 1765a3d7b23SAlexey Kardashevskiy 1775a3d7b23SAlexey Kardashevskiy static void xics_common_initfn(Object *obj) 1785a3d7b23SAlexey Kardashevskiy { 179*cc706a53SBenjamin Herrenschmidt XICSState *xics = XICS_COMMON(obj); 180*cc706a53SBenjamin Herrenschmidt 181*cc706a53SBenjamin Herrenschmidt QLIST_INIT(&xics->ics); 1825a3d7b23SAlexey Kardashevskiy object_property_add(obj, "nr_irqs", "int", 1835a3d7b23SAlexey Kardashevskiy xics_prop_get_nr_irqs, xics_prop_set_nr_irqs, 1845a3d7b23SAlexey Kardashevskiy NULL, NULL, NULL); 1855a3d7b23SAlexey Kardashevskiy object_property_add(obj, "nr_servers", "int", 1865a3d7b23SAlexey Kardashevskiy xics_prop_get_nr_servers, xics_prop_set_nr_servers, 1875a3d7b23SAlexey Kardashevskiy NULL, NULL, NULL); 1885a3d7b23SAlexey Kardashevskiy } 1895a3d7b23SAlexey Kardashevskiy 1905a3d7b23SAlexey Kardashevskiy static void xics_common_class_init(ObjectClass *oc, void *data) 1915a3d7b23SAlexey Kardashevskiy { 1925a3d7b23SAlexey Kardashevskiy DeviceClass *dc = DEVICE_CLASS(oc); 1935a3d7b23SAlexey Kardashevskiy 1945a3d7b23SAlexey Kardashevskiy dc->reset = xics_common_reset; 1955a3d7b23SAlexey Kardashevskiy } 1965a3d7b23SAlexey Kardashevskiy 1975a3d7b23SAlexey Kardashevskiy static const TypeInfo xics_common_info = { 1985a3d7b23SAlexey Kardashevskiy .name = TYPE_XICS_COMMON, 1995a3d7b23SAlexey Kardashevskiy .parent = TYPE_SYS_BUS_DEVICE, 2005a3d7b23SAlexey Kardashevskiy .instance_size = sizeof(XICSState), 2015a3d7b23SAlexey Kardashevskiy .class_size = sizeof(XICSStateClass), 2025a3d7b23SAlexey Kardashevskiy .instance_init = xics_common_initfn, 2035a3d7b23SAlexey Kardashevskiy .class_init = xics_common_class_init, 2045a3d7b23SAlexey Kardashevskiy }; 2055a3d7b23SAlexey Kardashevskiy 206b5cec4c5SDavid Gibson /* 207b5cec4c5SDavid Gibson * ICP: Presentation layer 208b5cec4c5SDavid Gibson */ 209b5cec4c5SDavid Gibson 210b5cec4c5SDavid Gibson #define XISR_MASK 0x00ffffff 211b5cec4c5SDavid Gibson #define CPPR_MASK 0xff000000 212b5cec4c5SDavid Gibson 213b5cec4c5SDavid Gibson #define XISR(ss) (((ss)->xirr) & XISR_MASK) 214b5cec4c5SDavid Gibson #define CPPR(ss) (((ss)->xirr) >> 24) 215b5cec4c5SDavid Gibson 216c04d6cfaSAnthony Liguori static void ics_reject(ICSState *ics, int nr); 217c04d6cfaSAnthony Liguori static void ics_resend(ICSState *ics); 218c04d6cfaSAnthony Liguori static void ics_eoi(ICSState *ics, int nr); 219b5cec4c5SDavid Gibson 220*cc706a53SBenjamin Herrenschmidt static void icp_check_ipi(ICPState *ss) 221b5cec4c5SDavid Gibson { 222b5cec4c5SDavid Gibson if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) { 223b5cec4c5SDavid Gibson return; 224b5cec4c5SDavid Gibson } 225b5cec4c5SDavid Gibson 226*cc706a53SBenjamin Herrenschmidt trace_xics_icp_check_ipi(ss->cs->cpu_index, ss->mfrr); 227500efa23SDavid Gibson 228*cc706a53SBenjamin Herrenschmidt if (XISR(ss) && ss->xirr_owner) { 229*cc706a53SBenjamin Herrenschmidt ics_reject(ss->xirr_owner, XISR(ss)); 230b5cec4c5SDavid Gibson } 231b5cec4c5SDavid Gibson 232b5cec4c5SDavid Gibson ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI; 233b5cec4c5SDavid Gibson ss->pending_priority = ss->mfrr; 234*cc706a53SBenjamin Herrenschmidt ss->xirr_owner = NULL; 235b5cec4c5SDavid Gibson qemu_irq_raise(ss->output); 236b5cec4c5SDavid Gibson } 237b5cec4c5SDavid Gibson 23827f24582SBenjamin Herrenschmidt static void icp_resend(XICSState *xics, int server) 239b5cec4c5SDavid Gibson { 24027f24582SBenjamin Herrenschmidt ICPState *ss = xics->ss + server; 241*cc706a53SBenjamin Herrenschmidt ICSState *ics; 242b5cec4c5SDavid Gibson 243b5cec4c5SDavid Gibson if (ss->mfrr < CPPR(ss)) { 244*cc706a53SBenjamin Herrenschmidt icp_check_ipi(ss); 245b5cec4c5SDavid Gibson } 246*cc706a53SBenjamin Herrenschmidt QLIST_FOREACH(ics, &xics->ics, list) { 247*cc706a53SBenjamin Herrenschmidt ics_resend(ics); 248*cc706a53SBenjamin Herrenschmidt } 249b5cec4c5SDavid Gibson } 250b5cec4c5SDavid Gibson 25127f24582SBenjamin Herrenschmidt void icp_set_cppr(XICSState *xics, int server, uint8_t cppr) 252b5cec4c5SDavid Gibson { 25327f24582SBenjamin Herrenschmidt ICPState *ss = xics->ss + server; 254b5cec4c5SDavid Gibson uint8_t old_cppr; 255b5cec4c5SDavid Gibson uint32_t old_xisr; 256b5cec4c5SDavid Gibson 257b5cec4c5SDavid Gibson old_cppr = CPPR(ss); 258b5cec4c5SDavid Gibson ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24); 259b5cec4c5SDavid Gibson 260b5cec4c5SDavid Gibson if (cppr < old_cppr) { 261b5cec4c5SDavid Gibson if (XISR(ss) && (cppr <= ss->pending_priority)) { 262b5cec4c5SDavid Gibson old_xisr = XISR(ss); 263b5cec4c5SDavid Gibson ss->xirr &= ~XISR_MASK; /* Clear XISR */ 264e03c902cSDavid Gibson ss->pending_priority = 0xff; 265b5cec4c5SDavid Gibson qemu_irq_lower(ss->output); 266*cc706a53SBenjamin Herrenschmidt if (ss->xirr_owner) { 267*cc706a53SBenjamin Herrenschmidt ics_reject(ss->xirr_owner, old_xisr); 268*cc706a53SBenjamin Herrenschmidt ss->xirr_owner = NULL; 269*cc706a53SBenjamin Herrenschmidt } 270b5cec4c5SDavid Gibson } 271b5cec4c5SDavid Gibson } else { 272b5cec4c5SDavid Gibson if (!XISR(ss)) { 27327f24582SBenjamin Herrenschmidt icp_resend(xics, server); 274b5cec4c5SDavid Gibson } 275b5cec4c5SDavid Gibson } 276b5cec4c5SDavid Gibson } 277b5cec4c5SDavid Gibson 27827f24582SBenjamin Herrenschmidt void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr) 279b5cec4c5SDavid Gibson { 28027f24582SBenjamin Herrenschmidt ICPState *ss = xics->ss + server; 281b5cec4c5SDavid Gibson 282b5cec4c5SDavid Gibson ss->mfrr = mfrr; 283b5cec4c5SDavid Gibson if (mfrr < CPPR(ss)) { 284*cc706a53SBenjamin Herrenschmidt icp_check_ipi(ss); 285b5cec4c5SDavid Gibson } 286b5cec4c5SDavid Gibson } 287b5cec4c5SDavid Gibson 2889c7027baSBenjamin Herrenschmidt uint32_t icp_accept(ICPState *ss) 289b5cec4c5SDavid Gibson { 290500efa23SDavid Gibson uint32_t xirr = ss->xirr; 291b5cec4c5SDavid Gibson 292b5cec4c5SDavid Gibson qemu_irq_lower(ss->output); 293b5cec4c5SDavid Gibson ss->xirr = ss->pending_priority << 24; 294e03c902cSDavid Gibson ss->pending_priority = 0xff; 295*cc706a53SBenjamin Herrenschmidt ss->xirr_owner = NULL; 296500efa23SDavid Gibson 297500efa23SDavid Gibson trace_xics_icp_accept(xirr, ss->xirr); 298500efa23SDavid Gibson 299b5cec4c5SDavid Gibson return xirr; 300b5cec4c5SDavid Gibson } 301b5cec4c5SDavid Gibson 3021cbd2220SBenjamin Herrenschmidt uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr) 3031cbd2220SBenjamin Herrenschmidt { 3041cbd2220SBenjamin Herrenschmidt if (mfrr) { 3051cbd2220SBenjamin Herrenschmidt *mfrr = ss->mfrr; 3061cbd2220SBenjamin Herrenschmidt } 3071cbd2220SBenjamin Herrenschmidt return ss->xirr; 3081cbd2220SBenjamin Herrenschmidt } 3091cbd2220SBenjamin Herrenschmidt 31027f24582SBenjamin Herrenschmidt void icp_eoi(XICSState *xics, int server, uint32_t xirr) 311b5cec4c5SDavid Gibson { 31227f24582SBenjamin Herrenschmidt ICPState *ss = xics->ss + server; 313*cc706a53SBenjamin Herrenschmidt ICSState *ics; 314*cc706a53SBenjamin Herrenschmidt uint32_t irq; 315b5cec4c5SDavid Gibson 316b5cec4c5SDavid Gibson /* Send EOI -> ICS */ 317b5cec4c5SDavid Gibson ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK); 318500efa23SDavid Gibson trace_xics_icp_eoi(server, xirr, ss->xirr); 319*cc706a53SBenjamin Herrenschmidt irq = xirr & XISR_MASK; 320*cc706a53SBenjamin Herrenschmidt QLIST_FOREACH(ics, &xics->ics, list) { 321*cc706a53SBenjamin Herrenschmidt if (ics_valid_irq(ics, irq)) { 322*cc706a53SBenjamin Herrenschmidt ics_eoi(ics, irq); 323*cc706a53SBenjamin Herrenschmidt } 324*cc706a53SBenjamin Herrenschmidt } 325b5cec4c5SDavid Gibson if (!XISR(ss)) { 32627f24582SBenjamin Herrenschmidt icp_resend(xics, server); 327b5cec4c5SDavid Gibson } 328b5cec4c5SDavid Gibson } 329b5cec4c5SDavid Gibson 330*cc706a53SBenjamin Herrenschmidt static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority) 331b5cec4c5SDavid Gibson { 332*cc706a53SBenjamin Herrenschmidt XICSState *xics = ics->xics; 33327f24582SBenjamin Herrenschmidt ICPState *ss = xics->ss + server; 334b5cec4c5SDavid Gibson 335500efa23SDavid Gibson trace_xics_icp_irq(server, nr, priority); 336500efa23SDavid Gibson 337b5cec4c5SDavid Gibson if ((priority >= CPPR(ss)) 338b5cec4c5SDavid Gibson || (XISR(ss) && (ss->pending_priority <= priority))) { 339*cc706a53SBenjamin Herrenschmidt ics_reject(ics, nr); 340b5cec4c5SDavid Gibson } else { 341*cc706a53SBenjamin Herrenschmidt if (XISR(ss) && ss->xirr_owner) { 342*cc706a53SBenjamin Herrenschmidt ics_reject(ss->xirr_owner, XISR(ss)); 343*cc706a53SBenjamin Herrenschmidt ss->xirr_owner = NULL; 344b5cec4c5SDavid Gibson } 345b5cec4c5SDavid Gibson ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK); 346*cc706a53SBenjamin Herrenschmidt ss->xirr_owner = ics; 347b5cec4c5SDavid Gibson ss->pending_priority = priority; 348500efa23SDavid Gibson trace_xics_icp_raise(ss->xirr, ss->pending_priority); 349b5cec4c5SDavid Gibson qemu_irq_raise(ss->output); 350b5cec4c5SDavid Gibson } 351b5cec4c5SDavid Gibson } 352b5cec4c5SDavid Gibson 353d1b5682dSAlexey Kardashevskiy static void icp_dispatch_pre_save(void *opaque) 354d1b5682dSAlexey Kardashevskiy { 355d1b5682dSAlexey Kardashevskiy ICPState *ss = opaque; 356d1b5682dSAlexey Kardashevskiy ICPStateClass *info = ICP_GET_CLASS(ss); 357d1b5682dSAlexey Kardashevskiy 358d1b5682dSAlexey Kardashevskiy if (info->pre_save) { 359d1b5682dSAlexey Kardashevskiy info->pre_save(ss); 360d1b5682dSAlexey Kardashevskiy } 361d1b5682dSAlexey Kardashevskiy } 362d1b5682dSAlexey Kardashevskiy 363d1b5682dSAlexey Kardashevskiy static int icp_dispatch_post_load(void *opaque, int version_id) 364d1b5682dSAlexey Kardashevskiy { 365d1b5682dSAlexey Kardashevskiy ICPState *ss = opaque; 366d1b5682dSAlexey Kardashevskiy ICPStateClass *info = ICP_GET_CLASS(ss); 367d1b5682dSAlexey Kardashevskiy 368d1b5682dSAlexey Kardashevskiy if (info->post_load) { 369d1b5682dSAlexey Kardashevskiy return info->post_load(ss, version_id); 370d1b5682dSAlexey Kardashevskiy } 371d1b5682dSAlexey Kardashevskiy 372d1b5682dSAlexey Kardashevskiy return 0; 373d1b5682dSAlexey Kardashevskiy } 374d1b5682dSAlexey Kardashevskiy 375c04d6cfaSAnthony Liguori static const VMStateDescription vmstate_icp_server = { 376c04d6cfaSAnthony Liguori .name = "icp/server", 377c04d6cfaSAnthony Liguori .version_id = 1, 378c04d6cfaSAnthony Liguori .minimum_version_id = 1, 379d1b5682dSAlexey Kardashevskiy .pre_save = icp_dispatch_pre_save, 380d1b5682dSAlexey Kardashevskiy .post_load = icp_dispatch_post_load, 381c04d6cfaSAnthony Liguori .fields = (VMStateField[]) { 382c04d6cfaSAnthony Liguori /* Sanity check */ 383c04d6cfaSAnthony Liguori VMSTATE_UINT32(xirr, ICPState), 384c04d6cfaSAnthony Liguori VMSTATE_UINT8(pending_priority, ICPState), 385c04d6cfaSAnthony Liguori VMSTATE_UINT8(mfrr, ICPState), 386c04d6cfaSAnthony Liguori VMSTATE_END_OF_LIST() 387c04d6cfaSAnthony Liguori }, 388c04d6cfaSAnthony Liguori }; 389c04d6cfaSAnthony Liguori 390c04d6cfaSAnthony Liguori static void icp_reset(DeviceState *dev) 391c04d6cfaSAnthony Liguori { 392c04d6cfaSAnthony Liguori ICPState *icp = ICP(dev); 393c04d6cfaSAnthony Liguori 394c04d6cfaSAnthony Liguori icp->xirr = 0; 395c04d6cfaSAnthony Liguori icp->pending_priority = 0xff; 396c04d6cfaSAnthony Liguori icp->mfrr = 0xff; 397c04d6cfaSAnthony Liguori 398c04d6cfaSAnthony Liguori /* Make all outputs are deasserted */ 399c04d6cfaSAnthony Liguori qemu_set_irq(icp->output, 0); 400c04d6cfaSAnthony Liguori } 401c04d6cfaSAnthony Liguori 402c04d6cfaSAnthony Liguori static void icp_class_init(ObjectClass *klass, void *data) 403c04d6cfaSAnthony Liguori { 404c04d6cfaSAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 405c04d6cfaSAnthony Liguori 406c04d6cfaSAnthony Liguori dc->reset = icp_reset; 407c04d6cfaSAnthony Liguori dc->vmsd = &vmstate_icp_server; 408c04d6cfaSAnthony Liguori } 409c04d6cfaSAnthony Liguori 410456df19cSAlexey Kardashevskiy static const TypeInfo icp_info = { 411c04d6cfaSAnthony Liguori .name = TYPE_ICP, 412c04d6cfaSAnthony Liguori .parent = TYPE_DEVICE, 413c04d6cfaSAnthony Liguori .instance_size = sizeof(ICPState), 414c04d6cfaSAnthony Liguori .class_init = icp_class_init, 415d1b5682dSAlexey Kardashevskiy .class_size = sizeof(ICPStateClass), 416c04d6cfaSAnthony Liguori }; 417c04d6cfaSAnthony Liguori 418b5cec4c5SDavid Gibson /* 419b5cec4c5SDavid Gibson * ICS: Source layer 420b5cec4c5SDavid Gibson */ 421c04d6cfaSAnthony Liguori static void resend_msi(ICSState *ics, int srcno) 422b5cec4c5SDavid Gibson { 423c04d6cfaSAnthony Liguori ICSIRQState *irq = ics->irqs + srcno; 424d07fee7eSDavid Gibson 425d07fee7eSDavid Gibson /* FIXME: filter by server#? */ 42698ca8c02SDavid Gibson if (irq->status & XICS_STATUS_REJECTED) { 42798ca8c02SDavid Gibson irq->status &= ~XICS_STATUS_REJECTED; 428d07fee7eSDavid Gibson if (irq->priority != 0xff) { 429*cc706a53SBenjamin Herrenschmidt icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 430d07fee7eSDavid Gibson } 431d07fee7eSDavid Gibson } 432d07fee7eSDavid Gibson } 433d07fee7eSDavid Gibson 434c04d6cfaSAnthony Liguori static void resend_lsi(ICSState *ics, int srcno) 435d07fee7eSDavid Gibson { 436c04d6cfaSAnthony Liguori ICSIRQState *irq = ics->irqs + srcno; 437d07fee7eSDavid Gibson 43898ca8c02SDavid Gibson if ((irq->priority != 0xff) 43998ca8c02SDavid Gibson && (irq->status & XICS_STATUS_ASSERTED) 44098ca8c02SDavid Gibson && !(irq->status & XICS_STATUS_SENT)) { 44198ca8c02SDavid Gibson irq->status |= XICS_STATUS_SENT; 442*cc706a53SBenjamin Herrenschmidt icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 443d07fee7eSDavid Gibson } 444d07fee7eSDavid Gibson } 445d07fee7eSDavid Gibson 446c04d6cfaSAnthony Liguori static void set_irq_msi(ICSState *ics, int srcno, int val) 447d07fee7eSDavid Gibson { 448c04d6cfaSAnthony Liguori ICSIRQState *irq = ics->irqs + srcno; 449b5cec4c5SDavid Gibson 450500efa23SDavid Gibson trace_xics_set_irq_msi(srcno, srcno + ics->offset); 451500efa23SDavid Gibson 452b5cec4c5SDavid Gibson if (val) { 453b5cec4c5SDavid Gibson if (irq->priority == 0xff) { 45498ca8c02SDavid Gibson irq->status |= XICS_STATUS_MASKED_PENDING; 455500efa23SDavid Gibson trace_xics_masked_pending(); 456b5cec4c5SDavid Gibson } else { 457*cc706a53SBenjamin Herrenschmidt icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 458b5cec4c5SDavid Gibson } 459b5cec4c5SDavid Gibson } 460b5cec4c5SDavid Gibson } 461b5cec4c5SDavid Gibson 462c04d6cfaSAnthony Liguori static void set_irq_lsi(ICSState *ics, int srcno, int val) 463d07fee7eSDavid Gibson { 464c04d6cfaSAnthony Liguori ICSIRQState *irq = ics->irqs + srcno; 465d07fee7eSDavid Gibson 466500efa23SDavid Gibson trace_xics_set_irq_lsi(srcno, srcno + ics->offset); 46798ca8c02SDavid Gibson if (val) { 46898ca8c02SDavid Gibson irq->status |= XICS_STATUS_ASSERTED; 46998ca8c02SDavid Gibson } else { 47098ca8c02SDavid Gibson irq->status &= ~XICS_STATUS_ASSERTED; 47198ca8c02SDavid Gibson } 472d07fee7eSDavid Gibson resend_lsi(ics, srcno); 473d07fee7eSDavid Gibson } 474d07fee7eSDavid Gibson 475d07fee7eSDavid Gibson static void ics_set_irq(void *opaque, int srcno, int val) 476d07fee7eSDavid Gibson { 477c04d6cfaSAnthony Liguori ICSState *ics = (ICSState *)opaque; 478d07fee7eSDavid Gibson 4794af88944SAlexey Kardashevskiy if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 480d07fee7eSDavid Gibson set_irq_lsi(ics, srcno, val); 481d07fee7eSDavid Gibson } else { 482d07fee7eSDavid Gibson set_irq_msi(ics, srcno, val); 483d07fee7eSDavid Gibson } 484d07fee7eSDavid Gibson } 485d07fee7eSDavid Gibson 486c04d6cfaSAnthony Liguori static void write_xive_msi(ICSState *ics, int srcno) 487d07fee7eSDavid Gibson { 488c04d6cfaSAnthony Liguori ICSIRQState *irq = ics->irqs + srcno; 489d07fee7eSDavid Gibson 49098ca8c02SDavid Gibson if (!(irq->status & XICS_STATUS_MASKED_PENDING) 49198ca8c02SDavid Gibson || (irq->priority == 0xff)) { 492d07fee7eSDavid Gibson return; 493d07fee7eSDavid Gibson } 494d07fee7eSDavid Gibson 49598ca8c02SDavid Gibson irq->status &= ~XICS_STATUS_MASKED_PENDING; 496*cc706a53SBenjamin Herrenschmidt icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 497d07fee7eSDavid Gibson } 498d07fee7eSDavid Gibson 499c04d6cfaSAnthony Liguori static void write_xive_lsi(ICSState *ics, int srcno) 500d07fee7eSDavid Gibson { 501d07fee7eSDavid Gibson resend_lsi(ics, srcno); 502d07fee7eSDavid Gibson } 503d07fee7eSDavid Gibson 5049c7027baSBenjamin Herrenschmidt void ics_write_xive(ICSState *ics, int nr, int server, 5053fe719f4SDavid Gibson uint8_t priority, uint8_t saved_priority) 506d07fee7eSDavid Gibson { 507d07fee7eSDavid Gibson int srcno = nr - ics->offset; 508c04d6cfaSAnthony Liguori ICSIRQState *irq = ics->irqs + srcno; 509d07fee7eSDavid Gibson 510d07fee7eSDavid Gibson irq->server = server; 511d07fee7eSDavid Gibson irq->priority = priority; 5123fe719f4SDavid Gibson irq->saved_priority = saved_priority; 513d07fee7eSDavid Gibson 514500efa23SDavid Gibson trace_xics_ics_write_xive(nr, srcno, server, priority); 515500efa23SDavid Gibson 5164af88944SAlexey Kardashevskiy if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 517d07fee7eSDavid Gibson write_xive_lsi(ics, srcno); 518d07fee7eSDavid Gibson } else { 519d07fee7eSDavid Gibson write_xive_msi(ics, srcno); 520d07fee7eSDavid Gibson } 521d07fee7eSDavid Gibson } 522d07fee7eSDavid Gibson 523c04d6cfaSAnthony Liguori static void ics_reject(ICSState *ics, int nr) 524b5cec4c5SDavid Gibson { 525c04d6cfaSAnthony Liguori ICSIRQState *irq = ics->irqs + nr - ics->offset; 526b5cec4c5SDavid Gibson 527500efa23SDavid Gibson trace_xics_ics_reject(nr, nr - ics->offset); 528056b9775SNikunj A Dadhania if (irq->flags & XICS_FLAGS_IRQ_MSI) { 529056b9775SNikunj A Dadhania irq->status |= XICS_STATUS_REJECTED; 530056b9775SNikunj A Dadhania } else if (irq->flags & XICS_FLAGS_IRQ_LSI) { 531056b9775SNikunj A Dadhania irq->status &= ~XICS_STATUS_SENT; 532056b9775SNikunj A Dadhania } 533b5cec4c5SDavid Gibson } 534b5cec4c5SDavid Gibson 535c04d6cfaSAnthony Liguori static void ics_resend(ICSState *ics) 536b5cec4c5SDavid Gibson { 537b5cec4c5SDavid Gibson int i; 538b5cec4c5SDavid Gibson 539b5cec4c5SDavid Gibson for (i = 0; i < ics->nr_irqs; i++) { 540b5cec4c5SDavid Gibson /* FIXME: filter by server#? */ 5414af88944SAlexey Kardashevskiy if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) { 542d07fee7eSDavid Gibson resend_lsi(ics, i); 543d07fee7eSDavid Gibson } else { 544d07fee7eSDavid Gibson resend_msi(ics, i); 545b5cec4c5SDavid Gibson } 546b5cec4c5SDavid Gibson } 547b5cec4c5SDavid Gibson } 548b5cec4c5SDavid Gibson 549c04d6cfaSAnthony Liguori static void ics_eoi(ICSState *ics, int nr) 550b5cec4c5SDavid Gibson { 551d07fee7eSDavid Gibson int srcno = nr - ics->offset; 552c04d6cfaSAnthony Liguori ICSIRQState *irq = ics->irqs + srcno; 553d07fee7eSDavid Gibson 554500efa23SDavid Gibson trace_xics_ics_eoi(nr); 555500efa23SDavid Gibson 5564af88944SAlexey Kardashevskiy if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 55798ca8c02SDavid Gibson irq->status &= ~XICS_STATUS_SENT; 558d07fee7eSDavid Gibson } 559b5cec4c5SDavid Gibson } 560b5cec4c5SDavid Gibson 561c04d6cfaSAnthony Liguori static void ics_reset(DeviceState *dev) 562c04d6cfaSAnthony Liguori { 563c04d6cfaSAnthony Liguori ICSState *ics = ICS(dev); 564c04d6cfaSAnthony Liguori int i; 565a7e519a8SAlexey Kardashevskiy uint8_t flags[ics->nr_irqs]; 566a7e519a8SAlexey Kardashevskiy 567a7e519a8SAlexey Kardashevskiy for (i = 0; i < ics->nr_irqs; i++) { 568a7e519a8SAlexey Kardashevskiy flags[i] = ics->irqs[i].flags; 569a7e519a8SAlexey Kardashevskiy } 570c04d6cfaSAnthony Liguori 571c04d6cfaSAnthony Liguori memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs); 572a7e519a8SAlexey Kardashevskiy 573c04d6cfaSAnthony Liguori for (i = 0; i < ics->nr_irqs; i++) { 574c04d6cfaSAnthony Liguori ics->irqs[i].priority = 0xff; 575c04d6cfaSAnthony Liguori ics->irqs[i].saved_priority = 0xff; 576a7e519a8SAlexey Kardashevskiy ics->irqs[i].flags = flags[i]; 577c04d6cfaSAnthony Liguori } 578c04d6cfaSAnthony Liguori } 579c04d6cfaSAnthony Liguori 580d1b5682dSAlexey Kardashevskiy static int ics_post_load(ICSState *ics, int version_id) 581c04d6cfaSAnthony Liguori { 582c04d6cfaSAnthony Liguori int i; 583c04d6cfaSAnthony Liguori 58427f24582SBenjamin Herrenschmidt for (i = 0; i < ics->xics->nr_servers; i++) { 58527f24582SBenjamin Herrenschmidt icp_resend(ics->xics, i); 586c04d6cfaSAnthony Liguori } 587c04d6cfaSAnthony Liguori 588c04d6cfaSAnthony Liguori return 0; 589c04d6cfaSAnthony Liguori } 590c04d6cfaSAnthony Liguori 591d1b5682dSAlexey Kardashevskiy static void ics_dispatch_pre_save(void *opaque) 592d1b5682dSAlexey Kardashevskiy { 593d1b5682dSAlexey Kardashevskiy ICSState *ics = opaque; 594d1b5682dSAlexey Kardashevskiy ICSStateClass *info = ICS_GET_CLASS(ics); 595d1b5682dSAlexey Kardashevskiy 596d1b5682dSAlexey Kardashevskiy if (info->pre_save) { 597d1b5682dSAlexey Kardashevskiy info->pre_save(ics); 598d1b5682dSAlexey Kardashevskiy } 599d1b5682dSAlexey Kardashevskiy } 600d1b5682dSAlexey Kardashevskiy 601d1b5682dSAlexey Kardashevskiy static int ics_dispatch_post_load(void *opaque, int version_id) 602d1b5682dSAlexey Kardashevskiy { 603d1b5682dSAlexey Kardashevskiy ICSState *ics = opaque; 604d1b5682dSAlexey Kardashevskiy ICSStateClass *info = ICS_GET_CLASS(ics); 605d1b5682dSAlexey Kardashevskiy 606d1b5682dSAlexey Kardashevskiy if (info->post_load) { 607d1b5682dSAlexey Kardashevskiy return info->post_load(ics, version_id); 608d1b5682dSAlexey Kardashevskiy } 609d1b5682dSAlexey Kardashevskiy 610d1b5682dSAlexey Kardashevskiy return 0; 611d1b5682dSAlexey Kardashevskiy } 612d1b5682dSAlexey Kardashevskiy 613c04d6cfaSAnthony Liguori static const VMStateDescription vmstate_ics_irq = { 614c04d6cfaSAnthony Liguori .name = "ics/irq", 6154af88944SAlexey Kardashevskiy .version_id = 2, 616c04d6cfaSAnthony Liguori .minimum_version_id = 1, 617c04d6cfaSAnthony Liguori .fields = (VMStateField[]) { 618c04d6cfaSAnthony Liguori VMSTATE_UINT32(server, ICSIRQState), 619c04d6cfaSAnthony Liguori VMSTATE_UINT8(priority, ICSIRQState), 620c04d6cfaSAnthony Liguori VMSTATE_UINT8(saved_priority, ICSIRQState), 621c04d6cfaSAnthony Liguori VMSTATE_UINT8(status, ICSIRQState), 6224af88944SAlexey Kardashevskiy VMSTATE_UINT8(flags, ICSIRQState), 623c04d6cfaSAnthony Liguori VMSTATE_END_OF_LIST() 624c04d6cfaSAnthony Liguori }, 625c04d6cfaSAnthony Liguori }; 626c04d6cfaSAnthony Liguori 627c04d6cfaSAnthony Liguori static const VMStateDescription vmstate_ics = { 628c04d6cfaSAnthony Liguori .name = "ics", 629c04d6cfaSAnthony Liguori .version_id = 1, 630c04d6cfaSAnthony Liguori .minimum_version_id = 1, 631d1b5682dSAlexey Kardashevskiy .pre_save = ics_dispatch_pre_save, 632d1b5682dSAlexey Kardashevskiy .post_load = ics_dispatch_post_load, 633c04d6cfaSAnthony Liguori .fields = (VMStateField[]) { 634c04d6cfaSAnthony Liguori /* Sanity check */ 635c04d6cfaSAnthony Liguori VMSTATE_UINT32_EQUAL(nr_irqs, ICSState), 636c04d6cfaSAnthony Liguori 637c04d6cfaSAnthony Liguori VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs, 638c04d6cfaSAnthony Liguori vmstate_ics_irq, ICSIRQState), 639c04d6cfaSAnthony Liguori VMSTATE_END_OF_LIST() 640c04d6cfaSAnthony Liguori }, 641c04d6cfaSAnthony Liguori }; 642c04d6cfaSAnthony Liguori 6435a3d7b23SAlexey Kardashevskiy static void ics_initfn(Object *obj) 6445a3d7b23SAlexey Kardashevskiy { 6455a3d7b23SAlexey Kardashevskiy ICSState *ics = ICS(obj); 6465a3d7b23SAlexey Kardashevskiy 6475a3d7b23SAlexey Kardashevskiy ics->offset = XICS_IRQ_BASE; 6485a3d7b23SAlexey Kardashevskiy } 6495a3d7b23SAlexey Kardashevskiy 650b45ff2d9SAlexey Kardashevskiy static void ics_realize(DeviceState *dev, Error **errp) 651c04d6cfaSAnthony Liguori { 652c04d6cfaSAnthony Liguori ICSState *ics = ICS(dev); 653c04d6cfaSAnthony Liguori 654b45ff2d9SAlexey Kardashevskiy if (!ics->nr_irqs) { 655b45ff2d9SAlexey Kardashevskiy error_setg(errp, "Number of interrupts needs to be greater 0"); 656b45ff2d9SAlexey Kardashevskiy return; 657b45ff2d9SAlexey Kardashevskiy } 658c04d6cfaSAnthony Liguori ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState)); 659c04d6cfaSAnthony Liguori ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs); 660c04d6cfaSAnthony Liguori } 661c04d6cfaSAnthony Liguori 662c04d6cfaSAnthony Liguori static void ics_class_init(ObjectClass *klass, void *data) 663c04d6cfaSAnthony Liguori { 664c04d6cfaSAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 665d1b5682dSAlexey Kardashevskiy ICSStateClass *isc = ICS_CLASS(klass); 666c04d6cfaSAnthony Liguori 667b45ff2d9SAlexey Kardashevskiy dc->realize = ics_realize; 668c04d6cfaSAnthony Liguori dc->vmsd = &vmstate_ics; 669c04d6cfaSAnthony Liguori dc->reset = ics_reset; 670d1b5682dSAlexey Kardashevskiy isc->post_load = ics_post_load; 671c04d6cfaSAnthony Liguori } 672c04d6cfaSAnthony Liguori 673456df19cSAlexey Kardashevskiy static const TypeInfo ics_info = { 674c04d6cfaSAnthony Liguori .name = TYPE_ICS, 675c04d6cfaSAnthony Liguori .parent = TYPE_DEVICE, 676c04d6cfaSAnthony Liguori .instance_size = sizeof(ICSState), 677c04d6cfaSAnthony Liguori .class_init = ics_class_init, 678d1b5682dSAlexey Kardashevskiy .class_size = sizeof(ICSStateClass), 6795a3d7b23SAlexey Kardashevskiy .instance_init = ics_initfn, 680c04d6cfaSAnthony Liguori }; 681c04d6cfaSAnthony Liguori 682b5cec4c5SDavid Gibson /* 683b5cec4c5SDavid Gibson * Exported functions 684b5cec4c5SDavid Gibson */ 685*cc706a53SBenjamin Herrenschmidt ICSState *xics_find_source(XICSState *xics, int irq) 686641c3493SAlexey Kardashevskiy { 687*cc706a53SBenjamin Herrenschmidt ICSState *ics; 688641c3493SAlexey Kardashevskiy 689*cc706a53SBenjamin Herrenschmidt QLIST_FOREACH(ics, &xics->ics, list) { 690641c3493SAlexey Kardashevskiy if (ics_valid_irq(ics, irq)) { 691*cc706a53SBenjamin Herrenschmidt return ics; 692641c3493SAlexey Kardashevskiy } 693641c3493SAlexey Kardashevskiy } 694*cc706a53SBenjamin Herrenschmidt return NULL; 695641c3493SAlexey Kardashevskiy } 696b5cec4c5SDavid Gibson 69727f24582SBenjamin Herrenschmidt qemu_irq xics_get_qirq(XICSState *xics, int irq) 698b5cec4c5SDavid Gibson { 699*cc706a53SBenjamin Herrenschmidt ICSState *ics = xics_find_source(xics, irq); 700641c3493SAlexey Kardashevskiy 701*cc706a53SBenjamin Herrenschmidt if (ics) { 702641c3493SAlexey Kardashevskiy return ics->qirqs[irq - ics->offset]; 703b5cec4c5SDavid Gibson } 704b5cec4c5SDavid Gibson 705641c3493SAlexey Kardashevskiy return NULL; 706a307d594SAlexey Kardashevskiy } 707a307d594SAlexey Kardashevskiy 7089c7027baSBenjamin Herrenschmidt void ics_set_irq_type(ICSState *ics, int srcno, bool lsi) 7094af88944SAlexey Kardashevskiy { 7104af88944SAlexey Kardashevskiy assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK)); 7114af88944SAlexey Kardashevskiy 7124af88944SAlexey Kardashevskiy ics->irqs[srcno].flags |= 7134af88944SAlexey Kardashevskiy lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI; 7144af88944SAlexey Kardashevskiy } 7154af88944SAlexey Kardashevskiy 716c04d6cfaSAnthony Liguori static void xics_register_types(void) 717c04d6cfaSAnthony Liguori { 7185a3d7b23SAlexey Kardashevskiy type_register_static(&xics_common_info); 719c04d6cfaSAnthony Liguori type_register_static(&ics_info); 720c04d6cfaSAnthony Liguori type_register_static(&icp_info); 721c04d6cfaSAnthony Liguori } 722c04d6cfaSAnthony Liguori 723c04d6cfaSAnthony Liguori type_init(xics_register_types) 724