On Sat, Dec 02, 2017 at 08:40:58AM -0600, Benjamin Herrenschmidt wrote: > On Thu, 2017-11-30 at 16:00 +1100, David Gibson wrote: > > > > > static uint64_t spapr_xive_icp_accept(sPAPRXiveICP *icp) > > > { > > > - return 0; > > > + uint8_t nsr = icp->tima_os[TM_NSR]; > > > + > > > + qemu_irq_lower(icp->output); > > > + > > > + if (icp->tima_os[TM_NSR] & TM_QW1_NSR_EO) { > > > + uint8_t cppr = icp->tima_os[TM_PIPR]; > > > + > > > + icp->tima_os[TM_CPPR] = cppr; > > > + > > > + /* Reset the pending buffer bit */ > > > + icp->tima_os[TM_IPB] &= ~priority_to_ipb(cppr); > > > > What if multiple irqs of the same priority were queued? > > It's the job of the OS to handle that case by consuming from the queue > until it's empty. There is an MMIO the guest can use if it wants to > that can set the IPB bits back to 1 for a given priority. Otherwise in > Linux we just have a SW way to force a replay.
Ok, so "accept" is effectively saying the OS is accepting all interrupts from that queue, right? > > > > + icp->tima_os[TM_PIPR] = ipb_to_pipr(icp->tima_os[TM_IPB]); > > > + > > > + /* Drop Exception bit for OS */ > > > + icp->tima_os[TM_NSR] &= ~TM_QW1_NSR_EO; > > > + } > > > + > > > + return (nsr << 8) | icp->tima_os[TM_CPPR]; > > > +} > > > + > > > +static void spapr_xive_icp_notify(sPAPRXiveICP *icp) > > > +{ > > > + if (icp->tima_os[TM_PIPR] < icp->tima_os[TM_CPPR]) { > > > + icp->tima_os[TM_NSR] |= TM_QW1_NSR_EO; > > > + qemu_irq_raise(icp->output); > > > + } > > > } > > > > > > static void spapr_xive_icp_set_cppr(sPAPRXiveICP *icp, uint8_t cppr) > > > @@ -51,6 +105,9 @@ static void spapr_xive_icp_set_cppr(sPAPRXiveICP *icp, > > > uint8_t cppr) > > > } > > > > > > icp->tima_os[TM_CPPR] = cppr; > > > + > > > + /* CPPR has changed, inform the ICP which might raise an exception */ > > > + spapr_xive_icp_notify(icp); > > > } > > > > > > /* > > > @@ -224,6 +281,8 @@ static void spapr_xive_irq(sPAPRXive *xive, int lisn) > > > XiveEQ *eq; > > > uint32_t eq_idx; > > > uint8_t priority; > > > + uint32_t server; > > > + sPAPRXiveICP *icp; > > > > > > ive = spapr_xive_get_ive(xive, lisn); > > > if (!ive || !(ive->w & IVE_VALID)) { > > > @@ -253,6 +312,13 @@ static void spapr_xive_irq(sPAPRXive *xive, int lisn) > > > qemu_log_mask(LOG_UNIMP, "XIVE: !UCOND_NOTIFY not > > > implemented\n"); > > > } > > > > > > + server = GETFIELD(EQ_W6_NVT_INDEX, eq->w6); > > > + icp = spapr_xive_icp_get(xive, server); > > > + if (!icp) { > > > + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No ICP for server %d\n", > > > server); > > > + return; > > > + } > > > + > > > if (GETFIELD(EQ_W6_FORMAT_BIT, eq->w6) == 0) { > > > priority = GETFIELD(EQ_W7_F0_PRIORITY, eq->w7); > > > > > > @@ -260,9 +326,18 @@ static void spapr_xive_irq(sPAPRXive *xive, int lisn) > > > if (priority == 0xff) { > > > g_assert_not_reached(); > > > } > > > + > > > + /* Update the IPB (Interrupt Pending Buffer) with the priority > > > + * of the new notification and inform the ICP, which will > > > + * decide to raise the exception, or not, depending the CPPR. > > > + */ > > > + icp->tima_os[TM_IPB] |= priority_to_ipb(priority); > > > + icp->tima_os[TM_PIPR] = ipb_to_pipr(icp->tima_os[TM_IPB]); > > > } else { > > > qemu_log_mask(LOG_UNIMP, "XIVE: w7 format1 not implemented\n"); > > > } > > > + > > > + spapr_xive_icp_notify(icp); > > > } > > > > > > /* > > > > > -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
signature.asc
Description: PGP signature