[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCH 15/25] spapr: notify the CPU when the XIVE interru
From: |
Benjamin Herrenschmidt |
Subject: |
Re: [Qemu-ppc] [PATCH 15/25] spapr: notify the CPU when the XIVE interrupt priority is more privileged |
Date: |
Mon, 04 Dec 2017 10:09:20 -0600 |
On Mon, 2017-12-04 at 12:17 +1100, David Gibson wrote:
> 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?
It's whatever you want it to mean. It's simply a test & clear on the
prio bit. From a HW standpoint, you could have multiple queues or just
set an internal SW flag to go chck again later etc...
>
> >
> > > > + 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);
> > > > }
> > > >
> > > > /*
> > >
> > >
>
>