|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 26/26] xen/riscv: manage IRQ_DISABLED flag in APLIC irq enable/disable callbacks
On 6/15/26 5:53 PM, Jan Beulich wrote: On 08.05.2026 16:43, Oleksii Kurochko wrote:desc->status is only set once during setup_irq(), but interrupts can be enabled/disabled at runtime, so update it in the corresponding callbacks. wmb() in aplic_irq_enable() ensures do_IRQ(), which can fire immediately after the interrupt is enabled, sees the updated desc->status.This doesn't look entirely correct. Aiui ... Good point. The RISC-V ISA spec is clear that fence orders memory predecessor and successor operations. CSR accesses are architecturally a distinct category. fence w,w carries no formal guarantee that a preceding memory store to desc->status becomes visible before a subsequent CSR write. Also, according to the spec:Each RISC-V hart normally observes its own CSR accesses, including its implicit CSR accesses, as performed in program order. In particular, unless specified otherwise, a CSR access is performed after the execution of any prior instructions in program order whose behavior modifies or is modified by the CSR state and before the execution of any subsequent instructions in program order whose behavior modifies or is modified by the CSR state. Furthermore, an explicit CSR read returns the CSR state before the execution of the instruction, while an explicit CSR write suppresses and overrides any implicit writes or modifications to the same CSR by the same instruction. and ... If not, you may need to resort to mb(), to order the ->status write against the ->irq read, in lieu of being able to order against a CSR write. Of course with imsic_irq_enable() itself acquiring a lock (which necessarily has a memory write), you could then further argue that wmb() is indeed sufficient, bot for a reason different from the one presently stated in the description. (I would also strongly suggest to annotate the wmb() with an explanatory comment.) ...After re-looking at imsic_irq_enable() it is calling imsic_local_eix_update() which targets the local hart's IMSIC interrupt file (note the function name), and IRQs are disabled at this point (the ASSERT(!local_irq_is_enabled())). So do_IRQ() can only fire on the same hart, after IRQs are re-enabled on return from aplic_irq_enable(). Same-hart program order already guarantees desc->status is committed (before of the mentioned above) before the CSR write retires, making the barrier redundant. So barrier could be dropped here.On the other side if some code will check on different CPU what is desc->status without a barrier it will see a stale value. But then in this case we have to use or atomic set_bit() here or spinlock(desc->lock) around an update of desc->status. Then the similar is needed for aplic_irq_disable().
The ordering is intentional: desc->status |= IRQ_DISABLED is placed after imsic_irq_disable() so that do_IRQ() can never observe IRQ_DISABLED while the interrupt is still enabled in hardware. Regarding the fence/CSR ordering concern: imsic_irq_disable() writes to the local hart's IMSIC interrupt file, so do_IRQ() for this irq can only run on the same hart. Same-hart program order already guarantees that both the CSR write and the desc->status update are visible in the correct sequence before any subsequent interrupt handler runs.
I will add the following to commit description:The removal of desc->status &= ~IRQ_DISABLED from setup_irq() is safe for RISC-V because aplic_irq_startup() calls aplic_irq_enable() directly, which now clears the flag itself. The explicit clear in setup_irq() is therefore redundant. Thanks. ~ Oleksii
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |