k-chow/k/gdt.c

123 lines
2.4 KiB
C

#include "gdt.h"
static struct gdt gdt = { 0 };
static void create_kernel_ds()
{
struct gdt_entry *entry = gdt.entries + KERNEL_DS_INDEX;
uint32_t limit = 0xfffff;
uint32_t base = 0x0;
entry->granularity = 1;
entry->db = 1;
entry->l = 0;
entry->available = 0;
entry->present = 1;
entry->desc_priv = 0;
entry->desc_type = 1;
entry->ex = 0;
entry->dc = 0;
entry->rw = 1;
entry->accessed = 0;
entry->limit_1 = limit & 0xffff;
entry->limit_2 = (limit >> 16) & 0xf;
entry->base_1 = base & 0xffff;
entry->base_2 = (base >> 16) & 0xff;
entry->base_3 = (base >> 24) & 0xff;
}
static void create_kernel_cs()
{
struct gdt_entry *entry = gdt.entries + KERNEL_CS_INDEX;
uint32_t limit = 0xfffff;
uint32_t base = 0x0;
entry->granularity = 1;
entry->db = 1;
entry->l = 0;
entry->available = 0;
entry->present = 1;
entry->desc_priv = 0;
entry->desc_type = 1;
entry->ex = 1;
entry->dc = 0;
entry->rw = 1;
entry->accessed = 0;
entry->limit_1 = limit & 0xffff;
entry->limit_2 = (limit >> 16) & 0xf;
entry->base_1 = base & 0xffff;
entry->base_2 = (base >> 16) & 0xff;
entry->base_3 = (base >> 24) & 0xff;
}
static void create_gdt()
{
create_kernel_ds();
create_kernel_cs();
}
static void load_gdt()
{
struct gdt_r gdtr;
gdtr.addr = (uint32_t)&gdt;
gdtr.limit = GDT_SIZE - 1;
asm volatile("lgdt %0\n"
:
: "m" (gdtr)
: "memory");
}
static void load_ds()
{
struct segment_selector selector;
selector.index = KERNEL_DS_INDEX;
selector.table_indicator = 0;
selector.rpl = 0;
asm volatile("movw %0, %%ax\n"
"movw %%ax, %%ds\n"
"movw %%ax, %%fs\n"
"movw %%ax, %%gs\n"
"movw %%ax, %%ss\n"
:
: "m" (selector)
: "ax");
}
static void load_cs()
{
struct segment_selector selector;
selector.index = KERNEL_CS_INDEX;
selector.table_indicator = 0;
selector.rpl = 0;
asm volatile("pushl %0\n"
"pushl $1f\n"
"lret\n"
"1:\n"
:
: "m" (selector));
}
static void reload_segment_selectors()
{
load_ds();
load_cs();
}
void init_gdt()
{
create_gdt();
load_gdt();
reload_segment_selectors();
}