]> Zhao Yanbai Git Server - kernel.git/commitdiff
优化ring3代码的链接配置;重写调用系统调用的函数和sysexit;修复未将sysexit页设置为用户级共享的问题; origin/master
authorzhaoyanbai <zhaoyanbai@126.com>
Sun, 16 Aug 2026 08:55:52 +0000 (16:55 +0800)
committerzhaoyanbai <zhaoyanbai@126.com>
Sun, 16 Aug 2026 08:55:52 +0000 (16:55 +0800)
kernel/ring3.S
kernel/syscall.S
kernel/task_user.c
lib/syscall.c
mm/mm.c
scripts/link.ld

index 59662ef1628ece1e146c3ff6838d78736f5714cc..57746859e2b5f1896272185b895ceb8470d0aa91 100644 (file)
@@ -27,23 +27,35 @@ ring3_entry:
     nop
     nop
 
-    pushl   $0                  # 模拟一个内核不需要的参数1
-    pushl   $SYSC_TEST
+    pushl   $5      #参数5
+    pushl   $4      #参数4
+    pushl   $3      #参数3
+    pushl   $2      #参数2
+    pushl   $1      #参数1
+    pushl   $SYSC_TEST          # 系统调用号
     call    ring3_syscall
-    addl    $8, %esp
+    addl    $0x18, %esp
 
-    pushl   $0                  # 模拟一个内核不需要的参数1
+    pushl   $5      #参数5
+    pushl   $4      #参数4
+    pushl   $3      #参数3
+    pushl   $2      #参数2
+    pushl   $1      #参数1
     pushl   $SYSC_RAND          # 系统调用号
     call    ring3_syscall
-    addl    $8, %esp
+    addl    $0x18, %esp
 
 
     movl    %eax, %ecx
     andl    $0x000000FF, %ecx
-    pushl   %ecx                # 参数1
+    pushl   $5      #参数5
+    pushl   $4      #参数4
+    pushl   $3      #参数3
+    pushl   $2      #参数2
+    pushl   %ecx    #参数1
     pushl   $SYSC_WAIT          # 系统调用号
     call    ring3_syscall
-    addl    $8, %esp
+    addl    $0x18, %esp
 
 
     # 纯消耗CPU时间
@@ -56,38 +68,55 @@ ring3_entry:
     nop
     jmp ring3_entry
 
-# 传入: 系统调用号, 参数1
+#
+# System V ABI
+# 参数: 从右向左压栈,调用者清栈
+# 返回值: eax; 64位在edx:eax
+# 调用者保存: eax ecx edx
+# 被调用者保存: ebx esi edi ebp esp
+#
+
+#
+# 输入:
+#   eax: 系统调用号
+#   ebx: 参数1
+#   ecx: 参数2
+#   edx: 参数3
+#   esi: 参数4
+#   edi: 参数5
+# 输出:
+#   eax: 返回码
+#
 ring3_syscall:
+    # 实现一个五个参数的完全版本,后续在lib/syscall.c里参数实现
+    pushl   %ebx
+    pushl   %esi
+    pushl   %edi
     pushl   %ebp
-    movl    %esp, %ebp
-
-    pushl   %ebx # 用于保存参数1
-    pushl   %edi # 用于保存sysexit后返回用户态的地址
-                 # ebp用于保存sysexit后的用户态栈,不过已经保存了,这里不用再保存
-
-    movl    0x08(%ebp), %eax # 系统调用号
-    movl    0x0C(%ebp), %ebx # 参数1
-
-    # 获取call get_eip后的地址
-    call    get_eip
-get_eip:
-    # 这里popl取得的就是上一个call指令自动压入栈中的地址
-    # 这个地址就是当前指令的地址
-    popl    %edi
 
-    # 算出sysenter后的地地址
-    addl    $8, %edi
+    # sysexit页 ret 时会得到的返回地址
+    pushl   $1f
 
-    # 设置sysexit返回用户态后的栈位置
     movl    %esp, %ebp
 
-    sysenter
+    # 根据栈内容,准备寄存器参数
+    movl    0x18(%esp), %eax
+    movl    0x1C(%esp), %ebx
+    movl    0x20(%esp), %ecx
+    movl    0x24(%esp), %edx
+    movl    0x28(%esp), %esi
+    movl    0x2C(%esp), %edi
 
