Kernel: start work on higher half kernel

This commit is contained in:
Bananymous 2023-05-30 08:00:17 +03:00
parent 79315d318c
commit 0907965dc5
5 changed files with 65 additions and 28 deletions

View File

@ -125,7 +125,7 @@ if(ENABLE_KERNEL_UBSAN)
endif() endif()
if("${BANAN_ARCH}" STREQUAL "x86_64") 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:-z,max-page-size=4096)
target_link_options(kernel PUBLIC LINKER:-T,${CMAKE_CURRENT_SOURCE_DIR}/arch/x86_64/linker.ld) target_link_options(kernel PUBLIC LINKER:-T,${CMAKE_CURRENT_SOURCE_DIR}/arch/x86_64/linker.ld)
elseif("${BANAN_ARCH}" STREQUAL "i386") elseif("${BANAN_ARCH}" STREQUAL "i386")

View File

@ -101,6 +101,9 @@ namespace IDT
extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, const Registers* regs) 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( dwarnln(
"{} (error code: 0x{16H}), pid {}, tid {}\r\n" "{} (error code: 0x{16H}), pid {}, tid {}\r\n"
"Register dump\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" "rsp=0x{16H}, rbp=0x{16H}, rdi=0x{16H}, rsi=0x{16H}\r\n"
"rip=0x{16H}, rflags=0x{16H}\r\n" "rip=0x{16H}, rflags=0x{16H}\r\n"
"cr0=0x{16H}, cr2=0x{16H}, cr3=0x{16H}, cr4=0x{16H}", "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->rax, regs->rbx, regs->rcx, regs->rdx,
regs->rsp, regs->rbp, regs->rdi, regs->rsi, regs->rsp, regs->rbp, regs->rdi, regs->rsi,
regs->rip, regs->rflags, regs->rip, regs->rflags,
regs->cr0, regs->cr2, regs->cr3, regs->cr4 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]); auto message = BAN::String::formatted("{}, aborting\n", isr_exceptions[isr]);
(void)Kernel::Process::current().write(STDERR_FILENO, message.data(), message.size()); (void)Kernel::Process::current().write(STDERR_FILENO, message.data(), message.size());

View File

