This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

VM Passthrough LPIs in GICv3 and priority drop

For wired IRQs (PPIs/SPIs), passing through a physical IRQ to a guest is done by:

  1. Dropping the priority of the IRQ (eoi with eoimode set to 1), so that it cannot trigger again
  2. Injecting it to the guest by populating the LR with the HW bit and the desired pINTID so that the GIC can automatically deactivate it when the guest EOIs the vINTID.

From my limited understanding the above will not work for passthrough LPIs (without GICv4), since:

  1. LPIs have no active state
  2. The pINTID list register field doesn't fit LPI IRQ IDs.

Someone could argue that you can inject it purely as a virtual IRQ and use a maintenance interrupt to finalize it manually from the hypervisor, but how do you ensure that the LPI won't fire again while the guest is servicing it? From the GICv3 software overview it sounds that just by ACKing the LPI it will go from pending to inactive, but it won't be masked. Does EOI have any effect on LPIs and should you use deactivation (DIR) at all?

The only other choice I can imagine is to ACK the LPI and then disable it, set the maintenance IRQ for the specific LR and when the maintenance IRQ is received, enabled the LPI again. However, this sounds way too expensive since it requires costly INV commands to do so. Am I missing something?

Any help would be welcome, thanks in advance.

Parents
  • You're not missing anything.  LPIs have a reduced state machine, meaning that when the hypervisor acknowledges the interrupt it will go from Pending -> Inactive.  If the device generates a new MSI after that point the LPI will go back to being Pending.  At which point it could become the HPPI for the target PE.

    There are different things a hypervisor could do.  It could, as you suggested, clear the Enable for LPI - but yes, that's potentially expensive.  You need to do an INV on both clearing and setting the Enable.  Another option is to do nothing.  If the device re-fires you get a new physical interrupt into the hypervisor.  The hypervisor can deal with that interrupt in a few different ways.  If the previous vLPI hasn't been consumed, it could "merge" the instances (in the same way the GIC does for physical interrupts).  If the vLPI has been consumed, it could queue up another instance of the vLPI (again, that's what the physical GIC would have done).

    Another option, if the GIC you have supports GICv4, is to use direct-injection.

Reply
  • You're not missing anything.  LPIs have a reduced state machine, meaning that when the hypervisor acknowledges the interrupt it will go from Pending -> Inactive.  If the device generates a new MSI after that point the LPI will go back to being Pending.  At which point it could become the HPPI for the target PE.

    There are different things a hypervisor could do.  It could, as you suggested, clear the Enable for LPI - but yes, that's potentially expensive.  You need to do an INV on both clearing and setting the Enable.  Another option is to do nothing.  If the device re-fires you get a new physical interrupt into the hypervisor.  The hypervisor can deal with that interrupt in a few different ways.  If the previous vLPI hasn't been consumed, it could "merge" the instances (in the same way the GIC does for physical interrupts).  If the vLPI has been consumed, it could queue up another instance of the vLPI (again, that's what the physical GIC would have done).

    Another option, if the GIC you have supports GICv4, is to use direct-injection.

Children