static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { ICSState *ics = spapr->ics; uint32_t nr, srcno, server, priority; if ((nargs != 3) || (nret != 1)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } if (!ics) { rtas_st(rets, 0, RTAS_OUT_HW_ERROR); return; } nr = rtas_ld(args, 0); server = rtas_ld(args, 1); priority = rtas_ld(args, 2); if (!ics_valid_irq(ics, nr) || !xics_icp_get(XICS_FABRIC(spapr), server) || (priority > 0xff)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } srcno = nr - ics->offset; ics_simple_write_xive(ics, srcno, server, priority, priority); rtas_st(rets, 0, RTAS_OUT_SUCCESS); }
void xics_cpu_setup(XICSFabric *xi, PowerPCCPU *cpu) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; ICPState *icp = xics_icp_get(xi, cs->cpu_index); ICPStateClass *icpc; assert(icp); icp->cs = cs; icpc = ICP_GET_CLASS(icp); if (icpc->cpu_setup) { icpc->cpu_setup(icp, cpu); } switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_POWER7: icp->output = env->irq_inputs[POWER7_INPUT_INT]; break; case PPC_FLAGS_INPUT_970: icp->output = env->irq_inputs[PPC970_INPUT_INT]; break; default: error_report("XICS interrupt controller does not support this CPU " "bus model"); abort(); } }
void xics_cpu_destroy(XICSFabric *xi, PowerPCCPU *cpu) { CPUState *cs = CPU(cpu); ICPState *icp = xics_icp_get(xi, cs->cpu_index); assert(icp); assert(cs == icp->cs); icp->output = NULL; icp->cs = NULL; }
static target_ulong h_ipi(PowerPCCPU *cpu, sPAPRMachineState *spapr, target_ulong opcode, target_ulong *args) { target_ulong mfrr = args[1]; ICPState *icp = xics_icp_get(XICS_FABRIC(spapr), args[0]); if (!icp) { return H_PARAMETER; } icp_set_mfrr(icp, mfrr); return H_SUCCESS; }
static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority) { ICPState *icp = xics_icp_get(ics->xics, server); trace_xics_icp_irq(server, nr, priority); if ((priority >= CPPR(icp)) || (XISR(icp) && (icp->pending_priority <= priority))) { ics_reject(ics, nr); } else { if (XISR(icp) && icp->xirr_owner) { ics_reject(icp->xirr_owner, XISR(icp)); icp->xirr_owner = NULL; } icp->xirr = (icp->xirr & ~XISR_MASK) | (nr & XISR_MASK); icp->xirr_owner = ics; icp->pending_priority = priority; trace_xics_icp_raise(icp->xirr, icp->pending_priority); qemu_irq_raise(icp->output); } }