summaryrefslogtreecommitdiff
path: root/src/kernel/arch/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/arch/amd64')
-rw-r--r--src/kernel/arch/amd64/32/boot.s14
-rw-r--r--src/kernel/arch/amd64/32/farjump.s8
-rw-r--r--src/kernel/arch/amd64/32/gdt.c26
-rw-r--r--src/kernel/arch/amd64/32/gdt.h3
-rw-r--r--src/kernel/arch/amd64/32/paging.c47
-rw-r--r--src/kernel/arch/amd64/32/util.c8
-rw-r--r--src/kernel/arch/amd64/32/util.h4
-rw-r--r--src/kernel/arch/amd64/boot.c8
-rw-r--r--src/kernel/arch/amd64/pagedir.c50
-rw-r--r--src/kernel/arch/amd64/paging.h54
-rw-r--r--src/kernel/arch/amd64/sysenter.s4
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