diff options
Diffstat (limited to 'src/kernel/arch/amd64')
-rw-r--r-- | src/kernel/arch/amd64/32/boot.s | 14 | ||||
-rw-r--r-- | src/kernel/arch/amd64/32/farjump.s | 8 | ||||
-rw-r--r-- | src/kernel/arch/amd64/32/gdt.c | 26 | ||||
-rw-r--r-- | src/kernel/arch/amd64/32/gdt.h | 3 | ||||
-rw-r--r-- | src/kernel/arch/amd64/32/paging.c | 47 | ||||
-rw-r--r-- | src/kernel/arch/amd64/32/util.c | 8 | ||||
-rw-r--r-- | src/kernel/arch/amd64/32/util.h | 4 | ||||
-rw-r--r-- | src/kernel/arch/amd64/boot.c | 8 | ||||
-rw-r--r-- | src/kernel/arch/amd64/pagedir.c | 50 | ||||
-rw-r--r-- | src/kernel/arch/amd64/paging.h | 54 | ||||
-rw-r--r-- | src/kernel/arch/amd64/sysenter.s | 4 |
11 files changed, 95 insertions, 131 deletions
diff --git a/src/kernel/arch/amd64/32/boot.s b/src/kernel/arch/amd64/32/boot.s index af32007..0e21036 100644 --- a/src/kernel/arch/amd64/32/boot.s +++ b/src/kernel/arch/amd64/32/boot.s @@ -37,15 +37,14 @@ _start: pop %edi - // TODO import gdt.h for globals - mov $(2<<3), %eax - mov %eax, %ds // SEG_r0data + mov $(2 << 3), %eax // SEG_r0data + mov %eax, %ds mov %eax, %ss mov %eax, %es mov %eax, %fs mov %eax, %gs - ljmp $(1<<3), $boot64 // SEG_r0code + ljmp $(1 << 3), $boot64 // SEG_r0code panic_early: // output a vga Fuck @@ -53,12 +52,6 @@ panic_early: movl $0x4F6B4F63, 0xB872E jmp cpu_halt -// TODO not part of anything yet - call sysenter_setup - // TODO will fail - push %ebx // address of the Multiboot struct - call kmain_early - .global cpu_shutdown .type cpu_shutdown, @function cpu_shutdown: @@ -80,7 +73,6 @@ cpu_halt: .global cpu_pause .type cpu_pause, @function cpu_pause: - xchgw %bx, %bx sti hlt cli diff --git a/src/kernel/arch/amd64/32/farjump.s b/src/kernel/arch/amd64/32/farjump.s deleted file mode 100644 index 2885d2b..0000000 --- a/src/kernel/arch/amd64/32/farjump.s +++ /dev/null @@ -1,8 +0,0 @@ -.section .text -.global gdt_farjump -.type gdt_farjump, @function -gdt_farjump: - /* retf pops off the return address and code segment off the stack. - * it turns out that in the i386 cdecl calling convention they're in - * the correct place already. */ - retf diff --git a/src/kernel/arch/amd64/32/gdt.c b/src/kernel/arch/amd64/32/gdt.c index d3d4aed..33fcf7b 100644 --- a/src/kernel/arch/amd64/32/gdt.c +++ b/src/kernel/arch/amd64/32/gdt.c @@ -1,5 +1,5 @@ #include <kernel/arch/amd64/32/gdt.h> -#include <kernel/arch/generic.h> +#include <kernel/arch/amd64/32/util.h> #include <stdbool.h> #include <stdint.h> @@ -40,21 +40,12 @@ struct lgdt_arg { } __attribute__((packed)); __attribute__((section(".shared"))) -struct gdt_entry GDT[SEG_end]; +static struct gdt_entry GDT[SEG_end]; __attribute__((section(".shared"))) -struct tss_entry TSS; +static struct tss_entry TSS; struct lgdt_arg lgdt_arg; - -static void *memset32(void *s, int c, size_t n) { - uint8_t *s2 = s; - for (size_t i = 0; i < n; i++) - s2[i] = c; - return s; -} - - static void gdt_fillout(struct gdt_entry* entry, uint8_t ring, bool code) { *entry = (struct gdt_entry) { // set up the identity mapping @@ -78,6 +69,7 @@ static void gdt_fillout(struct gdt_entry* entry, uint8_t ring, bool code) { }; } +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" void gdt_init(void) { GDT[SEG_null].present = 0; @@ -87,15 +79,15 @@ void gdt_init(void) { gdt_fillout(&GDT[SEG_r3data], 3, false); lgdt_arg.limit = sizeof(GDT) - 1; - lgdt_arg.base = (uint64_t)(int)&GDT; + lgdt_arg.base = (uint64_t)&GDT; memset32(&TSS, 0, sizeof(TSS)); for (int i = 0; i < 3; i++) - TSS.rsp[i] = (uint64_t)(int)&_isr_mini_stack; - TSS.ist[1] = (uint64_t)(int)&_isr_mini_stack; + TSS.rsp[i] = (uint64_t)&_isr_mini_stack; + TSS.ist[1] = (uint64_t)&_isr_mini_stack; - uint64_t tss_addr = (uint64_t)(int)&TSS; + uint64_t tss_addr = (uint64_t)&TSS; GDT[SEG_TSS] = (struct gdt_entry) { .limit_low = sizeof(TSS), .limit_high = sizeof(TSS) >> 16, @@ -114,5 +106,5 @@ void gdt_init(void) { .long_mode = 0, .x32 = 0, }; - *((uint64_t*)&GDT[SEG_TSS2]) = (tss_addr >> 32); + memset32(&GDT[SEG_TSS2], 0, sizeof GDT[SEG_TSS2]); } diff --git a/src/kernel/arch/amd64/32/gdt.h b/src/kernel/arch/amd64/32/gdt.h index fbaf681..4e08c88 100644 --- a/src/kernel/arch/amd64/32/gdt.h +++ b/src/kernel/arch/amd64/32/gdt.h @@ -14,4 +14,5 @@ enum { }; void gdt_init(void); -void gdt_farjump(int segment); + +extern struct lgdt_arg lgdt_arg; // used by amd64/32/boot.s diff --git a/src/kernel/arch/amd64/32/paging.c b/src/kernel/arch/amd64/32/paging.c index ef65ccf..f33168d 100644 --- a/src/kernel/arch/amd64/32/paging.c +++ b/src/kernel/arch/amd64/32/paging.c @@ -1,65 +1,34 @@ -#include <stddef.h> -#include <stdint.h> - -struct page_generic { - uint64_t present : 1; - uint64_t writeable : 1; - uint64_t user : 1; - uint64_t writethru : 1; - - uint64_t uncached : 1; - uint64_t accessed : 1; - uint64_t dirty : 1; - uint64_t large : 1; // also PAT - - uint64_t global : 1; // TODO enable CR4.PGE - uint64_t _unused2 : 2; - uint64_t _unused3 : 1; // HLAT - - uint64_t address : 40; - - uint64_t _unused4 : 7; - uint64_t pke : 4; - uint64_t noexec : 1; -} __attribute__((packed)); +#include <kernel/arch/amd64/32/util.h> +#include <kernel/arch/amd64/paging.h> __attribute__((aligned(4096))) -struct page_generic pml4_identity[512]; +pe_generic_t pml4_identity[512]; __attribute__((aligned(4096))) -struct page_generic pdpte_low[512]; // 0-512gb +static pe_generic_t pdpte_low[512]; // 0-512gb __attribute__((aligned(4096))) -struct page_generic pde_low[512]; // 0-1gb - - -static void *memset32(void *s, int c, size_t n) { - uint8_t *s2 = s; - for (size_t i = 0; i < n; i++) - s2[i] = c; - return s; -} - +static pe_generic_t pde_low[512]; // 0-1gb void pml4_identity_init(void) { memset32(pml4_identity, 0, sizeof pml4_identity); memset32(pdpte_low, 0, sizeof pdpte_low); memset32(pde_low, 0, sizeof pde_low); - pml4_identity[0] = (struct page_generic) { + pml4_identity[0] = (pe_generic_t) { .present = 1, .writeable = 1, .address = ((uintptr_t)pdpte_low) >> 12, }; - pdpte_low[0] = (struct page_generic) { + pdpte_low[0] = (pe_generic_t) { .present = 1, .writeable = 1, .address = ((uintptr_t)pde_low) >> 12, }; for (int i = 0; i < 512; i++) { - pde_low[i] = (struct page_generic) { + pde_low[i] = (pe_generic_t) { .present = 1, .writeable = 1, .large = 1, diff --git a/src/kernel/arch/amd64/32/util.c b/src/kernel/arch/amd64/32/util.c new file mode 100644 index 0000000..7915168 --- /dev/null +++ b/src/kernel/arch/amd64/32/util.c @@ -0,0 +1,8 @@ +#include <kernel/arch/amd64/32/util.h> + +void *memset32(void *s, int c, size_t n) { + unsigned char *s2 = s; + for (size_t i = 0; i < n; i++) + s2[i] = c; + return s; +} diff --git a/src/kernel/arch/amd64/32/util.h b/src/kernel/arch/amd64/32/util.h new file mode 100644 index 0000000..087f397 --- /dev/null +++ b/src/kernel/arch/amd64/32/util.h @@ -0,0 +1,4 @@ +#pragma once +#include <stddef.h> + +void *memset32(void *s, int c, size_t n); diff --git a/src/kernel/arch/amd64/boot.c b/src/kernel/arch/amd64/boot.c index 56cf8c8..e8f9a26 100644 --- a/src/kernel/arch/amd64/boot.c +++ b/src/kernel/arch/amd64/boot.c @@ -1,5 +1,3 @@ -#include <kernel/arch/generic.h> -#include <kernel/arch/amd64/32/gdt.h> #include <kernel/arch/amd64/ata.h> #include <kernel/arch/amd64/boot.h> #include <kernel/arch/amd64/driver/fsroot.h> @@ -9,6 +7,7 @@ #include <kernel/arch/amd64/interrupts/irq.h> #include <kernel/arch/amd64/multiboot.h> #include <kernel/arch/amd64/tty/tty.h> +#include <kernel/arch/generic.h> #include <kernel/main.h> #include <kernel/mem/alloc.h> #include <kernel/panic.h> @@ -16,9 +15,8 @@ static void find_init(struct multiboot_info *multiboot, struct kmain_info *info) { struct multiboot_mod *module = (void*)(long)multiboot->mods; - kprintf("mods count 0x%x", multiboot->mods_count); - if (multiboot->mods_count < 1) { - kprintf("can't find init! "); + if (multiboot->mods_count != 1) { + kprintf("unexpected amount of multiboot modules\n"); panic_invalid_state(); } info->init.at = (void*)(long)module->start; diff --git a/src/kernel/arch/amd64/pagedir.c b/src/kernel/arch/amd64/pagedir.c index 6d0546a..6f5fd4e 100644 --- a/src/kernel/arch/amd64/pagedir.c +++ b/src/kernel/arch/amd64/pagedir.c @@ -1,57 +1,10 @@ +#include <kernel/arch/amd64/paging.h> #include <kernel/arch/generic.h> #include <kernel/mem/alloc.h> #include <kernel/panic.h> #include <shared/mem.h> #include <stdint.h> -/* <heat> nitpick: I highly recommend you dont use bitfields for paging - * structures - * <heat> you can't change them atomically and the way they're layed out - * in memory is implementation defined iirc - */ -// TODO move to single shared header file for the 32bit bootstrap -typedef union pe_generic_t { - struct { - uint64_t present : 1; - uint64_t writeable : 1; - uint64_t user : 1; - uint64_t writethru : 1; - - uint64_t uncached : 1; - uint64_t accessed : 1; - uint64_t dirty : 1; - uint64_t large : 1; // also PAT - - uint64_t global : 1; // TODO enable CR4.PGE - uint64_t _unused2 : 2; - uint64_t _unused3 : 1; // HLAT - - uint64_t address : 40; - - uint64_t _unused4 : 7; - uint64_t pke : 4; - uint64_t noexec : 1; - } __attribute__((packed)); - void *as_ptr; -} pe_generic_t; // pageentry_generic - -struct pagedir { // actually pml4, TODO rename to a more generic name - pe_generic_t e[512]; -} __attribute__((packed)); - - -union virt_addr { - void __user *full; - struct { - uint64_t off_4k : 12; // 4Kb // offset in page - uint64_t pt : 9; // 2Mb // page table index - uint64_t pd : 9; // 1Gb // page directory index - uint64_t pdpt : 9; // 512Gb // page directory pointer table index - uint64_t pml4 : 9; // 256Tb // page map level 4 index - uint64_t sign : 16; - } __attribute__((packed)); -}; - static void *addr_extract(pe_generic_t pe) { return (void*)(uintptr_t)(pe.address << 12); } @@ -62,6 +15,7 @@ static void *addr_validate(void *addr) { return addr; } + struct pagedir *pagedir_new(void) { struct pagedir *dir = page_alloc(1); memset(dir, 0, sizeof *dir); diff --git a/src/kernel/arch/amd64/paging.h b/src/kernel/arch/amd64/paging.h new file mode 100644 index 0000000..a676bb8 --- /dev/null +++ b/src/kernel/arch/amd64/paging.h @@ -0,0 +1,54 @@ +#pragma once +#include <shared/types.h> + +/* <heat> nitpick: I highly recommend you dont use bitfields for paging + * structures + * <heat> you can't change them atomically and the way they're layed out + * in memory is implementation defined iirc + */ +typedef union pe_generic_t { + struct { + uint64_t present : 1; + uint64_t writeable : 1; + uint64_t user : 1; + uint64_t writethru : 1; + + uint64_t uncached : 1; + uint64_t accessed : 1; + uint64_t dirty : 1; + uint64_t large : 1; // also, PAT + + uint64_t global : 1; // CR4.PGE is disabled anyways + uint64_t _unused2 : 2; + uint64_t _unused3 : 1; // HLAT + + uint64_t address : 40; + + uint64_t _unused4 : 7; + uint64_t pke : 4; + uint64_t noexec : 1; + } __attribute__((packed)); + void *as_ptr; +} pe_generic_t; // pageentry_generic + +struct pagedir { // on amd64 actually points to pml4. TODO more sensible type + pe_generic_t e[512]; +} __attribute__((packed)); + + +union virt_addr { + void __user *full; + struct { + uint64_t off_4k : 12; // 4Kb // offset in page + uint64_t pt : 9; // 2Mb // page table index + uint64_t pd : 9; // 1Gb // page directory index + uint64_t pdpt : 9; // 512Gb // page directory pointer table index + uint64_t pml4 : 9; // 256Tb // page map level 4 index + uint64_t sign : 16; + } __attribute__((packed)); +}; + + +/* amd64/32/paging.c */ +extern pe_generic_t pml4_identity[512]; +void pml4_identity_init(void); // called from amd64/32/boot.s diff --git a/src/kernel/arch/amd64/sysenter.s b/src/kernel/arch/amd64/sysenter.s index 3f035dc..9dc907f 100644 --- a/src/kernel/arch/amd64/sysenter.s +++ b/src/kernel/arch/amd64/sysenter.s @@ -1,4 +1,4 @@ -/* TODO include gdt.h */ +// gdt.h .set SEG_r0code, 1 .set SEG_r3code, 3 .set SEG_r3data, 4 @@ -43,7 +43,7 @@ pagedir_current: .global _sysexit_real .type _sysexit_real, @function _sysexit_real: - /* + /* TODO check if SYSRET correctly sets segments mov $(SEG_r3data << 3 | 3), %ax mov %ax, %ds mov %ax, %es |