aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMarvin Borner2021-05-02 14:29:12 +0200
committerMarvin Borner2021-05-02 14:29:12 +0200
commit7e55005dda411b5adafb985e485e3756969f6ac0 (patch)
treef3c866df6995ae6991ad027a8c5481714b8cc431 /kernel
parented4d960607d754c407a6964af86afcf0ad294123 (diff)
Some GDT improvements (attempts to fix no I/O GPF)
Diffstat (limited to 'kernel')
-rw-r--r--kernel/drivers/gdt.c34
-rw-r--r--kernel/inc/gdt.h16
2 files changed, 33 insertions, 17 deletions
diff --git a/kernel/drivers/gdt.c b/kernel/drivers/gdt.c
index 8209eaf..693f25f 100644
--- a/kernel/drivers/gdt.c
+++ b/kernel/drivers/gdt.c
@@ -21,6 +21,12 @@ static struct tss_entry tss = { 0 };
PROTECTED static struct gdt_ptr gp = { 0 };
+CONST u8 gdt_offset(u8 gate)
+{
+ assert(gate && gate < COUNT(gdt));
+ return ((u32)&gdt[gate] - (u32)gdt) & 0xff;
+}
+
CLEAR static void gdt_set_gate(u32 num, u32 base, u32 limit, u8 access, u8 gran)
{
// Set descriptor base address
@@ -48,13 +54,14 @@ CLEAR static void tss_write(u32 num, u16 ss0, u32 esp0)
tss.ss0 = ss0;
tss.esp0 = esp0;
- tss.cs = 0x0b;
- tss.ss = tss.ds = tss.es = tss.fs = tss.gs = 0x13;
+ tss.cs = GDT_SUPER_CODE_OFFSET | 3;
+ tss.ss = tss.ds = tss.es = tss.fs = tss.gs = GDT_SUPER_DATA_OFFSET | 3;
+ tss.iomap_base = U16_MAX;
}
CLEAR static void tss_flush(void)
{
- __asm__ volatile("ltr %0" ::"r"((u16)((u32)&gdt[5] - (u32)gdt)));
+ __asm__ volatile("ltr %0" ::"r"((u16)(GDT_TSS_OFFSET | 3)));
}
CLEAR static void gdt_flush(void)
@@ -73,36 +80,35 @@ CLEAR void gdt_install(u32 esp)
{
// Set GDT pointer and limit
gp.limit = sizeof(gdt) - 1;
- gp.base = &gdt;
+ gp.base = gdt;
// NULL descriptor
gdt_set_gate(0, 0, 0, 0, 0);
// Code segment
- gdt_set_gate(1, 0, 0xffffffff,
+ gdt_set_gate(GDT_ROOT_CODE_GATE, 0, U32_MAX,
GDT_PRESENT | GDT_DESCRIPTOR | GDT_EXECUTABLE | GDT_READWRITE,
GDT_GRANULARITY | GDT_SIZE);
// Data segment
- gdt_set_gate(2, 0, 0xffffffff, GDT_PRESENT | GDT_DESCRIPTOR | GDT_READWRITE,
+ gdt_set_gate(GDT_ROOT_DATA_GATE, 0, U32_MAX, GDT_PRESENT | GDT_DESCRIPTOR | GDT_READWRITE,
GDT_GRANULARITY | GDT_SIZE);
// User mode code segment
- gdt_set_gate(3, 0, 0xffffffff,
+ gdt_set_gate(GDT_USER_CODE_GATE, 0, U32_MAX,
GDT_PRESENT | GDT_RING3 | GDT_DESCRIPTOR | GDT_EXECUTABLE | GDT_READWRITE,
GDT_GRANULARITY | GDT_SIZE);
// User mode data segment
- gdt_set_gate(4, 0, 0xffffffff, GDT_PRESENT | GDT_RING3 | GDT_DESCRIPTOR | GDT_READWRITE,
+ gdt_set_gate(GDT_USER_DATA_GATE, 0, U32_MAX,
+ GDT_PRESENT | GDT_RING3 | GDT_DESCRIPTOR | GDT_READWRITE,
GDT_GRANULARITY | GDT_SIZE);
// Write TSS
- tss_write(5, GDT_SUPER_DATA_OFFSET, esp);
+ tss_write(GDT_TSS_GATE, GDT_SUPER_DATA_OFFSET, esp);
// Remove old GDT and install the new changes!
gdt_flush();
- tss_flush();
-
__asm__ volatile("mov %%ax, %%ds\n"
"mov %%ax, %%es\n"
"mov %%ax, %%fs\n"
@@ -110,6 +116,8 @@ CLEAR void gdt_install(u32 esp)
"mov %%ax, %%ss\n" ::"a"(GDT_SUPER_DATA_OFFSET)
: "memory");
- __asm__ volatile("ljmpl $" STRINGIFY(GDT_SUPER_CODE_OFFSET) ", $code\n"
- "code:\n");
+ __asm__ volatile("ljmpl $0x08 , $code\n"
+ "code:\n");
+
+ tss_flush();
}
diff --git a/kernel/inc/gdt.h b/kernel/inc/gdt.h
index 9a9fd01..20261f3 100644
--- a/kernel/inc/gdt.h
+++ b/kernel/inc/gdt.h
@@ -5,10 +5,17 @@
#include <def.h>
-#define GDT_SUPER_CODE_OFFSET 0x08 // Super (kernel) code segment offset in GDT
-#define GDT_SUPER_DATA_OFFSET 0x10 // Super (kernel) data segment offset in GDT
-#define GDT_USER_CODE_OFFSET 0x1b // User code segment offset in GDT (with ring3 mask)
-#define GDT_USER_DATA_OFFSET 0x23 // User data segment offset in GDT (with ring3 mask)
+#define GDT_ROOT_CODE_GATE 1
+#define GDT_ROOT_DATA_GATE 2
+#define GDT_USER_CODE_GATE 3
+#define GDT_USER_DATA_GATE 4
+#define GDT_TSS_GATE 5
+
+#define GDT_SUPER_CODE_OFFSET (gdt_offset(GDT_ROOT_CODE_GATE))
+#define GDT_SUPER_DATA_OFFSET (gdt_offset(GDT_ROOT_DATA_GATE))
+#define GDT_USER_CODE_OFFSET (gdt_offset(GDT_USER_CODE_GATE) | 3)
+#define GDT_USER_DATA_OFFSET (gdt_offset(GDT_USER_DATA_GATE) | 3)
+#define GDT_TSS_OFFSET (gdt_offset(GDT_TSS_GATE))
struct gdt_entry {
u16 limit_low;
@@ -54,6 +61,7 @@ struct tss_entry {
u16 iomap_base;
} PACKED;
+u8 gdt_offset(u8 gate);
void gdt_install(u32 esp);
void tss_set_stack(u32 ss, u32 esp);