public inbox for opensbi@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH RFC 0/2] VIRQ (Virtual IRQ) layer to support paravirtual interrupt delivery
@ 2026-02-13 19:04 Raymond Mao
  2026-02-13 19:04 ` [PATCH RFC 1/3] lib: sbi: Prototype of Virtual IRQ (VIRQ) layer for mapping/routing/courier/ IRQs Raymond Mao
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Raymond Mao @ 2026-02-13 19:04 UTC (permalink / raw)
  To: opensbi
  Cc: scott, dave.patel, raymond.mao, robin.randhawa, samuel.holland,
	anup.patel, anuppate, dhaval, peter.lin

From: Raymond Mao <raymond.mao@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@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


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH RFC 1/3] lib: sbi: Prototype of Virtual IRQ (VIRQ) layer for mapping/routing/courier/ IRQs
  2026-02-13 19:04 [PATCH RFC 0/2] VIRQ (Virtual IRQ) layer to support paravirtual interrupt delivery Raymond Mao
@ 2026-02-13 19:04 ` Raymond Mao
  2026-02-13 19:04 ` [PATCH RFC 2/3] platform: generic: Add sample dts overlay for testing hwirq/domain route rules Raymond Mao
  2026-02-13 19:04 ` [PATCH RFC 3/3] lib: sbi: Add VIRQ ecall extension Raymond Mao
  2 siblings, 0 replies; 6+ messages in thread
From: Raymond Mao @ 2026-02-13 19:04 UTC (permalink / raw)
  To: opensbi
  Cc: scott, dave.patel, raymond.mao, robin.randhawa, samuel.holland,
	anup.patel, anuppate, dhaval, peter.lin

From: Raymond Mao <raymond.mao@riscstar.com>

VIRQ is an abstraction layer providing IRQ routing and couriering.
It manages per-(domain,hart) IRQ pending state with HWIRQ->VIRQ
mapping and VIRQ dispatching via SSE and ECALL extension.
When a HWIRQ is asserted, the layer maps it to VIRQ and push into the
routed domain's per-hart pending queue, then inject SSE to notify
S-mode payload and provides ecall extension for S-mode payload to pop
and complete the VIRQ.

VIRQ layer is composed of three major parts:
1. VIRQ mapping and allocation
   - Provides a stable mapping between a host interrupt endpoint
     (chip_uid, hwirq) and a VIRQ number.
   - VIRQ number allocation uses a scalable 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 ecall to pop pending VIRQ from the per-hart queue;
       runs its ISR for the device;
       issues ecall to complete the VIRQ, which unmasks the
       corresponding host HWIRQ.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 include/sbi/sbi_virq.h | 401 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 401 insertions(+)
 create mode 100644 include/sbi/sbi_virq.h