@ -12,6 +12,7 @@
kfree(s); \ kfree(s); \
} while (false) } while (false)
extern uint8_t g_kernel_start[];
extern uint8_t g_kernel_end[]; extern uint8_t g_kernel_end[];
namespace Kernel namespace Kernel
@ -20,6 +21,20 @@ namespace Kernel
static PageTable* s_kernel = nullptr; static PageTable* s_kernel = nullptr;
static PageTable* s_current = 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() void PageTable::initialize()
{ {
ASSERT(s_kernel == nullptr); 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 // 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. // 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*> PageTable::create_userspace() BAN::ErrorOr<PageTable*> PageTable::create_userspace()
@ -169,7 +184,7 @@ namespace Kernel
{ {
LockGuard _(m_lock); LockGuard _(m_lock);
ASSERT((address >> 48) == 0); uncanonicalize(address);
address &= PAGE_ADDR_MASK; address &= PAGE_ADDR_MASK;
@ -212,8 +227,8 @@ namespace Kernel
{ {
LockGuard _(m_lock); LockGuard _(m_lock);
ASSERT((paddr >> 48) == 0); ASSERT(is_canonical(paddr));
ASSERT((vaddr >> 48) == 0); uncanonicalize(vaddr);
ASSERT(paddr % PAGE_SIZE == 0); ASSERT(paddr % PAGE_SIZE == 0);
ASSERT(vaddr % PAGE_SIZE == 0);; ASSERT(vaddr % PAGE_SIZE == 0);;
@ -257,7 +272,7 @@ namespace Kernel
{ {
LockGuard _(m_lock); LockGuard _(m_lock);
ASSERT((address >> 48) == 0); uncanonicalize(address);
ASSERT(address % PAGE_SIZE == 0); ASSERT(address % PAGE_SIZE == 0);
uint64_t pml4e = (address >> 39) & 0x1FF; uint64_t pml4e = (address >> 39) & 0x1FF;

View File

@ -10,6 +10,9 @@
.set PG_READ_WRITE, 1<<1 .set PG_READ_WRITE, 1<<1
.set PG_PAGE_SIZE, 1<<7 .set PG_PAGE_SIZE, 1<<7
#define KERNEL_OFFSET 0xFFFFFFFF80000000
#define V2P(vaddr) ((vaddr) - KERNEL_OFFSET)
.code32 .code32
# Multiboot header # Multiboot header
@ -49,16 +52,23 @@
# Identity map first GiB # Identity map first GiB
.align 4096 .align 4096
boot_pml4: 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 .rept 511
.quad 0 .quad 0
.endr .endr
boot_pdpt: boot_pdpt_hi:
.quad boot_pd + (PG_READ_WRITE | PG_PRESENT) .rept 510
.rept 511
.quad 0 .quad 0
.endr .endr
boot_pd: .quad V2P(boot_pd) + (PG_READ_WRITE | PG_PRESENT)
.quad 0
boot_pd: # 1 GiB
.set i, 0 .set i, 0
.rept 512 .rept 512
.quad i + (PG_PAGE_SIZE | PG_READ_WRITE | PG_PRESENT) .quad i + (PG_PAGE_SIZE | PG_READ_WRITE | PG_PRESENT)
@ -71,7 +81,7 @@ boot_gdt:
.quad 0x00AF92000000FFFF # kernel data .quad 0x00AF92000000FFFF # kernel data
boot_gdtr: boot_gdtr:
.short . - boot_gdt - 1 .short . - boot_gdt - 1
.quad boot_gdt .quad V2P(boot_gdt)
has_cpuid: has_cpuid:
pushfl pushfl
@ -110,11 +120,11 @@ check_requirements:
copy_kernel_commandline: copy_kernel_commandline:
pushl %esi pushl %esi
pushl %edi pushl %edi
movl g_multiboot_info, %esi movl V2P(g_multiboot_info), %esi
addl $16, %esi addl $16, %esi
movl (%esi), %esi movl (%esi), %esi
movl $1024, %ecx movl $1024, %ecx
movl $g_kernel_cmdline, %edi movl $V2P(g_kernel_cmdline), %edi
rep movsl rep movsl
popl %edi popl %edi
popl %esi popl %esi
@ -143,7 +153,7 @@ initialize_paging:
wrmsr wrmsr
# set address of paging structures # set address of paging structures
movl $boot_pml4, %ecx movl $V2P(boot_pml4), %ecx
movl %ecx, %cr3 movl %ecx, %cr3
# enable paging # enable paging
@ -157,9 +167,9 @@ initialize_paging:
.type _start, @function .type _start, @function
_start: _start:
# Initialize stack and multiboot info # Initialize stack and multiboot info
movl $g_boot_stack_top, %esp movl $V2P(g_boot_stack_top), %esp
movl %eax, g_multiboot_magic movl %eax, V2P(g_multiboot_magic)
movl %ebx, g_multiboot_info movl %ebx, V2P(g_multiboot_info)
call copy_kernel_commandline call copy_kernel_commandline
call check_requirements call check_requirements
@ -168,8 +178,8 @@ _start:
call initialize_paging call initialize_paging
# flush gdt and jump to 64 bit # flush gdt and jump to 64 bit
lgdt boot_gdtr lgdt V2P(boot_gdtr)
ljmpl $0x08, $long_mode ljmpl $0x08, $V2P(long_mode)
.code64 .code64
long_mode: long_mode:
@ -183,6 +193,13 @@ long_mode:
movw %ax, %fs movw %ax, %fs
movw %ax, %gs 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 global constuctors
call _init call _init

View File

@ -1,24 +1,26 @@
ENTRY (_start) ENTRY (_start)
KERNEL_OFFSET = 0xFFFFFFFF80000000;
SECTIONS SECTIONS
{ {
. = 0x00100000; . = 0x00100000 + KERNEL_OFFSET;
g_kernel_start = .; g_kernel_start = .;
.text BLOCK(4K) : ALIGN(4K) .text ALIGN(4K) : AT(ADDR(.text) - KERNEL_OFFSET)
{ {
*(.multiboot) *(.multiboot)
*(.text) *(.text)
} }
.rodata BLOCK(4K) : ALIGN(4K) .rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET)
{ {
*(.rodata.*) *(.rodata.*)
} }
.data BLOCK(4K) : ALIGN(4K) .data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
{ {
*(.data) *(.data)
} }
.bss BLOCK(4K) : ALIGN(4K) .bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET)
{ {
*(COMMON) *(COMMON)
*(.bss) *(.bss)