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
