diff options
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | src/kernel/arch/amd64/32/boot.S (renamed from src/kernel/arch/amd64/32/boot.s) | 37 | ||||
-rw-r--r-- | src/kernel/arch/amd64/32/gdt.c | 111 | ||||
-rw-r--r-- | src/kernel/arch/amd64/boot64.S | 33 | ||||
-rw-r--r-- | src/kernel/arch/amd64/boot64.s | 12 | ||||
-rw-r--r-- | src/kernel/arch/amd64/interrupts/idt.c | 2 |
6 files changed, 69 insertions, 128 deletions
@@ -174,4 +174,4 @@ cc("libk/%.s", "$(CFLAGS_KERNEL)", "out/sysrootk/usr/include/") cc("libk/%.S", "$(CFLAGS_KERNEL)", "out/sysrootk/usr/include/") cc("kernel/arch/amd64/32/%.c", "$(CFLAGS_KERNEL) -fno-pic -m32", "out/sysrootk/usr/include/") -cc("kernel/arch/amd64/32/%.s", "$(CFLAGS_KERNEL) -fno-pic -m32", "out/sysrootk/usr/include/") +cc("kernel/arch/amd64/32/%.S", "$(CFLAGS_KERNEL) -fno-pic -m32", "out/sysrootk/usr/include/") diff --git a/src/kernel/arch/amd64/32/boot.s b/src/kernel/arch/amd64/32/boot.S index b0808d3..3f5798f 100644 --- a/src/kernel/arch/amd64/32/boot.s +++ b/src/kernel/arch/amd64/32/boot.S @@ -34,8 +34,9 @@ _start: and $(~4), %eax // disable coprocessor emulation mov %eax, %cr0 - call gdt_init - lgdt (lgdt_arg) + /* fill out the TSS's address */ + movw $TSS, (GdtTss + 2) + lgdt (GdtPointer) pop %edi @@ -79,3 +80,35 @@ cpu_pause: hlt cli ret + +.section .shared +.global GDT +.align 8 +GDT: +#define GdtLimit(p) (p & 0xFFFF) | ((p >> 16) << 48) /* doesn't check if p fits in 20 bits */ +#define GdtAccessed (1<<40) +#define GdtReadWrite (1<<41) +#define GdtCode (1<<43) +#define GdtCodeOrData (1<<44) +#define GdtRing(r) (r<<45) +#define GdtPresent (1<<47) +#define GdtAvailable (1<<52) +#define GdtLongMode (1<<53) +#define GdtPageGran (1<<55) /* limit is in pages */ +#define GdtCommon (GdtLimit(0xFFFFF) | GdtPageGran | GdtAccessed | \ + GdtReadWrite | GdtCodeOrData | GdtPresent | GdtAvailable) +.8byte 0 /* [0] = SEG_null */ +.8byte GdtCommon | GdtRing(0) | GdtLongMode | GdtCode /* [1] = SEG_r0code */ +.8byte GdtCommon | GdtRing(0) | GdtLongMode /* [2] = SEG_r0data */ +.8byte GdtCommon | GdtRing(3) | GdtCode /* [3] = SEG_r3code32 */ +.8byte GdtCommon | GdtRing(3) | GdtLongMode /* [4] = SEG_r3data */ +.8byte GdtCommon | GdtRing(3) | GdtLongMode | GdtCode /* [5] = SEG_r3code */ +GdtTss: +.8byte GdtLimit(104) | (9<<40) | GdtPresent | GdtAvailable /* [6] = SEG_TSS */ +.8byte 0 /* [7] = SEG_TSS2 */ + +.section .data +.global GdtPointer +GdtPointer: +.2byte 63 /* size of the GDT - 1 */ +.4byte GDT /* address of the GDT */ diff --git a/src/kernel/arch/amd64/32/gdt.c b/src/kernel/arch/amd64/32/gdt.c deleted file mode 100644 index e643f27..0000000 --- a/src/kernel/arch/amd64/32/gdt.c +++ /dev/null @@ -1,111 +0,0 @@ -#include <kernel/arch/amd64/32/util.h> -#include <kernel/arch/amd64/boot.h> -#include <stdbool.h> -#include <stdint.h> - -extern char _isr_mini_stack; - -struct gdt_entry { - uint64_t limit_low : 16; - uint64_t base_low : 24; - uint64_t accessed : 1; // set by the processor - // CODE | DATA - uint64_t rw : 1; // readable? | writeable? - uint64_t conforming : 1; // conforming? | expands down? - uint64_t code : 1; // 1 | 0 - - uint64_t codeordata : 1; // 1 for everything other than TSS and LDT - uint64_t ring : 2; - uint64_t present : 1; // always 1 - uint64_t limit_high : 4; - uint64_t available : 1; // ??? - uint64_t long_mode : 1; - uint64_t x32 : 1; - uint64_t gran : 1; // 1 - 4kb, 0 - 1b - uint64_t base_high : 8; -} __attribute__((packed)); - -struct tss_entry { - uint32_t reserved0; - uint64_t rsp[3]; - uint64_t ist[8]; - uint64_t reserved2; - uint16_t reserved3; - uint16_t iopb; -} __attribute__((packed)); - -struct lgdt_arg { - uint16_t limit; - uint32_t base; -} __attribute__((packed)); - -__attribute__((section(".shared"))) -static struct gdt_entry GDT[SEG_end]; -__attribute__((section(".shared"))) -static struct tss_entry TSS; - -struct lgdt_arg lgdt_arg; - -static void gdt_fillout(struct gdt_entry* entry, uint8_t ring, bool code) { - *entry = (struct gdt_entry) { - // set up the identity mapping - .limit_low = 0xFFFF, - .limit_high = 0xF, - .gran = 1, - .base_low = 0, - .base_high = 0, - - .ring = ring, - .code = code, - - .accessed = 0, - .rw = 1, - .conforming = 0, - .codeordata = 1, - .present = 1, - .long_mode = 1, - .available = 1, - .x32 = 0, - }; -} - -#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" -void gdt_init(void) { - GDT[SEG_null].present = 0; - - gdt_fillout(&GDT[SEG_r0code], 0, true); - gdt_fillout(&GDT[SEG_r0data], 0, false); - gdt_fillout(&GDT[SEG_r3code32], 3, true); - gdt_fillout(&GDT[SEG_r3data], 3, false); - gdt_fillout(&GDT[SEG_r3code], 3, true); - - lgdt_arg.limit = sizeof(GDT) - 1; - lgdt_arg.base = (uint64_t)&GDT; - - - memset32(&TSS, 0, sizeof(TSS)); - for (int i = 0; i < 3; i++) - TSS.rsp[i] = (uint64_t)&_isr_mini_stack; - TSS.ist[1] = (uint64_t)&_isr_mini_stack; - - uint64_t tss_addr = (uint64_t)&TSS; - GDT[SEG_TSS] = (struct gdt_entry) { - .limit_low = sizeof(TSS), - .limit_high = sizeof(TSS) >> 16, - .gran = 0, - .base_low = tss_addr, - .base_high = tss_addr >> 24, - - .accessed = 1, - .rw = 0, - .conforming = 0, - .code = 1, - .codeordata = 0, - .ring = 0, // was 3 pre-port - .present = 1, - .available = 1, - .long_mode = 0, - .x32 = 0, - }; - memset32(&GDT[SEG_TSS2], 0, sizeof GDT[SEG_TSS2]); -} diff --git a/src/kernel/arch/amd64/boot64.S b/src/kernel/arch/amd64/boot64.S new file mode 100644 index 0000000..f7ec60e --- /dev/null +++ b/src/kernel/arch/amd64/boot64.S @@ -0,0 +1,33 @@ +.global boot64 +boot64: + lgdt (GdtPointer) // try reloading gdt again + mov $(6 << 3 | 3), %ax // SEG_TSS + ltr %ax + + push %rdi // preserve multiboot struct + call sysenter_setup + pop %rdi + + // multiboot struct in %rdi + jmp kmain_early + + +.section .shared +/* https://wiki.osdev.org/Task_State_Segment#Long_Mode */ +.global TSS +.align 8 +TSS: + .4byte 0 /* reserved */ + .rept 3 + .8byte _isr_mini_stack /* stacks for privilege level changes */ + .endr + .8byte 0 /* reserved */ + .rept 7 + .8byte _isr_mini_stack /* IST - stack pointer loaded for interrupts */ + .endr + .8byte 0 /* reserved */ + .4byte 0 /* reserved + IOPB (unused) */ + .if . - TSS != 104 + .error "bad tss size" + .abort + .endif diff --git a/src/kernel/arch/amd64/boot64.s b/src/kernel/arch/amd64/boot64.s deleted file mode 100644 index 9bd9f0c..0000000 --- a/src/kernel/arch/amd64/boot64.s +++ /dev/null @@ -1,12 +0,0 @@ -.global boot64 -boot64: - lgdt (lgdt_arg) // try reloading gdt again - mov $(6 << 3 | 3), %ax // SEG_TSS - ltr %ax - - push %rdi // preserve multiboot struct - call sysenter_setup - pop %rdi - - // multiboot struct in %rdi - jmp kmain_early diff --git a/src/kernel/arch/amd64/interrupts/idt.c b/src/kernel/arch/amd64/interrupts/idt.c index 8f37cb9..2a5e8f7 100644 --- a/src/kernel/arch/amd64/interrupts/idt.c +++ b/src/kernel/arch/amd64/interrupts/idt.c @@ -17,8 +17,6 @@ struct idt_entry { uint32_t zero2; } __attribute__((packed)); -// is exactly the same as lgdt_arg, i should combine them into a single struct -// later struct lidt_arg { uint16_t limit; uintptr_t base; |