diff mbox

[RFC,16/26] ppc/xive: notify CPU when interrupt priority is more privileged

Message ID 1499274819-15607-17-git-send-email-clg@kaod.org
State New
Headers show

Commit Message

Cédric Le Goater July 5, 2017, 5:13 p.m. UTC
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/intc/xive.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Comments

Benjamin Herrenschmidt Sept. 9, 2017, 7:39 a.m. UTC | #1
On Wed, 2017-07-05 at 19:13 +0200, Cédric Le Goater wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/intc/xive.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/hw/intc/xive.c b/hw/intc/xive.c
> index c3c1e9c9db2d..cda1fa18e44d 100644
> --- a/hw/intc/xive.c
> +++ b/hw/intc/xive.c
> @@ -53,6 +53,21 @@ static uint64_t xive_icp_accept(XiveICPState *xicp)
>      return (nsr << 8) | xicp->tima_os[TM_CPPR];
>  }
>  
> +static uint8_t ipb_to_pipr(uint8_t ibp)
> +{
> +    return ibp ? clz32((uint32_t)ibp << 24) : 0xff;
> +}

The PIPR needs to be updated also on accept etc... anything that change
IPBs or CPPR really.

Also I just learned something from the designers: The IPIR is clamped
to CPPR.

So basically the value in the PIPR is:

	v = leftmost_bit_of(ipb) (or 0xff);
	pipr = v < cppr ? v : cppr;

which means it's never actually 0xff ... surprise !

That also means I need to fix my implementation of H_IPOLL in KVM.

