]> Zhao Yanbai Git Server - kernel.git/commitdiff
内核地址空间的页表项开启GLOBAL比特位
authorzhaoyanbai <zhaoyanbai@126.com>
Thu, 1 Oct 2026 04:17:35 +0000 (12:17 +0800)
committerzhaoyanbai <zhaoyanbai@126.com>
Thu, 1 Oct 2026 04:17:41 +0000 (12:17 +0800)
drivers/vga.c
include/page.h
include/processor.h
include/system.h
kernel/sched.c
kernel/setup.c
kernel/system.c
kernel/task_init.c
mm/mm.c

index b8697b6a01b8fa573464ec0470058deca2e06439..bd66bad7df49f6d88204e8193cdc80052ddb702a 100644 (file)
@@ -11,6 +11,7 @@
 #include <vga.h>
 #include <io.h>
 #include <irq.h>
+#include <page.h>
 
 static uint16_t* vga_vram_base_vaddr = (uint16_t*)pa2va(vga_vram_base_paddr);
 
index 22e56bc99a7e2910ac904ea446577c216111ff92..c2eb14ecaf8a9a4ada69af148a3bb22c94ffa3b8 100644 (file)
 #define _PAGE_H
 
 #include <kdef.h>
+#include <processor.h>
 
 /*
 
-| CR0的PG | CR4的PAE | CR4的PSE | PDE的PS | 页面规模 | 物理地址规模 |
-| ------- | -------- | -------- | ------- | -------- | ------------ |
-| 0       | ×       | ×       | ×      | ―      | 禁止分页 |
-| 1       | 0        | 0        | ×      | 4KB      | 32位        |
-| 1       | 0        | 1        | 0       | 4KB      | 32位        |
-| 1       | 0        | 1        | 1       | 4MB      | 32位        |
-| 1       | 1        | ×       | 0       | 4KB      | 36位        |
-| 1       | 1        | ×       | 1       | 2MB      | 36位        |
+| CR0.PG  | CR4.PAE  | CR4.PSE  | PDE.PS  | PAGE SIZE | 物理地址规模 |
+| ------- | -------- | -------- | ------- | --------- | ---------- |
+| 0       | ×        | ×        | ×       | ―         | disabled   |
+| 1       | 0        | 0        | ×       | 4KB       | 32bit      |
+| 1       | 0        | 1        | 0       | 4KB       | 32bit      |
+| 1       | 0        | 1        | 1       | 4MB       | 32bit      |
+| 1       | 1        | ×        | 0       | 4KB       | 36bit      |
+| 1       | 1        | ×        | 1       | 2MB       | 36bit      |
 
 */
 
-#define PAGE_P 0x1   // 在内存中
-#define PAGE_WR 0x2  // 表示可读写
-#define PAGE_US 0x4  // 用户级
+#define PAGE_P 0x001   // 在内存中
+#define PAGE_WR 0x002  // 表示可读写
+#define PAGE_US 0x004  // 用户级
+#define PAGE_G 0x100 // 全局页表项
 
 #define PAGE_SHIFT (12)
 #define PAGE_SIZE (1UL << PAGE_SHIFT)
 #define PAGE_PDE_CNT 1024
 #define PAGE_PTE_CNT 1024
 
