From 8d2d7e3e09fafdc26dfe0bf5c1706df7c4e84a70 Mon Sep 17 00:00:00 2001 From: TXuian <1163589503@qq.com> Date: Mon, 29 Apr 2024 10:46:07 +0800 Subject: [PATCH] Make sure that kernel is interrupt disabled. --- .../intr/arm/armv7-a/cortex-a9/trampoline.S | 112 +++++++++++------- .../boards/imx6q-sabrelite/test_irq_sender.c | 6 +- .../XiZi_AIoT/services/lib/ipc/libipc.c | 20 ++-- .../XiZi_AIoT/services/lib/ipc/session.h | 2 +- .../softkernel/syscall/sys_connect_session.c | 11 +- .../softkernel/syscall/sys_register_irq.c | 13 +- .../softkernel/trap/default_irq_handler.c | 5 +- 7 files changed, 106 insertions(+), 63 deletions(-) diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/trampoline.S b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/trampoline.S index 3dadefdc5..da7018964 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/trampoline.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/intr/arm/armv7-a/cortex-a9/trampoline.S @@ -47,9 +47,7 @@ trap_return: ldmfd r13!, {r14} ldmfd r13!, {r2} msr spsr_cxsf, r2 - ldmfd r13!, {r0-r12} // restore context and return - cpsie i - ldmfd r13!, {pc}^ // restore context and return + ldmfd r13!, {r0-r12, pc}^ // restore context and return user_trap_swi_enter: # save trapframe to swi stack @@ -98,62 +96,96 @@ trap_irq_enter: bl intr_irq_dispatch b trap_return -trap_reset_enter: - cpsid i - mov r14, #0 // lr: not defined on reset - stmfd r13!, {r0-r12, r14} - mrs r2, spsr // copy spsr to r2 - stmfd r13!, {r2} // save r2(spsr) to the stack - stmfd r13!, {r14} // save r14 again (it is not really correct) - stmfd r13, {sp, lr}^ // save user mode sp and lr - sub r13, r13, #8 - - # call traps (trapframe *fp) - mov r0, r13 // copy r13_svc to r0 - bl _vector_jumper - trap_dabort: + # save it on the stack as r14 is banked cpsid i - sub r14, r14, #8 // lr: instruction causing the abort - stmfd r13!, {r0-r12, r14} - mrs r2, spsr // copy spsr to r2 - stmfd r13!, {r2} // save r2(spsr) to the stack - stmfd r13!, {r14} // save r14 again (it is not really correct) + sub r14, r14, #8 // r14 (lr) contains the interrupted PC + stmfd r13!, {r0-r2, r14} // + mrs r1, spsr // save spsr_irq + mov r0, r13 // save stack stop (r13_irq) + add r13, r13, #16 // reset the IRQ stack + + # switch to the SVC mode + mrs r2, cpsr + bic r2, r2, #ARM_CPSR_MODE_MASK + orr r2, r2, #ARM_MODE_SVC + msr cpsr_cxsf, r2 + + # build the trap frame + ldr r2, [r0, #12] // read the r14_irq, then save it + stmfd r13!, {r2} + stmfd r13!, {r3-r12} // r4-r12 are preserved (non-banked) + ldmfd r0, {r3-r5} // copy r0-r2 over from irq stack + stmfd r13!, {r3-r5} + stmfd r13!, {r1} // save spsr + stmfd r13!, {lr} // save lr_svc + stmfd r13, {sp, lr}^ // save user mode sp and lr sub r13, r13, #8 - # call traps (trapframe *fp) - mov r0, r13 // save trapframe as the first parameter + mov r0, r13 // trapframe as parameters bl dabort_handler trap_iabort: +# save it on the stack as r14 is banked cpsid i - sub r14, r14, #4 // lr: instruction causing the abort - stmfd r13!, {r0-r12, r14} - mrs r2, spsr // copy spsr to r2 - stmfd r13!, {r2} // save r2(spsr) to the stack - stmfd r13!, {r14} // save r14 again (it is not really correct) - stmfd r13, {sp, lr}^ // save user mode sp and lr + sub r14, r14, #4 // r14 (lr) contains the interrupted PC + stmfd r13!, {r0-r2, r14} // + mrs r1, spsr // save spsr_irq + mov r0, r13 // save stack stop (r13_irq) + add r13, r13, #16 // reset the IRQ stack + + # switch to the SVC mode + mrs r2, cpsr + bic r2, r2, #ARM_CPSR_MODE_MASK + orr r2, r2, #ARM_MODE_SVC + msr cpsr_cxsf, r2 + + # build the trap frame + ldr r2, [r0, #12] // read the r14_irq, then save it + stmfd r13!, {r2} + stmfd r13!, {r3-r12} // r4-r12 are preserved (non-banked) + ldmfd r0, {r3-r5} // copy r0-r2 over from irq stack + stmfd r13!, {r3-r5} + stmfd r13!, {r1} // save spsr + stmfd r13!, {lr} // save lr_svc + + stmfd r13, {sp, lr}^ // save user mode sp and lr sub r13, r13, #8 - # call traps (trapframe *fp) - mov r0, r13 // save trapframe as the first parameter + mov r0, r13 // trapframe as parameters bl iabort_handler trap_undefined_instruction: + # save it on the stack as r14 is banked cpsid i - stmfd r13!, {r0-r12, r14} - mrs r2, spsr // copy spsr to r2 - stmfd r13!, {r2} // save r2(spsr) to the stack - stmfd r13!, {r14} // save r14 again (it is not really correct) - stmfd r13, {sp, lr}^ // save user mode sp and lr + sub r14, r14, #4 // r14 (lr) contains the interrupted PC + stmfd r13!, {r0-r2, r14} // + mrs r1, spsr // save spsr_irq + mov r0, r13 // save stack stop (r13_irq) + add r13, r13, #16 // reset the IRQ stack + + # switch to the SVC mode + mrs r2, cpsr + bic r2, r2, #ARM_CPSR_MODE_MASK + orr r2, r2, #ARM_MODE_SVC + msr cpsr_cxsf, r2 + + # build the trap frame + ldr r2, [r0, #12] // read the r14_irq, then save it + stmfd r13!, {r2} + stmfd r13!, {r3-r12} // r4-r12 are preserved (non-banked) + ldmfd r0, {r3-r5} // copy r0-r2 over from irq stack + stmfd r13!, {r3-r5} + stmfd r13!, {r1} // save spsr + stmfd r13!, {lr} // save lr_svc + + stmfd r13, {sp, lr}^ // save user mode sp and lr sub r13, r13, #8 - # call traps (trapframe *fp) - mov r0, r13 // save trapframe as the first parameter + mov r0, r13 // trapframe as parameters bl handle_undefined_instruction - init_stack: # set the stack for Other mode mrs r2, cpsr 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 index d89dba927..21e4a2fef 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/test_irq_sender.c +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/test_irq_sender.c @@ -88,9 +88,11 @@ int main() 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); - while (1) { + int send_time = 1000; + printf("%s: Sending soft interrupt for %d times\n", prog_name, send_time); + for (int i = 0; i < send_time; i++) { gic_send_sgi(SW_INTERRUPT_3, 0xF, kGicSgiFilter_UseTargetList); + printf("%s: Soft interrupt send 1 time\n", prog_name); } printf("%s: Soft interrupt send done\n", prog_name); exit(); diff --git a/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c b/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c index 7286146c6..e00df4e2d 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c +++ b/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c @@ -179,24 +179,22 @@ void ipc_server_loop(struct IpcNode* ipc_node) a session could be delay in case one of its message(current message) needs to wait for an interrupt message's arrival interfaces[opcode] should explicitly call delay_session() and return to delay this session */ - while (msg->header.magic == IPC_MSG_MAGIC && msg->header.valid == 1) { + while (msg->header.magic == IPC_MSG_MAGIC && msg->header.valid == 1 && msg->header.done == 0) { // printf("session %d [%d, %d]\n", session_list[i].id, session_list[i].head, session_list[i].tail); if (session_used_size(&session_list[i]) == 0 && session_forward_tail(&session_list[i], msg->header.len) < 0) { break; } // this is a message needs to handle - if (msg->header.done != 1) { - if (ipc_node->interfaces[msg->header.opcode]) { - ipc_node->interfaces[msg->header.opcode](msg); - // check if this session is delayed by op handler, all messages after the delayed message in current session is blocked. - if (session_delayed) { - session_delayed = false; - break; - } - } else { - printf("Unsupport opcode(%d) for server: %s\n", msg->header.opcode, ipc_node->name); + if (ipc_node->interfaces[msg->header.opcode]) { + ipc_node->interfaces[msg->header.opcode](msg); + // check if this session is delayed by op handler, all messages after the delayed message in current session is blocked. + if (session_delayed) { + session_delayed = false; + break; } + } else { + printf("Unsupport opcode(%d) for server: %s\n", msg->header.opcode, ipc_node->name); } // current msg is a message that needs to ignore // finish this message in server's perspective diff --git a/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.h b/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.h index 4979f74ca..196c6bf5b 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.h +++ b/Ubiquitous/XiZi_AIoT/services/lib/ipc/session.h @@ -56,7 +56,7 @@ __attribute__((__always_inline__)) static inline int session_remain_capacity(str __attribute__((__always_inline__)) static inline int session_forward_head(struct Session* session, int len) { if (len > session_used_size(session)) { - printf("forward head with too much size\n"); + printf("forward head with too much size, session used size: %d\n", session_used_size(session)); return -1; } session->head = (session->head + len) % session->capacity; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_connect_session.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_connect_session.c index 84fc74109..178ef83e3 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_connect_session.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_connect_session.c @@ -35,13 +35,13 @@ Modification: #include "syscall.h" #include "task.h" -int create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, int capacity, struct Session* user_session) +struct session_backend* create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, int capacity, struct Session* user_session) { // create share pages struct session_backend* session_backend = xizi_share_page_manager.create_share_pages(client, server, capacity); if (UNLIKELY(session_backend == NULL)) { DEBUG("create_share_pages failed\n"); - return -1; + return NULL; } // init user_session @@ -51,7 +51,7 @@ int create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDes user_session->tail = 0; user_session->id = session_backend->session_id; - return 0; + return session_backend; } int sys_connect_session(char* path, int capacity, struct Session* user_session) @@ -76,5 +76,8 @@ int sys_connect_session(char* path, int capacity, struct Session* user_session) struct TaskMicroDescriptor* server = AchieveResource(&server_tag); assert(server != NULL); - return create_session_inner(client, server, capacity, user_session); + if (create_session_inner(client, server, capacity, user_session) == NULL) { + return -1; + } + return 0; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c index 91016a7dc..e7e0eb8cc 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c @@ -45,6 +45,7 @@ static struct TaskMicroDescriptor* kernel_irq_proxy; static struct { struct TaskMicroDescriptor* handle_task; struct Session session; + struct session_backend* p_kernel_session; int opcode; } irq_forward_table[NR_IRQS]; @@ -53,10 +54,16 @@ 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); - /* get message space and add session tail */ + /* get message space and add session tail */ void* session_kern_vaddr = P2V(xizi_pager.address_translate(&kernel_irq_proxy->pgdir, (uintptr_t)session->buf)); struct IpcMsg* buf = session_kern_vaddr + session->tail; + + /* check if server session is full */ + if (buf->header.magic == IPC_MSG_MAGIC && buf->header.done == 0) { + DEBUG("irq server cannot handle new interrupt by now.\n"); + return; + } memset((void*)buf, 0, len); session->tail = (session->tail + len) % session->capacity; @@ -86,7 +93,7 @@ int user_irq_handler(int irq, void* tf, void* arg) return 0; } -extern int create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, int capacity, struct Session* user_session); +extern struct session_backend* create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, int capacity, struct Session* user_session); /// @warning no tested. static struct XiziTrapDriver* p_intr_driver = NULL; @@ -118,7 +125,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); + irq_forward_table[irq_num].p_kernel_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); cur_task->bind_irq = true; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/trap/default_irq_handler.c b/Ubiquitous/XiZi_AIoT/softkernel/trap/default_irq_handler.c index d3fceb839..7c3dc2c81 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/trap/default_irq_handler.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/trap/default_irq_handler.c @@ -97,13 +97,13 @@ intr_leave_interrupt: void xizi_enter_kernel() { - p_intr_driver->cpu_irq_disable(); + /// @warning trampoline is responsible for closing interrupt spinlock_lock(&whole_kernel_lock); } bool xizi_try_enter_kernel() { - p_intr_driver->cpu_irq_disable(); + /// @warning trampoline is responsible for closing interrupt if (spinlock_try_lock(&whole_kernel_lock)) { return true; } @@ -113,5 +113,6 @@ bool xizi_try_enter_kernel() void xizi_leave_kernel() { + /// @warning trampoline is responsible for eabling interrupt by using user's state register spinlock_unlock(&whole_kernel_lock); }