diff --git a/include/sbi/sbi_virq.h b/include/sbi/sbi_virq.h
new file mode 100644
index 00000000..d7ec9da9
--- /dev/null
+++ b/include/sbi/sbi_virq.h
@@ -0,0 +1,401 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Virtual IRQ (VIRQ) courier/routing layer for OpenSBI.
+ *
+ * This header defines:
+ *   1) VIRQ number allocation and (chip_uid,hwirq) <-> VIRQ mapping
+ *   2) HWIRQ -> Domain routing rules (from DeviceTree "opensbi,host-irqs")
+ *   3) Per-(domain,hart) pending queue (push in M-mode, pop/complete in S-mode)
+ *
+ * High-level design intent:
+ *   - All physical host IRQs are handled in M-mode by host irqchip drivers.
+ *   - For each incoming HWIRQ, OpenSBI determines the destination domain using
+ *     DT-defined routing rules and enqueues a VIRQ into the per-(domain,hart)
+ *     pending queue.
+ *   - S-mode payload consumes pending VIRQs via pop(), and completes them via
+ *     complete(), which unmasks the corresponding host HWIRQ line.
+ *
+ * Notes:
+ *   - "opensbi,host-irqs" is treated as *routing metadata* only. It does not
+ *     encode which privilege level receives the interrupt. Hardware delivery
+ *     (MEI vs SEI) is determined by platform IRQ topology and interrupt-parent.
+ *
+ * Copyright (c) 2026 RISCstar Solutions Corporation.
+ *
+ * Author: Raymond Mao <raymond.mao@riscstar.com>
+ */
+
+#ifndef __SBI_VIRQ_H__
+#define __SBI_VIRQ_H__
+
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_irqchip.h>
+#include <sbi/riscv_locks.h>
+#include <sbi/sbi_types.h>
+
+/*
+ * Keep the VIRQ pending queue small for bring-up.
+ *
+ * Current implementation behavior when queue overflows:
+ *   - Drop the incoming VIRQ
+ *   - Return SBI_ENOMEM
+ */
+#define VIRQ_QSIZE  32
+
+/*
+ * Reverse mapping table is chunked to avoid a single large static array.
+ * VIRQ is used as an index into a chunk; chunks are allocated on demand.
+ */
+#define VIRQ_CHUNK_SHIFT   6U
+#define VIRQ_CHUNK_SIZE    (1U << VIRQ_CHUNK_SHIFT)
+#define VIRQ_CHUNK_MASK    (VIRQ_CHUNK_SIZE - 1U)
+
+/* Minimum growth step for forward mapping vector and related metadata. */
+#define VEC_GROW_MIN       16U
+
+/*------------------------------------------------------------------------------
+ * VIRQ allocator and (chip_uid,hwirq) <-> VIRQ mapping
+ *----------------------------------------------------------------------------*/
+
+ /*
+ * VIRQ mapping model:
+ *   - Forward mapping:  (chip_uid,hwirq) -> VIRQ
+ *       Implementation: dynamic vector of entries (linear search).
+ *
+ *   - Reverse mapping:  VIRQ -> (chip_uid,hwirq)
+ *       Implementation: chunked table allocated on demand, O(1) lookup.
+ *
+ *   - VIRQ number allocation:
+ *       Implementation: growable bitmap; capacity expands as needed.
+ *
+ * Memory usage scales with the number of installed mappings.
+ */
+
+/* Entry of reverse mapping table: represents (chip_uid,hwirq) endpoint */
+struct virq_entry {
+	u32 chip_uid;
+	u32 hwirq;
+};
+
+/* Chunked reverse mapping table: VIRQ -> (chip_uid,hwirq) */
+struct virq_chunk {
+	struct virq_entry e[VIRQ_CHUNK_SIZE];
+};
+
+/*------------------------------------------------------------------------------
+ * HWIRQ -> Domain routing rules
+ *----------------------------------------------------------------------------*/
+
+/*
+ * A routing rule maps a closed interval of HWIRQs [first..last] to a domain.
+ *
+ * Rules are populated once during cold boot while parsing the DT
+ * opensbi-domains configuration (property "opensbi,host-irqs").
+ *
+ * DT encodes ranges as:
+ *   opensbi,host-irqs = <first_hwirq count> ...
+ *
+ * Internally they are converted to:
+ *   [first .. last] (inclusive), where:
+ *       last = first + count - 1
+ *
+ * Policy notes:
+ *   - Range overlap is rejected and returns SBI_EALREADY.
+ *   - If no rule matches, routing falls back to the root domain (&root).
+ */
+struct sbi_virq_route_rule {
+	u32 first;
+	u32 last;                 /* inclusive */
+	struct sbi_domain *dom;   /* owner domain */
+};
+
+/*
+ * Courier context passed as 'opaque' to sbi_virq_courier_handler(), created
+ * per host irqchip.
+ *
+ * The courier handler needs to:
+ *   - map (chip_uid,hwirq) -> VIRQ
+ *   - mask/unmask HWIRQ using the correct irqchip device
+ * Therefore the irqchip device pointer is carried here.
+ */
+struct sbi_virq_courier_ctx {
+	struct sbi_irqchip_device *chip;
+};
+
+/*------------------------------------------------------------------------------
+ * Per-(domain,hart) pending VIRQ state and queue management
+ *----------------------------------------------------------------------------*/
+
+/*
+ * Per-(domain,hart) VIRQ state.
+ *
+ * Locking:
+ *   - lock protects head/tail and q[].
+ *
+ * Queue semantics:
+ *   - q[] stores VIRQs pending handling for this (domain,hart).
+ *   - enqueue is performed by M-mode (courier handler) according to route rule
+ *     populated from DT.
+ *   - pop/complete is performed by S-mode payload running in the destination
+ *     domain on the current hart.
+ *   - chip caches the irqchip device for unmasking on complete().
+ */
+struct sbi_domain_virq_state {
+	spinlock_t lock;
+	u32 head;
+	u32 tail;
+
+	/* Pending VIRQ ring buffer. */
+	u32 q[VIRQ_QSIZE];
+
+	/* Cached irqchip device. */
+	struct sbi_irqchip_device *chip;
+};
+
+/*
+ * Per-domain private VIRQ context.
+ *
+ * Attached to struct sbi_domain and contains per-hart states.
+ */
+struct sbi_domain_virq_priv {
+	/* number of harts in the domain */
+	u32 nharts;
+
+	/* per-hart VIRQ state array */
+	struct sbi_domain_virq_state st[];
+};
+
+/* Courier binding used when enqueuing a VIRQ. */
+struct sbi_virq_courier_binding {
+	/* destination domain */
+	struct sbi_domain *dom;
+
+	/* irqchip device that asserted the HWIRQ */
+	struct sbi_irqchip_device *chip;
+
+	/* VIRQ number to enqueue */
+	u32 virq;
+};
+
+/*------------------------------------------------------------------------------
+ * Public APIs
+ *----------------------------------------------------------------------------*/
+
+/*
+ * Initialize the VIRQ allocator/mapping state.
+ *
+ * @init_virq_cap:
+ *   Initial capacity in VIRQ bits (e.g., 256). Implementation may grow beyond.
+ *
+ * Return:
+ *   SBI_OK on success
+ *   SBI_ENOMEM on allocation failure
+ */
+int sbi_virq_map_init(u32 init_virq_cap);
+
+/*
+ * Create or get a stable mapping for (chip_uid, hwirq) -> VIRQ.
+ *
+ * @chip_uid:
+ *   Unique 32-bit ID of the host irqchip device.
+ *
+ * @hwirq:
+ *   Host HWIRQ number as produced by the irqchip driver (e.g. APLIC claim ID).
+ *
+ * @allow_identity:
+ *   If true, allocator may attempt VIRQ == hwirq for small ranges.
+ *
+ * @identity_limit:
+ *   Upper bound (exclusive) for identity mapping trial: hwirq < identity_limit.
+ *
+ * @out_virq:
+ *   Output pointer receiving the mapped/allocated VIRQ (non-zero on success).
+ *
+ * Return:
+ *   SBI_OK on success
+ *   SBI_ENOMEM on allocation failure
+ *   SBI_ENOSPC if allocator cannot allocate
+ *   SBI_EINVAL on invalid parameters
+ */
+int sbi_virq_map_one(u32 chip_uid, u32 hwirq,
+		     bool allow_identity, u32 identity_limit, u32 *out_virq);
+
+/*
+ * Lookup existing mapping: (chip_uid, hwirq) -> VIRQ.
+ *
+ * @chip_uid: irqchip unique id
+ * @hwirq:    host hwirq number
+ * @out_virq: output VIRQ (non-zero on success)
+ *
+ * Return:
+ *   SBI_OK if found
+ *   SBI_ENOENT if not mapped
+ *   SBI_EINVAL on invalid input
+ */
+int sbi_virq_hwirq2virq(u32 chip_uid, u32 hwirq, u32 *out_virq);
+
+/*
+ * Reverse lookup: VIRQ -> (chip_uid, hwirq).
+ *
+ * @virq:
+ *   VIRQ number to look up.
+ *
+ * @out_chip_uid:
+ *   Output pointer receiving irqchip unique id.
+ *
+ * @out_hwirq:
+ *   Output pointer receiving host hwirq number.
+ *
+ * Return:
+ *   SBI_OK on success
+ *   SBI_EINVAL if virq is 0, out of range, not allocated, or reverse entry
+ *     missing
+ */
+int sbi_virq_virq2hwirq(u32 virq, u32 *out_chip_uid, u32 *out_hwirq);
+
+/*
+ * Unmap a single VIRQ mapping and free the VIRQ number.
+ *
+ * @virq:
+ *   VIRQ number to unmap.
+ *
+ * Return:
+ *   SBI_OK on success
+ *   SBI_EINVAL if virq is invalid or state is inconsistent
+ */
+int sbi_virq_unmap_one(u32 virq);
+
+/*
+ * Uninitialize the VIRQ mapping allocator and free all resources.
+ *
+ * Notes:
+ *   - This frees bitmap, forward vector, and reverse chunks.
+ */
+void sbi_virq_map_uninit(void);
+
+/*
+ * Reset all HWIRQ->Domain routing rules (frees the rule array).
+ *
+ * Typical usage:
+ *   - Called once at cold boot during init before parsing DT domains.
+ */
+void sbi_virq_route_reset(void);
+
+/*
+ * Add a routing rule: [first .. first+count-1] -> dom.
+ *
+ * @dom:
+ *   Target domain that should receive HWIRQs in this range.
+ *
+ * @first:
+ *   First HWIRQ number (inclusive).
+ *
+ * @count:
+ *   Number of HWIRQs in the range.
+ *
+ * Return:
+ *   SBI_OK on success
+ *   SBI_EINVAL on invalid parameters
+ *   SBI_ENOMEM on allocation failure
+ *   SBI_EALREADY if the new range overlaps an existing rule
+ */
+int sbi_virq_route_add_range(struct sbi_domain *dom, u32 first, u32 count);
+
+/*
+ * Lookup destination domain for a given HWIRQ.
+ *
+ * @hwirq:
+ *   Incoming host HWIRQ number.
+ *
+ * Return:
+ *   Pointer to destination domain. If no rule matches, returns &root.
+ */
+struct sbi_domain *sbi_virq_route_lookup_domain(u32 hwirq);
+
+/*
+ * Enqueue a VIRQ for the destination domain on the current hart.
+ *
+ * @c:
+ *   Courier binding containing:
+ *     - c->dom  : destination domain
+ *     - c->chip : irqchip device pointer
+ *     - c->virq : VIRQ number
+ *
+ * Return:
+ *   SBI_OK on success
+ *   SBI_EINVAL on invalid parameters
+ *   SBI_ENODEV if per-(domain,hart) state is not available
+ *   SBI_ENOMEM if queue is full
+ */
+int sbi_virq_enqueue(struct sbi_virq_courier_binding *c);
+
+/*
+ * Pop the next pending VIRQ for the current domain on the current hart.
+ *
+ * Return:
+ *   0 if none pending or state not available
+ *   otherwise a non-zero VIRQ number
+ */
+u32 sbi_virq_pop_thishart(void);
+
+/*
+ * Complete a previously couriered VIRQ for the current domain/hart.
+ *
+ * @virq:
+ *   VIRQ to complete.
+ */
+void sbi_virq_complete_thishart(u32 virq);
+
+/*
+ * Courier handler intended to be registered by host irqchip driver.
+ *
+ * @hwirq:
+ *   Incoming host HWIRQ number asserted on the irqchip.
+ *
+ * @opaque:
+ *   Point to a valid struct sbi_virq_courier_ctx, which provides the
+ *   irqchip device pointer used for mapping and mask/unmask.
+ *
+ * Return:
+ *   SBI_OK on success
+ *   SBI_EINVAL on invalid parameters
+ *   Other SBI_E* propagated from mapping or enqueue
+ */
+int sbi_virq_courier_handler(u32 hwirq, void *opaque);
+
+/*
+ * Initialize per-domain VIRQ state.
+ *
+ * @dom:
+ *   Domain to initialize.
+ *
+ * Return:
+ *   SBI_OK on success
+ *   SBI_EINVAL on invalid parameters
+ *   SBI_ENOMEM on allocation failure
+ */
+int sbi_virq_domain_init(struct sbi_domain *dom);
+
+/*
+ * Free per-domain VIRQ state.
+ *
+ * @dom:
+ *   Free the per-domain VIRQ state.
+ */
+void sbi_virq_domain_exit(struct sbi_domain *dom);
+
+/*
+ * Initialize VIRQ subsystem (mapping allocator + route rules).
+ *
+ * @init_virq_cap:
+ *   Initial VIRQ bitmap capacity in bits
+ *
+ * Return:
+ *   SBI_OK on success
+ *   SBI_ENOMEM on allocation failure
+ *   Other SBI_E* error codes propagated from mapping init
+ */
+int sbi_virq_init(u32 init_virq_cap);
+
+#endif
-- 
2.25.1


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH RFC 2/3] platform: generic: Add sample dts overlay for testing hwirq/domain route rules
  2026-02-13 19:04 [PATCH RFC 0/2] VIRQ (Virtual IRQ) layer to support paravirtual interrupt delivery Raymond Mao
  2026-02-13 19:04 ` [PATCH RFC 1/3] lib: sbi: Prototype of Virtual IRQ (VIRQ) layer for mapping/routing/courier/ IRQs Raymond Mao
@ 2026-02-13 19:04 ` Raymond Mao
  2026-02-13 19:04 ` [PATCH RFC 3/3] lib: sbi: Add VIRQ ecall extension Raymond Mao
  2 siblings, 0 replies; 6+ messages in thread
From: Raymond Mao @ 2026-02-13 19:04 UTC (permalink / raw)
  To: opensbi
  Cc: scott, dave.patel, raymond.mao, robin.randhawa, samuel.holland,
	anup.patel, anuppate, dhaval, peter.lin

From: Raymond Mao <raymond.mao@riscstar.com>

Add sample dts overlay for testing hwirq/domain route rules.
Each domain uses property "opensbi,host-irqs" to describe one hwirq
route rule.
  'opensbi,host-irqs = <first_hwirq count> ...;'

During cold boot, route rules are converted and cached for VIRQ
routing/couriering purpose.

Usage:
1. Compile the overlay.
   $ dtc -@ -I dts -O dtb -o hwirq_bind_domain.dto \
         platform/generic/virt/hwirq_bind_domain.dts
2. Dump the base dtb from QEMU.
   $ qemu-system-riscv64 -M virt,aia=aplic-imsic -cpu rv64,zkr=on -m 4096 \
         -nographic -bios out/platform/generic/firmware/fw_jump.bin \
         -machine dumpdtb=qemu.dtb
3. Apply the overlay on the base.
   $ fdtoverlay -i qemu.dtb -o qemu_merge.dtb hwirq_bind_domain.dto
4. Re-run QEMU with adding argument '-dtb qemu_merge.dtb'

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 platform/generic/virt/hwirq_bind_domain.dts | 79 +++++++++++++++++++++
 1 file changed, 79 insertions(+)
 create mode 100644 platform/generic/virt/hwirq_bind_domain.dts

diff --git a/platform/generic/virt/hwirq_bind_domain.dts b/platform/generic/virt/hwirq_bind_domain.dts
new file mode 100644
index 00000000..b836901e
--- /dev/null
+++ b/platform/generic/virt/hwirq_bind_domain.dts
@@ -0,0 +1,79 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+	/*
+	 * Fragment 0: OpenSBI domain configuration under /chosen
+	 */
+	fragment@0 {
+		target-path = "/chosen";
+		__overlay__ {
+			opensbi-domains {
+				compatible = "opensbi,domain,config";
+
+				/*
+				 * DRAM region for domain1 (2GB from 0x8000_0000).
+				 * base is 64-bit: <hi lo>, order is log2(size).
+				 */
+				memregion_dram_2g: memregion_dram_2g {
+					compatible = "opensbi,domain,memregion";
+					base  = <0x0 0x80000000>;
+					order = <31>;
+				};
+
+				/*
+				 * UART MMIO region so S-mode payload can access UART registers
+				 * without fault. 0x1000_0000 size 4KB.
+				 */
+				uart0_mmio: memregion_uart0 {
+					compatible = "opensbi,domain,memregion";
+					base  = <0x0 0x10000000>;
+					order = <12>;
+				};
+
+				/*
+				 * Domain instance:
+				 * - possible-harts = <cpu0 phandle> (your cpu@0 phandle is 1)
+				 * - regions use label references (fdtoverlay will fixup phandles)
+				 * - opensbi,host-irqs uses <first count> pairs (NO chip phandle)
+				 */
+				domain1: domain1 {
+					compatible = "opensbi,domain,instance";
+
+					/* cpu@0 phandle in your base qemu dtb is 1 */
+					possible-harts = <0x1>;
+
+					/*
+					 * Keep permissive for test.
+					 * access=0x3f: enable all M+SU R/W/X flags (test only).
+					 */
+					regions = <&memregion_dram_2g 0x3f>,
+						  <&uart0_mmio 0x3f>;
+
+					/*
+					 * Route rule: Bind host HWIRQs ranges to this domain.
+					 * Format: <first_hwirq count> ...
+					 * If no route rule matches, HWIRQs default to root domain.
+					 *
+					 * UART RX is hwirq=10 on QEMU virt:
+					 *   fdtget -t i qemu_merge.dtb /soc/serial@10000000 interrupts
+					 *     => "10 4"
+					 *
+					 * Start with only <10 1> for clean bring-up.
+					 */
+					opensbi,host-irqs = <10 1>;
+				};
+			};
+		};
+	};
+
+	/*
+	 * Fragment 1: Assign cpu0 to domain1 using label reference
+	 */
+	fragment@1 {
+		target-path = "/cpus/cpu@0";
+		__overlay__ {
+			opensbi-domain = <&domain1>;
+		};
+	};
+};
\ No newline at end of file
-- 
2.25.1


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH RFC 3/3] lib: sbi: Add VIRQ ecall extension
  2026-02-13 19:04 [PATCH RFC 0/2] VIRQ (Virtual IRQ) layer to support paravirtual interrupt delivery Raymond Mao
  2026-02-13 19:04 ` [PATCH RFC 1/3] lib: sbi: Prototype of Virtual IRQ (VIRQ) layer for mapping/routing/courier/ IRQs Raymond Mao
  2026-02-13 19:04 ` [PATCH RFC 2/3] platform: generic: Add sample dts overlay for testing hwirq/domain route rules Raymond Mao
@ 2026-02-13 19:04 ` Raymond Mao
  2026-02-13 21:03   ` Andrew Jones
  2 siblings, 1 reply; 6+ messages in thread
From: Raymond Mao @ 2026-02-13 19:04 UTC (permalink / raw)
  To: opensbi
  Cc: scott, dave.patel, raymond.mao, robin.randhawa, samuel.holland,
	anup.patel, anuppate, dhaval, peter.lin

From: Raymond Mao <raymond.mao@riscstar.com>

Add vendor SBI extension ecall for VIRQ.
This allows S-mode payload to pop/complete the next pending VIRQ has
couried into the current domain.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 include/sbi/sbi_ecall_interface.h | 18 ++++++++++
 lib/sbi/Kconfig                   |  5 +++
 lib/sbi/objects.mk                |  3 ++
 lib/sbi/sbi_ecall_virq.c          | 57 +++++++++++++++++++++++++++++++
 4 files changed, 83 insertions(+)
 create mode 100644 lib/sbi/sbi_ecall_virq.c

diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
index 76624e3f..9cb9a7eb 100644
--- a/include/sbi/sbi_ecall_interface.h
+++ b/include/sbi/sbi_ecall_interface.h
@@ -126,6 +126,24 @@
 #define SBI_EXT_FWFT_SET		0x0
 #define SBI_EXT_FWFT_GET		0x1
 
+#ifdef CONFIG_SBI_ECALL_VIRQ
+
+/* Vendor extension base range is defined by the SBI spec. Choose a private ID. */
+#define SBI_EXT_VIRQ			0x0900524d
+
+/* Function IDs for SBI_EXT_VIRQ */
+#define SBI_EXT_VIRQ_POP		0
+#define SBI_EXT_VIRQ_COMPLETE		1
+
+/*
+ * SBI_EXT_VIRQ_POP
+ * Returns:
+ *   a0: SBI error code (0 for success)
+ *   a1: next pending hwirq (0 if none pending)
+ */
+
+#endif
+
 enum sbi_fwft_feature_t {
 	SBI_FWFT_MISALIGNED_EXC_DELEG		= 0x0,
 	SBI_FWFT_LANDING_PAD			= 0x1,
diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
index c6cc04bc..8479f861 100644
--- a/lib/sbi/Kconfig
+++ b/lib/sbi/Kconfig
@@ -69,4 +69,9 @@ config SBI_ECALL_SSE
 config SBI_ECALL_MPXY
 	bool "MPXY extension"
 	default y
+
+config SBI_ECALL_VIRQ
+	bool "VIRQ extension"
+	default y
+
 endmenu
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 07d13229..18e590ab 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -64,6 +64,9 @@ libsbi-objs-$(CONFIG_SBI_ECALL_SSE) += sbi_ecall_sse.o
 carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_MPXY) += ecall_mpxy
 libsbi-objs-$(CONFIG_SBI_ECALL_MPXY) += sbi_ecall_mpxy.o
 
+carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_VIRQ) += ecall_virq
+libsbi-objs-$(CONFIG_SBI_ECALL_VIRQ) += sbi_ecall_virq.o
+
 libsbi-objs-y += sbi_bitmap.o
 libsbi-objs-y += sbi_bitops.o
 libsbi-objs-y += sbi_console.o
diff --git a/lib/sbi/sbi_ecall_virq.c b/lib/sbi/sbi_ecall_virq.c
new file mode 100644
index 00000000..b192598e
--- /dev/null
+++ b/lib/sbi/sbi_ecall_virq.c
@@ -0,0 +1,57 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 RISCstar Solutions.
+ *
+ * Author: Raymond Mao <raymond.mao@riscstar.com>
+ */
+
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_ecall.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_trap.h>
+#include <sbi/sbi_virq.h>
+
+static int sbi_ecall_virq_handler(unsigned long extid,
+				  unsigned long funcid,
+				  struct sbi_trap_regs *regs,
+				  struct sbi_ecall_return *out)
+{
+	(void)extid;
+
+	sbi_printf("[ECALL VIRQ] VIRQ ecall handler, funcid: %ld\n", funcid);
+
+	switch (funcid) {
+	case SBI_EXT_VIRQ_POP:
+		out->value = (unsigned long)sbi_virq_pop_thishart();
+		return SBI_OK;
+	case SBI_EXT_VIRQ_COMPLETE:
+		u32 hwirq = (u32)regs->a0;
+
+		sbi_virq_complete_thishart(hwirq);
+		regs->a0 = 0;
+		return SBI_OK;
+	default:
+		return SBI_ENOTSUPP;
+	}
+}
+
+struct sbi_ecall_extension ecall_virq;
+
+static int sbi_ecall_virq_register_extensions(void)
+{
+	int ret;
+
+	ret = sbi_ecall_register_extension(&ecall_virq);
+	sbi_printf("[ECALL VIRQ] register VIRQ ecall extensions, ret=%d\n", ret);
+	return ret;
+}
+
+struct sbi_ecall_extension ecall_virq = {
+	.name        = "virq",
+	.extid_start = SBI_EXT_VIRQ,
+	.extid_end   = SBI_EXT_VIRQ,
+	.register_extensions    = sbi_ecall_virq_register_extensions,
+	.handle      = sbi_ecall_virq_handler,
+};
-- 
2.25.1


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH RFC 3/3] lib: sbi: Add VIRQ ecall extension
  2026-02-13 19:04 ` [PATCH RFC 3/3] lib: sbi: Add VIRQ ecall extension Raymond Mao
