From 0907965dc59c5b1efff90576a3e6bda03639002c Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 30 May 2023 08:00:17 +0300 Subject: [PATCH] Kernel: start work on higher half kernel --- kernel/CMakeLists.txt | 2 +- kernel/arch/x86_64/IDT.cpp | 7 +++-- kernel/arch/x86_64/PageTable.cpp | 25 +++++++++++++---- kernel/arch/x86_64/boot.S | 47 ++++++++++++++++++++++---------- kernel/arch/x86_64/linker.ld | 12 ++++---- 5 files changed, 65 insertions(+), 28 deletions(-) diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 235cd9d2..ff654ded 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -125,7 +125,7 @@ if(ENABLE_KERNEL_UBSAN) endif() if("${BANAN_ARCH}" STREQUAL "x86_64") - target_compile_options(kernel PUBLIC -mcmodel=large -mno-red-zone -mno-mmx) + target_compile_options(kernel PUBLIC -mcmodel=kernel -mno-red-zone -mno-mmx) target_link_options(kernel PUBLIC LINKER:-z,max-page-size=4096) target_link_options(kernel PUBLIC LINKER:-T,${CMAKE_CURRENT_SOURCE_DIR}/arch/x86_64/linker.ld) elseif("${BANAN_ARCH}" STREQUAL "i386") diff --git a/kernel/arch/x86_64/IDT.cpp b/kernel/arch/x86_64/IDT.cpp index a1d451f2..93a6a469 100644 --- a/kernel/arch/x86_64/IDT.cpp +++ b/kernel/arch/x86_64/IDT.cpp @@ -101,6 +101,9 @@ namespace IDT extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, const Registers* regs) { + pid_t tid = Kernel::Scheduler::current_tid(); + pid_t pid = tid ? Kernel::Process::current().pid() : 0; + dwarnln( "{} (error code: 0x{16H}), pid {}, tid {}\r\n" "Register dump\r\n" @@ -108,14 +111,14 @@ namespace IDT "rsp=0x{16H}, rbp=0x{16H}, rdi=0x{16H}, rsi=0x{16H}\r\n" "rip=0x{16H}, rflags=0x{16H}\r\n" "cr0=0x{16H}, cr2=0x{16H}, cr3=0x{16H}, cr4=0x{16H}", - isr_exceptions[isr], error, Kernel::Process::current().pid(), Kernel::Thread::current().tid(), + isr_exceptions[isr], error, pid, tid, regs->rax, regs->rbx, regs->rcx, regs->rdx, regs->rsp, regs->rbp, regs->rdi, regs->rsi, regs->rip, regs->rflags, regs->cr0, regs->cr2, regs->cr3, regs->cr4 ); - if (Kernel::Thread::current().is_userspace() && !Kernel::Thread::current().is_in_syscall()) + if (tid && Kernel::Thread::current().is_userspace() && !Kernel::Thread::current().is_in_syscall()) { auto message = BAN::String::formatted("{}, aborting\n", isr_exceptions[isr]); (void)Kernel::Process::current().write(STDERR_FILENO, message.data(), message.size()); diff --git a/kernel/arch/x86_64/PageTable.cpp b/kernel/arch/x86_64/PageTable.cpp index aea52958..3b4502de 100644 --- a/kernel/arch/x86_64/PageTable.cpp +++ b/kernel/arch/x86_64/PageTable.cpp @@ -12,6 +12,7 @@ kfree(s); \ } while (false) +extern uint8_t g_kernel_start[]; extern uint8_t g_kernel_end[]; namespace Kernel @@ -20,6 +21,20 @@ namespace Kernel static PageTable* s_kernel = nullptr; static PageTable* s_current = nullptr; + static inline bool is_canonical(uintptr_t addr) + { + static constexpr uintptr_t mask = 0xFFFF800000000000; + addr &= mask; + return addr == mask || addr == 0; + } + + static inline void uncanonicalize(uintptr_t& addr) + { + static constexpr uintptr_t mask = 0xFFFF800000000000; + addr &= mask; + ASSERT(addr == mask || addr == 0); + } + void PageTable::initialize() { ASSERT(s_kernel == nullptr); @@ -56,7 +71,7 @@ namespace Kernel // Identity map 4 KiB -> kernel end. We don't map the first page since nullptr derefs should // page fault. Also there isn't anything useful in that memory. - identity_map_range(PAGE_SIZE, (uintptr_t)g_kernel_end, Flags::ReadWrite | Flags::Present); + identity_map_range((uintptr_t)g_kernel_start, (uintptr_t)(g_kernel_end - g_kernel_start), Flags::ReadWrite | Flags::Present); } BAN::ErrorOr PageTable::create_userspace() @@ -169,7 +184,7 @@ namespace Kernel { LockGuard _(m_lock); - ASSERT((address >> 48) == 0); + uncanonicalize(address); address &= PAGE_ADDR_MASK; @@ -212,8 +227,8 @@ namespace Kernel { LockGuard _(m_lock); - ASSERT((paddr >> 48) == 0); - ASSERT((vaddr >> 48) == 0); + ASSERT(is_canonical(paddr)); + uncanonicalize(vaddr); ASSERT(paddr % PAGE_SIZE == 0); ASSERT(vaddr % PAGE_SIZE == 0);; @@ -257,7 +272,7 @@ namespace Kernel { LockGuard _(m_lock); - ASSERT((address >> 48) == 0); + uncanonicalize(address); ASSERT(address % PAGE_SIZE == 0); uint64_t pml4e = (address >> 39) & 0x1FF; diff --git a/kernel/arch/x86_64/boot.S b/kernel/arch/x86_64/boot.S index 2a6cfa68..189baf0b 100644 --- a/kernel/arch/x86_64/boot.S +++ b/kernel/arch/x86_64/boot.S @@ -10,6 +10,9 @@ .set PG_READ_WRITE, 1<<1 .set PG_PAGE_SIZE, 1<<7 +#define KERNEL_OFFSET 0xFFFFFFFF80000000 +#define V2P(vaddr) ((vaddr) - KERNEL_OFFSET) + .code32 # Multiboot header @@ -49,16 +52,23 @@ # Identity map first GiB .align 4096 boot_pml4: - .quad boot_pdpt + (PG_READ_WRITE | PG_PRESENT) + .quad V2P(boot_pdpt_lo) + (PG_READ_WRITE | PG_PRESENT) + .rept 510 + .quad 0 + .endr + .quad V2P(boot_pdpt_hi) + (PG_READ_WRITE | PG_PRESENT) +boot_pdpt_lo: + .quad V2P(boot_pd) + (PG_READ_WRITE | PG_PRESENT) .rept 511 .quad 0 .endr -boot_pdpt: - .quad boot_pd + (PG_READ_WRITE | PG_PRESENT) - .rept 511 +boot_pdpt_hi: + .rept 510 .quad 0 - .endr -boot_pd: + .endr + .quad V2P(boot_pd) + (PG_READ_WRITE | PG_PRESENT) + .quad 0 +boot_pd: # 1 GiB .set i, 0 .rept 512 .quad i + (PG_PAGE_SIZE | PG_READ_WRITE | PG_PRESENT) @@ -71,7 +81,7 @@ boot_gdt: .quad 0x00AF92000000FFFF # kernel data boot_gdtr: .short . - boot_gdt - 1 - .quad boot_gdt + .quad V2P(boot_gdt) has_cpuid: pushfl @@ -110,11 +120,11 @@ check_requirements: copy_kernel_commandline: pushl %esi pushl %edi - movl g_multiboot_info, %esi + movl V2P(g_multiboot_info), %esi addl $16, %esi movl (%esi), %esi movl $1024, %ecx - movl $g_kernel_cmdline, %edi + movl $V2P(g_kernel_cmdline), %edi rep movsl popl %edi popl %esi @@ -143,7 +153,7 @@ initialize_paging: wrmsr # set address of paging structures - movl $boot_pml4, %ecx + movl $V2P(boot_pml4), %ecx movl %ecx, %cr3 # enable paging @@ -157,9 +167,9 @@ initialize_paging: .type _start, @function _start: # Initialize stack and multiboot info - movl $g_boot_stack_top, %esp - movl %eax, g_multiboot_magic - movl %ebx, g_multiboot_info + movl $V2P(g_boot_stack_top), %esp + movl %eax, V2P(g_multiboot_magic) + movl %ebx, V2P(g_multiboot_info) call copy_kernel_commandline call check_requirements @@ -168,8 +178,8 @@ _start: call initialize_paging # flush gdt and jump to 64 bit - lgdt boot_gdtr - ljmpl $0x08, $long_mode + lgdt V2P(boot_gdtr) + ljmpl $0x08, $V2P(long_mode) .code64 long_mode: @@ -183,6 +193,13 @@ long_mode: movw %ax, %fs movw %ax, %gs + # jump to higher half + movq $g_boot_stack_top, %rsp + movabsq $higher_half, %rcx + jmp *%rcx + +higher_half: + # call global constuctors call _init diff --git a/kernel/arch/x86_64/linker.ld b/kernel/arch/x86_64/linker.ld index 5da5dc4d..b6b1fa90 100644 --- a/kernel/arch/x86_64/linker.ld +++ b/kernel/arch/x86_64/linker.ld @@ -1,24 +1,26 @@ ENTRY (_start) +KERNEL_OFFSET = 0xFFFFFFFF80000000; + SECTIONS { - . = 0x00100000; + . = 0x00100000 + KERNEL_OFFSET; g_kernel_start = .; - .text BLOCK(4K) : ALIGN(4K) + .text ALIGN(4K) : AT(ADDR(.text) - KERNEL_OFFSET) { *(.multiboot) *(.text) } - .rodata BLOCK(4K) : ALIGN(4K) + .rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET) { *(.rodata.*) } - .data BLOCK(4K) : ALIGN(4K) + .data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET) { *(.data) } - .bss BLOCK(4K) : ALIGN(4K) + .bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET) { *(COMMON) *(.bss)