[PATCH RFC 0/2] VIRQ (Virtual IRQ) layer to support paravirtual interrupt delivery
Raymond Mao
raymondmaoca at gmail.com
Fri Feb 13 11:04:56 PST 2026
From: Raymond Mao <raymond.mao at riscstar.com>
This RFC proposes a lightweight VIRQ courier/routing layer for
OpenSBI to support paravirtual / trap-n-emulate style interrupt
delivery to S-mode payloads, while keeping host physical interrupts
handled in M-mode.
# VIRQ High-level design
At a high-level the VIRQ layer is composed of three major parts:
1. VIRQ mapping and allocation
- Provide a stable mapping between a host interrupt endpoint
(chip_uid, hwirq) and a VIRQ number.
- VIRQ number allocation uses a growable bitmap.
2. HWIRQ->Domain route rules
- Route rules are described in DeviceTree under the OpenSBI domain
configuration using:
'opensbi,host-irqs = <first_hwirq count> ...;'
- Each <first_hwirq count> entry is converted into an internal
inclusive range [first .. first+count-1] and cached as a route
rule.
- Default behavior: if an asserted HWIRQ does not match any route
rule, it is routed to the root domain.
3. Per-(domain,hart) pending queue couriering
- Each domain maintains a per-hart ring buffer queue of pending
VIRQs.
- On an asserted HWIRQ, the courier handler:
maps (chip_uid,hwirq) -> VIRQ;
finds destination domain via route rules;
masks the host HWIRQ (to avoid level-trigger storms);
pushes the VIRQ into the per-(domain,hart) pending queue;
injects an SSE event to notify the destination S-mode payload
- In S-mode, the payload’s SSE trap handler:
issues an ecall to pop pending VIRQ from the per-hart queue;
runs its ISR for the device;
issues an ecall to complete the VIRQ, which unmasks the
corresponding host HWIRQ
# VIRQ ECALL extension
Add a vendor-defined SBI extension ecall for VIRQ.
This allows S-mode payload to pop/complete the next pending VIRQ has
couried into the current domain.
# Reference DT overlay for introducing the route rules:
A reference DT overlay can be used to add route rules to a domain
using 'opensbi,host-irqs' property.
For example, to route UART RX HWIRQ 10 to domain1:
```
/ {
fragment at 0 {
target-path = "/chosen";
__overlay__ {
opensbi-domains {
compatible = "opensbi,domain,config";
domain1: domain1 {
compatible = "opensbi,domain,instance";
possible-harts = <0x1>; /* cpu0 */
regions = <...>; /* minimal executable + device MMIO */
opensbi,host-irqs = <10 1>; /* route hwirq 10 to domain1 */
};
};
};
};
};
```
A sample DT overlay dts for reference is attached together with the
RFC.
# Boot-time and runtime flow
1. Cold boot flow (M-mode):
- During FDT domain parsing, extract 'opensbi,host-irqs' from each
domain instance and cache the route rules in VIRQ layer.
- Initialize host irqchip drivers and register the VIRQ courier
handler.
2. When a host HWIRQ is asserted and trapped/handled in M-mode by the
host irqchip driver.
- The courier handler maps (chip_uid,hwirq) to a stable VIRQ number.
- The courier handler routes the interrupt to the destination
domain using cached route rules (or defaults to root domain if no
rules match).
- The courier handler masks the host HWIRQ and pushes the VIRQ into
the per-hart pending queue of the routed domain.
- The courier handler injects an SSE event to notify S-mode.
- The S-mode payload traps the SSE, pops the pending VIRQ(s) via
ecall, and runs the ISR.
- The S-mode payload completes the interrupt via ecall, which
unmasks the host HWIRQ, allowing further interrupts.
Raymond Mao (2):
lib: sbi: Prototype of Virtual IRQ (VIRQ) layer for
mapping/routing/courier/ IRQs
platform: generic: Add sample dts overlay for testing hwirq/domain
route rules
include/sbi/sbi_virq.h | 401 ++++++++++++++++++++
platform/generic/virt/hwirq_bind_domain.dts | 79 ++++
2 files changed, 480 insertions(+)
create mode 100644 include/sbi/sbi_virq.h
create mode 100644 platform/generic/virt/hwirq_bind_domain.dts
--
2.25.1
More information about the opensbi
mailing list