-    # 从栈中恢复保存的易失寄存器
-    popl    %edi
-    popl    %ebx
+    # 系统调用能保证除 eax ecx edx 外的寄存器都不会被修改
+    sysenter
+1:
+    # 此处不用恢复esp
+    # 因为esp已经通过ebp传进系统调用
+    # 系统调用返回前已经根据ebp设置好了esp
 
     #
     popl    %ebp
-
+    popl    %edi
+    popl    %esi
+    popl    %ebx
     ret
index 657e4e56ace4f25a3025a9fa81a331e427b9d560..46f3fccd910249313020e06e11ecb412b7f6974d 100644 (file)
@@ -62,13 +62,13 @@ syscall_entry:
  .normal_syscall:
     call    *sysc_handler_table(,%eax,4)
 
-// normal_syscall_exit:
-//     leal    sysexit, %edx
-//     movl    %edx, PT_REGS_EDX(%esp)
-//     movl    PT_REGS_EBP(%esp), %edx
-//     movl    %edx, PT_REGS_ECX(%esp)
+normal_syscall_exit:
+    leal    sysexit, %edx
+    movl    %edx, PT_REGS_EDX(%esp)
+    movl    PT_REGS_EBP(%esp), %edx
+    movl    %edx, PT_REGS_ECX(%esp)
 
-//syscall_exit:
+syscall_exit:
 
     // 保存返回值
     movl    %eax, PT_REGS_EAX(%esp)
@@ -80,13 +80,7 @@ syscall_entry:
 
     // TODO 应该要检查一下这两个返回参数
 
-    // 返回用户态的eip
-    // sysexit指令从edx中恢复用户态eip
-    movl %edi, %edx
 
-    // 在系统调用前,用户态的esp保存在ebp中
-    // sysexit指令从ecx中恢复用户态esp
-    movl    %ebp, %ecx
 
     sysexit
 
@@ -119,7 +113,7 @@ ret_from_fork_krnl:
 .section .sysexit
 .align 0x1000
 sysexit:
-    popl    %ebp;
-    popl    %edx;
-    popl    %ecx;
+    nop
+    nop
+    nop
     ret