> +static void xive_icp_notify(XiveICPState *xicp)
> +{
> +    xicp->tima_os[TM_PIPR] = ipb_to_pipr(xicp->tima_os[TM_IPB]);
> +
> +    if (xicp->tima_os[TM_PIPR] < xicp->tima_os[TM_CPPR]) {
> +        xicp->tima_os[TM_NSR] |= TM_QW1_NSR_EO;
> +        qemu_irq_raise(ICP(xicp)->output);
> +    }
> +}
> +
>  static void xive_icp_set_cppr(XiveICPState *xicp, uint8_t cppr)
>  {
>      if (cppr > XIVE_PRIORITY_MAX) {
> @@ -60,6 +75,10 @@ static void xive_icp_set_cppr(XiveICPState *xicp, uint8_t cppr)
>      }
>  
>      xicp->tima_os[TM_CPPR] = cppr;
> +
> +    /* CPPR has changed, inform the ICP which might raise an
> +     * exception */
> +    xive_icp_notify(xicp);
>  }
>  
>  /*
> @@ -339,6 +358,8 @@ static void xive_icp_irq(XiveICSState *xs, int lisn)
>      } else {
>          qemu_log_mask(LOG_UNIMP, "XIVE: w7 format1 not implemented\n");
>      }
> +
> +    xive_icp_notify(xicp);
>  }
>  
>  /*
Cédric Le Goater Sept. 9, 2017, 8:08 a.m. UTC | #2
On 09/09/2017 09:39 AM, Benjamin Herrenschmidt wrote:
> On Wed, 2017-07-05 at 19:13 +0200, Cédric Le Goater wrote:
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  hw/intc/xive.c | 21 +++++++++++++++++++++
>>  1 file changed, 21 insertions(+)
>>
>> diff --git a/hw/intc/xive.c b/hw/intc/xive.c
>> index c3c1e9c9db2d..cda1fa18e44d 100644
>> --- a/hw/intc/xive.c
>> +++ b/hw/intc/xive.c
>> @@ -53,6 +53,21 @@ static uint64_t xive_icp_accept(XiveICPState *xicp)
>>      return (nsr << 8) | xicp->tima_os[TM_CPPR];
>>  }
>>  
>> +static uint8_t ipb_to_pipr(uint8_t ibp)
>> +{
>> +    return ibp ? clz32((uint32_t)ibp << 24) : 0xff;
>> +}
> 
> The PIPR needs to be updated also on accept etc... anything that change
> IPBs or CPPR really.

I did forget the update in accept ... thanks. 

> Also I just learned something from the designers: The IPIR is clamped
> to CPPR.
> 
> So basically the value in the PIPR is:
> 
> 	v = leftmost_bit_of(ipb) (or 0xff);
> 	pipr = v < cppr ? v : cppr;
> 
> which means it's never actually 0xff ... surprise !

ah. that is not what the specs say but it shouldn't be a problem.
I will change the code to reflect that.

C.

> That also means I need to fix my implementation of H_IPOLL in KVM.
> 
>> +static void xive_icp_notify(XiveICPState *xicp)
>> +{
>> +    xicp->tima_os[TM_PIPR] = ipb_to_pipr(xicp->tima_os[TM_IPB]);
>> +
>> +    if (xicp->tima_os[TM_PIPR] < xicp->tima_os[TM_CPPR]) {
>> +        xicp->tima_os[TM_NSR] |= TM_QW1_NSR_EO;
>> +        qemu_irq_raise(ICP(xicp)->output);
>> +    }
>> +}
>> +
>>  static void xive_icp_set_cppr(XiveICPState *xicp, uint8_t cppr)
>>  {
>>      if (cppr > XIVE_PRIORITY_MAX) {
>> @@ -60,6 +75,10 @@ static void xive_icp_set_cppr(XiveICPState *xicp, uint8_t cppr)
>>      }
>>  
>>      xicp->tima_os[TM_CPPR] = cppr;
>> +
>> +    /* CPPR has changed, inform the ICP which might raise an
>> +     * exception */
>> +    xive_icp_notify(xicp);
>>  }
>>  
>>  /*
>> @@ -339,6 +358,8 @@ static void xive_icp_irq(XiveICSState *xs, int lisn)
>>      } else {
>>          qemu_log_mask(LOG_UNIMP, "XIVE: w7 format1 not implemented\n");
>>      }
>> +
>> +    xive_icp_notify(xicp);
>>  }
>>  
>>  /*
Cédric Le Goater Sept. 9, 2017, 8:24 a.m. UTC | #3
On 09/09/2017 09:39 AM, Benjamin Herrenschmidt wrote:
> On Wed, 2017-07-05 at 19:13 +0200, Cédric Le Goater wrote:
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  hw/intc/xive.c | 21 +++++++++++++++++++++
>>  1 file changed, 21 insertions(+)
>>
>> diff --git a/hw/intc/xive.c b/hw/intc/xive.c
>> index c3c1e9c9db2d..cda1fa18e44d 100644
>> --- a/hw/intc/xive.c
>> +++ b/hw/intc/xive.c
>> @@ -53,6 +53,21 @@ static uint64_t xive_icp_accept(XiveICPState *xicp)
>>      return (nsr << 8) | xicp->tima_os[TM_CPPR];
>>  }
>>  
>> +static uint8_t ipb_to_pipr(uint8_t ibp)
>> +{
>> +    return ibp ? clz32((uint32_t)ibp << 24) : 0xff;
>> +}
> 
> The PIPR needs to be updated also on accept etc... anything that change
> IPBs or CPPR really.

but not for the SET_OS_PENDING special write I suppose.

C.
Benjamin Herrenschmidt Sept. 9, 2017, 8:40 a.m. UTC | #4
On Sat, 2017-09-09 at 10:08 +0200, Cédric Le Goater wrote:
> On 09/09/2017 09:39 AM, Benjamin Herrenschmidt wrote:
> > On Wed, 2017-07-05 at 19:13 +0200, Cédric Le Goater wrote:
> > > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > > ---
> > >  hw/intc/xive.c | 21 +++++++++++++++++++++
> > >  1 file changed, 21 insertions(+)
> > > 
> > > diff --git a/hw/intc/xive.c b/hw/intc/xive.c
> > > index c3c1e9c9db2d..cda1fa18e44d 100644
> > > --- a/hw/intc/xive.c
> > > +++ b/hw/intc/xive.c
> > > @@ -53,6 +53,21 @@ static uint64_t xive_icp_accept(XiveICPState *xicp)
> > >      return (nsr << 8) | xicp->tima_os[TM_CPPR];
> > >  }
> > >  
> > > +static uint8_t ipb_to_pipr(uint8_t ibp)
> > > +{
> > > +    return ibp ? clz32((uint32_t)ibp << 24) : 0xff;
> > > +}
> > 
> > The PIPR needs to be updated also on accept etc... anything that change
> > IPBs or CPPR really.
> 
> I did forget the update in accept ... thanks. 
> 
> > Also I just learned something from the designers: The IPIR is clamped
> > to CPPR.
> > 
> > So basically the value in the PIPR is:
> > 
> > 	v = leftmost_bit_of(ipb) (or 0xff);
> > 	pipr = v < cppr ? v : cppr;
> > 
> > which means it's never actually 0xff ... surprise !
> 
> ah. that is not what the specs say but it shouldn't be a problem.
> I will change the code to reflect that.

Right, I've asked the HW guys to update the spec.

Cheers,
Ben.

> C.
> 
> > That also means I need to fix my implementation of H_IPOLL in KVM.
> > 
> > > +static void xive_icp_notify(XiveICPState *xicp)
> > > +{
> > > +    xicp->tima_os[TM_PIPR] = ipb_to_pipr(xicp->tima_os[TM_IPB]);
> > > +
> > > +    if (xicp->tima_os[TM_PIPR] < xicp->tima_os[TM_CPPR]) {
> > > +        xicp->tima_os[TM_NSR] |= TM_QW1_NSR_EO;
> > > +        qemu_irq_raise(ICP(xicp)->output);
> > > +    }
> > > +}
> > > +
> > >  static void xive_icp_set_cppr(XiveICPState *xicp, uint8_t cppr)
> > >  {
> > >      if (cppr > XIVE_PRIORITY_MAX) {
> > > @@ -60,6 +75,10 @@ static void xive_icp_set_cppr(XiveICPState *xicp, uint8_t cppr)
> > >      }
> > >  
> > >      xicp->tima_os[TM_CPPR] = cppr;
> > > +
> > > +    /* CPPR has changed, inform the ICP which might raise an
> > > +     * exception */
> > > +    xive_icp_notify(xicp);
> > >  }
> > >  
> > >  /*
> > > @@ -339,6 +358,8 @@ static void xive_icp_irq(XiveICSState *xs, int lisn)
> > >      } else {
> > >          qemu_log_mask(LOG_UNIMP, "XIVE: w7 format1 not implemented\n");
> > >      }
> > > +
> > > +    xive_icp_notify(xicp);
> > >  }
> > >  
> > >  /*
diff mbox

Patch

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index c3c1e9c9db2d..cda1fa18e44d 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -53,6 +53,21 @@  static uint64_t xive_icp_accept(XiveICPState *xicp)
     return (nsr << 8) | xicp->tima_os[TM_CPPR];
 }
 
+static uint8_t ipb_to_pipr(uint8_t ibp)
+{
+    return ibp ? clz32((uint32_t)ibp << 24) : 0xff;
+}
+
+static void xive_icp_notify(XiveICPState *xicp)
+{
+    xicp->tima_os[TM_PIPR] = ipb_to_pipr(xicp->tima_os[TM_IPB]);
+
+    if (xicp->tima_os[TM_PIPR] < xicp->tima_os[TM_CPPR]) {
+        xicp->tima_os[TM_NSR] |= TM_QW1_NSR_EO;
+        qemu_irq_raise(ICP(xicp)->output);
+    }
+}
+
 static void xive_icp_set_cppr(XiveICPState *xicp, uint8_t cppr)
 {
     if (cppr > XIVE_PRIORITY_MAX) {
@@ -60,6 +75,10 @@  static void xive_icp_set_cppr(XiveICPState *xicp, uint8_t cppr)
     }
 
     xicp->tima_os[TM_CPPR] = cppr;
+
+    /* CPPR has changed, inform the ICP which might raise an
+     * exception */
+    xive_icp_notify(xicp);
 }
 
 /*
@@ -339,6 +358,8 @@  static void xive_icp_irq(XiveICSState *xs, int lisn)
     } else {
         qemu_log_mask(LOG_UNIMP, "XIVE: w7 format1 not implemented\n");
     }
+
+    xive_icp_notify(xicp);
 }
 
 /*