X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/b60166b327a9108b07e3069fa6568a451529ffd9..34f6af4f61e0eec9c96113e07f140b609b4113c8:/lunaix-os/kernel/process/fork.c diff --git a/lunaix-os/kernel/process/fork.c b/lunaix-os/kernel/process/fork.c index f087028..6a6be4b 100644 --- a/lunaix-os/kernel/process/fork.c +++ b/lunaix-os/kernel/process/fork.c @@ -1,7 +1,6 @@ #include #include -#include -#include +#include #include #include #include @@ -9,9 +8,10 @@ #include #include #include +#include -#include -#include +#include +#include #include @@ -25,26 +25,24 @@ region_maybe_cow(struct mm_region* region) return; } - ptr_t start_vpn = PN(region->start); - ptr_t end_vpn = PN(region->end); - for (size_t i = start_vpn; i <= end_vpn; i++) { - x86_pte_t* curproc = &PTE_MOUNTED(VMS_SELF, i); - x86_pte_t* newproc = &PTE_MOUNTED(VMS_MOUNT_1, i); - - cpu_flush_page((ptr_t)newproc); + pfn_t start_pn = pfn(region->start); + pfn_t end_pn = pfn(region->end); + + for (size_t i = start_pn; i <= end_pn; i++) { + pte_t* self = mkptep_pn(VMS_SELF, i); + pte_t* guest = mkptep_pn(VMS_MOUNT_1, i); + ptr_t va = page_addr(ptep_pfn(self)); if ((attr & REGION_MODE_MASK) == REGION_RSHARED) { - // 如果读共享,则将两者的都标注为只读,那么任何写入都将会应用COW策略。 - cpu_flush_page((ptr_t)curproc); - cpu_flush_page((ptr_t)(i << 12)); - - *curproc = *curproc & ~PG_WRITE; - *newproc = *newproc & ~PG_WRITE; + set_pte(self, pte_mkwprotect(*self)); + set_pte(guest, pte_mkwprotect(*guest)); } else { // 如果是私有页,则将该页从新进程中移除。 - *newproc = 0; + set_pte(guest, null_pte); } } + + tlb_flush_vmr_all(region); } static inline void @@ -62,23 +60,30 @@ __dup_fdtable(struct proc_info* pcb) static void __dup_kernel_stack(struct thread* thread, ptr_t vm_mnt) { - ptr_t kstack_pn = PN(current_thread->kstack); + struct leaflet* leaflet; + + ptr_t kstack_pn = pfn(current_thread->kstack); + kstack_pn -= pfn(KSTACK_SIZE); // copy the kernel stack - for (size_t i = 0; i < PN(KSTACK_SIZE); i++) { - volatile x86_pte_t* orig_ppte = &PTE_MOUNTED(VMS_SELF, kstack_pn); - x86_pte_t p = *orig_ppte; - ptr_t kstack = kstack_pn * PG_SIZE; + pte_t* src_ptep = mkptep_pn(VMS_SELF, kstack_pn); + pte_t* dest_ptep = mkptep_pn(vm_mnt, kstack_pn); + for (size_t i = 0; i <= pfn(KSTACK_SIZE); i++) { + pte_t p = *src_ptep; - if (guardian_page(p)) { - vmm_set_mapping(vm_mnt, kstack, 0, 0, VMAP_GUARDPAGE); + if (pte_isguardian(p)) { + set_pte(dest_ptep, guard_pte); } else { - ptr_t ppa = vmm_dup_page(PG_ENTRY_ADDR(p)); - vmm_set_mapping(vm_mnt, kstack, ppa, p & 0xfff, 0); + leaflet = dup_leaflet(pte_leaflet(p)); + i += ptep_map_leaflet(dest_ptep, p, leaflet); } - kstack_pn--; + src_ptep++; + dest_ptep++; } + + struct proc_mm* mm = vmspace(thread->process); + tlb_flush_mm_range(mm, kstack_pn, leaf_count(KSTACK_SIZE)); } /* @@ -102,7 +107,7 @@ dup_active_thread(ptr_t vm_mnt, struct proc_info* duped_pcb) return NULL; } - th->intr_ctx = current_thread->intr_ctx; + th->hstate = current_thread->hstate; th->kstack = current_thread->kstack; signal_dup_context(&th->sigctx); @@ -145,6 +150,8 @@ done: pid_t dup_proc() { + no_preemption(); + struct proc_info* pcb = alloc_process(); if (!pcb) { syscall_result(ENOMEM); @@ -166,14 +173,14 @@ dup_proc() } __dup_fdtable(pcb); - procvm_dup(pcb); - vmm_mount_pd(VMS_MOUNT_1, vmroot(pcb)); + struct proc_mm* mm = vmspace(pcb); + procvm_dupvms_mount(mm); - struct thread* main_thread = dup_active_thread(VMS_MOUNT_1, pcb); + struct thread* main_thread = dup_active_thread(mm->vm_mnt, pcb); if (!main_thread) { syscall_result(ENOMEM); - vmm_unmount_pd(VMS_MOUNT_1); + procvm_unmount(mm); delete_process(pcb); return -1; } @@ -185,7 +192,7 @@ dup_proc() region_maybe_cow(pos); } - vmm_unmount_pd(VMS_MOUNT_1); + procvm_unmount(mm); commit_process(pcb); commit_thread(main_thread);