@ 2026-02-13 21:03   ` Andrew Jones
  2026-02-13 22:07     ` Raymond Mao
  0 siblings, 1 reply; 6+ messages in thread
From: Andrew Jones @ 2026-02-13 21:03 UTC (permalink / raw)
  To: Raymond Mao
  Cc: opensbi, scott, dave.patel, raymond.mao, robin.randhawa,
	samuel.holland, anup.patel, anuppate, dhaval, peter.lin

On Fri, Feb 13, 2026 at 02:04:59PM -0500, Raymond Mao wrote:
> From: Raymond Mao <raymond.mao@riscstar.com>
> 
> Add vendor SBI extension ecall for VIRQ.
> This allows S-mode payload to pop/complete the next pending VIRQ has
> couried into the current domain.
> 
> Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
> ---
>  include/sbi/sbi_ecall_interface.h | 18 ++++++++++
>  lib/sbi/Kconfig                   |  5 +++
>  lib/sbi/objects.mk                |  3 ++
>  lib/sbi/sbi_ecall_virq.c          | 57 +++++++++++++++++++++++++++++++
>  4 files changed, 83 insertions(+)
>  create mode 100644 lib/sbi/sbi_ecall_virq.c
> 
> diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
> index 76624e3f..9cb9a7eb 100644
> --- a/include/sbi/sbi_ecall_interface.h
> +++ b/include/sbi/sbi_ecall_interface.h
> @@ -126,6 +126,24 @@
>  #define SBI_EXT_FWFT_SET		0x0
>  #define SBI_EXT_FWFT_GET		0x1
>  
> +#ifdef CONFIG_SBI_ECALL_VIRQ
> +
> +/* Vendor extension base range is defined by the SBI spec. Choose a private ID. */
> +#define SBI_EXT_VIRQ			0x0900524d

