From 82e9f02aef1ea1a6588234ee58e3625e3561005f Mon Sep 17 00:00:00 2001 From: Aleksa Vuckovic Date: Thu, 8 Sep 2022 14:37:47 +0200 Subject: higher half in x86_64 kernel is now located at -2GB heap blocks are aligned on block size paging will allocate new page tables on heap --- kernel/src/boot/boot.S | 158 ++++++++++++----------------------------- kernel/src/boot/boot64.S | 25 ++++--- kernel/src/boot/multiboot2.c | 3 +- kernel/src/cpu/gdt.c | 6 +- kernel/src/devices/disc.c | 5 +- kernel/src/kernel.ld | 9 ++- kernel/src/libk/stdio.c | 2 +- kernel/src/main.c | 6 +- kernel/src/mem/heap.c | 23 +++--- kernel/src/mem/paging.c | 55 +++++++------- kernel/src/mem/paging_asm.S | 4 +- kernel/src/misc/debug.c | 6 -- kernel/src/sys/userspace_asm.S | 2 +- 13 files changed, 122 insertions(+), 182 deletions(-) delete mode 100644 kernel/src/misc/debug.c (limited to 'kernel/src') diff --git a/kernel/src/boot/boot.S b/kernel/src/boot/boot.S index a96be00..704acbf 100644 --- a/kernel/src/boot/boot.S +++ b/kernel/src/boot/boot.S @@ -1,99 +1,60 @@ .code32 .extern begin_long_mode -.set KERNEL_VMA, 0xc0000000 +.section .boot32.text, "a" -.section .boot.text, "a" .global _start _start: cli - mov $stack_top - KERNEL_VMA, %esp + mov $stack_top, %esp pushl $0 pushl %eax pushl $0 pushl %ebx - call check_multiboot - call check_cpuid - call check_long_mode - call setup_page_tables call enable_paging - addl $KERNEL_VMA, %esp - mov $4f, %ecx - jmp *%ecx - -check_multiboot: - cmp $0x36d76289, %eax - jne no_multiboot - - ret - -check_cpuid: - pushfl - pop %eax - mov %eax, %ecx - xor $1<<21, %eax - push %eax - popfl - pushfl - pop %eax - push %ecx - popfl - cmp %eax, %ecx - je no_cpuid - - ret - -check_long_mode: - mov $0x80000000, %eax - cpuid - cmp $0x80000001, %eax - jb no_long_mode - - mov $0x80000001, %eax - cpuid - test $1<<29, %edx - jz no_long_mode - - ret + lgdt gdtp + ljmp $0x08, $begin_long_mode setup_page_tables: - mov $pt_lvl3 - KERNEL_VMA, %eax - or $0x3, %eax - mov %eax, pt_lvl4 - KERNEL_VMA - - // 0x00000000 - 0x00200000 : 0x00000000 - 0x00200000 - mov $pt_lvl2 - KERNEL_VMA, %eax +// first 2mb + mov $pt_lvl3, %eax or $0x3, %eax - mov %eax, pt_lvl3 - KERNEL_VMA + mov %eax, pt_lvl4 - // 0xc0000000 - 0xc0200000 : 0xc0000000 - 0xc0200000 - mov $pt_lvl2_hh - KERNEL_VMA, %eax + mov $pt_lvl2, %eax or $0x3, %eax - mov %eax, pt_lvl3 + 24 - KERNEL_VMA + mov %eax, pt_lvl3 -// first 2mb xor %ecx, %ecx 1: movl $0x00200000, %eax mul %ecx or $0b10000011, %eax - movl $pt_lvl2 - KERNEL_VMA, %edx + movl $pt_lvl2, %edx leal (%edx, %ecx, 8), %edx movl %eax, (%edx) inc %ecx cmp $1, %ecx jne 1b -// first 2mb in higher_half +// first 2mb in hh + mov $pt_lvl3_hh, %eax + or $0x3, %eax + mov %eax, pt_lvl4 + 4096 - 8 + + mov $pt_lvl2_hh, %eax + or $0x3, %eax + mov %eax, pt_lvl3_hh + 4096 - 16 + xor %ecx, %ecx 2: movl $0x00200000, %eax mul %ecx or $0b10000011, %eax - movl $pt_lvl2_hh - KERNEL_VMA, %edx + movl $pt_lvl2_hh, %edx leal (%edx, %ecx, 8), %edx movl %eax, (%edx) inc %ecx @@ -115,7 +76,7 @@ enable_paging: wrmsr // pt_lvl4 - mov $pt_lvl4 - KERNEL_VMA, %eax + mov $pt_lvl4, %eax mov %eax, %cr3 // enable paging (+ protected mode if not already enabled) @@ -125,70 +86,43 @@ enable_paging: ret -no_multiboot: - hlt -no_cpuid: - hlt +.section .boot32.rodata -no_long_mode: - hlt - -.section .text -4: - lgdt gdtp - ljmp $0x08, $begin_long_mode +gdt: +gdt_null = . - gdt + .quad 0 +gdt_code = . - gdt + .long 0xFFFF + .byte 0 + .byte 0x9A + .byte 0xAF + .byte 0 +gdt_data = . - gdt + .long 0xFFFF + .byte 0 + .byte 0xA2 + .byte 0xAF + .byte 0 +gdtp: + .word . - gdt - 1 + .quad gdt -.section .bss +.section .boot32.bss .align 4096 -// stack -stack_bottom: - .skip 4096*16 -stack_top: - - -// page tables pt_lvl4: .skip 4096 pt_lvl3: .skip 4096 +pt_lvl3_hh: + .skip 4096 pt_lvl2: .skip 4096 pt_lvl2_hh: .skip 4096 - -// Access bits -.section .rodata -.set PRESENT, 1 << 7 -.set NOT_SYS, 1 << 4 -.set EXEC, 1 << 3 -.set DC, 1 << 2 -.set RW, 1 << 1 -.set ACCESSED, 1 << 0 - -// Flags bits -.set GRAN_4K, 1 << 7 -.set SZ_32, 1 << 6 -.set LONG_MODE, 1 << 5 - -gdt: -gdt_null = . - gdt - .quad 0 -gdt_code = . - gdt - .long 0xFFFF // Limit & Base (low, bits 0-15) - .byte 0 // Base (mid, bits 16-23) - .byte PRESENT | NOT_SYS | EXEC | RW // Access - .byte GRAN_4K | LONG_MODE | 0xF // Flags & Limit (high, bits 16-19) - .byte 0 // Base (high, bits 24-31) -gdt_data = . - gdt - .long 0xFFFF - .byte 0 - .byte PRESENT | NOT_SYS | RW - .byte GRAN_4K | SZ_32 | 0xF - .byte 0 -gdtp: - .word . - gdt - 1 - .quad gdt +stack_bottom: + .skip 4096*4 +stack_top: diff --git a/kernel/src/boot/boot64.S b/kernel/src/boot/boot64.S index cc79c36..e95f55b 100644 --- a/kernel/src/boot/boot64.S +++ b/kernel/src/boot/boot64.S @@ -1,16 +1,25 @@ -.section .text .code64 +.set KERNEL_VMA, 0xffffffff80000000 + +.section .boot64.text, "a" + .global begin_long_mode begin_long_mode: - // reload segment registers - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %ss - mov %ax, %fs - mov %ax, %gs +// xchgw %bx, %bx +// mov $0x10, %ax +// mov %ax, %ds +// mov %ax, %es +// mov %ax, %ss +// mov %ax, %fs +// mov %ax, %gs + add $KERNEL_VMA, %rsp + movabs $jump_main, %rax + jmp *%rax + +.section .text +jump_main: popq %rdi popq %rsi call kernel_main diff --git a/kernel/src/boot/multiboot2.c b/kernel/src/boot/multiboot2.c index 1bb9aac..12f3c38 100644 --- a/kernel/src/boot/multiboot2.c +++ b/kernel/src/boot/multiboot2.c @@ -8,8 +8,7 @@ #include #include #include - -#define KERNEL_VMA 0xc0000000 +#include /* https://www.gnu.org/software/grub/manual/multiboot2/html_node/Boot-information-format.html */ diff --git a/kernel/src/cpu/gdt.c b/kernel/src/cpu/gdt.c index 7ce51f1..743b629 100644 --- a/kernel/src/cpu/gdt.c +++ b/kernel/src/cpu/gdt.c @@ -17,7 +17,11 @@ void add_gdt_entry(uint32_t num, uint32_t offset, uint32_t limit, uint8_t access void add_gdt_tss(uint32_t num, uint64_t offset, uint32_t limit, uint8_t access, uint8_t flags) { - add_gdt_entry(num, offset & 0xffffffff, limit, access, flags); + uint32_t offset_low = (offset & 0xffffffff); + uint32_t offset_high = (uint32_t)(offset >> 32); + add_gdt_entry(num, offset_low, limit, access, flags); + gdt[num+1].limit = (offset_high & 0xffff); + gdt[num+1].offset1 = (uint16_t)(offset_high >> 16); } void reload_gdt() diff --git a/kernel/src/devices/disc.c b/kernel/src/devices/disc.c index 8d34473..12ed62f 100644 --- a/kernel/src/devices/disc.c +++ b/kernel/src/devices/disc.c @@ -3,14 +3,13 @@ #include #include #include - -#define KERNEL_VMA 0xc0000000 +#include disc_sector_t* disc; void disc_init() { - disc = (disc_sector_t*)(uint64_t)ext2_module->mod_start; + disc = (disc_sector_t*)((uint64_t)ext2_module->mod_start + KERNEL_VMA); if (disc == NULL) { printf("Error opening disc\n"); } diff --git a/kernel/src/kernel.ld b/kernel/src/kernel.ld index 56b5647..f0247b2 100644 --- a/kernel/src/kernel.ld +++ b/kernel/src/kernel.ld @@ -1,7 +1,7 @@ ENTRY(_start) -KERNEL_PMA = 0x00100000; -KERNEL_VMA = 0xc0000000; +KERNEL_PMA = 0x0000000000100000; +KERNEL_VMA = 0xffffffff80000000; SECTIONS { @@ -10,7 +10,10 @@ SECTIONS .boot BLOCK(4K) : ALIGN(4K) { KEEP(*(.multiboot_header)) - *(.boot.text) + *(.boot32.text) + *(.boot32.rodata) + *(.boot32.bss) + *(.boot64.text) } . += KERNEL_VMA; diff --git a/kernel/src/libk/stdio.c b/kernel/src/libk/stdio.c index 61681f0..898f3c6 100644 --- a/kernel/src/libk/stdio.c +++ b/kernel/src/libk/stdio.c @@ -30,7 +30,7 @@ inline void print_char(char c) } return; } - fb_draw_character(main_fb, c, (int32_t)curr_x * 8, (int32_t)curr_y * 16, WHITE, BLACK); +// fb_draw_character(main_fb, c, (int32_t)curr_x * 8, (int32_t)curr_y * 16, WHITE, BLACK); curr_x++; write_serial(c); diff --git a/kernel/src/main.c b/kernel/src/main.c index 03e0168..7424f56 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -27,9 +27,9 @@ int kernel_main(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic) init_heap(); init_tss(); read_mb2(multiboot_bootinfo, multiboot_magic); -// disc_init(); -// ext2_init(); -// ls(path_to_inode("/")); + disc_init(); + ext2_init(); + ls(path_to_inode("/")); jump_userspace(); for(;;) { diff --git a/kernel/src/mem/heap.c b/kernel/src/mem/heap.c index 229933b..e37e003 100644 --- a/kernel/src/mem/heap.c +++ b/kernel/src/mem/heap.c @@ -34,12 +34,12 @@ void kheap_add_block(kheap_t* kheap, uint64_t addr, uint32_t size, uint32_t bsiz bm[i] = 0; } - bcnt = upper_div(bcnt, bsize); - for (size_t i = 0; i < bcnt; i++) { + uint32_t bcnt_used = upper_div((bcnt + (uint32_t)sizeof(kheapblock_t)), bsize); + for (size_t i = 0; i < bcnt_used; i++) { bm[i] = 5; } - kheapblock->used = bcnt; + kheapblock->used = bcnt_used; } void* kheap_alloc(kheap_t* kheap, uint32_t size) @@ -52,6 +52,13 @@ void* kheap_alloc(kheap_t* kheap, uint32_t size) continue; } + // use heap with bsize 4096 just for that block size + bool ind1 = ((size % 4096) == 0); + bool ind2 = (kheapblock->bsize == 4096); + if (ind1 + ind2 == 1) { + continue; + } + uint32_t bcnt = kheapblock->size / kheapblock->bsize; uint32_t bneed = upper_div(size, kheapblock->bsize); uint8_t* bm = (uint8_t*)&kheapblock[1]; @@ -81,7 +88,7 @@ void* kheap_alloc(kheap_t* kheap, uint32_t size) kheapblock->used += bneed; - return (void*)(i * kheapblock->bsize + (uintptr_t)&kheapblock[1]); + return (void*)(i * kheapblock->bsize + (uintptr_t)&kheapblock[0]); } } printf("Error: there is no remaining memory in kheap\n"); @@ -118,10 +125,6 @@ void kheap_free(kheap_t* kheap, void* pointer) void init_heap() { kheap_init(&main_kheap); - - // allocate pages for kheap - for (size_t i = 0; i < upper_div(HEAP_SIZE, PAGE_SIZE); i++) - map_addr(HEAP_VMEM_ADDR + i * PAGE_SIZE, HEAP_PMEM_ADDR + i * PAGE_SIZE, FLAG_PRESENT + FLAG_WRITABLE + FLAG_HUGE); - - kheap_add_block(&main_kheap, HEAP_VMEM_ADDR, HEAP_SIZE, HEAP_BLOCK_SIZE); + kheap_add_block(&main_kheap, HEAP1_VMEM_ADDR, HEAP1_SIZE, HEAP1_BLOCK_SIZE); + kheap_add_block(&main_kheap, HEAP2_VMEM_ADDR, HEAP2_SIZE, HEAP2_BLOCK_SIZE); } diff --git a/kernel/src/mem/paging.c b/kernel/src/mem/paging.c index 19a2c3a..f714f66 100644 --- a/kernel/src/mem/paging.c +++ b/kernel/src/mem/paging.c @@ -1,17 +1,15 @@ #include #include +#include #include -#include +#include void load_pt_lvl4(uint64_t*); __attribute__((aligned(4096))) uint64_t page_table_lvl4[512]; __attribute__((aligned(4096))) uint64_t page_table_lvl3[512]; -__attribute__((aligned(4096))) uint64_t page_table_lvl2_0[512]; -__attribute__((aligned(4096))) uint64_t page_table_lvl2_1[512]; -__attribute__((aligned(4096))) uint64_t page_table_lvl2_2[512]; -__attribute__((aligned(4096))) uint64_t page_table_lvl2_3[512]; +__attribute__((aligned(4096))) uint64_t page_table_lvl2[512]; void map_addr(uint64_t virt, uint64_t phys, uint32_t flags) { @@ -24,38 +22,35 @@ void map_addr(uint64_t virt, uint64_t phys, uint32_t flags) size_t pt_lvl2_i = (virt >> 21) % 0x200; // 2mb entry // size_t pt_lvl1_i = (virt >> 12) % 0x200; // 4kb entry - // first 4gb - if (pt_lvl4_i == 0) { - switch(pt_lvl3_i) { - case 0: - page_table_lvl2_0[pt_lvl2_i] = phys | flags; - break; - case 1: - page_table_lvl2_1[pt_lvl2_i] = phys | flags; - break; - case 2: - page_table_lvl2_2[pt_lvl2_i] = phys | flags; - break; - case 3: - page_table_lvl2_3[pt_lvl2_i] = phys | flags; - break; - } + uint64_t* pt_lvl3 = (uint64_t*)(page_table_lvl4[pt_lvl4_i] + KERNEL_VMA); + if (!((uint64_t)pt_lvl3 & FLAG_PRESENT)) { + pt_lvl3 = (uint64_t*)kalloc(4096); + page_table_lvl4[pt_lvl4_i] = ((uint64_t)pt_lvl3 - KERNEL_VMA) | flags; + } else { + pt_lvl3 = (uint64_t*)((uint64_t)pt_lvl3 - (uint64_t)pt_lvl3 % 4096); } + + uint64_t* pt_lvl2 = (uint64_t*)(pt_lvl3[pt_lvl3_i] + KERNEL_VMA); + if (!((uint64_t)pt_lvl2 & FLAG_PRESENT)) { + pt_lvl2 = (uint64_t*)kalloc(4096); + pt_lvl3[pt_lvl3_i] = ((uint64_t)pt_lvl2 - KERNEL_VMA) | flags; + } else { + pt_lvl2 -= (uint64_t)pt_lvl2 % 4096; + } + + pt_lvl2[pt_lvl2_i] = virt | flags; } void init_paging(void) { - page_table_lvl4[0] = (uint64_t)page_table_lvl3 + FLAG_PRESENT + FLAG_WRITABLE + FLAG_USER - KERNEL_VMA; - page_table_lvl3[0] = (uint64_t)page_table_lvl2_0 + FLAG_PRESENT + FLAG_WRITABLE + FLAG_USER - KERNEL_VMA; - page_table_lvl3[1] = (uint64_t)page_table_lvl2_1 + FLAG_PRESENT + FLAG_WRITABLE + FLAG_USER - KERNEL_VMA; - page_table_lvl3[2] = (uint64_t)page_table_lvl2_2 + FLAG_PRESENT + FLAG_WRITABLE + FLAG_USER - KERNEL_VMA; - page_table_lvl3[3] = (uint64_t)page_table_lvl2_3 + FLAG_PRESENT + FLAG_WRITABLE + FLAG_USER - KERNEL_VMA; - - // higher half map first 6mb - for (size_t i = 0; i < 3; i++) { - map_addr(KERNEL_VMA + PAGE_SIZE * i, 0x00000000 + PAGE_SIZE * i, FLAG_PRESENT + FLAG_WRITABLE + FLAG_USER + FLAG_HUGE); + page_table_lvl4[511] = (uint64_t)page_table_lvl3 + FLAG_PRESENT + FLAG_WRITABLE + FLAG_USER - KERNEL_VMA; + page_table_lvl3[510] = (uint64_t)page_table_lvl2 + FLAG_PRESENT + FLAG_WRITABLE + FLAG_USER - KERNEL_VMA; + // 16mb kernel + 32mb heap + for (size_t i = 0; i < 24; i++) { + page_table_lvl2[i] = (uint64_t)0x0 + PAGE_SIZE * i + FLAG_PRESENT + FLAG_WRITABLE + FLAG_USER + FLAG_HUGE; } + load_pt_lvl4(page_table_lvl4); } diff --git a/kernel/src/mem/paging_asm.S b/kernel/src/mem/paging_asm.S index c7e11f3..e7c7814 100644 --- a/kernel/src/mem/paging_asm.S +++ b/kernel/src/mem/paging_asm.S @@ -1,6 +1,6 @@ .section .text -.set KERNEL_VMA, 0xc0000000 +.set KERNEL_VMA, 0xffffffff80000000 .global load_pt_lvl4 load_pt_lvl4: @@ -8,7 +8,7 @@ load_pt_lvl4: mov %rsp, %rbp push %r12 - mov $KERNEL_VMA, %r12 + movabs $KERNEL_VMA, %r12 sub %r12, %rdi mov %rdi, %cr3 pop %r12 diff --git a/kernel/src/misc/debug.c b/kernel/src/misc/debug.c deleted file mode 100644 index d244d7a..0000000 --- a/kernel/src/misc/debug.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -void bochs_breakpoint(void) -{ - __asm__ volatile ("xchgw %bx, %bx;"); -} diff --git a/kernel/src/sys/userspace_asm.S b/kernel/src/sys/userspace_asm.S index 5817a8c..02181bd 100644 --- a/kernel/src/sys/userspace_asm.S +++ b/kernel/src/sys/userspace_asm.S @@ -26,6 +26,6 @@ jump_userspace: mov $0x00100008, %edx wrmsr - mov $begin_userspace, %ecx + movabs $begin_userspace, %rcx mov $0x202, %r11 sysretq -- cgit v1.2.3