Merge branch 'interrupt-rework' into prog-loader
authorMinep <zelong56@gmail.com>
Wed, 4 Jan 2023 16:12:56 +0000 (16:12 +0000)
committerMinep <zelong56@gmail.com>
Wed, 4 Jan 2023 16:12:56 +0000 (16:12 +0000)
1  2 
lunaix-os/config/make-cc
lunaix-os/includes/lunaix/process.h
lunaix-os/kernel/asm/x86/pfault.c
lunaix-os/kernel/asm/x86/syscall.S
lunaix-os/kernel/k_init.c
lunaix-os/kernel/process/sched.c

diff --combined lunaix-os/config/make-cc
index 6fd8494c4d81902ebe74313e95be918fdef59236,a7c24680518417518dc76d2ead79bfb843738878..7915afe89a0949d305ea569d5c9664564b9c3e52
@@@ -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
index 0029e363d759a4366d1b684351341145ce388f7f,0b8d302e6e093e7122d7afcc93222f64b3e1ef43..27137a103db53763d07f7c28d02b5f9a5107df29
@@@ -6,7 -6,6 +6,7 @@@
  #include <lunaix/ds/waitq.h>
  #include <lunaix/fs.h>
  #include <lunaix/mm/mm.h>
 +#include <lunaix/mm/region.h>
  #include <lunaix/signal.h>
  #include <lunaix/timer.h>
  #include <lunaix/types.h>
  
  #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 ---- */
  
index f6c4355a1c0fabc58fc745b315bd4d74d0c604c6,2e4750397602e55a3cc3deff8a8aa0d688252494..2b0a8f1a4e81c234dbb09002fc82bab54126b2c6
@@@ -1,16 -1,14 +1,16 @@@
  #include <arch/x86/interrupts.h>
  #include <lunaix/common.h>
 -#include <lunaix/lxsignal.h>
  #include <lunaix/mm/mm.h>
  #include <lunaix/mm/pmm.h>
  #include <lunaix/mm/region.h>
  #include <lunaix/mm/vmm.h>
  #include <lunaix/sched.h>
 +#include <lunaix/signal.h>
  #include <lunaix/status.h>
  #include <lunaix/syslog.h>
  
 +#include <klibc/string.h>
 +
  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;
          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
index bde7f36d9d79b6a0f2e59736be6fd5e4ad191fdc,ff30f444d9c6b8d32352cf030768b84d928de89b..62e07212264d300aed2a80d7aaee2c0d0267d635
@@@ -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
  .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
          
index e98be8883cd3bbeb3ca161ed8071fd016a594c52,25af27e1ce80166093a92b2fe2ca15ca1b2ded1d..a2edf1a9d5c66007b5ada75b4e93aa0e80ad92cb
@@@ -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之后禁用。否则当进程被调度时,中断依然是关闭的!
      // 为内核创建一个专属栈空间。
      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));
      }
  }
index 19a31c7a7626438839f142bccf9f7c30f20fb656,4ed9d3438ad9c2d818ee0421de6463cea8ca12da..ade13b31c6414f4e1e1588b26645f255475f2c6c
@@@ -6,7 -6,7 +6,7 @@@
  
  #include <lunaix/fs/taskfs.h>
  #include <lunaix/mm/cake.h>
 -#include <lunaix/mm/kalloc.h>
 +#include <lunaix/mm/mmap.h>
  #include <lunaix/mm/pmm.h>
  #include <lunaix/mm/valloc.h>
  #include <lunaix/mm/vmm.h>
@@@ -18,8 -18,6 +18,8 @@@
  #include <lunaix/syscall.h>
  #include <lunaix/syslog.h>
  
 +#include <klibc/string.h>
 +
  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);