diff mbox series

hw/intc/arm_gicv3_cpuif: Tolerate spurious EOIR writes

Message ID 20210603110012.1182530-1-jean-philippe@linaro.org
State New
Headers show
Series hw/intc/arm_gicv3_cpuif: Tolerate spurious EOIR writes | expand

Commit Message

Jean-Philippe Brucker June 3, 2021, 11 a.m. UTC
Commit 382c7160d1cd ("hw/intc/arm_gicv3_cpuif: Fix EOIR write access
check logic") added an assert_not_reached() if the guest writes the EOIR
register while no interrupt is active.

It turns out some software does this: EDK2, in GicV3ExitBootServicesEvent(),
unconditionally write EOIR for all interrupts that it manages. This now
causes QEMU to abort when running UEFI on a VM with GICv3. Although it
is UNPREDICTABLE behavior and EDK2 does need fixing, the punishment
seems a little harsh, especially since icc_eoir_write() already
tolerates writes of nonexistent interrupt numbers. Simply ignore
spurious EOIR writes.

Fixes: 382c7160d1cd ("hw/intc/arm_gicv3_cpuif: Fix EOIR write access check logic")
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>

---
 hw/intc/arm_gicv3_cpuif.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

-- 
2.31.1

Comments

Philippe Mathieu-Daudé June 3, 2021, 12:39 p.m. UTC | #1
Hi Jean-Philippe,

On 6/3/21 1:00 PM, Jean-Philippe Brucker wrote:
> Commit 382c7160d1cd ("hw/intc/arm_gicv3_cpuif: Fix EOIR write access

> check logic") added an assert_not_reached() if the guest writes the EOIR

> register while no interrupt is active.

> 

> It turns out some software does this: EDK2, in GicV3ExitBootServicesEvent(),

> unconditionally write EOIR for all interrupts that it manages. This now

> causes QEMU to abort when running UEFI on a VM with GICv3. Although it

> is UNPREDICTABLE behavior and EDK2 does need fixing, the punishment

> seems a little harsh, especially since icc_eoir_write() already

> tolerates writes of nonexistent interrupt numbers. Simply ignore

> spurious EOIR writes.

> 

> Fixes: 382c7160d1cd ("hw/intc/arm_gicv3_cpuif: Fix EOIR write access check logic")

> Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>

> ---

>  hw/intc/arm_gicv3_cpuif.c | 3 ++-

>  1 file changed, 2 insertions(+), 1 deletion(-)

> 

> diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c

> index 81f94c7f4a..1d0964c9bf 100644

> --- a/hw/intc/arm_gicv3_cpuif.c

> +++ b/hw/intc/arm_gicv3_cpuif.c

> @@ -1357,7 +1357,8 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,

>          }

>          break;

>      default:

> -        g_assert_not_reached();

> +        /* No interrupt was active, this is UNPREDICTABLE. Ignore it. */


A qemu_log_mask(LOG_GUEST_ERROR, ...) call here could be useful,
do you mind adding it?

> +        return;

>      }

>  

>      icc_drop_prio(cs, grp);

>
Peter Maydell June 3, 2021, 12:56 p.m. UTC | #2
On Thu, 3 Jun 2021 at 12:01, Jean-Philippe Brucker
<jean-philippe@linaro.org> wrote:
>

> Commit 382c7160d1cd ("hw/intc/arm_gicv3_cpuif: Fix EOIR write access

> check logic") added an assert_not_reached() if the guest writes the EOIR

> register while no interrupt is active.

>

> It turns out some software does this: EDK2, in GicV3ExitBootServicesEvent(),

> unconditionally write EOIR for all interrupts that it manages. This now

> causes QEMU to abort when running UEFI on a VM with GICv3. Although it

> is UNPREDICTABLE behavior and EDK2 does need fixing, the punishment

> seems a little harsh, especially since icc_eoir_write() already

> tolerates writes of nonexistent interrupt numbers. Simply ignore

> spurious EOIR writes.

>

> Fixes: 382c7160d1cd ("hw/intc/arm_gicv3_cpuif: Fix EOIR write access check logic")

> Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>

> ---

>  hw/intc/arm_gicv3_cpuif.c | 3 ++-

>  1 file changed, 2 insertions(+), 1 deletion(-)

>

> diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c

> index 81f94c7f4a..1d0964c9bf 100644

> --- a/hw/intc/arm_gicv3_cpuif.c

> +++ b/hw/intc/arm_gicv3_cpuif.c

> @@ -1357,7 +1357,8 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,

>          }

>          break;

>      default:

> -        g_assert_not_reached();

> +        /* No interrupt was active, this is UNPREDICTABLE. Ignore it. */

> +        return;

>


Makes sense (and looking at the comment in icc_highest_active_group()
that says "return -1 so the caller ignores the spurious EOI attempt"
it is what the code originally intended).

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>


Shashi, I guess this also fixes the assert you were seeing here ?

thanks
-- PMM
Jean-Philippe Brucker June 3, 2021, 1:14 p.m. UTC | #3
On Thu, Jun 03, 2021 at 02:39:30PM +0200, Philippe Mathieu-Daudé wrote:
> > diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c

> > index 81f94c7f4a..1d0964c9bf 100644

> > --- a/hw/intc/arm_gicv3_cpuif.c

> > +++ b/hw/intc/arm_gicv3_cpuif.c

> > @@ -1357,7 +1357,8 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,

> >          }

> >          break;

> >      default:

> > -        g_assert_not_reached();

> > +        /* No interrupt was active, this is UNPREDICTABLE. Ignore it. */

> 

> A qemu_log_mask(LOG_GUEST_ERROR, ...) call here could be useful,

> do you mind adding it?