I'm not sure where this number comes from. I'd expect it to be
0x56495251 == "VIRQ"

> +
> +/* Function IDs for SBI_EXT_VIRQ */
> +#define SBI_EXT_VIRQ_POP		0
> +#define SBI_EXT_VIRQ_COMPLETE		1
> +
> +/*
> + * SBI_EXT_VIRQ_POP
> + * Returns:
> + *   a0: SBI error code (0 for success)
> + *   a1: next pending hwirq (0 if none pending)
                         ^ virq, but...

how about creating an SBI function which allows registering a shared
memory region (as several SBI extensions already do) and then place a
bitmap in that shared memory which represents all virqs (a set bit means
that that virq is pending). That would allow S-mode to immediately get
all pending virqs in its SSE handler and we wouldn't need to worry about
a queue filling up. The downside is that S-mode wouldn't necessarily
handle the virqs in FIFO order. But, that can be a feature, because the
queue forces FIFO order whereas S-mode may need to handle them in some
priority order instead.

> + */
> +
> +#endif
> +
>  enum sbi_fwft_feature_t {
>  	SBI_FWFT_MISALIGNED_EXC_DELEG		= 0x0,
>  	SBI_FWFT_LANDING_PAD			= 0x1,
> diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
> index c6cc04bc..8479f861 100644
> --- a/lib/sbi/Kconfig
> +++ b/lib/sbi/Kconfig
> @@ -69,4 +69,9 @@ config SBI_ECALL_SSE
>  config SBI_ECALL_MPXY
>  	bool "MPXY extension"
>  	default y
> +
> +config SBI_ECALL_VIRQ
> +	bool "VIRQ extension"
> +	default y
> +
>  endmenu
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index 07d13229..18e590ab 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -64,6 +64,9 @@ libsbi-objs-$(CONFIG_SBI_ECALL_SSE) += sbi_ecall_sse.o
>  carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_MPXY) += ecall_mpxy
>  libsbi-objs-$(CONFIG_SBI_ECALL_MPXY) += sbi_ecall_mpxy.o
>  
> +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_VIRQ) += ecall_virq
> +libsbi-objs-$(CONFIG_SBI_ECALL_VIRQ) += sbi_ecall_virq.o
> +
>  libsbi-objs-y += sbi_bitmap.o
>  libsbi-objs-y += sbi_bitops.o
>  libsbi-objs-y += sbi_console.o
> diff --git a/lib/sbi/sbi_ecall_virq.c b/lib/sbi/sbi_ecall_virq.c
> new file mode 100644
> index 00000000..b192598e
> --- /dev/null
> +++ b/lib/sbi/sbi_ecall_virq.c
> @@ -0,0 +1,57 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2026 RISCstar Solutions.
> + *
> + * Author: Raymond Mao <raymond.mao@riscstar.com>
> + */
> +
> +#include <sbi/sbi_console.h>
> +#include <sbi/sbi_ecall.h>
> +#include <sbi/sbi_ecall_interface.h>
> +#include <sbi/sbi_error.h>
> +#include <sbi/sbi_trap.h>
> +#include <sbi/sbi_virq.h>
> +
> +static int sbi_ecall_virq_handler(unsigned long extid,
> +				  unsigned long funcid,
> +				  struct sbi_trap_regs *regs,
> +				  struct sbi_ecall_return *out)
> +{
> +	(void)extid;
> +
> +	sbi_printf("[ECALL VIRQ] VIRQ ecall handler, funcid: %ld\n", funcid);

You'll want to get rid of these print statements when posting without the
RFC.

Thanks,
drew

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH RFC 3/3] lib: sbi: Add VIRQ ecall extension
  2026-02-13 21:03   ` Andrew Jones
@ 2026-02-13 22:07     ` Raymond Mao
  0 siblings, 0 replies; 6+ messages in thread
