From fb359b05ea7758dc16afaaa1107676f7d2ebbdc5 Mon Sep 17 00:00:00 2001 From: acevest Date: Sat, 20 May 2023 00:36:37 +0800 Subject: [PATCH] =?utf8?q?=E9=87=8D=E5=86=99=E4=BA=86fork=E6=8B=B7?= =?utf8?q?=E8=B4=9D=E9=A1=B5=E7=9B=AE=E5=BD=95=E9=80=BB=E8=BE=91=E5=92=8C?= =?utf8?q?=E9=A1=B5=E5=86=99=E4=BF=9D=E6=8A=A4=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- include/page.h | 3 ++- kernel/fork.c | 4 ++++ mm/page.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/include/page.h b/include/page.h index afa35e1..e13173a 100644 --- a/include/page.h +++ b/include/page.h @@ -36,7 +36,8 @@ #define PAGE_SHIFT (12) #define PAGE_SIZE (1UL << PAGE_SHIFT) -#define PAGE_MASK (~((1UL << PAGE_SHIFT) - 1)) +#define PAGE_FLAG_MASK ((1UL << PAGE_SHIFT) - 1) +#define PAGE_MASK (~PAGE_FLAG_MASK) #define PAGE_OFFSET (0xC0000000) #define PAGE_PDE_CNT 1024 #define PAGE_PTE_CNT 1024 diff --git a/kernel/fork.c b/kernel/fork.c index e7e4590..057fcc9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -51,6 +51,9 @@ int do_fork(pt_regs_t *regs, unsigned long flags) { continue; } +#if 1 + pde_dst[i] = pde_src[i] & (~PDE_RW); +#else // 这里不用再为每个PDE拷贝一次PageTable,只需要拷贝PageDirectory并将其低于768的写权限去掉 // 同时需要修改缺页异常doPageFault的逻辑 if (PAGE_ALIGN(spde) != 0) { @@ -77,6 +80,7 @@ int do_fork(pt_regs_t *regs, unsigned long flags) { page_t *page = pa2page(pte_src[j]); page->count++; } +#endif } tsk->pid = get_next_pid(); diff --git a/mm/page.c b/mm/page.c index 6ac0e51..925580b 100644 --- a/mm/page.c +++ b/mm/page.c @@ -51,6 +51,58 @@ void do_wp_page(void *addr) { int npde = get_npde(addr); int npte = get_npte(addr); + pde_t *page_dir = (pde_t *)pa2va(current->cr3); + pde_t *pde = page_dir + npde; + + // 如果是因为PDE被写保护 + if (*pde & PDE_RW == 0) { + // 1. 分配一个页表 + unsigned long newtbl = alloc_one_page(0); + assert(newtbl != 0); + + // 2. 拷贝页表 + pte_t *oldtbl = pa2va(PAGE_ALIGN(page_dir[npde])); + memcpy((void *)newtbl, (void *)oldtbl, PAGE_SIZE); + + // 3. 对所有PTE加上写保护 + pte_t *pte = (pte_t *)newtbl; + for (int i = 0; i < PTECNT_PER_PAGE; i++) { + *pte &= ~PTE_RW; + pte++; + } + + // 4. 记下原PDE的权限 + unsigned long flags = PAGE_FLAGS(*pde); + + // 5. 设置新的PDE + *pde = va2pa(newtbl); + *pde |= flags; + + // 6. 解除PDE的写保护 + *pde |= PDE_RW; + } + + pte_t *page_tbl = pa2va(PAGE_ALIGN(page_dir[npde])); + pte_t *pte = page_tbl + npte; + + // 如果PTE的位置被写保护 + if (*pte & PTE_RW == 0) { + // 1. 分配一个页表 + unsigned long newaddr = alloc_one_page(0); + assert(newaddr != 0); + + // 2. 拷贝页表 + pte_t *oldaddr = pa2va(PAGE_ALIGN(page_dir[npde])); + memcpy((void *)newaddr, (void *)oldaddr, PAGE_SIZE); + + // 3. 解除PTE的写保护 + *pte |= PTE_RW; + } + +#if 0 + int npde = get_npde(addr); + int npte = get_npte(addr); + pde_t *page_dir = (pde_t *)pa2va(current->cr3); pte_t *page_tbl = pa2va(PAGE_ALIGN(page_dir[npde])); @@ -70,6 +122,7 @@ void do_wp_page(void *addr) { } page_tbl[npte] |= PAGE_WR; +#endif #if 0 page_tbl[npte] |= PAGE_US; page_dir[npde] |= PAGE_WR; -- 2.44.0