No problem. I had it at first, but then wondered if that meant I should
update similar cases in the GIC device that silently ignore guest errors
at the moment (e.g. the guest writes a number > 1023 to EOIR) and decided
against it. I'll resend with only this error report if there is no
objection.

Thanks,
Jean

> > +        return;

> >      }

> >  

> >      icc_drop_prio(cs, grp);

> > 

>
Shashi Mallela June 3, 2021, 2:52 p.m. UTC | #4
Yes it does.

Thanks
Shashi

On Jun 3 2021, at 8:56 am, Peter Maydell <peter.maydell@linaro.org> wrote:
> On Thu, 3 Jun 2021 at 12:01, Jean-Philippe Brucker

> <jean-philippe@linaro.org> wrote:

> >

> > Commit 382c7160d1cd ("hw/intc/arm_gicv3_cpuif: Fix EOIR write access

> > check logic") added an assert_not_reached() if the guest writes the EOIR

> > register while no interrupt is active.

> >

> > It turns out some software does this: EDK2, in GicV3ExitBootServicesEvent(),

> > unconditionally write EOIR for all interrupts that it manages. This now

> > causes QEMU to abort when running UEFI on a VM with GICv3. Although it

> > is UNPREDICTABLE behavior and EDK2 does need fixing, the punishment

> > seems a little harsh, especially since icc_eoir_write() already

> > tolerates writes of nonexistent interrupt numbers. Simply ignore

> > spurious EOIR writes.

> >

> > Fixes: 382c7160d1cd ("hw/intc/arm_gicv3_cpuif: Fix EOIR write access check logic")

> > Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>

> > ---

> > hw/intc/arm_gicv3_cpuif.c | 3 ++-

> > 1 file changed, 2 insertions(+), 1 deletion(-)

> >

> > diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c

> > index 81f94c7f4a..1d0964c9bf 100644

> > --- a/hw/intc/arm_gicv3_cpuif.c

> > +++ b/hw/intc/arm_gicv3_cpuif.c

> > @@ -1357,7 +1357,8 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,

> > }

> > break;

> > default:

> > - g_assert_not_reached();

> > + /* No interrupt was active, this is UNPREDICTABLE. Ignore it. */

> > + return;

> >

>

> Makes sense (and looking at the comment in icc_highest_active_group()

> that says "return -1 so the caller ignores the spurious EOI attempt"

> it is what the code originally intended).

>

> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

> Shashi, I guess this also fixes the assert you were seeing here ?

> thanks

> -- PMM

>
<div>Yes it does.</div><br><div>Thanks</div><div>Shashi</div><br><div class="gmail_quote_attribution">On Jun 3 2021, at 8:56 am, Peter Maydell &lt;peter.maydell@linaro.org&gt; wrote:</div><blockquote><div><div>On Thu, 3 Jun 2021 at 12:01, Jean-Philippe Brucker</div><div>&lt;jean-philippe@linaro.org&gt; wrote:</div><div>&gt;</div><div>&gt; Commit 382c7160d1cd ("hw/intc/arm_gicv3_cpuif: Fix EOIR write access</div><div>&gt; check logic") added an assert_not_reached() if the guest writes the EOIR</div><div>&gt; register while no interrupt is active.</div><div>&gt;</div><div>&gt; It turns out some software does this: EDK2, in GicV3ExitBootServicesEvent(),</div><div>&gt; unconditionally write EOIR for all interrupts that it manages. This now</div><div>&gt; causes QEMU to abort when running UEFI on a VM with GICv3. Although it</div><div>&gt; is UNPREDICTABLE behavior and EDK2 does need fixing, the punishment</div><div>&gt; seems a little harsh, especially since icc_eoir_write() already</div><div>&gt; tolerates writes of nonexistent interrupt numbers. Simply ignore</div><div>&gt; spurious EOIR writes.</div><div>&gt;</div><div>&gt; Fixes: 382c7160d1cd ("hw/intc/arm_gicv3_cpuif: Fix EOIR write access check logic")</div><div>&gt; Signed-off-by: Jean-Philippe Brucker &lt;jean-philippe@linaro.org&gt;</div><div>&gt; ---</div><div>&gt; hw/intc/arm_gicv3_cpuif.c | 3 ++-</div><div>&gt; 1 file changed, 2 insertions(+), 1 deletion(-)</div><div>&gt;</div><div>&gt; diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c</div><div>&gt; index 81f94c7f4a..1d0964c9bf 100644</div><div>&gt; --- a/hw/intc/arm_gicv3_cpuif.c</div><div>&gt; +++ b/hw/intc/arm_gicv3_cpuif.c</div><div>&gt; @@ -1357,7 +1357,8 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,</div><div>&gt; }</div><div>&gt; break;</div><div>&gt; default:</div><div>&gt; - g_assert_not_reached();</div><div>&gt; + /* No interrupt was active, this is UNPREDICTABLE. Ignore it. */</div><div>&gt; + return;</div><div>&gt;</div><br><div>Makes sense (and looking at the comment in icc_highest_active_group()</div><div>that says "return -1 so the caller ignores the spurious EOI attempt"</div><div>it is what the code originally intended).</div><br><div>Reviewed-by: Peter Maydell &lt;peter.maydell@linaro.org&gt;</div><br><div>Shashi, I guess this also fixes the assert you were seeing here ?</div><br><div>thanks</div><div>-- PMM</div></div></blockquote>
diff mbox series

Patch

diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 81f94c7f4a..1d0964c9bf 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -1357,7 +1357,8 @@  static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
         }
         break;
     default:
-        g_assert_not_reached();
+        /* No interrupt was active, this is UNPREDICTABLE. Ignore it. */
+        return;
     }
 
     icc_drop_prio(cs, grp);