From: acevest Date: Tue, 30 Dec 2025 09:27:38 +0000 (+0800) Subject: 内核空间所有页表都固定分配出来(不再变动)便于所有进程共享内核地址空间 X-Git-Url: http://repos.zhaoyanbai.com/Mou_128.png?a=commitdiff_plain;h=5b0e9ed1df0555445cbd0c2409d58ceb56292e59;p=kernel.git 内核空间所有页表都固定分配出来(不再变动)便于所有进程共享内核地址空间 --- diff --git a/kernel/task_init.c b/kernel/task_init.c index 1a30bf0..6670b3d 100644 --- a/kernel/task_init.c +++ b/kernel/task_init.c @@ -194,7 +194,7 @@ void init_task_entry() { #if 1 kernel_task("ide/1", disk_task_entry, (void *)1); - kernel_task("user", user_task_entry, NULL); + // kernel_task("user", user_task_entry, NULL); kernel_task("tskA", taskA_entry, NULL); kernel_task("tskB", taskB_entry, NULL); kernel_task("tskC", taskC_entry, NULL); diff --git a/mm/bootmem.c b/mm/bootmem.c index 05facda..f7f8853 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -294,11 +294,11 @@ find_next_block: } reserve_bootmem(bgn_pfn, end_pfn); - region = pfn2va(bgn_pfn); + region = pfn2pa(bgn_pfn); pbd->prepare_alloc_pfn = end_pfn; - printk("%s alloc bootmem size: %x pfn cnt: %d [%d, %d)\n", title, size, pfn_cnt, bgn_pfn, end_pfn); + printk("[bootmem][%s] alloc size: 0x%x pfn cnt: %d [%d, %d) %x\n", title, size, pfn_cnt, bgn_pfn, end_pfn, region); return region; } diff --git a/mm/buddy.c b/mm/buddy.c index c8d4f99..e2a16e2 100644 --- a/mm/buddy.c +++ b/mm/buddy.c @@ -207,6 +207,7 @@ void init_buddy_system() { unsigned long page_map_size = pfn_cnt * sizeof(page_t); void *alloc_from_bootmem(unsigned long size, char *title); buddy_system.page_map = alloc_from_bootmem(page_map_size, "buddy"); + buddy_system.page_map = pa2va(buddy_system.page_map); if (0 == buddy_system.page_map) { printk("can not go on playing...\n"); while (1); diff --git a/mm/mm.c b/mm/mm.c index c370ea7..15d5ed6 100644 --- a/mm/mm.c +++ b/mm/mm.c @@ -39,41 +39,72 @@ void set_page_shared(void *x) { pte[get_npte(addr)] |= PAGE_US; } +char *paging_page = "paging"; + void init_paging() { unsigned int i; unsigned long pfn = 0; - pte_t *pte = 0; - unsigned long *pgtb_addr = 0; + pte_t *pg_table = 0; void *alloc_from_bootmem(unsigned long size, char *title); // 在multiboot.S是已经初始化了BOOT_INIT_PAGETBL_CNT个页 // 这里接着初始化剩余的页 // 最大限制内存1G for (pfn = pa2pfn(BOOT_INIT_PAGETBL_CNT << 22); pfn < bootmem_data.max_pfn; ++pfn) { - unsigned long ti = pfn % PAGE_PTE_CNT; + unsigned long npte = pfn % PAGE_PTE_CNT; unsigned long page_addr = (unsigned long)pfn2pa(pfn); - if (ti == 0) { - pgtb_addr = (unsigned long *)alloc_from_bootmem(PAGE_SIZE, "paging"); - if (0 == pgtb_addr) { + if (npte == 0) { + pg_table = (pte_t *)alloc_from_bootmem(PAGE_SIZE, paging_page); + if (0 == pg_table) { panic("no pages for paging..."); } - memset((void *)pgtb_addr, 0, PAGE_SIZE); + memset((void *)pg_table, 0, PAGE_SIZE); - init_pgd[get_npde(page_addr)] = (pde_t)((unsigned long)va2pa(pgtb_addr) | PAGE_P | PAGE_WR); + init_pgd[get_npde(page_addr)] = (pde_t)((unsigned long)(pg_table) | PAGE_P | PAGE_WR); } - pte = ((pte_t *)pgtb_addr) + ti; - *pte = (pte_t)(page_addr | PAGE_P | PAGE_WR); + pg_table[npte] = (pte_t)(page_addr | PAGE_P | PAGE_WR); } // paging for kernel space - unsigned long delta = get_npde(PAGE_OFFSET); - for (i = delta; i < PDECNT_PER_PAGE; ++i) { - init_pgd[i] = init_pgd[i - delta]; - init_pgd[i - delta] = 0; + // 在此处让内核空间对[0, MAX_SUPT_PHYMM_SIZE]物理内存也作直接映射 + int kernel_npde_base = get_npde(PAGE_OFFSET); + for (i = kernel_npde_base; i < PDECNT_PER_PAGE; ++i) { + init_pgd[i] = init_pgd[i - kernel_npde_base]; + } + + // 接下来还有部分内核空间需要处理,例如 VRAM_VADDR FIXED_MAP_VADDR 等 + // 这部分空间也需要给他们分配固定的页表 + // 这部分页表在pgd里的pde就不再允许修改了 + // 这样,无论内核空间映射如何变化,这部分空间所有进程都能共享到变化 + for (i = kernel_npde_base; i < PDECNT_PER_PAGE; ++i) { + if(0 != init_pgd[i]) { + continue; + } + + // 分配一个页表 + pte_t *pg_table = (pte_t *)alloc_from_bootmem(PAGE_SIZE, paging_page); + if(0 == pg_table) { + panic("no pages for paging..."); + } + + // 清空页表 + memset((void *)pg_table, 0xAC, PAGE_SIZE); + + // 把页表地址填入pgd + init_pgd[i] = (pde_t)((unsigned long)(pg_table) | PAGE_P | PAGE_WR); + } + + + // 建立完内核空间的页映射,需要清空用户空间的映射 + for (i = 0; i < kernel_npde_base; ++i) { + init_pgd[i] = 0; } + + +#if 0 // 接下来为显存建立页映射 unsigned long vram_phys_addr = system.vbe_phys_addr; printk("vram_phys_addr: 0x%x\n", vram_phys_addr); @@ -84,7 +115,7 @@ void init_paging() { } // 后续要初始化,所以此处不用memset // memset((void *)pgtb_addr, 0, PAGE_SIZE); - init_pgd[get_npde(VRAM_VADDR_BASE) + pde_inx] = (pde_t)((unsigned long)va2pa(pgtb_addr) | PAGE_P | PAGE_WR); + init_pgd[get_npde(VRAM_VADDR_BASE) + pde_inx] = (pde_t)((unsigned long)(pgtb_addr) | PAGE_P | PAGE_WR); for (int pte_inx = 0; pte_inx < PTECNT_PER_PAGE; pte_inx++) { pgtb_addr[pte_inx] = vram_phys_addr | PAGE_P | PAGE_WR; @@ -105,6 +136,7 @@ void init_paging() { // 在内存中 [B, G, R, A] 因为x86是小端序 所以实际是 ARGB 顺序 vram[i] = 0x000000FF; } +#endif #if 0 bool flag = false; diff --git a/scripts/link.ld b/scripts/link.ld index e7049e0..5c62472 100644 --- a/scripts/link.ld +++ b/scripts/link.ld @@ -57,7 +57,6 @@ SECTIONS .text : AT(ADDR(.text)-kernel_virtual_addr_start) ALIGN(0x1000) { code = .; - /* 单独把 multiboot.S 的 .text 放在这个位置是为了便于调试,实际是可以不写这一句的 */ *(.text) *(.ring3.text); *(.sysexit) /* last */