From: Raymond Mao @ 2026-02-13 22:07 UTC (permalink / raw)
  To: Andrew Jones
  Cc: opensbi, scott, dave.patel, raymond.mao, robin.randhawa,
	samuel.holland, anup.patel, anuppate, dhaval, peter.lin

Hi Andrew,

On Fri, Feb 13, 2026 at 4:03 PM Andrew Jones
<andrew.jones@oss.qualcomm.com> wrote:
>
> On Fri, Feb 13, 2026 at 02:04:59PM -0500, Raymond Mao wrote:
> > From: Raymond Mao <raymond.mao@riscstar.com>
> >
> > Add vendor SBI extension ecall for VIRQ.
> > This allows S-mode payload to pop/complete the next pending VIRQ has
> > couried into the current domain.
> >
> > Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
> > ---
> >  include/sbi/sbi_ecall_interface.h | 18 ++++++++++
> >  lib/sbi/Kconfig                   |  5 +++
> >  lib/sbi/objects.mk                |  3 ++
> >  lib/sbi/sbi_ecall_virq.c          | 57 +++++++++++++++++++++++++++++++
> >  4 files changed, 83 insertions(+)
> >  create mode 100644 lib/sbi/sbi_ecall_virq.c
> >
> > diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
> > index 76624e3f..9cb9a7eb 100644
> > --- a/include/sbi/sbi_ecall_interface.h
> > +++ b/include/sbi/sbi_ecall_interface.h
> > @@ -126,6 +126,24 @@
> >  #define SBI_EXT_FWFT_SET             0x0
> >  #define SBI_EXT_FWFT_GET             0x1
> >
> > +#ifdef CONFIG_SBI_ECALL_VIRQ
> > +
> > +/* Vendor extension base range is defined by the SBI spec. Choose a private ID. */
> > +#define SBI_EXT_VIRQ                 0x0900524d
>
> I'm not sure where this number comes from. I'd expect it to be
> 0x56495251 == "VIRQ"
>
> > +
> > +/* Function IDs for SBI_EXT_VIRQ */
> > +#define SBI_EXT_VIRQ_POP             0
> > +#define SBI_EXT_VIRQ_COMPLETE                1
> > +
> > +/*
> > + * SBI_EXT_VIRQ_POP
> > + * Returns:
> > + *   a0: SBI error code (0 for success)
> > + *   a1: next pending hwirq (0 if none pending)
>                          ^ virq, but...
>
> how about creating an SBI function which allows registering a shared
> memory region (as several SBI extensions already do) and then place a
> bitmap in that shared memory which represents all virqs (a set bit means
> that that virq is pending). That would allow S-mode to immediately get
> all pending virqs in its SSE handler and we wouldn't need to worry about
> a queue filling up. The downside is that S-mode wouldn't necessarily
> handle the virqs in FIFO order. But, that can be a feature, because the
> queue forces FIFO order whereas S-mode may need to handle them in some
> priority order instead.
>

This sounds good. Maybe we can make both implementations selectable
via Kconfigs.
Let me collect more feedback, I can make the optional bitmap in a second phase.

> > + */
> > +
> > +#endif
> > +
> >  enum sbi_fwft_feature_t {
> >       SBI_FWFT_MISALIGNED_EXC_DELEG           = 0x0,
> >       SBI_FWFT_LANDING_PAD                    = 0x1,
> > diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
> > index c6cc04bc..8479f861 100644
> > --- a/lib/sbi/Kconfig
> > +++ b/lib/sbi/Kconfig
> > @@ -69,4 +69,9 @@ config SBI_ECALL_SSE
> >  config SBI_ECALL_MPXY
> >       bool "MPXY extension"
> >       default y
> > +
> > +config SBI_ECALL_VIRQ
> > +     bool "VIRQ extension"
> > +     default y
> > +
> >  endmenu
> > diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> > index 07d13229..18e590ab 100644
> > --- a/lib/sbi/objects.mk
> > +++ b/lib/sbi/objects.mk
> > @@ -64,6 +64,9 @@ libsbi-objs-$(CONFIG_SBI_ECALL_SSE) += sbi_ecall_sse.o
> >  carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_MPXY) += ecall_mpxy
> >  libsbi-objs-$(CONFIG_SBI_ECALL_MPXY) += sbi_ecall_mpxy.o
> >
> > +carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_VIRQ) += ecall_virq
> > +libsbi-objs-$(CONFIG_SBI_ECALL_VIRQ) += sbi_ecall_virq.o
> > +
> >  libsbi-objs-y += sbi_bitmap.o
> >  libsbi-objs-y += sbi_bitops.o
> >  libsbi-objs-y += sbi_console.o
> > diff --git a/lib/sbi/sbi_ecall_virq.c b/lib/sbi/sbi_ecall_virq.c
> > new file mode 100644
> > index 00000000..b192598e
> > --- /dev/null
> > +++ b/lib/sbi/sbi_ecall_virq.c
> > @@ -0,0 +1,57 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2026 RISCstar Solutions.
> > + *
> > + * Author: Raymond Mao <raymond.mao@riscstar.com>
> > + */
> > +
> > +#include <sbi/sbi_console.h>
> > +#include <sbi/sbi_ecall.h>
> > +#include <sbi/sbi_ecall_interface.h>
> > +#include <sbi/sbi_error.h>
> > +#include <sbi/sbi_trap.h>
> > +#include <sbi/sbi_virq.h>
> > +
> > +static int sbi_ecall_virq_handler(unsigned long extid,
> > +                               unsigned long funcid,
> > +                               struct sbi_trap_regs *regs,
> > +                               struct sbi_ecall_return *out)
> > +{
> > +     (void)extid;
> > +
> > +     sbi_printf("[ECALL VIRQ] VIRQ ecall handler, funcid: %ld\n", funcid);
>
> You'll want to get rid of these print statements when posting without the
> RFC.
>

Sure. No worries. The formal patch will come together with the
complete VIRQ implementation and all verbose prints will be removed.

Thanks and regards,
Raymond

> Thanks,
> drew

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-02-13 22:07 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-13 19:04 [PATCH RFC 0/2] VIRQ (Virtual IRQ) layer to support paravirtual interrupt delivery Raymond Mao
2026-02-13 19:04 ` [PATCH RFC 1/3] lib: sbi: Prototype of Virtual IRQ (VIRQ) layer for mapping/routing/courier/ IRQs Raymond Mao
2026-02-13 19:04 ` [PATCH RFC 2/3] platform: generic: Add sample dts overlay for testing hwirq/domain route rules Raymond Mao
2026-02-13 19:04 ` [PATCH RFC 3/3] lib: sbi: Add VIRQ ecall extension Raymond Mao
2026-02-13 21:03   ` Andrew Jones
2026-02-13 22:07     ` Raymond Mao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox