]> Zhao Yanbai Git Server - kernel.git/commitdiff
优化ring3相关逻辑
authoracevest <zhaoyanbai@126.com>
Wed, 31 Dec 2025 03:03:41 +0000 (11:03 +0800)
committeracevest <zhaoyanbai@126.com>
Wed, 31 Dec 2025 03:03:41 +0000 (11:03 +0800)
boot/acpi.c
include/page.h
include/types.h
kernel/apic.c
kernel/ring3.S
kernel/syscall.S
kernel/task_user.c
mm/page.c
scripts/link.ld

index faf8a0953f29986a4a16d2a90507619fa8e7d9a6..55c7db713c7b9d61f7d19ae3885bc189861cd783 100644 (file)
@@ -48,7 +48,7 @@ typedef struct {
 } __attribute__((packed)) madt_t;
 
 
-void parse_madt(void *addr) {
+void parse_madt(paddr_t addr) {
     if(0 == addr) {
         printk("MADT addr is null\n");
         return;
@@ -125,7 +125,7 @@ void parse_madt(void *addr) {
     }
 }
 
-void parse_rsdt(void *addr) {
+void parse_rsdt(paddr_t addr) {
     if(0 == addr) {
         printk("RSDT addr is null\n");
         return;
@@ -149,7 +149,7 @@ void parse_rsdt(void *addr) {
 
     for(int i=0; i<table_count; i++) {
         uint32_t table_phys_addr = rsdt->table_ptrs[i];
-        page_map((void *)table_phys_addr, (void *)table_phys_addr, PAGE_P | PAGE_WR);
+        page_map((vaddr_t)table_phys_addr, (paddr_t)table_phys_addr, PAGE_P | PAGE_WR);
 
         acpi_sdt_header_t *table = (acpi_sdt_header_t *)table_phys_addr;
         if(table == 0) {
@@ -164,7 +164,7 @@ void parse_rsdt(void *addr) {
         }
         printk("ACPI table %u signature %s addr %08x len %u\n", i, sig, table_phys_addr, table->length);
         if(memcmp(sig, "APIC", 4) == 0) {
-            parse_madt(table);
+            parse_madt((paddr_t)table);
         }
     }
 
index 6d15fb63d584209c24fbd947334c404990a79caa..4fb2d287dfb009b70d8d8fbb66b896430f428aa4 100644 (file)
@@ -231,7 +231,7 @@ struct kmem_cache {
 };
 
 
-void page_map(void *vaddr, void *paddr, uint32_t flags);
+void page_map(vaddr_t vaddr, paddr_t paddr, uint32_t flags);
 
 #endif  // ASM
 
index 308f8c90bf70fa341f2d8d39e6a68e868d5435d1..8b51fdc47eb6beb1230e0550ffec28567a31e096 100644 (file)
@@ -50,6 +50,11 @@ typedef long int32_t;
 typedef unsigned long long uint64_t;
 typedef long long int64_t;
 
+
+typedef uint32_t uintptr_t;
+typedef uint32_t paddr_t;
+typedef uint32_t vaddr_t;
+
 typedef int64_t loff_t;
 
 typedef uint32_t dev_t;
index a18268a8235d8f3a8fc2bdf418fbe38734f640d9..b89913793fb2413c420c119bd5a42e09e3fc4f38 100644 (file)
@@ -43,8 +43,8 @@
     printk("apic version: %08lx\n", apic_version);
 
 
-    unsigned long apic_phys_base_addr = apic_base & 0xFFFFF000;
-    unsigned long apic_virt_base_addr = apic_phys_base_addr;
+    paddr_t apic_phys_base_addr = apic_base & 0xFFFFF000;
+    vaddr_t apic_virt_base_addr = apic_phys_base_addr;
     #if 0
     unsigned long ddd = 0xFEC00000;
     while(ddd < 0xFF000000)  {
@@ -52,7 +52,7 @@
         ddd += 0x1000;
     }
     #endif
-    page_map((void*)apic_virt_base_addr, (void*)apic_phys_base_addr, PAGE_P);
+    page_map((vaddr_t)apic_virt_base_addr, (paddr_t)apic_phys_base_addr, PAGE_P);
 
     {
         volatile uint32_t *base = (volatile uint32_t *)apic_virt_base_addr;
index dcab14041b8b5560d89ab76fd50df7df22b756a6..36a19c034f10ecfb8ac08c837a3fe2c9bceec5d6 100644 (file)
@@ -7,7 +7,9 @@
  * ------------------------------------------------------------------------
  */
 
-.global ring3_entrys
+#define ASM
+#include <syscall.h>
+
 # a allocatable 可分配,表示这个节在程序运行时需要加载到内存中
 # x executable  可执行,表示这个节包含可执行的代码
 # w writable    可写,通常用于数据节
 #
 # @progbits     包含了程序数据  目标文件中实际包含数据/代码,如.text、.data节
 # @nobits       不包含程序数据  目标文件中不占空间,运行时分配零初始化内存,如.bss节
-.section .ring3.entry, "aw", @progbits
-#.type ring3_entry, @function
+.section .ring3.entry, "ax", @progbits
 .align 0x1000
-ring3_entrys:
-    nop;
-    nop;
+ring3_entry:
+    nop
     nop
+    nop
+
     pushal
-    movl $5, %eax
-    call get_eip
-    get_eip:
-    popl %edi
-    addl $8,%edi
-    movl %esp, %ebp;
-    sysenter;
+
+    movl    $7, %ebx
+    movl    $SYSC_WAIT, %eax
+    call    get_eip
+get_eip:
+    # 这里popl取得的就是上一个call指令自动压入栈中的地址
+    # 这个地址就是当前指令的地址
+    popl    %edi
+    addl    $8,%edi
+    movl    %esp, %ebp;
+
+    sysenter
+
     popal
+
     nop
     nop
-    jmp ring3_entrys
+    jmp ring3_entry
index 3efe83e211ccf96f28000a486302d124742457e1..130546d4895bd1037d636f4537fa98d57b90b86b 100644 (file)
@@ -85,7 +85,7 @@ syscall_entry:
 
     // 在系统调用前,用户态的esp保存在ebp中
     // sysexit指令从ecx中恢复用户态esp
-    xchgl   %ebp, %ecx
+    movl    %ebp, %ecx
 
     sysexit
 
index e90d5133d518a68d24bf12e529bec49fb23aa6a1..231e019b6a78608093c56aa8f63622213f82ddb2 100644 (file)
@@ -17,6 +17,7 @@
 #include <syscall.h>
 #include <system.h>
 #include <types.h>
+#include <page.h>
 
 void flush_tlb() {
     asm volatile("movl %%cr3, %%eax;"
@@ -31,30 +32,18 @@ void user_task_entry() {
 
     // ring3只占用一个page,页的起始位置放的是代码,页的末尾当栈用
     // ring3的地址直接是物理地址
-    extern unsigned long ring3_page_addr;
-    extern unsigned long ring3_page_end;
-    unsigned long ring3_text_page =(unsigned long) &ring3_page_addr; // 不在内核空间的物理地址
-    unsigned long ring3_stack_top = (unsigned long) &ring3_page_end;  // 不在内核空间的物理地址
-
-    unsigned long ring3_page_vaddr = 0x08000000; // 指定的ring3的虚拟地址
-    unsigned long ring3_stack_top_vaddr = ring3_page_vaddr + (ring3_stack_top - ring3_text_page);
-    int npte = get_npte(ring3_page_vaddr);
-    int npde = get_npde(ring3_page_vaddr);
+    extern char ring3_page_begin;
 
-    // 分配一个页表在用户空间对这页进行映射
-    pte_t *pgt = (pte_t *)page2va(alloc_one_page(0));
+    paddr_t ring3_page_addr = (paddr_t)&ring3_page_begin; // 不在内核空间的物理地址
+    paddr_t ring3_stack_top = ring3_page_addr + PAGE_SIZE;
 
-    memset(pgt, 0, PAGE_SIZE);
-    pgt[npte] = (pte_t)(ring3_text_page | PAGE_P | PAGE_US | PAGE_WR);
+    vaddr_t ring3_page_vaddr = 0x08000000; // 指定的ring3的虚拟地址
+    vaddr_t ring3_stack_top_vaddr = PAGE_OFFSET - 0x100000;
 
-    // 把这个页表映射到页目录
-    pde_t *pgd = pa2va(get_pgd());
-    pgd[npde] = (pde_t)(((unsigned long)va2pa(pgt)) | PAGE_P | PAGE_US | PAGE_WR);
+    page_map(ring3_page_vaddr, ring3_page_addr, PAGE_P | PAGE_US);
 
-    // 到此完成了 ring3_page_vaddr -> ring3_text_page的映射
-    // 刷新tlb
-    flush_tlb();
+    // 这里减去PAGE_SIZE是因为栈是向下生长的,所以得把栈顶虚拟地址空间的前一页映射到ring3_page
+    page_map((ring3_stack_top_vaddr-PAGE_SIZE), ring3_page_addr, PAGE_P | PAGE_US | PAGE_WR);
 
-    // 现在准备返回用户态
-    asm volatile("sysexit;" ::"d"(ring3_page_vaddr), "c"(ring3_stack_top_vaddr - 0x10));
+    asm volatile("sysexit;" ::"d"(ring3_page_vaddr), "c"(ring3_stack_top_vaddr));
 }
index deb5210e48e30336a7c4c4556eadf61429632b94..58924b352e01e7de0230987c4a27877c57c6c955 100644 (file)
--- a/mm/page.c
+++ b/mm/page.c
@@ -133,14 +133,16 @@ void do_wp_page(void *addr) {
 }
 
 
-void page_map(void *vaddr, void *paddr, uint32_t flags) {
+void page_map(vaddr_t vaddr, paddr_t paddr, uint32_t flags) {
+    assert(PAGE_ALIGN(vaddr) == vaddr);
+    assert(PAGE_ALIGN(paddr) == paddr);
+    assert(PAGE_FLAGS(flags) == flags);
+
     int npde = get_npde(vaddr);
     int npte = get_npte(vaddr);
 
     // 获取页目录地址
-    uint32_t pgd_pyhs_addr;
-    asm("mov %%cr3, %0" : "=r"(pgd_pyhs_addr));
-    pde_t *pgd = (pde_t *) pa2va(pgd_pyhs_addr);
+    pde_t *pgd = (pde_t *) pa2va(get_pgd());
 
     pte_t *pgt = 0;
     pde_t pde = pgd[npde];
@@ -162,12 +164,4 @@ void page_map(void *vaddr, void *paddr, uint32_t flags) {
 
 
     asm volatile("invlpg (%0)" : : "r"(vaddr));
-
-    uint32_t cr3 = 0;
-    asm("mov %%cr3, %0" : "=r"(cr3));
-
-    asm("nop;nop;nop;");
-
-    asm("mov %0, %%cr3" : : "r"(cr3));
-    // asm volatile("mov %0, %%cr3" : : "r"(pgd_pyhs_addr));
 }
index 1a55db4d0ced29ac9664fca86cb3c3758f1379aa..ea3009b87855f8a31a19cbcc6dd681e6d0834158 100644 (file)
@@ -52,7 +52,7 @@ SECTIONS
     eunpaged_rodata = .;
 
     . = ALIGN(0x1000);
-    ring3_page_addr = .;
+    ring3_page_begin = .;
     .ring3 :
     {
         *(.ring3.entry)