Re: [PATCH v5 21/26] xen/riscv: implement IRQ routing for device passthrough
Jan Beulich <[email protected]>
| Newsgroups | org.xenproject.lists.xen-devel |
|---|---|
| Message-ID | <[email protected]> |
On 06.07.2026 17:58, Oleksii Kurochko wrote: > dom0less device passthrough requires granting guest domains access to > device interrupts. Introduce map_device_irqs_to_domain() to enumerate > a DT node's interrupt properties, skipping those not owned by > the primary interrupt controller (as at the moment I haven't seen usages > of it), and map_irq_to_domain() to grant domain access and configure > Xen's interrupt descriptor accordingly. Sharing IRQ between domains is > rejected. > > Both map_irq_to_domain() and map_device_irqs_to_domain() are marked > __overlay_init, mirroring Arm: without CONFIG_OVERLAY_DTB this expands to > __init, so the functions are init-only and need no XSM check; with > CONFIG_OVERLAY_DTB they become runtime-callable, but the only runtime > entry point is dt_overlay_domctl(), which performs the XSM checks at the > domctl layer. RISC-V does not wire up DT overlay yet, so today these are > strictly __init; if/when overlay support is added, the domctl-level XSM > gating must be added together with it, as on Arm. > > route_irq_to_guest() and release_irq() manage irq_desc ownership for > guest-assigned interrupts. Each assignment carries a small irq_guest > structure as irqaction::dev_id, recording the owning domain and virtual > IRQ number which is 1:1 mapped to physical IRQ number. A per-domain > vIRQ allocation bitmap (used_irqs in struct vintc), managed by > vintc_reserve_virq(), prevents the same vIRQ being claimed twice. > > Host and guest interrupts may differ in some operations (EOI timing in > particular, possibly others): a host IRQ is completed once Xen's handler > runs, whereas a passthrough IRQ must defer the physical completion until > the guest issues its own EOI, otherwise a still-asserted level line would > immediately retrigger and storm. This affects only the .end callback; > the rest of hw_interrupt_type is shared, hence the separate host and > guest hw_interrupt_type instances. > > With APLIC+IMSIC, guest interrupts are delivered directly by hardware > through the IMSIC, bypassing do_IRQ(). The _IRQ_GUEST branch in > do_IRQ() is therefore left as BUG() until a platform without direct > IMSIC delivery is encountered. > > Signed-off-by: Oleksii Kurochko <[email protected]> Acked-by: Jan Beulich <[email protected]> Irrespective I'm pretty curious how ... > --- a/xen/arch/riscv/aplic.c > +++ b/xen/arch/riscv/aplic.c > @@ -306,9 +306,13 @@ static const hw_irq_controller aplic_xen_irq_type = { > .set_affinity = aplic_set_irq_affinity, > }; > > +/* At the moment there is no difference between guest and Xen ops */ > +#define aplic_guest_irq_type aplic_xen_irq_type > + > static const struct intc_hw_operations aplic_ops = { > .info = &aplic_info, > .host_irq_type = &aplic_xen_irq_type, > + .guest_irq_type = &aplic_guest_irq_type, > .handle_interrupt = aplic_handle_interrupt, > .set_irq_type = aplic_set_irq_type, > }; ... this duplication of the same struct into ... > --- a/xen/arch/riscv/include/asm/intc.h > +++ b/xen/arch/riscv/include/asm/intc.h > @@ -15,6 +15,7 @@ enum intc_variant { > }; > > struct cpu_user_regs; > +struct domain; > struct irq_desc; > struct kernel_info; > struct vcpu; > @@ -34,6 +35,9 @@ struct intc_hw_operations { > /* hw_irq_controller to enable/disable/eoi host irq */ > const struct hw_interrupt_type *host_irq_type; > > + /* hw_irq_controller to enable/disable/eoi guest irq */ > + const struct hw_interrupt_type *guest_irq_type; ... two distinct fields is going to work / be useful. Jan