-// P:  有效位。0 表示当前表项无效。
-// R/W: 0 表示只读。1表示可读写。
-// U/S: 0 表示只能0、1、2特权级可访问。3 表示只有特权级程序可访问
-// A:   0 表示该页未被访问,1表示已被访问。
-// D:   脏位。0表示该页未写过,1表示该页被写过
-// PS:  只存在于页目录表。在CR4中的PSE打开的情况下,0表示这是4KB页,指向一个页表。1表示这是4MB大页,直接指向物理页。
+// P:  有效位
+//      0 表示当前表项无效,访问该虚拟地址直接#PF缺页异常,CPU不翻译,也不看其它位,此时余下31位CPU完全不管,内核可以随便用。
+//      修改必须刷对应TLB
+// R/W: 0 表示只读写就#PF; 1表示可读写。PDE和PTE要同时看,逻辑与。比如PDE.RW=0 && PTE.RW=1 最终还是只读。
+//      另外还需要注意CR0.WP,如果CR0.WP=0(默认),那么只限制用户态,内核写只读页也不缺页; CR0.WP=1,那么内核写只读页也#PF。
+// U/S: 0 表示只能0、1、2特权级可访问; 3 表示只有特权级程序可访问。
+//      同样是PDE与PTE按逻辑与。
+// PWT: 0 表示写进缓存,迟早刷回内存; 1 表示写缓存同时写内存,慢但内存总是新的。
+//      普通内存映射一般PWT=0,对页表自身、设备内存特殊映射才考虑设置为1。
+//      CR0.CD=1时这个位被忽略。
+// PCD: 0 表示可以进cache; 1表示这一页不进CPU cache。
+//      映射设备寄存器、MMIO、帧缓冲时用。普通RAM页不要开,开了性能会崩。
+//      CR0.CD=1时这个位也被忽略。
+// A:   0 表示该页未被访问; 1表示已被访问。
+//      改此位从1清0时,如果P=1,建议顺手刷TLB,避免硬件状态不一致。
+// D:   脏位。0表示该页未写过; 1表示该页被写过。只有PTE用这位,PDE这个位忽略或保留。
+//      用于换出页面时判断要不要写回磁盘。D=0的页换出可直接丢弃,磁盘上已经有相同内容; D=1才需要写回。
+//      清D位也要刷新TLB。
+// PS:  PAGE SIZE. 只存在于页目录表项。在CR4中的PSE打开的情况下,0表示这是4KB页,指向一个页表。1表示这是4MB大页,直接指向物理页。
+// PAT: PAGE ATTRIBUTE TABLE. 只存在于页表项。 Pentium III后引入的机制。
+// G:   GLOBAL 全局位
+//      4K分页下PDE.G被忽略,如果用4MB大页映射内核空间,PDE.G有效
+//      内核空间映射在所有进程页表里都一样,设为全局,切换进程不刷新这些TLB项,减少内核映射的TLB miss。
+//      用户页不能随便设G,会跨进程泄露TLB翻译。改G相关属性也需要注意TLB一致性。
+// AVL: 内核可用
+//      常见用法:
+//          1. COW标记(软件位,不是硬件COW)
+//          2. 页类型标记: 匿名页、文件页、设备页、共享页
+//          3. 写时复制里记录"这是共享只读页"
+//          4. 页面锁标记,禁止换出
+
+
+// x
 
 // |<------ 31~12------>|<------ 11~0 --------->| 比特
 //                      |b a 9 8 7 6 5 4 3 2 1 0|
@@ -123,15 +152,9 @@ typedef unsigned long pte_t;
 
 #define MAX_ORDER (11)
 
