[PATCH 07/10] lib: utils: irqchip: derive APLIC targets from sysirq nodes
Raymond Mao
raymondmaoca at gmail.com
Thu May 14 15:57:53 PDT 2026
From: Raymond Mao <raymond.mao at riscstar.com>
Derive a per-HWIRQ target hartindex map from each sysirq node's
target domain boot-hart, and store the result in aplic_data.
This is used for setting IDC target per HWIRQ under irqchip driver
instead of hardcoding to a specific target.
Signed-off-by: Raymond Mao <raymond.mao at riscstar.com>
---
include/sbi_utils/irqchip/aplic.h | 1 +
lib/utils/irqchip/fdt_irqchip_aplic.c | 103 ++++++++++++++++++++++++++
2 files changed, 104 insertions(+)
diff --git a/include/sbi_utils/irqchip/aplic.h b/include/sbi_utils/irqchip/aplic.h
index 3461d1c7..d6e088f8 100644
--- a/include/sbi_utils/irqchip/aplic.h
+++ b/include/sbi_utils/irqchip/aplic.h
@@ -47,6 +47,7 @@ struct aplic_data {
struct aplic_msicfg_data msicfg_smode;
struct aplic_delegate_data delegate[APLIC_MAX_DELEGATE];
u32 *idc_map;
+ u32 *hwirq_target_hartindex;
};
int aplic_cold_irqchip_init(struct aplic_data *aplic);
diff --git a/lib/utils/irqchip/fdt_irqchip_aplic.c b/lib/utils/irqchip/fdt_irqchip_aplic.c
index f9b567f5..cbbdf8d8 100644
--- a/lib/utils/irqchip/fdt_irqchip_aplic.c
+++ b/lib/utils/irqchip/fdt_irqchip_aplic.c
@@ -13,6 +13,7 @@
#include <sbi/sbi_console.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_heap.h>
+#include <sbi/sbi_scratch.h>
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/irqchip/fdt_irqchip.h>
#include <sbi_utils/irqchip/aplic.h>
@@ -54,6 +55,88 @@ static int irqchip_aplic_update_idc_map(const void *fdt, int nodeoff,
return 0;
}
+static u32 irqchip_aplic_domain_boot_hartindex(void *fdt, int domain_offset)
+{
+ int len, cpu_offset;
+ const fdt32_t *val;
+
+ val = fdt_getprop(fdt, domain_offset, "boot-hart", &len);
+ if (val && len >= 4) {
+ cpu_offset = fdt_node_offset_by_phandle(fdt,
+ fdt32_to_cpu(*val));
+ if (cpu_offset >= 0) {
+ u32 hartid;
+
+ if (!fdt_parse_hart_id(fdt, cpu_offset, &hartid)) {
+ u32 hidx = sbi_hartid_to_hartindex(hartid);
+
+ if (sbi_hartindex_valid(hidx))
+ return hidx;
+ }
+ }
+ }
+
+ return current_hartindex();
+}
+
+static void irqchip_aplic_fill_hwirq_targets_from_sysirq(const void *fdt,
+ int aplic_nodeoff,
+ struct aplic_data *pd)
+{
+ int chosen_off, nodeoff;
+ int len, rc, index;
+ const fdt32_t *val;
+ u32 boot_hartindex;
+
+ if (!fdt || aplic_nodeoff < 0 || !pd || !pd->hwirq_target_hartindex)
+ return;
+
+ chosen_off = fdt_path_offset(fdt, "/chosen/opensbi-domains");
+ if (chosen_off < 0)
+ return;
+
+ fdt_for_each_subnode(nodeoff, fdt, chosen_off) {
+ if (fdt_node_check_compatible(fdt, nodeoff,
+ "opensbi,mpxy-sysirq"))
+ continue;
+
+ val = fdt_getprop(fdt, nodeoff, "opensbi,domain", &len);
+ if (!val || len < 4)
+ continue;
+
+ rc = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
+ if (rc < 0)
+ continue;
+
+ boot_hartindex = irqchip_aplic_domain_boot_hartindex((void *)fdt,
+ rc);
+
+ for (index = 0; ; index++) {
+ struct fdt_phandle_args args;
+
+ rc = fdt_parse_phandle_with_args(fdt, nodeoff,
+ "interrupts-extended",
+ "#interrupt-cells",
+ index, &args);
+ if (rc)
+ break;
+ if (args.args_count < 1)
+ continue;
+ if (args.node_offset != aplic_nodeoff)
+ continue;
+
+ u32 hwirq = args.args[0];
+
+ if (!hwirq || hwirq > pd->num_source)
+ continue;
+
+ if (pd->hwirq_target_hartindex[hwirq] == -1U)
+ pd->hwirq_target_hartindex[hwirq] =
+ boot_hartindex;
+ }
+ }
+}
+
static int irqchip_aplic_cold_init(const void *fdt, int nodeoff,
const struct fdt_match *match)
{
@@ -85,6 +168,24 @@ static int irqchip_aplic_cold_init(const void *fdt, int nodeoff,
goto fail_free_idc_map;
}
+ /* Precompute target hartindex per HWIRQ from DT. */
+ if (pd->targets_mmode) {
+ u32 i;
+
+ pd->hwirq_target_hartindex =
+ sbi_zalloc(sizeof(*pd->hwirq_target_hartindex) *
+ (pd->num_source + 1));
+ if (!pd->hwirq_target_hartindex) {
+ rc = SBI_ENOMEM;
+ goto fail_free_idc_map;
+ }
+
+ for (i = 0; i <= pd->num_source; i++)
+ pd->hwirq_target_hartindex[i] = -1U;
+
+ irqchip_aplic_fill_hwirq_targets_from_sysirq(fdt, nodeoff, pd);
+ }
+
rc = aplic_cold_irqchip_init(pd);
if (rc)
goto fail_free_idc_map;
@@ -93,6 +194,8 @@ static int irqchip_aplic_cold_init(const void *fdt, int nodeoff,
return 0;
fail_free_idc_map:
+ if (pd->hwirq_target_hartindex)
+ sbi_free(pd->hwirq_target_hartindex);
if (pd->num_idc)
sbi_free(pd->idc_map);
fail_free_data:
--
2.25.1
More information about the opensbi
mailing list