index 0c9162b11a6c86a43a7e4c690412c9ab496c8ef1..31ee601eeb2db083634b415af266e1f8563fbebf 100644 (file)
@@ -32,13 +32,13 @@ void user_task_entry() {
     task_reset_priority(TASK_PRIORITY_LEVEL_USER + 9);
 
     // ring3只占用一个page,页的起始位置放的是代码,页的末尾当栈用
-    // ring3的地址直接是物理地址
-    extern uint8_t ring3_page_begin;
+    extern uint8_t ring3_page_begin[];
+    extern uint8_t ring3_lma[];
+    extern uint32_t ring3_text_size[];
 
-    paddr_t ring3_page_addr = (paddr_t)&ring3_page_begin;  // 不在内核空间的物理地址
-    // paddr_t ring3_stack_top = ring3_page_addr + PAGE_SIZE;
+    paddr_t ring3_page_addr = (paddr_t)ring3_lma;  // 不在内核空间的物理地址
 
-    vaddr_t ring3_page_vaddr = 0x08000000;  // 指定的ring3的虚拟地址
+    vaddr_t ring3_page_vaddr = (vaddr_t)ring3_page_begin;
     vaddr_t ring3_stack_top_vaddr = PAGE_OFFSET - 0x100000;
 
     page_map(ring3_page_vaddr, ring3_page_addr, PAGE_P | PAGE_US);
@@ -48,12 +48,16 @@ void user_task_entry() {
 
     {
         // 在ring3_page里非代码的地方插入特征值方便调试
-        extern uint8_t ring3_text_end;
-        uint32_t ring3_text_size = (&ring3_text_end) - (&ring3_page_begin);
-        for (uint32_t i = ring3_text_size; i < PAGE_SIZE; i++) {
+        for (uint32_t i = (uint32_t)ring3_text_size; i < PAGE_SIZE; i++) {
             ((uint8_t*)(pa2va(ring3_page_addr)))[i] = 0xCC;
         }
     }
 
+    asm volatile(
+        "mov %%ax, %%ds;"
+        "mov %%ax, %%es;"
+        "mov %%ax, %%fs;"
+        "mov %%ax, %%gs;" ::"a"(SELECTOR_USER_DS));
+
     asm volatile("sysexit;" ::"d"(ring3_page_vaddr), "c"(ring3_stack_top_vaddr));
 }
index 1570296dba05bf3f5d378ed8bac43e2e89645323..cf62cbb098459ffdf7bd65d529d1452e5a89825d 100644 (file)
     "sysenter;"             \
     "1:"
 
-static int __volatile__ __syscall0(int nr) {
+static int volatile __syscall0(int nr) {
     int __sysc_ret__ = 0;
     asm(SYSENTER_ASM : "=a"(__sysc_ret__) : "a"(nr));
     return __sysc_ret__;
 }
 
-static int __volatile__ __syscall1(int nr, unsigned long a) {
+static int volatile __syscall1(int nr, unsigned long a) {
     int __sysc_ret__ = 0;
     asm(SYSENTER_ASM : "=a"(__sysc_ret__) : "a"(nr), "b"(a));
     return __sysc_ret__;
 }
 
-static int __volatile__ __syscall2(int nr, unsigned long a, unsigned long b) {
+static int volatile __syscall2(int nr, unsigned long a, unsigned long b) {
     int __sysc_ret__ = 0;
     asm(SYSENTER_ASM : "=a"(__sysc_ret__) : "a"(nr), "b"(a), "c"(b));
     return __sysc_ret__;
 }
 
-static int __volatile__ __syscall3(int nr, unsigned long a, unsigned long b, unsigned long c) {
+static int volatile __syscall3(int nr, unsigned long a, unsigned long b, unsigned long c) {
     int __sysc_ret__ = 0;
     asm(SYSENTER_ASM : "=a"(__sysc_ret__) : "a"(nr), "b"(a), "c"(b), "d"(c));
     return __sysc_ret__;
 }
 
-static int __volatile__ __syscall4(int nr, unsigned long a, unsigned long b, unsigned long c, unsigned long d) {
+static int volatile __syscall4(int nr, unsigned long a, unsigned long b, unsigned long c, unsigned long d) {
     int __sysc_ret__ = 0;
     asm(SYSENTER_ASM : "=a"(__sysc_ret__) : "a"(nr), "b"(a), "c"(b), "d"(c), "S"(d));
     return __sysc_ret__;
diff --git a/mm/mm.c b/mm/mm.c
index 717996327ef39daa826071074c27bd6943ac115e..999e433b6ecaac3805d8a4fe4d26c50c317f8b7f 100644 (file)
--- a/mm/mm.c
+++ b/mm/mm.c
@@ -101,6 +101,10 @@ void init_paging() {
         init_pgd[i] = 0;
     }
 
+    // paging for user space
+    extern void sysexit();
+    set_page_shared(sysexit);
+
 #if 0
     // 接下来为显存建立页映射
     unsigned long vram_phys_addr = system.vbe_phys_addr;
@@ -120,10 +124,6 @@ void init_paging() {
         }
     }
 
-    // paging for user space
-    extern void sysexit();
-    set_page_shared(sysexit);
-
     set_cr3(va2pa(init_pgd));
 
     // 测试显存
index c00322020b020fcc9f3b70106197540851395391..d80f3750ed15878140b2fccaacf2a8ba85f210b8 100644 (file)
  *--------------------------------------------------------------------------
  */
 
+ /* VMA = Virtual Memory Address */
+ /* LMA = Load Memory Address */
+ /* ADDR(section): 计算该节的 VMA */
+ /* LOADADDR(section): 计算该节的 LMA */
+ /* SIZEOF(section): 计算该节的大小 */
+
 OUTPUT_FORMAT("elf32-i386")
 ENTRY(kernel_entry)
 
@@ -53,19 +59,22 @@ SECTIONS
     eunpaged_rodata = .;
 
     . = ALIGN(0x1000);
-    ring3_page_begin = .;
-    .ring3 :
+    ring3_lma = .;
+    .ring3 0x08000000 : AT(ring3_lma)
     {
+        ring3_page_begin = .;
         *(.ring3.entry)
         . = ALIGN(0x100);
-        ring3_text_end = .;
+        ring3_text_size = SIZEOF(.ring3);
+        ring3_page_end = .;
     }
-    . = ALIGN(0x1000);
-    ring3_page_end = .;
+    /* 恢复LMA */
+    /* 带绝对 VMA 的节写完后 . 不会自动接上,而是变成 该节VMA+SIZEOF(该节名) */
+    . = ring3_lma + SIZEOF(.ring3);
 
+    . = ALIGN(0x1000);
     /* . = kernel_begin; */
     . += kernel_virtual_addr_start;
-    . = ALIGN(0x1000);
     .text : AT(ADDR(.text)-kernel_virtual_addr_start) ALIGN(0x1000)
     {
         code = .;