From 90258fd94494eb74c92066bcb071a173ffa8f8c5 Mon Sep 17 00:00:00 2001 From: heyuanjie87 <943313837@qq.com> Date: Fri, 22 Nov 2024 18:11:26 +0800 Subject: [PATCH 1/8] =?UTF-8?q?[libcpu][riscv]=E7=BB=9F=E4=B8=80plic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/risc-v/{t-head/c908 => plic}/plic.c | 10 +++++----- libcpu/risc-v/{t-head/c908 => plic}/plic.h | 10 ++-------- libcpu/risc-v/t-head/c906/interrupt.c | 6 +++++- libcpu/risc-v/t-head/c908/interrupt.c | 6 +++++- 4 files changed, 17 insertions(+), 15 deletions(-) rename libcpu/risc-v/{t-head/c908 => plic}/plic.c (96%) rename libcpu/risc-v/{t-head/c908 => plic}/plic.h (85%) diff --git a/libcpu/risc-v/t-head/c908/plic.c b/libcpu/risc-v/plic/plic.c similarity index 96% rename from libcpu/risc-v/t-head/c908/plic.c rename to libcpu/risc-v/plic/plic.c index 08cb6c18d2f..18572cf8da9 100644 --- a/libcpu/risc-v/t-head/c908/plic.c +++ b/libcpu/risc-v/plic/plic.c @@ -31,7 +31,7 @@ struct plic_handler }; rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable); -struct plic_handler plic_handlers[C908_NR_CPUS]; +struct plic_handler plic_handlers[NR_CPUS]; static void *plic_irq_priority[INTERRUPTS_MAX] = {RT_NULL}; rt_inline void plic_irq_toggle(int hwirq, int enable) @@ -153,7 +153,7 @@ rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable) } } -void plic_init(void) +void plic_init(unsigned long base_pa) { int nr_irqs; int nr_context; @@ -167,16 +167,16 @@ void plic_init(void) return; } - nr_context = C908_NR_CONTEXT; + nr_context = PLIC_NR_CONTEXT; - plic_regs = (void *)C908_PLIC_PHY_ADDR; + plic_regs = (void *)base_pa; if (!plic_regs) { LOG_E("fatal error, plic is reg space is null."); return; } - nr_irqs = C908_PLIC_NR_EXT_IRQS; + nr_irqs = IRQ_MAX_NR; for (i = 0; i < nr_context; i ++) { diff --git a/libcpu/risc-v/t-head/c908/plic.h b/libcpu/risc-v/plic/plic.h similarity index 85% rename from libcpu/risc-v/t-head/c908/plic.h rename to libcpu/risc-v/plic/plic.h index 94f00eacdb8..8c66e347538 100644 --- a/libcpu/risc-v/t-head/c908/plic.h +++ b/libcpu/risc-v/plic/plic.h @@ -14,14 +14,8 @@ #include -#ifndef C908_PLIC_PHY_ADDR -#define C908_PLIC_PHY_ADDR (0xF00000000UL) -#endif -#define C908_PLIC_NR_EXT_IRQS (IRQ_MAX_NR) -#define C908_NR_CPUS (NR_CPUS) - /* M and S mode context. */ -#define C908_NR_CONTEXT (2) +#define PLIC_NR_CONTEXT (2) #define MAX_DEVICES 1024 #define MAX_CONTEXTS 15872 @@ -50,7 +44,7 @@ #define CONTEXT_THRESHOLD 0x00 #define CONTEXT_CLAIM 0x04 -void plic_init(void); +void plic_init(unsigned long base_pa); void plic_enable_irq(int irqno); void plic_disable_irq(int irqno); // tell PLIC that we've served this IRQ diff --git a/libcpu/risc-v/t-head/c906/interrupt.c b/libcpu/risc-v/t-head/c906/interrupt.c index 2f7a86e6802..b7290bd4298 100644 --- a/libcpu/risc-v/t-head/c906/interrupt.c +++ b/libcpu/risc-v/t-head/c906/interrupt.c @@ -15,6 +15,10 @@ #include "riscv.h" #include "plic.h" +#ifndef C906_PLIC_PHY_ADDR +#define C906_PLIC_PHY_ADDR (0x10000000) +#endif + extern rt_atomic_t rt_interrupt_nest; extern rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; extern rt_uint32_t rt_thread_switch_interrupt_flag; @@ -32,7 +36,7 @@ static void rt_hw_interrupt_handler(int vector, void *param) void rt_hw_interrupt_init(void) { /* init interrupt controller */ - plic_init(); + plic_init(C906_PLIC_PHY_ADDR); rt_int32_t idx; diff --git a/libcpu/risc-v/t-head/c908/interrupt.c b/libcpu/risc-v/t-head/c908/interrupt.c index 2f7a86e6802..5349b0b4e93 100644 --- a/libcpu/risc-v/t-head/c908/interrupt.c +++ b/libcpu/risc-v/t-head/c908/interrupt.c @@ -15,6 +15,10 @@ #include "riscv.h" #include "plic.h" +#ifndef C908_PLIC_PHY_ADDR +#define C908_PLIC_PHY_ADDR (0xF00000000UL) +#endif + extern rt_atomic_t rt_interrupt_nest; extern rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; extern rt_uint32_t rt_thread_switch_interrupt_flag; @@ -32,7 +36,7 @@ static void rt_hw_interrupt_handler(int vector, void *param) void rt_hw_interrupt_init(void) { /* init interrupt controller */ - plic_init(); + plic_init(C908_PLIC_PHY_ADDR); rt_int32_t idx; From 467aed29c3049150354f31104c5056ea68ab06fa Mon Sep 17 00:00:00 2001 From: heyuanjie87 <943313837@qq.com> Date: Fri, 22 Nov 2024 18:15:53 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/risc-v/plic/SConscript | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 libcpu/risc-v/plic/SConscript diff --git a/libcpu/risc-v/plic/SConscript b/libcpu/risc-v/plic/SConscript new file mode 100644 index 00000000000..d6bcf2cee20 --- /dev/null +++ b/libcpu/risc-v/plic/SConscript @@ -0,0 +1,10 @@ +# RT-Thread building script for component + +from building import * +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') From f4342388118667a17619b417fdc29f9bc68d7155 Mon Sep 17 00:00:00 2001 From: heyuanjie87 <943313837@qq.com> Date: Fri, 22 Nov 2024 19:28:37 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E6=B8=85=E7=90=86virt64=E7=9A=84plic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/qemu-virt64-riscv/driver/board.c | 2 - libcpu/risc-v/SConscript | 3 + libcpu/risc-v/plic/plic.c | 92 +++++++++------- libcpu/risc-v/plic/plic.h | 2 + libcpu/risc-v/virt64/interrupt.c | 35 +++--- libcpu/risc-v/virt64/interrupt.h | 10 +- libcpu/risc-v/virt64/plic.c | 156 --------------------------- libcpu/risc-v/virt64/plic.h | 77 ------------- 8 files changed, 90 insertions(+), 287 deletions(-) delete mode 100644 libcpu/risc-v/virt64/plic.c delete mode 100644 libcpu/risc-v/virt64/plic.h diff --git a/bsp/qemu-virt64-riscv/driver/board.c b/bsp/qemu-virt64-riscv/driver/board.c index c5116aad0c5..35ea0fa7fb2 100644 --- a/bsp/qemu-virt64-riscv/driver/board.c +++ b/bsp/qemu-virt64-riscv/driver/board.c @@ -76,8 +76,6 @@ void rt_hw_board_init(void) rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); #endif - plic_init(); - rt_hw_interrupt_init(); rt_hw_uart_init(); diff --git a/libcpu/risc-v/SConscript b/libcpu/risc-v/SConscript index 273c997e8eb..82ee5e5e444 100644 --- a/libcpu/risc-v/SConscript +++ b/libcpu/risc-v/SConscript @@ -16,6 +16,9 @@ if rtconfig.CPU in common64_arch : else : group += SConscript(os.path.join('common', 'SConscript')) + +group += SConscript(os.path.join('plic', 'SConscript')) + # cpu porting code files if 'VENDOR' in vars(rtconfig) and rtconfig.VENDOR != '': group = group + SConscript(os.path.join(rtconfig.VENDOR, rtconfig.CPU, 'SConscript')) diff --git a/libcpu/risc-v/plic/plic.c b/libcpu/risc-v/plic/plic.c index 18572cf8da9..df59a8fc53d 100644 --- a/libcpu/risc-v/plic/plic.c +++ b/libcpu/risc-v/plic/plic.c @@ -20,35 +20,29 @@ #include "encoding.h" #include "ioremap.h" -static void *plic_regs = RT_NULL; +static void *plic_regs = RT_NULL; extern struct rt_irq_desc isr_table[]; struct plic_handler { rt_bool_t present; - void *hart_base; - void *enable_base; + void *hart_base; + void *enable_base; }; -rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable); +rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable); struct plic_handler plic_handlers[NR_CPUS]; -static void *plic_irq_priority[INTERRUPTS_MAX] = {RT_NULL}; +static void *plic_irq_priority[INTERRUPTS_MAX] = {RT_NULL}; + +static inline struct plic_handler* plic_get_handler(int cpu) +{ + return &plic_handlers[cpu]; +} rt_inline void plic_irq_toggle(int hwirq, int enable) { - int cpu = 0; - void *priority_addr; + int cpu = 0; - /* set priority of interrupt, interrupt 0 is zero. */ - priority_addr = (void *)((rt_size_t)plic_regs + PRIORITY_BASE + hwirq * PRIORITY_PER_ID); -#ifdef RT_USING_SMART - if (plic_irq_priority[hwirq] == RT_NULL) - { - plic_irq_priority[hwirq] = (void *)rt_ioremap(priority_addr, 0x1000); - } - priority_addr = plic_irq_priority[hwirq]; -#endif - writel(enable, priority_addr); struct plic_handler *handler = &plic_handlers[cpu]; if (handler->present) @@ -60,7 +54,7 @@ rt_inline void plic_irq_toggle(int hwirq, int enable) static void generic_handle_irq(int irq) { rt_isr_handler_t isr; - void *param; + void *param; if (irq < 0 || irq >= IRQ_MAX_NR) { @@ -68,12 +62,12 @@ static void generic_handle_irq(int irq) return; } - if (!irq) // irq = 0 => no irq + if (!irq) // irq = 0 => no irq { LOG_W("no irq!\n"); return; } - isr = isr_table[IRQ_OFFSET + irq].handler; + isr = isr_table[IRQ_OFFSET + irq].handler; param = isr_table[IRQ_OFFSET + irq].param; if (isr != RT_NULL) { @@ -85,7 +79,7 @@ static void generic_handle_irq(int irq) void plic_complete(int irqno) { - int cpu = 0; + int cpu = 0; struct plic_handler *handler = &plic_handlers[cpu]; writel(irqno, (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM)); @@ -109,11 +103,11 @@ void plic_enable_irq(int irqno) */ void plic_handle_irq(void) { - int cpu = 0; + int cpu = 0; unsigned int irq; struct plic_handler *handler = &plic_handlers[cpu]; - void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM); + void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM); if (plic_regs == RT_NULL || !handler->present) { @@ -140,8 +134,8 @@ void plic_handle_irq(void) rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable) { - uint32_t *reg = (uint32_t *)((rt_size_t)handler->enable_base + (hwirq / 32) * sizeof(uint32_t)); - uint32_t hwirq_mask = 1 << (hwirq % 32); + uint32_t *reg = (uint32_t *)((rt_size_t)handler->enable_base + (hwirq / 32) * sizeof(uint32_t)); + uint32_t hwirq_mask = 1 << (hwirq % 32); if (enable) { @@ -155,11 +149,11 @@ rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable) void plic_init(unsigned long base_pa) { - int nr_irqs; - int nr_context; - int i; + int nr_irqs; + int nr_context; + int i; unsigned long hwirq; - int cpu = 0; + int cpu = 0; if (plic_regs) { @@ -178,10 +172,10 @@ void plic_init(unsigned long base_pa) nr_irqs = IRQ_MAX_NR; - for (i = 0; i < nr_context; i ++) + for (i = 0; i < nr_context; i++) { struct plic_handler *handler; - uint32_t threshold = 0; + uint32_t threshold = 0; cpu = 0; @@ -195,18 +189,18 @@ void plic_init(unsigned long base_pa) handler = &plic_handlers[cpu]; if (handler->present) { - threshold = 0xffffffff; + threshold = 0xffffffff; goto done; } - handler->present = RT_TRUE; - handler->hart_base = (void *)((rt_size_t)plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART); + handler->present = RT_TRUE; + handler->hart_base = (void *)((rt_size_t)plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART); handler->enable_base = (void *)((rt_size_t)plic_regs + ENABLE_BASE + i * ENABLE_PER_HART); #ifdef RT_USING_SMART - handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000); + handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000); handler->enable_base = (void *)rt_ioremap(handler->enable_base, 0x1000); #endif -done: + done: /* priority must be > threshold to trigger an interrupt */ writel(threshold, (void *)((rt_size_t)handler->hart_base + CONTEXT_THRESHOLD)); for (hwirq = 1; hwirq <= nr_irqs; hwirq++) @@ -218,3 +212,29 @@ void plic_init(unsigned long base_pa) /* Enable supervisor external interrupts. */ set_csr(sie, SIE_SEIE); } + +void plic_set_threshold(int threshold) +{ + int hart = 0; + struct plic_handler *handler; + + handler = plic_get_handler(hart); + + writel(threshold, (void *)((rt_size_t)handler->hart_base + CONTEXT_THRESHOLD)); +} + +void plic_set_priority(int irq, int priority) +{ + void *priority_addr; + + /* set priority of interrupt, interrupt 0 is zero. */ + priority_addr = (void *)((rt_size_t)plic_regs + PRIORITY_BASE + irq * PRIORITY_PER_ID); +#ifdef RT_USING_SMART + if (plic_irq_priority[hwirq] == RT_NULL) + { + plic_irq_priority[hwirq] = (void *)rt_ioremap(priority_addr, 0x1000); + } + priority_addr = plic_irq_priority[hwirq]; +#endif + writel(priority, priority_addr); +} diff --git a/libcpu/risc-v/plic/plic.h b/libcpu/risc-v/plic/plic.h index 8c66e347538..46a6860f7aa 100644 --- a/libcpu/risc-v/plic/plic.h +++ b/libcpu/risc-v/plic/plic.h @@ -50,5 +50,7 @@ void plic_disable_irq(int irqno); // tell PLIC that we've served this IRQ void plic_complete(int irq); void plic_handle_irq(void); +void plic_set_threshold(int mthreshold); +void plic_set_priority(int irq, int priority); #endif diff --git a/libcpu/risc-v/virt64/interrupt.c b/libcpu/risc-v/virt64/interrupt.c index f627210dac2..ace4bb35c0f 100644 --- a/libcpu/risc-v/virt64/interrupt.c +++ b/libcpu/risc-v/virt64/interrupt.c @@ -15,7 +15,11 @@ #include "riscv.h" #include "interrupt.h" -struct rt_irq_desc irq_desc[MAX_HANDLERS]; +#ifndef PLIC_BASE_ADDR +#define PLIC_BASE_ADDR 0x0c000000 +#endif + +struct rt_irq_desc isr_table[INTERRUPTS_MAX]; static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param) { @@ -25,13 +29,13 @@ static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param) int rt_hw_plic_irq_enable(int irq_number) { - plic_irq_enable(irq_number); + plic_enable_irq(irq_number); return 0; } int rt_hw_plic_irq_disable(int irq_number) { - plic_irq_disable(irq_number); + plic_disable_irq(irq_number); return 0; } @@ -57,16 +61,16 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, { rt_isr_handler_t old_handler = RT_NULL; - if(vector < MAX_HANDLERS) + if(vector < INTERRUPTS_MAX) { - old_handler = irq_desc[vector].handler; + old_handler = isr_table[vector].handler; if (handler != RT_NULL) { - irq_desc[vector].handler = (rt_isr_handler_t)handler; - irq_desc[vector].param = param; + isr_table[vector].handler = (rt_isr_handler_t)handler; + isr_table[vector].param = param; #ifdef RT_USING_INTERRUPT_INFO - rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name); - irq_desc[vector].counter = 0; + rt_snprintf(isr_table[vector].name, RT_NAME_MAX - 1, "%s", name); + isr_table[vector].counter = 0; #endif } } @@ -79,14 +83,17 @@ void rt_hw_interrupt_init() /* Enable machine external interrupts. */ // set_csr(sie, SIP_SEIP); int idx = 0; + + plic_init(PLIC_BASE_ADDR); + /* init exceptions table */ - for (idx = 0; idx < MAX_HANDLERS; idx++) + for (idx = 0; idx < INTERRUPTS_MAX; idx++) { - irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; - irq_desc[idx].param = RT_NULL; + isr_table[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; + isr_table[idx].param = RT_NULL; #ifdef RT_USING_INTERRUPT_INFO - rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default"); - irq_desc[idx].counter = 0; + rt_snprintf(isr_table[idx].name, RT_NAME_MAX - 1, "default"); + isr_table[idx].counter = 0; #endif } diff --git a/libcpu/risc-v/virt64/interrupt.h b/libcpu/risc-v/virt64/interrupt.h index 5b7ff57a476..f4d057a31d0 100644 --- a/libcpu/risc-v/virt64/interrupt.h +++ b/libcpu/risc-v/virt64/interrupt.h @@ -11,11 +11,17 @@ #ifndef INTERRUPT_H__ #define INTERRUPT_H__ -#define MAX_HANDLERS 128 - #include #include "stack.h" +#define NR_CPUS 1 + +#define IRQ_OFFSET 0 +#ifndef IRQ_MAX_NR +#define IRQ_MAX_NR 128 +#endif +#define INTERRUPTS_MAX (IRQ_OFFSET + IRQ_MAX_NR) + enum { EP_INSTRUCTION_ADDRESS_MISALIGNED = 0, diff --git a/libcpu/risc-v/virt64/plic.c b/libcpu/risc-v/virt64/plic.c deleted file mode 100644 index f222146f34d..00000000000 --- a/libcpu/risc-v/virt64/plic.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-20 bigmagic first version - * 2022-09-16 WangXiaoyao Porting to rv64 - */ -#include -#include -#include -#include "plic.h" -#include -#include "encoding.h" -#include - -#include -#include -#include - -#ifdef RT_USING_SMART -#include -#else -#define rt_ioremap(addr, ...) (addr) -#endif - -size_t plic_base = 0x0c000000L; - -/* - * Each PLIC interrupt source can be assigned a priority by writing - * to its 32-bit memory-mapped priority register. - * The QEMU-virt (the same as FU540-C000) supports 7 levels of priority. - * A priority value of 0 is reserved to mean "never interrupt" and - * effectively disables the interrupt. - * Priority 1 is the lowest active priority, and priority 7 is the highest. - * Ties between global interrupts of the same priority are broken by - * the Interrupt ID; interrupts with the lowest ID have the highest - * effective priority. - */ -void plic_set_priority(int irq, int priority) -{ - *(uint32_t *)PLIC_PRIORITY(irq) = priority; -} - -/* - * Each global interrupt can be enabled by setting the corresponding - * bit in the enables registers. - */ -void plic_irq_enable(int irq) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_ENABLE(hart) = ((*(uint32_t *)PLIC_ENABLE(hart)) | (1 << irq)); -#ifdef RISCV_S_MODE - set_csr(sie, read_csr(sie) | MIP_SEIP); -#else - set_csr(mie, read_csr(mie) | MIP_MEIP); -#endif -} - -void plic_irq_disable(int irq) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_ENABLE(hart) = (((*(uint32_t *)PLIC_ENABLE(hart)) & (~(1 << irq)))); -} - -/* - * PLIC will mask all interrupts of a priority less than or equal to threshold. - * Maximum threshold is 7. - * For example, a threshold value of zero permits all interrupts with - * non-zero priority, whereas a value of 7 masks all interrupts. - * Notice, the threshold is global for PLIC, not for each interrupt source. - */ -void plic_set_threshold(int threshold) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_THRESHOLD(hart) = threshold; -} - -/* - * DESCRIPTION: - * Query the PLIC what interrupt we should serve. - * Perform an interrupt claim by reading the claim register, which - * returns the ID of the highest-priority pending interrupt or zero if there - * is no pending interrupt. - * A successful claim also atomically clears the corresponding pending bit - * on the interrupt source. - * RETURN VALUE: - * the ID of the highest-priority pending interrupt or zero if there - * is no pending interrupt. - */ -int plic_claim(void) -{ - int hart = __raw_hartid(); - int irq = *(uint32_t *)PLIC_CLAIM(hart); - return irq; -} - -/* - * DESCRIPTION: - * Writing the interrupt ID it received from the claim (irq) to the - * complete register would signal the PLIC we've served this IRQ. - * The PLIC does not check whether the completion ID is the same as the - * last claim ID for that target. If the completion ID does not match an - * interrupt source that is currently enabled for the target, the completion - * is silently ignored. - * RETURN VALUE: none - */ -void plic_complete(int irq) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_COMPLETE(hart) = irq; -} - -void plic_set_ie(rt_uint32_t word_index, rt_uint32_t val) -{ - volatile void *plic_ie = (void *)(rt_ubase_t)(plic_base + PLIC_ENABLE_BASE + 0x80 + word_index * 4); - writel(val, plic_ie); -} - -static void _set_sie(int hartid) -{ - for (size_t i = hartid * WORD_CNT_BYTE; i < 32; i++) - plic_set_ie(i, 0xffffffff); -} - -void plic_init() -{ - // PLIC takes up 64 MB space - plic_base = (size_t)rt_ioremap((void *)plic_base, 64 * 1024 * 1024); - - plic_set_threshold(0); - - for (int i = 0; i < CONFIG_IRQ_NR; i++) - { - plic_set_priority(i, 1); - } - - // in a single core system, only current context was set - _set_sie(__raw_hartid()); -} - -extern struct rt_irq_desc irq_desc[MAX_HANDLERS]; -/* - * Handling an interrupt is a two-step process: first you claim the interrupt - * by reading the claim register, then you complete the interrupt by writing - * that source ID back to the same claim register. This automatically enables - * and disables the interrupt, so there's nothing else to do. - */ -void plic_handle_irq(void) -{ - int plic_irq = plic_claim(); - plic_complete(plic_irq); - irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param); -} diff --git a/libcpu/risc-v/virt64/plic.h b/libcpu/risc-v/virt64/plic.h deleted file mode 100644 index 314210c66b5..00000000000 --- a/libcpu/risc-v/virt64/plic.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-20 bigmagic first version - * 2021-10-20 bernard fix s-mode issue - */ - -#ifndef __PLIC_H__ -#define __PLIC_H__ - -#include -#include - -#define PLIC_PRIORITY_BASE 0x0 -#define PLIC_PENDING_BASE 0x1000 -#define PLIC_ENABLE_BASE 0x2000 -#define PLIC_CONTEXT_BASE 0x200000 - -extern size_t plic_base; - -#define VIRT_PLIC_BASE (plic_base) - -#define PLIC_PRIORITY_OFFSET (0x0) -#define PLIC_PENDING_OFFSET (0x1000) - -#define PLIC_ENABLE_STRIDE 0x80 -#define PLIC_CONTEXT_STRIDE 0x1000 - -#ifndef RISCV_S_MODE -#define PLIC_MENABLE_OFFSET (0x2000) -#define PLIC_MTHRESHOLD_OFFSET (0x200000) -#define PLIC_MCLAIM_OFFSET (0x200004) -#define PLIC_MCOMPLETE_OFFSET (0x200004) - -#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_MENABLE_OFFSET + (hart * 2) * PLIC_ENABLE_STRIDE) -#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_MTHRESHOLD_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_MCLAIM_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_MCOMPLETE_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) - -#else -#define PLIC_SENABLE_OFFSET (0x2000 + PLIC_ENABLE_STRIDE) -#define PLIC_STHRESHOLD_OFFSET (0x200000 + PLIC_CONTEXT_STRIDE) -#define PLIC_SCLAIM_OFFSET (0x200004 + PLIC_CONTEXT_STRIDE) -#define PLIC_SCOMPLETE_OFFSET (0x200004 + PLIC_CONTEXT_STRIDE) - -#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_SENABLE_OFFSET + (hart * 2) * PLIC_ENABLE_STRIDE) -#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_STHRESHOLD_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_SCLAIM_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_SCOMPLETE_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#endif - -#define PLIC_PRIORITY(id) (VIRT_PLIC_BASE + PLIC_PRIORITY_OFFSET + (id) * 4) -#define PLIC_PENDING(id) (VIRT_PLIC_BASE + PLIC_PENDING_OFFSET + ((id) / 32)) - -#define WORD_CNT_BYTE (1024 / 8) - -/* IRQ config in system, max 1024 (from 0 to 1023) */ -#define CONFIG_IRQ_NR (128) -#define CONFIG_IRQ_WORD (CONFIG_IRQ_NR / 32) - -void plic_set_priority(int irq, int priority); -void plic_irq_enable(int irq); -void plic_irq_disable(int irq); -void plic_set_threshold(int mthreshold); -int plic_claim(void); -void plic_complete(int irq); - -void plic_set_thresh(rt_uint32_t val); -void plic_set_ie(rt_uint32_t word_index,rt_uint32_t val); -void plic_init(); -void plic_handle_irq(void); - -#endif From cfc4c1158cd2a719ecd1ffb7ff4ee099837743eb Mon Sep 17 00:00:00 2001 From: heyuanjie87 <943313837@qq.com> Date: Tue, 26 Nov 2024 16:45:32 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/risc-v/plic/plic.c | 77 +++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 32 deletions(-) diff --git a/libcpu/risc-v/plic/plic.c b/libcpu/risc-v/plic/plic.c index df59a8fc53d..d450827cc55 100644 --- a/libcpu/risc-v/plic/plic.c +++ b/libcpu/risc-v/plic/plic.c @@ -20,7 +20,6 @@ #include "encoding.h" #include "ioremap.h" -static void *plic_regs = RT_NULL; extern struct rt_irq_desc isr_table[]; struct plic_handler @@ -30,20 +29,33 @@ struct plic_handler void *enable_base; }; -rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable); -struct plic_handler plic_handlers[NR_CPUS]; -static void *plic_irq_priority[INTERRUPTS_MAX] = {RT_NULL}; +struct plic +{ + void *base_pa; + volatile rt_uint32_t *priority_base; + + struct plic_handler handlers[NR_CPUS]; +}; + +static struct plic _plic = {}; + +rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable); + +rt_inline struct plic_handler *plic_get_handler(int cpu) +{ + return &_plic.handlers[cpu]; +} -static inline struct plic_handler* plic_get_handler(int cpu) +rt_inline struct plic *plic_get(void) { - return &plic_handlers[cpu]; + return &_plic; } rt_inline void plic_irq_toggle(int hwirq, int enable) { - int cpu = 0; + int cpu = 0; - struct plic_handler *handler = &plic_handlers[cpu]; + struct plic_handler *handler = plic_get_handler(cpu); if (handler->present) { @@ -79,8 +91,8 @@ static void generic_handle_irq(int irq) void plic_complete(int irqno) { - int cpu = 0; - struct plic_handler *handler = &plic_handlers[cpu]; + int cpu = 0; + struct plic_handler *handler = plic_get_handler(cpu); writel(irqno, (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM)); } @@ -106,10 +118,10 @@ void plic_handle_irq(void) int cpu = 0; unsigned int irq; - struct plic_handler *handler = &plic_handlers[cpu]; + struct plic_handler *handler = plic_get_handler(cpu); void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM); - if (plic_regs == RT_NULL || !handler->present) + if (!handler->present) { LOG_E("plic state not initialized."); return; @@ -153,29 +165,29 @@ void plic_init(unsigned long base_pa) int nr_context; int i; unsigned long hwirq; - int cpu = 0; + int cpu = 0; + struct plic *plic = plic_get(); - if (plic_regs) + if (plic->base_pa) { LOG_E("plic already initialized!"); return; } - nr_context = PLIC_NR_CONTEXT; - - plic_regs = (void *)base_pa; - if (!plic_regs) + if (!base_pa) { LOG_E("fatal error, plic is reg space is null."); return; } + plic->base_pa = (void*)base_pa; - nr_irqs = IRQ_MAX_NR; + nr_context = PLIC_NR_CONTEXT; + nr_irqs = IRQ_MAX_NR; for (i = 0; i < nr_context; i++) { struct plic_handler *handler; - uint32_t threshold = 0; + uint32_t threshold = 0; cpu = 0; @@ -186,7 +198,7 @@ void plic_init(unsigned long base_pa) } // we always use CPU0 M-mode target register. - handler = &plic_handlers[cpu]; + handler = plic_get_handler(cpu); if (handler->present) { threshold = 0xffffffff; @@ -194,8 +206,8 @@ void plic_init(unsigned long base_pa) } handler->present = RT_TRUE; - handler->hart_base = (void *)((rt_size_t)plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART); - handler->enable_base = (void *)((rt_size_t)plic_regs + ENABLE_BASE + i * ENABLE_PER_HART); + handler->hart_base = (void *)(plic->base_pa + CONTEXT_BASE + i * CONTEXT_PER_HART); + handler->enable_base = (void *)(plic->base_pa + ENABLE_BASE + i * ENABLE_PER_HART); #ifdef RT_USING_SMART handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000); handler->enable_base = (void *)rt_ioremap(handler->enable_base, 0x1000); @@ -215,7 +227,7 @@ void plic_init(unsigned long base_pa) void plic_set_threshold(int threshold) { - int hart = 0; + int hart = 0; struct plic_handler *handler; handler = plic_get_handler(hart); @@ -225,16 +237,17 @@ void plic_set_threshold(int threshold) void plic_set_priority(int irq, int priority) { - void *priority_addr; + struct plic *plic = plic_get(); /* set priority of interrupt, interrupt 0 is zero. */ - priority_addr = (void *)((rt_size_t)plic_regs + PRIORITY_BASE + irq * PRIORITY_PER_ID); -#ifdef RT_USING_SMART - if (plic_irq_priority[hwirq] == RT_NULL) + if (plic->priority_base == RT_NULL) { - plic_irq_priority[hwirq] = (void *)rt_ioremap(priority_addr, 0x1000); - } - priority_addr = plic_irq_priority[hwirq]; +#ifdef RT_USING_SMART + plic->priority_base = (rt_uint32_t *)rt_ioremap(plic->base_pa, 0x1000); +#else + plic->priority_base = (rt_uint32_t *)plic->base_pa; #endif - writel(priority, priority_addr); + } + + plic->priority_base[irq] = priority; } From 79cc063ac80edf79e3dfdb5604e6932130c0a84d Mon Sep 17 00:00:00 2001 From: heyuanjie87 <943313837@qq.com> Date: Tue, 26 Nov 2024 17:15:14 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=95=8C=E9=99=90?= =?UTF-8?q?=E5=88=A4=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/risc-v/t-head/c906/interrupt.c | 2 +- libcpu/risc-v/t-head/c908/interrupt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libcpu/risc-v/t-head/c906/interrupt.c b/libcpu/risc-v/t-head/c906/interrupt.c index b7290bd4298..09a89dede2c 100644 --- a/libcpu/risc-v/t-head/c906/interrupt.c +++ b/libcpu/risc-v/t-head/c906/interrupt.c @@ -92,7 +92,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name) { rt_isr_handler_t old_handler = RT_NULL; - if ((vector < 0) || (vector > IRQ_MAX_NR)) + if ((vector < 0) || (vector >= IRQ_MAX_NR)) { return old_handler; } diff --git a/libcpu/risc-v/t-head/c908/interrupt.c b/libcpu/risc-v/t-head/c908/interrupt.c index 5349b0b4e93..b1ba5b81673 100644 --- a/libcpu/risc-v/t-head/c908/interrupt.c +++ b/libcpu/risc-v/t-head/c908/interrupt.c @@ -92,7 +92,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name) { rt_isr_handler_t old_handler = RT_NULL; - if ((vector < 0) || (vector > IRQ_MAX_NR)) + if ((vector < 0) || (vector >= IRQ_MAX_NR)) { return old_handler; } From c81fef9bb8e7f9018485783731f16e943f7d4ec9 Mon Sep 17 00:00:00 2001 From: heyuanjie87 <943313837@qq.com> Date: Tue, 26 Nov 2024 18:04:37 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E5=9C=A8plic=E4=B8=AD=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E5=9B=9E=E8=B0=83=E5=87=BD=E6=95=B0=E8=AE=BF=E9=97=AE=E4=B8=AD?= =?UTF-8?q?=E6=96=AD=E6=8F=8F=E8=BF=B0=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/risc-v/plic/plic.c | 19 +++++++++---------- libcpu/risc-v/plic/plic.h | 2 +- libcpu/risc-v/t-head/c906/interrupt.c | 15 ++++++++++++++- libcpu/risc-v/t-head/c908/interrupt.c | 15 ++++++++++++++- libcpu/risc-v/virt64/interrupt.c | 17 +++++++++++++++-- 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/libcpu/risc-v/plic/plic.c b/libcpu/risc-v/plic/plic.c index d450827cc55..faed9b6861d 100644 --- a/libcpu/risc-v/plic/plic.c +++ b/libcpu/risc-v/plic/plic.c @@ -34,6 +34,8 @@ struct plic void *base_pa; volatile rt_uint32_t *priority_base; + void (*irq_handler)(int irq); + struct plic_handler handlers[NR_CPUS]; }; @@ -65,9 +67,6 @@ rt_inline void plic_irq_toggle(int hwirq, int enable) static void generic_handle_irq(int irq) { - rt_isr_handler_t isr; - void *param; - if (irq < 0 || irq >= IRQ_MAX_NR) { LOG_E("bad irq number %d!\n", irq); @@ -79,11 +78,10 @@ static void generic_handle_irq(int irq) LOG_W("no irq!\n"); return; } - isr = isr_table[IRQ_OFFSET + irq].handler; - param = isr_table[IRQ_OFFSET + irq].param; - if (isr != RT_NULL) + + if (plic_get()->irq_handler != RT_NULL) { - isr(irq, param); + plic_get()->irq_handler(irq); } /* complete irq. */ plic_complete(irq); @@ -159,7 +157,7 @@ rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable) } } -void plic_init(unsigned long base_pa) +void plic_init(unsigned long base_pa, void (*irq_handler)(int irq)) { int nr_irqs; int nr_context; @@ -174,12 +172,13 @@ void plic_init(unsigned long base_pa) return; } - if (!base_pa) + if (!base_pa || !irq_handler) { - LOG_E("fatal error, plic is reg space is null."); + LOG_E("fatal error, plic init params is null."); return; } plic->base_pa = (void*)base_pa; + plic->irq_handler = irq_handler; nr_context = PLIC_NR_CONTEXT; nr_irqs = IRQ_MAX_NR; diff --git a/libcpu/risc-v/plic/plic.h b/libcpu/risc-v/plic/plic.h index 46a6860f7aa..3175f28351c 100644 --- a/libcpu/risc-v/plic/plic.h +++ b/libcpu/risc-v/plic/plic.h @@ -44,7 +44,7 @@ #define CONTEXT_THRESHOLD 0x00 #define CONTEXT_CLAIM 0x04 -void plic_init(unsigned long base_pa); +void plic_init(unsigned long base_pa, void (*irq_handler)(int irq)); void plic_enable_irq(int irqno); void plic_disable_irq(int irqno); // tell PLIC that we've served this IRQ diff --git a/libcpu/risc-v/t-head/c906/interrupt.c b/libcpu/risc-v/t-head/c906/interrupt.c index 09a89dede2c..c7e85250d36 100644 --- a/libcpu/risc-v/t-head/c906/interrupt.c +++ b/libcpu/risc-v/t-head/c906/interrupt.c @@ -30,13 +30,26 @@ static void rt_hw_interrupt_handler(int vector, void *param) rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); } +static void __isr(int irq) +{ + rt_isr_handler_t isr; + void *param; + + isr = isr_table[IRQ_OFFSET + irq].handler; + param = isr_table[IRQ_OFFSET + irq].param; + if (isr != RT_NULL) + { + isr(irq, param); + } +} + /** * This function will initialize hardware interrupt */ void rt_hw_interrupt_init(void) { /* init interrupt controller */ - plic_init(C906_PLIC_PHY_ADDR); + plic_init(C906_PLIC_PHY_ADDR, __isr); rt_int32_t idx; diff --git a/libcpu/risc-v/t-head/c908/interrupt.c b/libcpu/risc-v/t-head/c908/interrupt.c index b1ba5b81673..9d7eaf1afa1 100644 --- a/libcpu/risc-v/t-head/c908/interrupt.c +++ b/libcpu/risc-v/t-head/c908/interrupt.c @@ -30,13 +30,26 @@ static void rt_hw_interrupt_handler(int vector, void *param) rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); } +static void __isr(int irq) +{ + rt_isr_handler_t isr; + void *param; + + isr = isr_table[IRQ_OFFSET + irq].handler; + param = isr_table[IRQ_OFFSET + irq].param; + if (isr != RT_NULL) + { + isr(irq, param); + } +} + /** * This function will initialize hardware interrupt */ void rt_hw_interrupt_init(void) { /* init interrupt controller */ - plic_init(C908_PLIC_PHY_ADDR); + plic_init(C908_PLIC_PHY_ADDR, __isr); rt_int32_t idx; diff --git a/libcpu/risc-v/virt64/interrupt.c b/libcpu/risc-v/virt64/interrupt.c index ace4bb35c0f..bf4471da8ac 100644 --- a/libcpu/risc-v/virt64/interrupt.c +++ b/libcpu/risc-v/virt64/interrupt.c @@ -78,13 +78,26 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, return old_handler; } -void rt_hw_interrupt_init() +static void __isr(int irq) +{ + rt_isr_handler_t isr; + void *param; + + isr = isr_table[IRQ_OFFSET + irq].handler; + param = isr_table[IRQ_OFFSET + irq].param; + if (isr != RT_NULL) + { + isr(irq, param); + } +} + +void rt_hw_interrupt_init(void) { /* Enable machine external interrupts. */ // set_csr(sie, SIP_SEIP); int idx = 0; - plic_init(PLIC_BASE_ADDR); + plic_init(PLIC_BASE_ADDR, __isr); /* init exceptions table */ for (idx = 0; idx < INTERRUPTS_MAX; idx++) From 941f9c31d5405cb2ca5af3517a1140cbb5ccb3ad Mon Sep 17 00:00:00 2001 From: heyuanjie87 <943313837@qq.com> Date: Tue, 26 Nov 2024 19:19:23 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E6=9A=82=E6=97=B6=E5=8F=AA=E6=94=AF?= =?UTF-8?q?=E6=8C=8164=E4=BD=8D=E4=BD=BF=E7=94=A8plic=E9=80=9A=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/risc-v/SConscript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcpu/risc-v/SConscript b/libcpu/risc-v/SConscript index 82ee5e5e444..14e06661d1e 100644 --- a/libcpu/risc-v/SConscript +++ b/libcpu/risc-v/SConscript @@ -16,8 +16,8 @@ if rtconfig.CPU in common64_arch : else : group += SConscript(os.path.join('common', 'SConscript')) - -group += SConscript(os.path.join('plic', 'SConscript')) +if GetDepend('ARCH_CPU_64BIT'): + group += SConscript(os.path.join('plic', 'SConscript')) # cpu porting code files if 'VENDOR' in vars(rtconfig) and rtconfig.VENDOR != '': From 86918db928f1deb10fdaf82bceb89af80038e1f3 Mon Sep 17 00:00:00 2001 From: heyuanjie87 <943313837@qq.com> Date: Tue, 26 Nov 2024 20:22:36 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E6=9A=82=E6=97=B6=E9=99=90=E5=AE=9Aplic?= =?UTF-8?q?=E7=9A=84=E4=BD=BF=E7=94=A8=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/risc-v/SConscript | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libcpu/risc-v/SConscript b/libcpu/risc-v/SConscript index 14e06661d1e..d8e80adfe25 100644 --- a/libcpu/risc-v/SConscript +++ b/libcpu/risc-v/SConscript @@ -16,7 +16,8 @@ if rtconfig.CPU in common64_arch : else : group += SConscript(os.path.join('common', 'SConscript')) -if GetDepend('ARCH_CPU_64BIT'): +# FIXME: remove implementation of plic in BSP +if rtconfig.CPU in common64_arch: group += SConscript(os.path.join('plic', 'SConscript')) # cpu porting code files