From eabe5f62316465e9bf397a83f5eec20b9d132e39 Mon Sep 17 00:00:00 2001 From: acevest Date: Wed, 31 Dec 2025 11:03:41 +0800 Subject: [PATCH] =?utf8?q?=E4=BC=98=E5=8C=96ring3=E7=9B=B8=E5=85=B3?= =?utf8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- boot/acpi.c | 8 ++++---- include/page.h | 2 +- include/types.h | 5 +++++ kernel/apic.c | 6 +++--- kernel/ring3.S | 37 +++++++++++++++++++++++-------------- kernel/syscall.S | 2 +- kernel/task_user.c | 31 ++++++++++--------------------- mm/page.c | 18 ++++++------------ scripts/link.ld | 2 +- 9 files changed, 54 insertions(+), 57 deletions(-) diff --git a/boot/acpi.c b/boot/acpi.c index faf8a09..55c7db7 100644 --- a/boot/acpi.c +++ b/boot/acpi.c @@ -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; itable_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); } } diff --git a/include/page.h b/include/page.h index 6d15fb6..4fb2d28 100644 --- a/include/page.h +++ b/include/page.h @@ -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 diff --git a/include/types.h b/include/types.h index 308f8c9..8b51fdc 100644 --- a/include/types.h +++ b/include/types.h @@ -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; diff --git a/kernel/apic.c b/kernel/apic.c index a18268a..b899137 100644 --- a/kernel/apic.c +++ b/kernel/apic.c @@ -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; diff --git a/kernel/ring3.S b/kernel/ring3.S index dcab140..36a19c0 100644 --- a/kernel/ring3.S +++ b/kernel/ring3.S @@ -7,7 +7,9 @@ * ------------------------------------------------------------------------ */ -.global ring3_entrys +#define ASM +#include + # a allocatable 可分配,表示这个节在程序运行时需要加载到内存中 # x executable 可执行,表示这个节包含可执行的代码 # w writable 可写,通常用于数据节 @@ -18,22 +20,29 @@ # # @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 diff --git a/kernel/syscall.S b/kernel/syscall.S index 3efe83e..130546d 100644 --- a/kernel/syscall.S +++ b/kernel/syscall.S @@ -85,7 +85,7 @@ syscall_entry: // 在系统调用前,用户态的esp保存在ebp中 // sysexit指令从ecx中恢复用户态esp - xchgl %ebp, %ecx + movl %ebp, %ecx sysexit diff --git a/kernel/task_user.c b/kernel/task_user.c index e90d513..231e019 100644 --- a/kernel/task_user.c +++ b/kernel/task_user.c @@ -17,6 +17,7 @@ #include #include #include +#include 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)); } diff --git a/mm/page.c b/mm/page.c index deb5210..58924b3 100644 --- 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)); } diff --git a/scripts/link.ld b/scripts/link.ld index 1a55db4..ea3009b 100644 --- a/scripts/link.ld +++ b/scripts/link.ld @@ -52,7 +52,7 @@ SECTIONS eunpaged_rodata = .; . = ALIGN(0x1000); - ring3_page_addr = .; + ring3_page_begin = .; .ring3 : { *(.ring3.entry) -- 2.47.0