From 0f6d6b2ef221a05cc174f172cb904b4d2828efe0 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Fri, 27 Sep 2024 18:39:19 +0800 Subject: [PATCH] drivers: gicv3: add distributor safe configuration In case of multiple OSes running on different CPU Cores which share the same GIC controller, need to avoid the distributor re-configured to avoid crash the OS has already been started. Signed-off-by: Jiafei Pan --- drivers/interrupt_controller/Kconfig.gic | 10 ++++++++++ drivers/interrupt_controller/intc_gicv3.c | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/interrupt_controller/Kconfig.gic b/drivers/interrupt_controller/Kconfig.gic index 0e90f9874fa..b482bf3336b 100644 --- a/drivers/interrupt_controller/Kconfig.gic +++ b/drivers/interrupt_controller/Kconfig.gic @@ -63,4 +63,14 @@ config GIC_V3_ITS that ITS uses dynamic memory, so HEAP_MEM_POOL_SIZE should be enough to allocate ITS tables (size is probed at runtime). +config GIC_SAFE_CONFIG + bool "GIC Distributor Safe Configuration" + depends on GIC_V3 + default n + help + In case of multiple OSes running on different CPU Cores which share the + same GIC controller, need to avoid the distributor re-configured to avoid + crash the OS has already been started. With this enabled, it will bypass + GIC distributor configuration if it has been configured by other OS. + endif # CPU_CORTEX diff --git a/drivers/interrupt_controller/intc_gicv3.c b/drivers/interrupt_controller/intc_gicv3.c index f3f9259f5ea..c84a42c7e36 100644 --- a/drivers/interrupt_controller/intc_gicv3.c +++ b/drivers/interrupt_controller/intc_gicv3.c @@ -447,6 +447,17 @@ static void gicv3_dist_init(void) unsigned int idx; mem_addr_t base = GIC_DIST_BASE; +#ifdef CONFIG_GIC_SAFE_CONFIG + /* + * Currently multiple OSes can run one the different CPU Cores which share single GIC, + * but GIC distributor should avoid to be re-configured in order to avoid crash the + * OSes has already been started. + */ + if (sys_read32(GICD_CTLR) & (BIT(GICD_CTLR_ENABLE_G0) | BIT(GICD_CTLR_ENABLE_G1NS))) { + return; + } +#endif + num_ints = sys_read32(GICD_TYPER); num_ints &= GICD_TYPER_ITLINESNUM_MASK; num_ints = (num_ints + 1) << 5;