x86_64: implement TSS initialisation and user/kernel stack pointer switching
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
#include <mango/libc/string.h>
|
||||
#include <arch/gdt.h>
|
||||
#include <arch/tss.h>
|
||||
#include <mango/libc/string.h>
|
||||
#include <mango/types.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static void init_entry(struct gdt_entry *entry, int access, int flags)
|
||||
{
|
||||
@@ -15,13 +18,42 @@ int gdt_init(struct gdt *gdt, struct gdt_ptr *gdtp)
|
||||
{
|
||||
memset(&gdt->g_entries[0], 0x0, sizeof gdt->g_entries[0]);
|
||||
|
||||
init_entry(&gdt->g_entries[1], GDT_A_PRESENT | GDT_A_CODEREAD | GDT_A_CODE, GDT_F_64BIT);
|
||||
init_entry(&gdt->g_entries[2], GDT_A_PRESENT | GDT_A_DATAWRITE | GDT_A_DATA, GDT_F_64BIT);
|
||||
init_entry(&gdt->g_entries[3], GDT_A_PRESENT | GDT_A_USER | GDT_A_CODEREAD | GDT_A_CODE, GDT_F_64BIT);
|
||||
init_entry(&gdt->g_entries[4], GDT_A_PRESENT | GDT_A_USER | GDT_A_DATAWRITE | GDT_A_DATA, GDT_F_64BIT);
|
||||
init_entry(
|
||||
&gdt->g_entries[1],
|
||||
GDT_A_PRESENT | GDT_A_CODEREAD | GDT_A_CODE,
|
||||
GDT_F_64BIT);
|
||||
init_entry(
|
||||
&gdt->g_entries[2],
|
||||
GDT_A_PRESENT | GDT_A_DATAWRITE | GDT_A_DATA,
|
||||
GDT_F_64BIT);
|
||||
init_entry(
|
||||
&gdt->g_entries[3],
|
||||
GDT_A_PRESENT | GDT_A_USER | GDT_A_CODEREAD | GDT_A_CODE,
|
||||
GDT_F_64BIT);
|
||||
init_entry(
|
||||
&gdt->g_entries[4],
|
||||
GDT_A_PRESENT | GDT_A_USER | GDT_A_DATAWRITE | GDT_A_DATA,
|
||||
GDT_F_64BIT);
|
||||
|
||||
gdtp->g_ptr = (uint64_t)gdt;
|
||||
gdtp->g_limit = sizeof(*gdt) - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gdt_write_tss(struct gdt *gdt, struct tss *tss)
|
||||
{
|
||||
struct tss_gdt_entry *tss_entry = &gdt->g_tss;
|
||||
|
||||
virt_addr_t base = (virt_addr_t)tss;
|
||||
size_t limit = sizeof *tss;
|
||||
|
||||
tss_entry->ge_base_low = (base & 0xFFFF);
|
||||
tss_entry->ge_base_mid = (base >> 16) & 0xFF;
|
||||
tss_entry->ge_base_hi = (base >> 24) & 0xFF;
|
||||
tss_entry->ge_base_ext = (base >> 32) & 0xFFFFFFFF;
|
||||
tss_entry->ge_limit_low = (limit & 0xFFFF);
|
||||
tss_entry->ge_gran = (limit >> 16) & 0xF;
|
||||
tss_entry->ge_access = 0xE9;
|
||||
tss_entry->ge_reserved = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user