On Tue, 13 Oct 2026 at 09:40, Peter Maydell <[email protected]> wrote:
>
> The GICv5 cpuif allows the hypervisor to configure PPIs to be
> directly injected into a VM.  Setting the appropriate bit in
> ICH_PPI_DVIR<n>_EL2 causes that physical PPI to appear as a virtual
> PPI in the virtual interupt domain.

"interrupt"

>
> Directly injected PPIs mostly behave like true virtual PPIs; the
> exception is that their pending state tracks the pending state of the
> underlying physical PPI, and guest operations that read or update the
> pending state work on the physical PPI's pending state.  (Hypervisor
> operations via ICH_PPI_PENDR<n>_EL2 are not changed, and don't work
> with the physical PPI pending state.)
>
> The complication here is that when nested virtualization is active
> the EL1 timer PPIs must be redirected so that they appear with
> different virtual PPI IDs from their physical PPI IDs.  All other
> injection is a simple 1:1 mapping with a physical PPI always
> injecting to the virtual PPI with the same ID.
>
> In this commit we update the places which read the pending state
> of virtual PPIs to honour the DVI bits and report the pending
> state of the underlying direct-injected PPI.
>
> Signed-off-by: Peter Maydell <[email protected]>


> +static uint64_t gic_virt_ppi_pending(CPUARMState *env, int reg)
> +{
> +    /*
> +     * Return the pending state of the virtual PPIs; this is the
> +     * combination of the ICH_PPI_PENDR<n>_EL2 state and the pending
> +     * state of the physical PPIs which are being direct-injected.
> +     */
> +    uint64_t dvi_pend = env->gicv5_cpuif.ppi_pend[reg];
> +    uint64_t ppi_dvi = env->gicv5_cpuif.ich_ppi_dvi[reg];
> +    uint64_t dvi_mask = gic_virt_dvi_mask(env, reg);
> +
> +    if (reg == 0 &&
> +        (arm_hcr_el2_eff(env) & (HCR_NV | HCR_NV1)) == HCR_NV) {
> +        if (arm_is_secure_below_el3(env)) {
> +            /* 30 -> 20 and 27 -> 19 */
> +            if (extract64(ppi_dvi, 30, 1)) {
> +                dvi_pend = deposit64(dvi_pend, extract64(dvi_pend, 30, 1), 
> 20, 1);
> +            }
> +            if (extract64(ppi_dvi, 27, 1)) {
> +                dvi_pend = deposit64(dvi_pend, extract64(dvi_pend, 27, 1), 
> 19, 1);
> +            }
> +        } else {
> +            /* 30 -> 26 and 27 -> 28 */
> +            if (extract64(ppi_dvi, 30, 1)) {
> +                dvi_pend = deposit64(dvi_pend, extract64(dvi_pend, 30, 1), 
> 26, 1);
> +            }
> +            if (extract64(ppi_dvi, 27, 1)) {
> +                dvi_pend = deposit64(dvi_pend, extract64(dvi_pend, 27, 1), 
> 28, 1);
> +            }
> +        }

This code gets the order of arguments to deposit64() wrong:
they are value, start, length, fieldval, so should be
  dvi_pend = deposit64(dvi_pend, 20, 1, extract64(....))
and so on.

-- PMM

Reply via email to