-#define set_cr3(cr3) asm volatile("movl %0, %%cr3" ::"r"(cr3))
-static inline unsigned long get_cr3() {
-    unsigned long cr3;
-    asm volatile("movl %%cr3, %0" : "=r"(cr3));
-    return cr3;
-}
 
 static inline pde_t* get_pgd() {
-    return (pde_t*)pa2va((get_cr3() & PAGE_MASK));
+    return (pde_t*)pa2va((read_cr3() & PAGE_MASK));
 }
 
 enum page_flags {
index 1aefc19e9249590635d1ec13196e40b50efd5326..8ce6618bba97f3fbd78cdfcb3f9e6359222ce058 100644 (file)
@@ -221,4 +221,10 @@ extern tss_t tss;
 #define CR4_OSXMMEEXCPT (1 << 10)  // R/W  Operating System Unmasked Exception Support
 #define CR4_OSXSAVE (1 << 18)      // R/W XSAVE and Processor Extended States Enable Bit
 
+
+uint32_t read_cr3();
+uint32_t read_cr4();
+void write_cr3(uint32_t cr3);
+void write_cr4(uint32_t cr4);
+
 #endif  //_DESCRIPTOR_H
index fb6a90094f8458435cf9fee406cdc51eb3eb39f9..1cd8597903dbb9b4674e422333e060ed38c1dffd 100644 (file)
@@ -18,7 +18,6 @@
 #define _SYSTEM_H
 
 #include <assert.h>
-#include <page.h>
 #include <kdef.h>
 
 #define PT_REGS_EBX 0
index bb26559593b88b77047cb1cc98be00cc600ff247..2ef444a35a4782f88dd8b6158c2f18824067a115 100644 (file)
@@ -39,7 +39,7 @@ pid_t get_next_pid() {
 }
 
 void load_cr3(task_t* tsk) {
-    set_cr3(tsk->cr3);
+    write_cr3(tsk->cr3);
 }
 
 extern pde_t __initdata init_pgd[PDECNT_PER_PAGE] __attribute__((__aligned__(PAGE_SIZE)));
@@ -220,7 +220,7 @@ task_t* alloc_task_t() {
 }
 
 void switch_to() {
-    set_cr3(current->cr3);
+    write_cr3(current->cr3);
     tss.esp0 = current->esp0;
 }
 
index ae304182cc283deb7ec841e4af762bf5e80c6a32..4b062ff3c313ab40d8f354b5bac6b20cb0561636 100644 (file)
@@ -161,4 +161,8 @@ void setup_kernel() {
 
     void dump_fixmap();
     dump_fixmap();
+
+    uint32_t read_cr4();
+    uint32_t cr4 = read_cr4();
+    printk("CR4: %08x\n", cr4);
 }
index 0b3ca1e991b02e6121f91bbace5fe5ffc4ff2d12..d4121b50025bdc56d9877e9eaa1c3a95a87280d7 100644 (file)
@@ -214,6 +214,26 @@ void set_tss() {
     asm("ltr %%ax" ::"a"((INDEX_TSS << 3) + 3));
 }
 
+uint32_t read_cr3() {
+    uint32_t cr3 = 0;
+    asm volatile("movl %%cr3, %0" : "=r"(cr3));
+    return cr3;
+}
+
+void write_cr3(uint32_t cr3) {
+    asm volatile("movl %0, %%cr3" ::"r"(cr3));
+}
+
+uint32_t read_cr4() {
+    uint32_t cr4 = 0;
+    asm volatile("movl %%cr4, %0" : "=r"(cr4));
+    return cr4;
+}
+
+void write_cr4(uint32_t cr4) {
+    asm volatile("movl %0, %%cr4" ::"r"(cr4));
+}
+
 int sysc_reboot(int mode) {
     void do_reboot();
     void do_poweroff();
index f5661c7a39ed61ba49993a9570c44dc523bc6053..e71eaa8711a187687381a65d74ab339098d42022 100644 (file)
@@ -226,7 +226,7 @@ void init_task_entry() {
 
     printk("RING3 ENTRY %x page %x pgd inx %u pt inx %u\n", mod_start, text_at, pgd_index, pt_index);
 
-    set_cr3(current->cr3);
+    write_cr3(current->cr3);
 
     asm("sysexit;" ::"d"(mod_start), "c"(mod_start + PAGE_SIZE - 4));
 #endif
diff --git a/mm/mm.c b/mm/mm.c
index 999e433b6ecaac3805d8a4fe4d26c50c317f8b7f..8e9d74b3cc155df62aeb15b1311ed8a187af85bc 100644 (file)
--- a/mm/mm.c
+++ b/mm/mm.c
@@ -47,6 +47,11 @@ void init_paging() {
     pte_t* pg_table = 0;
     void* alloc_from_bootmem(unsigned long size, char* title);
 
+    // 打开CR4的 PAGE GLOBAL 功能
+    uint32_t cr4 = read_cr4();
+    cr4 |= CR4_PGE;
+    write_cr4(cr4);
+
     // 在multiboot.S是已经初始化了BOOT_INIT_PAGETBL_CNT个页
     // 这里接着初始化剩余的页
     // 最大限制内存1G
@@ -64,7 +69,7 @@ void init_paging() {
             init_pgd[get_npde(page_addr)] = (pde_t)((unsigned long)(pg_table) | PAGE_P | PAGE_WR);
         }
 
-        pg_table[npte] = (pte_t)(page_addr | PAGE_P | PAGE_WR);
+        pg_table[npte] = (pte_t)(page_addr | PAGE_P | PAGE_WR | PAGE_G);
     }
 
     // paging for kernel space
@@ -124,7 +129,7 @@ void init_paging() {
         }
     }
 
-    set_cr3(va2pa(init_pgd));
+    write_cr3(va2pa(init_pgd));
 
     // 测试显存
     for (int i = 0; i < system.x_resolution * (system.y_resolution - 32); i++) {