From 52b549c14cc465380a993be914799f28854b8e89 Mon Sep 17 00:00:00 2001 From: TXuian <1163589503@qq.com> Date: Thu, 25 Apr 2024 09:32:10 +0800 Subject: [PATCH] support irq --- .../cortex-a9/imx6q-sabrelite/trap_common.c | 2 +- Ubiquitous/XiZi_AIoT/services/app/Makefile | 10 ++- .../XiZi_AIoT/services/app/test_irq_handler.c | 42 ++++++++++ .../services/boards/imx6q-sabrelite/Makefile | 2 +- .../boards/imx6q-sabrelite/test_irq_sender.c | 82 +++++++++++++++++++ .../XiZi_AIoT/softkernel/include/task.h | 1 + .../XiZi_AIoT/softkernel/memory/share_page.c | 2 +- .../softkernel/syscall/sys_register_irq.c | 39 +++++++-- Ubiquitous/XiZi_AIoT/softkernel/task/task.c | 2 +- 9 files changed, 170 insertions(+), 12 deletions(-) create mode 100644 Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/test_irq_sender.c diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/imx6q-sabrelite/trap_common.c b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/imx6q-sabrelite/trap_common.c index 58e7fb35c..53c0a4be2 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/imx6q-sabrelite/trap_common.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/imx6q-sabrelite/trap_common.c @@ -96,7 +96,7 @@ static void _sys_irq_init(int cpu_id) // Set Interrupt handler start address vector_base[1] = (uint32_t)trap_undefined_instruction; // Undefined Instruction vector_base[2] = (uint32_t)user_trap_swi_enter; // Software Interrupt - // vector_base[3] = (uint32_t)trap_iabort; // Prefetch Abort + vector_base[3] = (uint32_t)trap_iabort; // Prefetch Abort vector_base[4] = (uint32_t)trap_dabort; // Data Abort vector_base[5] = (uint32_t)handle_reserved; // Reserved vector_base[6] = (uint32_t)trap_irq_enter; // IRQ diff --git a/Ubiquitous/XiZi_AIoT/services/app/Makefile b/Ubiquitous/XiZi_AIoT/services/app/Makefile index 288a23c1b..2490122ac 100644 --- a/Ubiquitous/XiZi_AIoT/services/app/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/app/Makefile @@ -23,7 +23,7 @@ INC_DIR = -I$(KERNEL_ROOT)/services/shell/letter-shell \ -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ -I$(KERNEL_ROOT)/services/app -all: init test_fs simple_client simple_server shell fs_server test_priority readme.txt | bin +all: init test_fs simple_client simple_server shell fs_server test_priority test_irq_hdlr test_irq_send readme.txt | bin ../tools/mkfs/mkfs ./fs.img $^ @mv $(filter-out readme.txt, $^) bin @mv *.o bin @@ -32,6 +32,14 @@ all: init test_fs simple_client simple_server shell fs_server test_priority read bin: @mkdir -p bin +test_irq_send: test_irq_sender.o usyscall.o libserial.o + @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} + @${objdump} -S $@ > $@.asm + +test_irq_hdlr: test_irq_handler.o libserial.o libipc.o session.o usyscall.o libmem.o + @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} + @${objdump} -S $@ > $@.asm + shell: shell_port.o libserial.o shell_cmd_list.o shell.o shell_ext.o libfs_to_client.o libipc.o session.o usyscall.o libmem.o @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} @${objdump} -S $@ > $@.asm diff --git a/Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c b/Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c new file mode 100644 index 000000000..8aed9eb14 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +#include "libipc.h" +#include "libserial.h" +#include "usyscall.h" + +IPC_SERVICES(IpcSwIntrHandler, Ipc_intr_3); + +enum { + SW_INTERRUPT_3 = 3, +}; + +void sgi_test_handler(void) +{ + printf("TEST_SW_HDLR: In %s()\n", __func__); +} + +int IPC_DO_SERVE_FUNC(Ipc_intr_3)(void* useless) +{ + sgi_test_handler(); + return 0; +} + +IPC_SERVER_INTERFACE(Ipc_intr_3, 1); +IPC_SERVER_REGISTER_INTERFACES(IpcSwIntrHandler, 1, Ipc_intr_3); +int main() +{ + register_irq(SW_INTERRUPT_3, Ipc_intr_3); + ipc_server_loop(&IpcSwIntrHandler); + + exit(); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile index 1a44e7a85..96a8dc345 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile @@ -18,7 +18,7 @@ INC_DIR = -I$(KERNEL_ROOT)/services/fs/libfs \ -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ -I$(KERNEL_ROOT)/services/app -board: libserial.o usyscall.o +board: libserial.o usyscall.o test_irq_sender.o @mv $^ ../../app %.o: %.c diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/test_irq_sender.c b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/test_irq_sender.c new file mode 100644 index 000000000..cd0cc4262 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/test_irq_sender.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "libserial.h" +#include "usyscall.h" + +enum { + SW_INTERRUPT_3 = 3, +}; + +enum { + ARM_PERIPHERAL_BASE = 0x00A00000, + MX6Q_GICD_BASE_OFFSET = 0x1000, + MX6Q_GICC_BASE_OFFSET = 0x100, + + ARM_PERIPHERAL_VIRT_BASE = 0x50000000, +}; + +struct _gicd_registers { + uint32_t CTLR; //!< Distributor Control Register. + uint32_t TYPER; //!< Interrupt Controller Type Register. + uint32_t IIDR; //!< Distributor Implementer Identification Register. + uint32_t _reserved0[29]; + uint32_t IGROUPRn[8]; //!< Interrupt Group Registers. + uint32_t _reserved1[24]; + uint32_t ISENABLERn[32]; //!< Interrupt Set-Enable Registers. + uint32_t ICENABLERn[32]; //!< Interrupt Clear-Enable Registers. + uint32_t ISPENDRn[32]; //!< Interrupt Set-Pending Registers. + uint32_t ICPENDRn[32]; //!< Interrupt Clear-Pending Registers. + uint32_t ICDABRn[32]; //!< Active Bit Registers. + uint32_t _reserved2[32]; + uint8_t IPRIORITYRn[255 * sizeof(uint32_t)]; //!< Interrupt Priority Registers. (Byte accessible) + uint32_t _reserved3; + uint8_t ITARGETSRn[255 * sizeof(uint32_t)]; //!< Interrupt Processor Targets Registers. (Byte accessible) + uint32_t _reserved4; + uint32_t ICFGRn[64]; //!< Interrupt Configuration Registers. + uint32_t _reserved5[128]; + uint32_t SGIR; //!< Software Generated Interrupt Register +}; +typedef volatile struct _gicd_registers gicd_t; + +enum _gicd_sgir_fields { + kBP_GICD_SGIR_TargetListFilter = 24, + kBM_GICD_SGIR_TargetListFilter = (0x3 << kBP_GICD_SGIR_TargetListFilter), + + kBP_GICD_SGIR_CPUTargetList = 16, + kBM_GICD_SGIR_CPUTargetList = (0xff << kBP_GICD_SGIR_CPUTargetList), + + kBP_GICD_SGIR_NSATT = 15, + kBM_GICD_SGIR_NSATT = (1 << kBP_GICD_SGIR_NSATT), + + kBP_GICD_SGIR_SGIINTID = 0, + kBM_GICD_SGIR_SGIINTID = 0xf +}; + +void gic_send_sgi(uint32_t irqID, uint32_t target_list, uint32_t filter_list) +{ + gicd_t* gicd = (gicd_t*)(ARM_PERIPHERAL_VIRT_BASE + MX6Q_GICD_BASE_OFFSET); + gicd->SGIR = (filter_list << kBP_GICD_SGIR_TargetListFilter) // + | (target_list << kBP_GICD_SGIR_CPUTargetList) // + | (irqID & 0xf); +} + +int main() +{ + static char prog_name[] = "TEST_IRQ_SEND"; + printf("%s: Mapping GIC\n", prog_name); + mmap(ARM_PERIPHERAL_VIRT_BASE, ARM_PERIPHERAL_BASE, 0x2000, true); + + printf("%s: Sending soft interrupt\n", prog_name); + gic_send_sgi(SW_INTERRUPT_3, 0, 2); + printf("%s: Soft interrupt send done\n", prog_name); + exit(); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/task.h b/Ubiquitous/XiZi_AIoT/softkernel/include/task.h index 2add2df49..fa9263196 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/task.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/task.h @@ -48,6 +48,7 @@ enum ProcState { READY, RUNNING, DEAD, + NEVER_RUN, }; /* Thread Control Block */ diff --git a/Ubiquitous/XiZi_AIoT/softkernel/memory/share_page.c b/Ubiquitous/XiZi_AIoT/softkernel/memory/share_page.c index 9a07aa676..081367e70 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/memory/share_page.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/memory/share_page.c @@ -104,7 +104,7 @@ static uintptr_t map_task_share_page(struct TaskMicroDescriptor* task, const uin ERROR("Alloc task buddy failed.\n"); return (uintptr_t)NULL; } - vaddr = (uintptr_t)KBuddyAlloc(task->massive_ipc_allocator, nr_pages * 2); + return map_task_share_page(task, paddr, nr_pages); } } diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c index 1ed2965b5..0a953892a 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c @@ -34,40 +34,55 @@ Modification: #include "actracer.h" #include "assert.h" #include "ipc.h" +#include "mmu_common.h" #include "multicores.h" #include "share_page.h" #include "syscall.h" #include "task.h" -static struct TaskMicroDescriptor kernel_irq_proxy; +static struct TaskMicroDescriptor* kernel_irq_proxy; static struct { struct TaskMicroDescriptor* handle_task; - struct Session* session; + struct Session session; int opcode; } irq_forward_table[NR_IRQS]; static void send_irq_to_user(int irq_num) { + struct Session* session = &irq_forward_table[irq_num].session; int len = IPC_ARG_INFO_BASE_OFFSET; + len += sizeof(struct IpcArgInfo); + /* add session tail */ - struct IpcMsg* buf = irq_forward_table[irq_num].session->buf + irq_forward_table[irq_num].session->tail; - irq_forward_table[irq_num].session->tail += len; + struct IpcMsg* buf = session->buf + session->tail; memset((void*)buf, 0, len); + session->tail = (session->tail + len) % session->capacity; + /* construct message */ buf->header.len = len; - buf->header.nr_args = 0; + buf->header.nr_args = 1; buf->header.init = 1; buf->header.opcode = irq_forward_table[irq_num].opcode; buf->header.done = 0; buf->header.magic = IPC_MSG_MAGIC; buf->header.valid = 1; + /* add session head */ - irq_forward_table[irq_num].session->head += len; + session->head = (session->head + len) % session->capacity; } int user_irq_handler(int irq, void* tf, void* arg) { + static struct MmuCommonDone* p_mmu_driver = NULL; + if (p_mmu_driver == NULL) { + struct TraceTag mmu_driver_tag; + AchieveResourceTag(&mmu_driver_tag, RequireRootTag(), "/hardkernel/mmu-ac-resource"); + p_mmu_driver = (struct MmuCommonDone*)AchieveResource(&mmu_driver_tag); + } + p_mmu_driver->LoadPgdir((uintptr_t)V2P(kernel_irq_proxy->pgdir.pd_addr)); send_irq_to_user(irq); + p_mmu_driver->LoadPgdir((uintptr_t)V2P(cur_cpu()->task->pgdir.pd_addr)); + next_task_emergency = irq_forward_table[irq].handle_task; xizi_task_manager.cur_task_yield_noschedule(); return 0; @@ -77,6 +92,7 @@ extern int create_session_inner(struct TaskMicroDescriptor* client, struct TaskM /// @warning no tested. int sys_register_irq(int irq_num, int irq_opcode) { + // init intr resource; static struct TraceTag intr_ac_tag; if (!AchieveResourceTag(&intr_ac_tag, RequireRootTag(), "hardkernel/intr-ac-resource")) { ERROR("intr not initialized.\n"); @@ -84,6 +100,15 @@ int sys_register_irq(int irq_num, int irq_opcode) } struct XiziTrapDriver* p_intr_driver = AchieveResource(&intr_ac_tag); + // init kerenl sender proxy + if (kernel_irq_proxy == NULL) { + kernel_irq_proxy = xizi_task_manager.new_task_cb(); + kernel_irq_proxy->state = NEVER_RUN; + xizi_pager.new_pgdir(&kernel_irq_proxy->pgdir); + memcpy(kernel_irq_proxy->pgdir.pd_addr, kern_pgdir.pd_addr, TOPLEVLE_PAGEDIR_SIZE); + } + + // bind irq to session if (p_intr_driver->sw_irqtbl[irq_num].handler != NULL) { ERROR("irq %d is occupied.\n", irq_num); return -1; @@ -91,7 +116,7 @@ int sys_register_irq(int irq_num, int irq_opcode) struct TaskMicroDescriptor* cur_task = cur_cpu()->task; irq_forward_table[irq_num].handle_task = cur_task; irq_forward_table[irq_num].opcode = irq_opcode; - create_session_inner(&kernel_irq_proxy, cur_task, PAGE_SIZE, irq_forward_table[irq_num].session); + create_session_inner(kernel_irq_proxy, cur_task, PAGE_SIZE, &irq_forward_table[irq_num].session); p_intr_driver->bind_irq_handler(irq_num, user_irq_handler); return 0; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/task.c b/Ubiquitous/XiZi_AIoT/softkernel/task/task.c index 0299c4972..9fa3f57e1 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/task.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/task.c @@ -179,7 +179,7 @@ static void _scheduler(struct SchedulerRightGroup right_group) next_task = NULL; /* find next runnable task */ assert(cur_cpu()->task == NULL); - if (next_task_emergency != NULL) { + if (next_task_emergency != NULL && next_task->state == READY) { next_task = next_task_emergency; next_task->state = RUNNING; next_task_emergency = NULL;