-LOG_MODULE("PROC")
-
-void*
-__dup_pagetable(pid_t pid, uintptr_t mount_point)
-{
- void* ptd_pp = pmm_alloc_page(pid, PP_FGPERSIST);
- vmm_set_mapping(VMS_SELF, PG_MOUNT_1, ptd_pp, PG_PREM_RW, VMAP_NULL);
-
- x86_page_table* ptd = PG_MOUNT_1;
- x86_page_table* pptd = (x86_page_table*)(mount_point | (0x3FF << 12));
-
- size_t kspace_l1inx = L1_INDEX(KERNEL_MM_BASE);
-
- for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++) {
-
- x86_pte_t ptde = pptd->entry[i];
- // 空或者是未在内存中的L1页表项直接照搬过去。
- // 内核地址空间直接共享过去。
- if (!ptde || i >= kspace_l1inx || !(ptde & PG_PRESENT)) {
- ptd->entry[i] = ptde;
- continue;
- }
-
- // 复制L2页表
- void* pt_pp = pmm_alloc_page(pid, PP_FGPERSIST);
- vmm_set_mapping(VMS_SELF, PG_MOUNT_2, pt_pp, PG_PREM_RW, VMAP_NULL);
-
- x86_page_table* ppt = (x86_page_table*)(mount_point | (i << 12));
- x86_page_table* pt = PG_MOUNT_2;
-
- for (size_t j = 0; j < PG_MAX_ENTRIES; j++) {
- x86_pte_t pte = ppt->entry[j];
- pmm_ref_page(pid, PG_ENTRY_ADDR(pte));
- pt->entry[j] = pte;
- }
-
- ptd->entry[i] = (uintptr_t)pt_pp | PG_ENTRY_FLAGS(ptde);
- }
-
- ptd->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, ptd_pp);
-
- return ptd_pp;
-}
-
-void
-__del_pagetable(pid_t pid, uintptr_t mount_point)
-{
- x86_page_table* pptd = (x86_page_table*)(mount_point | (0x3FF << 12));
-
- // only remove user address space
- for (size_t i = 0; i < L1_INDEX(KERNEL_MM_BASE); i++) {
- x86_pte_t ptde = pptd->entry[i];
- if (!ptde || !(ptde & PG_PRESENT)) {
- continue;
- }
-
- x86_page_table* ppt = (x86_page_table*)(mount_point | (i << 12));
-
- for (size_t j = 0; j < PG_MAX_ENTRIES; j++) {
- x86_pte_t pte = ppt->entry[j];
- // free the 4KB data page
- if ((pte & PG_PRESENT)) {
- pmm_free_page(pid, PG_ENTRY_ADDR(pte));
- }
- }
- // free the L2 page table
- pmm_free_page(pid, PG_ENTRY_ADDR(ptde));
- }
- // free the L1 directory
- pmm_free_page(pid, PG_ENTRY_ADDR(pptd->entry[PG_MAX_ENTRIES - 1]));
-}
-
-void*
-vmm_dup_vmspace(pid_t pid)
-{
- return __dup_pagetable(pid, VMS_SELF);
-}