From: Minep Date: Wed, 4 Jan 2023 16:12:56 +0000 (+0000) Subject: Merge branch 'interrupt-rework' into prog-loader X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/0cf90cca0c924622f3fee8d2a3fafa8238363dc6?hp=0ca0e2a565657cd3e37315fe665b45b13daaebf4 Merge branch 'interrupt-rework' into prog-loader --- diff --git a/lunaix-os/config/make-cc b/lunaix-os/config/make-cc index 6fd8494..7915afe 100644 --- a/lunaix-os/config/make-cc +++ b/lunaix-os/config/make-cc @@ -17,7 +17,10 @@ OFLAGS := -fno-gcse\ -fno-cse-follow-jumps\ -fno-cse-skip-blocks\ -fno-optimize-strlen\ - -fno-tree-builtin-call-dce + -fno-inline-functions-called-once \ + -fno-inline-functions \ + -fno-inline-small-functions \ + -fno-indirect-inlining CFLAGS := -std=gnu99 -ffreestanding $(O) $(OFLAGS) $(W) $(ARCH_OPT) LDFLAGS := -ffreestanding $(O) -nostdlib -lgcc \ No newline at end of file diff --git a/lunaix-os/debug/bg_lsdbg.c b/lunaix-os/debug/bg_lsdbg.c index 0f0496d..9c428b2 100644 --- a/lunaix-os/debug/bg_lsdbg.c +++ b/lunaix-os/debug/bg_lsdbg.c @@ -29,9 +29,11 @@ lunaix_sdbg_loop(isr_param* param) char c; if (sdbg_state == SDBG_STATE_WAIT_BRK) { - (param)->eflags &= ~(1 << 8); + (param)->execp->eflags &= ~(1 << 8); sdbg_state = SDBG_STATE_INSESSION; - sdbg_printf("[%p:%p] Break point reached.\n", param->cs, param->eip); + sdbg_printf("[%p:%p] Break point reached.\n", + param->execp->cs, + param->execp->eip); } while (1) { @@ -44,12 +46,14 @@ lunaix_sdbg_loop(isr_param* param) switch (c) { case SDBG_CLNT_HI: if (sdbg_state == SDBG_STATE_START) { - sdbg_printf( - "[%p:%p] Session started.\n", param->cs, param->eip); + sdbg_printf("[%p:%p] Session started.\n", + param->execp->cs, + param->execp->eip); sdbg_state = SDBG_STATE_INSESSION; } else { - sdbg_printf( - "[%p:%p] Session resumed.\n", param->cs, param->eip); + sdbg_printf("[%p:%p] Session resumed.\n", + param->execp->cs, + param->execp->eip); } break; case SDBG_CLNT_RREG: @@ -57,7 +61,7 @@ lunaix_sdbg_loop(isr_param* param) serial_tx_buffer(SERIAL_COM1, (char*)param, sizeof(isr_param)); break; case SDBG_CLNT_STEP: - ((isr_param*)param)->eflags |= (1 << 8); // set TF flags + ((isr_param*)param)->execp->eflags |= (1 << 8); // set TF flags sdbg_state = SDBG_STATE_WAIT_BRK; return; case SDBG_CLNT_BRKP: diff --git a/lunaix-os/debug/gdbstub.c b/lunaix-os/debug/gdbstub.c index 9546b85..d87db19 100644 --- a/lunaix-os/debug/gdbstub.c +++ b/lunaix-os/debug/gdbstub.c @@ -1211,7 +1211,7 @@ void gdbstub_loop(isr_param* param) { /* Translate vector to signal */ - switch (param->vector) { + switch (param->execp->vector) { case 1: gdb_state.signum = 5; break; @@ -1227,14 +1227,14 @@ gdbstub_loop(isr_param* param) gdb_state.registers[GDB_CPU_I386_REG_ECX] = param->registers.ecx; gdb_state.registers[GDB_CPU_I386_REG_EDX] = param->registers.edx; gdb_state.registers[GDB_CPU_I386_REG_EBX] = param->registers.ebx; - gdb_state.registers[GDB_CPU_I386_REG_ESP] = param->registers.esp; + gdb_state.registers[GDB_CPU_I386_REG_ESP] = param->esp; gdb_state.registers[GDB_CPU_I386_REG_EBP] = param->registers.ebp; gdb_state.registers[GDB_CPU_I386_REG_ESI] = param->registers.esi; gdb_state.registers[GDB_CPU_I386_REG_EDI] = param->registers.edi; - gdb_state.registers[GDB_CPU_I386_REG_PC] = param->eip; - gdb_state.registers[GDB_CPU_I386_REG_CS] = param->cs; - gdb_state.registers[GDB_CPU_I386_REG_PS] = param->eflags; - gdb_state.registers[GDB_CPU_I386_REG_SS] = param->ss; + gdb_state.registers[GDB_CPU_I386_REG_PC] = param->execp->eip; + gdb_state.registers[GDB_CPU_I386_REG_CS] = param->execp->cs; + gdb_state.registers[GDB_CPU_I386_REG_PS] = param->execp->eflags; + gdb_state.registers[GDB_CPU_I386_REG_SS] = param->execp->ss; gdb_state.registers[GDB_CPU_I386_REG_DS] = param->registers.ds; gdb_state.registers[GDB_CPU_I386_REG_ES] = param->registers.es; gdb_state.registers[GDB_CPU_I386_REG_FS] = param->registers.fs; @@ -1247,14 +1247,14 @@ gdbstub_loop(isr_param* param) param->registers.ecx = gdb_state.registers[GDB_CPU_I386_REG_ECX]; param->registers.edx = gdb_state.registers[GDB_CPU_I386_REG_EDX]; param->registers.ebx = gdb_state.registers[GDB_CPU_I386_REG_EBX]; - param->registers.esp = gdb_state.registers[GDB_CPU_I386_REG_ESP]; + param->esp = gdb_state.registers[GDB_CPU_I386_REG_ESP]; param->registers.ebp = gdb_state.registers[GDB_CPU_I386_REG_EBP]; param->registers.esi = gdb_state.registers[GDB_CPU_I386_REG_ESI]; param->registers.edi = gdb_state.registers[GDB_CPU_I386_REG_EDI]; - param->eip = gdb_state.registers[GDB_CPU_I386_REG_PC]; - param->cs = gdb_state.registers[GDB_CPU_I386_REG_CS]; - param->eflags = gdb_state.registers[GDB_CPU_I386_REG_PS]; - param->ss = gdb_state.registers[GDB_CPU_I386_REG_SS]; + param->execp->eip = gdb_state.registers[GDB_CPU_I386_REG_PC]; + param->execp->cs = gdb_state.registers[GDB_CPU_I386_REG_CS]; + param->execp->eflags = gdb_state.registers[GDB_CPU_I386_REG_PS]; + param->execp->ss = gdb_state.registers[GDB_CPU_I386_REG_SS]; param->registers.ds = gdb_state.registers[GDB_CPU_I386_REG_DS]; param->registers.es = gdb_state.registers[GDB_CPU_I386_REG_ES]; param->registers.fs = gdb_state.registers[GDB_CPU_I386_REG_FS]; diff --git a/lunaix-os/debug/sdbg.c b/lunaix-os/debug/sdbg.c index 3cc23cf..60a89f3 100644 --- a/lunaix-os/debug/sdbg.c +++ b/lunaix-os/debug/sdbg.c @@ -22,7 +22,8 @@ sdbg_loop(const isr_param* param) // synchronized way. And we don't want these irq queue up at our APIC and // confuse the CPU after ACK with APIC. serial_disable_irq(SERIAL_COM1); - if (param->vector == 1 || param->vector == 3) { + struct exec_param* execp = param->execp; + if (execp->vector == 1 || execp->vector == 3) { goto cont; } @@ -74,10 +75,11 @@ done: void sdbg_imm(const isr_param* param) { + struct exec_param* execp = param->execp; kprintf(KDEBUG "Quick debug mode\n"); kprintf(KDEBUG "cs=%p eip=%p eax=%p ebx=%p\n", - param->cs, - param->eip, + execp->cs, + execp->eip, param->registers.eax, param->registers.ebx); kprintf(KDEBUG "ecx=%p edx=%p edi=%p esi=%p\n", @@ -86,12 +88,12 @@ sdbg_imm(const isr_param* param) param->registers.edi, param->registers.esi); kprintf(KDEBUG "u.esp=%p k.esp=%p ebp=%p ps=%p\n", - param->registers.esp, param->esp, + execp->esp, param->registers.ebp, - param->eflags); + execp->eflags); kprintf(KDEBUG "ss=%p ds=%p es=%p fs=%p gs=%p\n", - param->ss, + execp->ss, param->registers.ds, param->registers.es, param->registers.fs, diff --git a/lunaix-os/hal/ahci/io_event.c b/lunaix-os/hal/ahci/io_event.c index e11016a..c1bd6a5 100644 --- a/lunaix-os/hal/ahci/io_event.c +++ b/lunaix-os/hal/ahci/io_event.c @@ -15,7 +15,7 @@ __ahci_hba_isr(const isr_param* param) struct ahci_driver *pos, *n; llist_for_each(pos, n, &ahcis, ahci_drvs) { - if (pos->id == param->vector) { + if (pos->id == param->execp->vector) { hba = &pos->hba; goto proceed; } diff --git a/lunaix-os/includes/arch/x86/interrupts.h b/lunaix-os/includes/arch/x86/interrupts.h index d25fbe3..f1684a8 100644 --- a/lunaix-os/includes/arch/x86/interrupts.h +++ b/lunaix-os/includes/arch/x86/interrupts.h @@ -5,8 +5,12 @@ #ifndef __ASM__ #include + +struct exec_param; + typedef struct { + unsigned int depth; struct { reg32 eax; @@ -20,9 +24,18 @@ typedef struct reg32 es; reg32 fs; reg32 gs; - reg32 esp; } __attribute__((packed)) registers; + union + { + reg32 esp; + volatile struct exec_param* execp; + }; +} __attribute__((packed)) isr_param; + +struct exec_param +{ + isr_param saved_prev_ctx; unsigned int vector; unsigned int err_code; unsigned int eip; @@ -30,7 +43,9 @@ typedef struct unsigned int eflags; unsigned int esp; unsigned int ss; -} __attribute__((packed)) isr_param; +} __attribute__((packed)); + +#define ISR_PARAM_SIZE sizeof(isr_param) void intr_handler(isr_param* param); diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index 0029e36..27137a1 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -52,9 +52,9 @@ struct proc_info pid_t pid; // offset = 0 struct proc_info* parent; // offset = 4 isr_param intr_ctx; // offset = 8 - uintptr_t ustack_top; // offset = 84 - void* page_table; // offset = 88 - void* fxstate; // offset = 92 + uintptr_t ustack_top; // offset = 84 -> 56 -> 60 + void* page_table; // offset = 88 -> 60 -> 64 + void* fxstate; // offset = 92 -> 64 -> 68 /* ---- critical section end ---- */ diff --git a/lunaix-os/kernel/asm/x86/interrupt.S b/lunaix-os/kernel/asm/x86/interrupt.S index 2961f3b..c869db0 100644 --- a/lunaix-os/kernel/asm/x86/interrupt.S +++ b/lunaix-os/kernel/asm/x86/interrupt.S @@ -9,6 +9,8 @@ .global debug_resv debug_resv: .skip 16 + tmp_store: + .skip 4 #endif .section .bss @@ -22,30 +24,35 @@ interrupt_wrapper: /* Stack layout (layout of struct isr_param) - msa: [ss] - [esp] - eflags > offset = 48 + 16 = 64 - cs - eip - err_code - vector > offset = 28 + 16 + 4 = 48 + msa: [ss] > 76 + [esp] > 72 + eflags > 68 + cs > 64 + eip > 60 + err_code > 56 + vector > offset = 52 + [saved_prev_ctx] > offset = 0 + --- esp gs fs es - ds > offset = 7 * 4 = 28 + ds > offset = 7 * 4 = 28 + 4 esi ebp edi edx ecx ebx - lsa: eax > offset = 0 + eax + lsa: depth > offset = 0 las: Least Significant Address msa: Most Significant Address */ cld + + subl $52, %esp pushl %esp subl $16, %esp @@ -62,7 +69,12 @@ pushl %ebx pushl %eax - movl 60(%esp), %eax /* 取出 %cs */ + movl __current, %eax + movl 8(%eax), %eax + incl %eax + pushl %eax # nested intr: current depth + + movl 116(%esp), %eax /* 取出 %cs */ andl $0x3, %eax /* 判断 RPL */ jz 1f @@ -74,14 +86,14 @@ # 保存用户栈顶指针。这是因为我们允许系统调用内进行上下文切换,而这样一来,我们就失去了用户栈的信息, # 这样一来,就无法设置信号上下文。这主要是为了实现了pause()而做的准备 - movl (__current), %eax + movl __current, %eax # 保存x87FPU的状态 - movl 92(%eax), %ebx + movl 68(%eax), %ebx fxsave (%ebx) - movl 68(%esp), %ebx # 取出esp - movl %ebx, 84(%eax) # 存入__current->ustack_top + movl 124(%esp), %ebx # 取出esp + movl %ebx, 60(%eax) # 存入__current->ustack_top 1: movl %esp, %eax @@ -99,16 +111,18 @@ #ifdef __ASM_INTR_DIAGNOSIS movl %eax, (debug_resv + 8) - movl 56(%esp), %eax - movl %eax, (debug_resv + 4) + movl 48(%esp), %eax + movl 60(%eax), %eax + movl %eax, (debug_resv + 4) # eip #endif - movl (__current), %eax - movl 92(%eax), %eax + movl __current, %eax + movl 68(%eax), %eax test %eax, %eax # do we have stored x87 context? jz 1f fxrstor (%eax) 1: + popl %eax # discard isr_param::depth popl %eax popl %ebx popl %ecx @@ -124,24 +138,40 @@ movl 16(%esp), %esp + movl %eax, tmp_store + movl __current, %eax + # nested intr: restore saved context + popl 8(%eax) # depth + popl 12(%eax) # eax + popl 16(%eax) # ebx + popl 20(%eax) # ecx + popl 24(%eax) # edx + popl 28(%eax) # edi + popl 32(%eax) # ebp + popl 36(%eax) # esi + popl 40(%eax) # ds + popl 44(%eax) # es + popl 48(%eax) # fs + popl 52(%eax) # gs + popl 56(%eax) # esp + addl $8, %esp - pushl %eax #ifdef __ASM_INTR_DIAGNOSIS - movl 4(%esp), %eax + movl (%esp), %eax movl %eax, debug_resv #endif # 处理TSS.ESP的一些边界条件。如果是正常iret(即从内核模式*优雅地*退出) # 那么TSS.ESP0应该为iret进行弹栈后,%esp的值。 # 所以这里的边界条件是:如返回用户模式,iret会额外弹出8个字节(ss,esp) - movl 8(%esp), %eax + movl 4(%esp), %eax andl $3, %eax setnz %al shll $3, %eax - addl $16, %eax + addl $12, %eax addl %esp, %eax movl %eax, (_tss + 4) - popl %eax + movl tmp_store, %eax iret .global switch_to @@ -151,8 +181,8 @@ popl %ebx # next movl __current, %eax - movl 88(%eax), %ecx # __current->pagetable - movl 88(%ebx), %eax # next->pagetable + movl 64(%eax), %ecx # __current->pagetable + movl 64(%ebx), %eax # next->pagetable cmpl %ecx, %eax # if(next->pagtable != __current->pagetable) { jz 1f @@ -181,7 +211,8 @@ pushl $UDATA_SEG # proc_sig->prev_context.proc_regs.ss pushl %eax # esp - pushl 64(%ebx) # proc_sig->prev_context.proc_regs.eflags + movl 48(%ebx), %ebx + pushl 68(%ebx) # proc_sig->prev_context.proc_regs.execp->eflags pushl $UCODE_SEG # cs pushl $sig_wrapper # eip for sig wrapper @@ -201,7 +232,7 @@ pushl %eax # Addr to proc_sig structure pushl 4(%eax) # proc_sig->sig_num ---- 16 bytes aligned - call (%eax) # invoke signal handler + call *(%eax) # invoke signal handler # invoke the sigreturn syscall to exit the signal wrapper movl $__SYSCALL_sigreturn, %eax diff --git a/lunaix-os/kernel/asm/x86/interrupts.c b/lunaix-os/kernel/asm/x86/interrupts.c index 25b3791..3fb24cb 100644 --- a/lunaix-os/kernel/asm/x86/interrupts.c +++ b/lunaix-os/kernel/asm/x86/interrupts.c @@ -19,26 +19,27 @@ extern x86_page_table* __kernel_ptd; void intr_handler(isr_param* param) { + param->execp->saved_prev_ctx = __current->intr_ctx; __current->intr_ctx = *param; - isr_param* lparam = &__current->intr_ctx; + volatile struct exec_param* execp = __current->intr_ctx.execp; - if (lparam->vector <= 255) { - isr_cb subscriber = isrm_get(lparam->vector); + if (execp->vector <= 255) { + isr_cb subscriber = isrm_get(execp->vector); subscriber(param); goto done; } kprint_panic("INT %u: (%x) [%p: %p] Unknown", - lparam->vector, - lparam->err_code, - lparam->cs, - lparam->eip); + execp->vector, + execp->err_code, + execp->cs, + execp->eip); done: // for all external interrupts except the spurious interrupt // this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5 - if (lparam->vector >= IV_EX && lparam->vector != APIC_SPIV_IV) { + if (execp->vector >= IV_EX && execp->vector != APIC_SPIV_IV) { apic_done_servicing(); } diff --git a/lunaix-os/kernel/asm/x86/intr_routines.c b/lunaix-os/kernel/asm/x86/intr_routines.c index 97903cf..f4bebae 100644 --- a/lunaix-os/kernel/asm/x86/intr_routines.c +++ b/lunaix-os/kernel/asm/x86/intr_routines.c @@ -22,11 +22,12 @@ extern u32_t debug_resv; void __print_panic_msg(const char* msg, const isr_param* param) { + struct exec_param* execp = param->execp; kprint_panic(" INT %u: (%x) [%p: %p] %s", - param->vector, - param->err_code, - param->cs, - param->eip, + execp->vector, + execp->err_code, + execp->cs, + execp->eip, msg); } diff --git a/lunaix-os/kernel/asm/x86/pfault.c b/lunaix-os/kernel/asm/x86/pfault.c index f6c4355..2b0a8f1 100644 --- a/lunaix-os/kernel/asm/x86/pfault.c +++ b/lunaix-os/kernel/asm/x86/pfault.c @@ -38,7 +38,7 @@ intr_routine_page_fault(const isr_param* param) goto segv_term; } - if (!SEL_RPL(param->cs)) { + if (!SEL_RPL(param->execp->cs)) { // 如果是内核页错误…… if (do_kernel(&mapping)) { return; @@ -130,8 +130,8 @@ segv_term: kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p)\n", __current->pid, ptr, - param->cs, - param->eip); + param->execp->cs, + param->execp->eip); __SIGSET(__current->sig_pending, _SIGSEGV); schedule(); // should not reach diff --git a/lunaix-os/kernel/asm/x86/syscall.S b/lunaix-os/kernel/asm/x86/syscall.S index bde7f36..62e0721 100644 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@ -72,10 +72,11 @@ .section .text syscall_hndlr: pushl %ebp - movl 8(%esp), %ebp + movl 8(%esp), %ebp // isr_param* - movl (%ebp), %eax /* eax: call code as well as the return value from syscall */ - cmpl $__SYSCALL_MAX, %eax + addl $4, %ebp + movl (%ebp), %eax /* eax: call code as well as the return value from syscall */ + cmpl $__SYSCALL_MAX, %eax jae 2f shll $2, %eax diff --git a/lunaix-os/kernel/k_init.c b/lunaix-os/kernel/k_init.c index e98be88..a2edf1a 100644 --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@ -127,11 +127,7 @@ spawn_proc0() proc0->intr_ctx = (isr_param){ .registers = { .ds = KDATA_SEG, .es = KDATA_SEG, .fs = KDATA_SEG, - .gs = KDATA_SEG }, - .cs = KCODE_SEG, - .eip = (void*)__proc0, - .ss = KDATA_SEG, - .eflags = cpu_reflags() }; + .gs = KDATA_SEG } }; proc0->parent = proc0; // 方案1:必须在读取eflags之后禁用。否则当进程被调度时,中断依然是关闭的! @@ -155,19 +151,14 @@ spawn_proc0() VMAP_NULL); } - // 手动设置进程上下文:用于第一次调度 - asm volatile("movl %%esp, %%ebx\n" - "movl %1, %%esp\n" - "pushf\n" - "pushl %2\n" - "pushl %3\n" - "pushl $0\n" - "pushl $0\n" - "movl %%esp, %0\n" - "movl %%ebx, %%esp\n" - : "=m"(proc0->intr_ctx.registers.esp) - : "i"(KSTACK_TOP), "i"(KCODE_SEG), "r"(proc0->intr_ctx.eip) - : "%ebx", "memory"); + struct exec_param* execp = + (struct exec_param*)(KSTACK_TOP - sizeof(struct exec_param)); + + *execp = (struct exec_param){ .cs = KCODE_SEG, + .eip = (void*)__proc0, + .ss = KDATA_SEG, + .eflags = cpu_reflags() }; + proc0->intr_ctx.execp = execp; // 加载x87默认配置 asm volatile("fninit\n" diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index 19a31c7..ade13b3 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -60,23 +60,23 @@ sched_init_dummy() extern void my_dummy(); static char dummy_stack[DUMMY_STACK_SIZE] __attribute__((aligned(16))); - // memset to 0 - dummy_proc = (struct proc_info){}; - dummy_proc.intr_ctx = (isr_param){ - .registers = { .ds = KDATA_SEG, - .es = KDATA_SEG, - .fs = KDATA_SEG, - .gs = KDATA_SEG, - .esp = (void*)dummy_stack + DUMMY_STACK_SIZE - 20 }, + struct exec_param* execp = + (void*)dummy_stack + DUMMY_STACK_SIZE - sizeof(struct exec_param); + + *execp = (struct exec_param){ .cs = KCODE_SEG, + .eflags = cpu_reflags() | 0x0200, .eip = (void*)my_dummy, .ss = KDATA_SEG, - .eflags = cpu_reflags() | 0x0200 }; - *(u32_t*)(&dummy_stack[DUMMY_STACK_SIZE - 4]) = dummy_proc.intr_ctx.eflags; - *(u32_t*)(&dummy_stack[DUMMY_STACK_SIZE - 8]) = KCODE_SEG; - *(u32_t*)(&dummy_stack[DUMMY_STACK_SIZE - 12]) = dummy_proc.intr_ctx.eip; + // memset to 0 + dummy_proc = (struct proc_info){}; + dummy_proc.intr_ctx = (isr_param){ .registers = { .ds = KDATA_SEG, + .es = KDATA_SEG, + .fs = KDATA_SEG, + .gs = KDATA_SEG }, + .execp = execp }; dummy_proc.page_table = cpu_rcr3(); dummy_proc.state = PS_READY; @@ -99,7 +99,7 @@ run(struct proc_info* proc) 由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部 这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数) */ - tss_update_esp(proc->intr_ctx.registers.esp); + tss_update_esp(proc->intr_ctx.esp); apic_done_servicing();