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?ds=inline;hp=-c Merge branch 'interrupt-rework' into prog-loader --- 0cf90cca0c924622f3fee8d2a3fafa8238363dc6 diff --combined lunaix-os/config/make-cc index 6fd8494,a7c2468..7915afe --- a/lunaix-os/config/make-cc +++ b/lunaix-os/config/make-cc @@@ -1,6 -1,5 +1,6 @@@ CC := i686-elf-gcc AS := i686-elf-as +AR := i686-elf-ar ARCH_OPT := -D__ARCH_IA32 -include flags.h @@@ -17,7 -16,10 +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 diff --combined lunaix-os/includes/lunaix/process.h index 0029e36,0b8d302..27137a1 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@@ -6,7 -6,6 +6,7 @@@ #include #include #include +#include #include #include #include @@@ -26,6 -25,12 +26,6 @@@ #define PROC_FINPAUSE 1 -struct proc_mm -{ - heap_context_t u_heap; - struct mm_region regions; -}; - struct proc_sigstate { isr_param proc_regs; @@@ -52,9 -57,9 +52,9 @@@ struct proc_inf 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 --combined lunaix-os/kernel/asm/x86/pfault.c index f6c4355,2e47503..2b0a8f1 --- a/lunaix-os/kernel/asm/x86/pfault.c +++ b/lunaix-os/kernel/asm/x86/pfault.c @@@ -1,16 -1,14 +1,16 @@@ #include #include -#include #include #include #include #include #include +#include #include #include +#include + static void kprintf(const char* fmt, ...) { @@@ -38,7 -36,7 +38,7 @@@ intr_routine_page_fault(const isr_param goto segv_term; } - if (!SEL_RPL(param->cs)) { + if (!SEL_RPL(param->execp->cs)) { // 如果是内核页错误…… if (do_kernel(&mapping)) { return; @@@ -53,85 -51,48 +53,85 @@@ goto segv_term; } - volatile x86_pte_t* pte = &PTE_MOUNTED(PD_REFERENCED, ptr >> 12); - if ((*pte & PG_PRESENT)) { + volatile x86_pte_t* pte = &PTE_MOUNTED(VMS_SELF, ptr >> 12); + if (PG_IS_PRESENT(*pte)) { if ((hit_region->attr & COW_MASK) == COW_MASK) { // normal page fault, do COW cpu_invplg(pte); uintptr_t pa = (uintptr_t)vmm_dup_page(__current->pid, PG_ENTRY_ADDR(*pte)); pmm_free_page(__current->pid, *pte & ~0xFFF); - *pte = (*pte & 0xFFF) | pa | PG_WRITE; + *pte = (*pte & 0xFFF & ~PG_DIRTY) | pa | PG_WRITE; goto resolved; } // impossible cases or accessing privileged page goto segv_term; } - if (!(*pte)) { - // Invalid location + // an anonymous page and not present + // -> a new page need to be alloc + if ((hit_region->attr & REGION_ANON)) { + if (!PG_IS_PRESENT(*pte)) { + cpu_invplg(pte); + uintptr_t pa = pmm_alloc_page(__current->pid, 0); + if (!pa) { + goto oom; + } + + *pte = *pte | pa | PG_PRESENT; + goto resolved; + } + // permission denied on anon page (e.g., write on readonly page) goto segv_term; } - uintptr_t loc = *pte & ~0xfff; + // if mfile is set (Non-anonymous), then it is a mem map + if (hit_region->mfile && !PG_IS_PRESENT(*pte)) { + struct v_file* file = hit_region->mfile; + u32_t offset = + ((ptr - hit_region->start) & (PG_SIZE - 1)) + hit_region->foff; + uintptr_t pa = pmm_alloc_page(__current->pid, 0); + + if (!pa) { + goto oom; + } - // a writable page, not present, not cached, pte attr is not null - // -> a new page need to be alloc - if ((hit_region->attr & REGION_WRITE) && (*pte & 0xfff) && !loc) { cpu_invplg(pte); - uintptr_t pa = pmm_alloc_page(__current->pid, 0); - *pte = *pte | pa | PG_PRESENT; + *pte = (*pte & 0xFFF) | pa | PG_PRESENT; + + ptr = PG_ALIGN(ptr); + memset(ptr, 0, PG_SIZE); + + int errno = 0; + if (hit_region->init_page) { + errno = hit_region->init_page(hit_region, ptr, offset); + } else { + errno = file->ops->read_page(file->inode, ptr, PG_SIZE, offset); + } + + if (errno < 0) { + kprintf(KERROR "fail to populate page (%d)\n", errno); + goto segv_term; + } + + *pte &= ~PG_DIRTY; + goto resolved; } - // page not present, bring it from disk or somewhere else + // page not present, might be a chance to introduce swap file? __print_panic_msg("WIP page fault route", param); while (1) ; +oom: + kprintf(KERROR "out of memory\n"); 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 --combined lunaix-os/kernel/asm/x86/syscall.S index bde7f36,ff30f44..62e0721 --- a/lunaix-os/kernel/asm/x86/syscall.S +++ b/lunaix-os/kernel/asm/x86/syscall.S @@@ -30,7 -30,7 +30,7 @@@ .long __lxsys_close /* 20 */ .long __lxsys_read .long __lxsys_write - .long __lxsys_readdir + .long __lxsys_sys_readdir .long __lxsys_mkdir .long __lxsys_lseek /* 25 */ .long __lxsys_geterrno @@@ -59,9 -59,6 +59,9 @@@ .long __lxsys_getpgid .long __lxsys_setpgid /* 50 */ .long __lxsys_syslog + .long __lxsys_sys_mmap + .long __lxsys_munmap + .long __lxsys_execve 2: .rept __SYSCALL_MAX - (2b - 1b)/4 .long 0 @@@ -72,10 -69,11 +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 @@@ -87,7 -85,8 +88,7 @@@ popl %ebp ret 1: - pushl 24(%ebp) /* esi - #6 arg */ - pushl 20(%ebp) /* ebp - #5 arg */ + pushl 24(%ebp) /* esi - #5 arg */ pushl 16(%ebp) /* edi - #4 arg */ pushl 12(%ebp) /* edx - #3 arg */ pushl 8(%ebp) /* ecx - #2 arg */ @@@ -97,7 -96,7 +98,7 @@@ movl %eax, (%ebp) /* save the return value */ - addl $24, %esp /* remove the parameters from stack */ + addl $20, %esp /* remove the parameters from stack */ popl %ebp diff --combined lunaix-os/kernel/k_init.c index e98be88,25af27e..a2edf1a --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@@ -127,11 -127,7 +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之后禁用。否则当进程被调度时,中断依然是关闭的! @@@ -148,26 -144,21 +144,21 @@@ // 为内核创建一个专属栈空间。 for (size_t i = 0; i < (KSTACK_SIZE >> PG_SIZE_BITS); i++) { uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0); - vmm_set_mapping(PD_REFERENCED, + vmm_set_mapping(VMS_SELF, KSTACK_START + (i << PG_SIZE_BITS), pa, PG_PREM_RW, 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" @@@ -210,11 -201,11 +201,11 @@@ setup_memory(multiboot_memory_map_t* ma pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, PP_FGLOCKED); for (uintptr_t i = &__usrtext_start; i < &__usrtext_end; i += PG_SIZE) { - vmm_set_mapping(PD_REFERENCED, i, V2P(i), PG_PREM_UR, VMAP_NULL); + vmm_set_mapping(VMS_SELF, i, V2P(i), PG_PREM_UR, VMAP_NULL); } // reserve higher half for (size_t i = L1_INDEX(KERNEL_MM_BASE); i < 1023; i++) { - assert(vmm_set_mapping(PD_REFERENCED, i << 22, 0, 0, VMAP_NOMAP)); + assert(vmm_set_mapping(VMS_SELF, i << 22, 0, 0, VMAP_NOMAP)); } } diff --combined lunaix-os/kernel/process/sched.c index 19a31c7,4ed9d34..ade13b3 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@@ -6,7 -6,7 +6,7 @@@ #include #include -#include +#include #include #include #include @@@ -18,8 -18,6 +18,8 @@@ #include #include +#include + volatile struct proc_info* __current; static struct proc_info dummy_proc; @@@ -60,23 -58,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 -97,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(); @@@ -326,14 -324,13 +326,14 @@@ alloc_process( proc->state = PS_CREATED; proc->pid = i; + proc->mm.pid = i; proc->created = clock_systime(); proc->pgid = proc->pid; proc->fdtable = vzalloc(sizeof(struct v_fdtable)); proc->fxstate = vzalloc_dma(512); // FXSAVE需要十六位对齐地址,使用DMA块(128位对齐) - llist_init_head(&proc->mm.regions.head); + llist_init_head(&proc->mm.regions); llist_init_head(&proc->tasks); llist_init_head(&proc->children); llist_init_head(&proc->grp_member); @@@ -403,18 -400,17 +403,18 @@@ destroy_process(pid_t pid vfree(proc->fdtable); vfree_dma(proc->fxstate); + vmm_mount_pd(VMS_MOUNT_1, proc->page_table); + struct mm_region *pos, *n; - llist_for_each(pos, n, &proc->mm.regions.head, head) + llist_for_each(pos, n, &proc->mm.regions, head) { - vfree(pos); + mem_sync_pages(VMS_MOUNT_1, pos, pos->start, pos->end - pos->start, 0); + region_release(pos); } - vmm_mount_pd(PD_MOUNT_1, proc->page_table); - - __del_pagetable(pid, PD_MOUNT_1); + __del_pagetable(pid, VMS_MOUNT_1); - vmm_unmount_pd(PD_MOUNT_1); + vmm_unmount_pd(VMS_MOUNT_1); cake_release(proc_pile, proc);