summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/amd64/amd64/gdt.c76
-rw-r--r--sys/arch/amd64/amd64/machdep.c8
-rw-r--r--sys/include/arch/amd64/gdt.h69
3 files changed, 100 insertions, 53 deletions
diff --git a/sys/arch/amd64/amd64/gdt.c b/sys/arch/amd64/amd64/gdt.c
index a8fe54d..40d8f48 100644
--- a/sys/arch/amd64/amd64/gdt.c
+++ b/sys/arch/amd64/amd64/gdt.c
@@ -29,50 +29,70 @@
#include <machine/gdt.h>
-struct gdt_entry g_gdt_data[256] = {
+/*
+ * The GDT should be cache line aligned, since it is accessed every time a
+ * segment selector is reloaded
+ */
+__cacheline_aligned struct gdt_entry g_gdt_data[GDT_ENTRY_COUNT] = {
/* Null */
{0},
- /* Kernel code (0x8) */
+ /* Kernel code (0x08) */
{
- .limit = 0x0000,
- .base_low = 0x0000,
- .base_mid = 0x00,
- .access = 0x9A,
- .granularity = 0x20,
- .base_hi = 0x00
+ .limit = 0x0000,
+ .base_low = 0x0000,
+ .base_mid = 0x00,
+ .attributes = GDT_ATTRIBUTE_64BIT_CODE | GDT_ATTRIBUTE_PRESENT |
+ GDT_ATTRIBUTE_DPL0 | GDT_ATTRIBUTE_NONSYSTEM |
+ GDT_ATTRIBUTE_EXECUTABLE | GDT_ATTRIBUTE_READABLE,
+ .base_hi = 0x00
},
/* Kernel data (0x10) */
{
- .limit = 0x0000,
- .base_low = 0x0000,
- .base_mid = 0x00,
- .access = 0x92,
- .granularity = 0x00,
- .base_hi = 0x00
+ .limit = 0x0000,
+ .base_low = 0x0000,
+ .base_mid = 0x00,
+ .attributes = GDT_ATTRIBUTE_PRESENT | GDT_ATTRIBUTE_DPL0 |
+ GDT_ATTRIBUTE_NONSYSTEM | GDT_ATTRIBUTE_WRITABLE,
+ .base_hi = 0x00
},
/* User code (0x18) */
{
- .limit = 0x0000,
- .base_low = 0x0000,
- .base_mid = 0x00,
- .access = 0xFA,
- .granularity = 0xAF,
- .base_hi = 0x00
+ .limit = 0x0000,
+ .base_low = 0x0000,
+ .base_mid = 0x00,
+ .attributes = GDT_ATTRIBUTE_64BIT_CODE | GDT_ATTRIBUTE_PRESENT |
+ GDT_ATTRIBUTE_DPL3 | GDT_ATTRIBUTE_NONSYSTEM |
+ GDT_ATTRIBUTE_EXECUTABLE | GDT_ATTRIBUTE_READABLE,
+ .base_hi = 0x00
},
/* User data (0x20) */
{
- .limit = 0x0000,
- .base_low = 0x0000,
- .base_mid = 0x00,
- .access = 0xF2,
- .granularity = 0x00,
- .base_hi = 0x00
+ .limit = 0x0000,
+ .base_low = 0x0000,
+ .base_mid = 0x00,
+ .attributes = GDT_ATTRIBUTE_PRESENT | GDT_ATTRIBUTE_DPL3 |
+ GDT_ATTRIBUTE_NONSYSTEM | GDT_ATTRIBUTE_WRITABLE,
+ .base_hi = 0x00
},
- /* TSS segment (0x28) */
- {0}
+ /*
+ * TSS segment (0x28)
+ *
+ * NOTE: 64-bit TSS descriptors are 16 bytes, equivalent to the size of two
+ * regular descriptor entries.
+ * See Intel SPG 3/25 Section 9.2.3 - TSS Descriptor in 64-bit mode.
+ */
+ {0}, {0}
+};
+
+/* Verify that the GDT is of the correct size */
+__static_assert(sizeof(g_gdt_data) == (8 * GDT_ENTRY_COUNT));
+
+const struct gdtr g_gdtr = {
+ .limit = sizeof(g_gdt_data) - 1,
+ .offset = (uintptr_t)&g_gdt_data[0]
};
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index da6e554..3381437 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -59,10 +59,6 @@ void syscall_isr(void);
void pin_isr_load(void);
struct cpu_info g_bsp_ci = {0};
-static struct gdtr bsp_gdtr = {
- .limit = sizeof(struct gdt_entry) * 256 - 1,
- .offset = (uintptr_t)&g_gdt_data[0]
-};
__attribute__((__interrupt__))
static void
@@ -97,7 +93,7 @@ init_tss(struct cpu_info *ci)
{
struct tss_desc *desc;
- desc = (struct tss_desc *)&g_gdt_data[GDT_TSS];
+ desc = (struct tss_desc *)&g_gdt_data[GDT_TSS_INDEX];
write_tss(ci, desc);
tss_load();
}
@@ -239,7 +235,7 @@ void
cpu_startup(struct cpu_info *ci)
{
ci->self = ci;
- gdt_load(&bsp_gdtr);
+ gdt_load();
idt_load();
setup_vectors();
diff --git a/sys/include/arch/amd64/gdt.h b/sys/include/arch/amd64/gdt.h
index 55666a7..0c5faf1 100644
--- a/sys/include/arch/amd64/gdt.h
+++ b/sys/include/arch/amd64/gdt.h
@@ -4,18 +4,48 @@
#include <sys/types.h>
#include <sys/cdefs.h>
+#define GDT_TSS_INDEX 5
+#define GDT_ENTRY_COUNT 7
+
+/* Segment selectors */
#define KERNEL_CS 0x08
#define KERNEL_DS 0x10
-#define USER_CS 0x18
-#define USER_DS 0x20
-#define GDT_TSS 5
+#define USER_CS 0x18
+#define USER_DS 0x20
+
+/*
+ * Bit definitions for regular segment descriptors
+ *
+ * See Intel SPG 3/25 Section 3.4.5 - Segment Descriptors
+ */
+
+#define GDT_ATTRIBUTE_ACCESSED BIT(0) /* Accessed */
+#define GDT_ATTRIBUTE_EXECUTABLE BIT(3) /* Executable */
+#define GDT_ATTRIBUTE_NONSYSTEM BIT(4) /* Code/data */
+#define GDT_ATTRIBUTE_PRESENT BIT(7) /* Present */
+#define GDT_ATTRIBUTE_64BIT_CODE BIT(13) /* 64-bit code */
+#define GDT_ATTRIBUTE_32BIT BIT(14) /* 32-bit code/data */
+#define GDT_ATTRIBUTE_GRANULARITY BIT(15) /* 4KiB limit granularity */
+
+/* Attributes for executable segments */
+#define GDT_ATTRIBUTE_READABLE BIT(1) /* Readable */
+#define GDT_ATTRIBUTE_CONFORMING BIT(2) /* Conforming */
+
+/* Attributes for non-executable segments */
+#define GDT_ATTRIBUTE_WRITABLE BIT(1) /* Writable */
+#define GDT_ATTRIBUTE_EXPANDS_DOWN BIT(2) /* See SPG 3/25 Section 6.8.1 */
+
+/* DPL (Descriptor Privilege Level) specifier */
+#define GDT_ATTRIBUTE_DPL0 0
+#define GDT_ATTRIBUTE_DPL1 (1 << 5)
+#define GDT_ATTRIBUTE_DPL2 (2 << 5)
+#define GDT_ATTRIBUTE_DPL3 (3 << 5)
struct __packed gdt_entry {
uint16_t limit;
uint16_t base_low;
uint8_t base_mid;
- uint8_t access;
- uint8_t granularity;
+ uint16_t attributes;
uint8_t base_hi;
};
@@ -24,27 +54,28 @@ struct __packed gdtr {
uintptr_t offset;
};
+extern struct gdt_entry g_gdt_data[GDT_ENTRY_COUNT];
+extern const struct gdtr g_gdtr;
+
__always_inline static inline void
-gdt_load(struct gdtr *gdtr)
+gdt_load(void)
{
__ASMV("lgdt %0\n"
- "push $8\n" /* Push CS */
- "lea 1f(%%rip), %%rax\n" /* Load 1 label address into RAX */
- "push %%rax\n" /* Push the return address (label 1) */
- "lretq\n" /* Far return to update CS */
+ "push %1\n" /* Push code segment selector */
+ "lea 1f(%%rip), %%rax\n" /* Load label 1 address into RAX */
+ "push %%rax\n" /* Push return address (label 1) */
+ "lretq\n" /* Far return to update CS */
"1:\n"
- " mov $0x10, %%eax\n"
- " mov %%eax, %%ds\n"
- " mov %%eax, %%es\n"
- " mov %%eax, %%fs\n"
- " mov %%eax, %%gs\n"
- " mov %%eax, %%ss\n"
+ " mov %2, %%ax\n" /* Load data segment selectors */
+ " mov %%ax, %%ds\n"
+ " mov %%ax, %%es\n"
+ " mov %%ax, %%fs\n"
+ " mov %%ax, %%gs\n"
+ " mov %%ax, %%ss\n"
:
- : "m" (*gdtr)
+ : "m" (g_gdtr), "i"(KERNEL_CS), "i"(KERNEL_DS)
: "rax", "memory"
);
}
-extern struct gdt_entry g_gdt_data[256];
-
#endif /* !AMD64_GDT_H_ */