95 lines
2.4 KiB
C
95 lines
2.4 KiB
C
#include "../include/gdt.h"
|
|
#include "../include/string.h"
|
|
#include "../include/paging.h"
|
|
|
|
struct tss_entry_struct tss;
|
|
|
|
struct seg_desc gdt[NR_GDT_ENTRIES];
|
|
|
|
struct desc_r gdtr = {
|
|
sizeof(gdt) - 1,
|
|
(uint32_t)&gdt
|
|
};
|
|
|
|
void bss_init()
|
|
{
|
|
memset((void *)((int)_edata), 0, KERNEL_BSS_SIZE);
|
|
}
|
|
|
|
uint32_t get_last_boot_addr()
|
|
{
|
|
return ((uint32_t)_end & PAGE_MASK) + PAGE_SIZE;
|
|
}
|
|
|
|
void load_gdt(uint32_t gdt_ptr) {
|
|
asm volatile (
|
|
"lgdt (%0)\n\t"
|
|
"movw %1, %%ax\n\t"
|
|
"movw %%ax, %%ds\n\t"
|
|
"movw %%ax, %%es\n\t"
|
|
"movw %%ax, %%fs\n\t"
|
|
"movw %%ax, %%gs\n\t"
|
|
"movw %%ax, %%ss\n\t"
|
|
"ljmp %2, $1f\n\t"
|
|
"1:\n\t"
|
|
:
|
|
: "r" (gdt_ptr), "i" (KERNEL_DS), "i" (KERNEL_CS)
|
|
: "eax"
|
|
);
|
|
}
|
|
|
|
void flush_tss(void) {
|
|
asm volatile (
|
|
"mov %0, %%ax\n\t"
|
|
"ltr %%ax\n\t"
|
|
:
|
|
: "i" (0x28)
|
|
: "ax"
|
|
);
|
|
}
|
|
|
|
static void gdt_set_entry(int num, uint32_t base_addr, uint32_t limit, char loflags, char hiflags)
|
|
{
|
|
num /= sizeof(struct seg_desc);
|
|
gdt[num].sd_lolimit = limit & 0xFFFF;
|
|
gdt[num].sd_lobase = base_addr & 0xFFFFFF;
|
|
gdt[num].sd_loflags = loflags;
|
|
gdt[num].sd_hilimit = (limit >> 16) & 0x0F;
|
|
gdt[num].sd_hiflags = hiflags;
|
|
gdt[num].sd_hibase = (base_addr >> 24) & 0xFF;
|
|
}
|
|
|
|
void gdt_init(void)
|
|
{
|
|
uint8_t loflags;
|
|
|
|
memset(&tss, 0, sizeof(tss));
|
|
tss.ss0 = KERNEL_DS;
|
|
tss.iomap_base = 0xFFFF; // Disable I/O bitmap
|
|
tss.esp0 = 0xC0010000; /* kernel stack address (firstly defined in boot.asm)*/
|
|
tss.cs = KERNEL_CS;
|
|
tss.ds = KERNEL_DS;
|
|
tss.es = KERNEL_DS;
|
|
tss.fs = KERNEL_DS;
|
|
tss.gs = KERNEL_DS;
|
|
tss.ss = KERNEL_DS;
|
|
|
|
gdt_set_entry(0, 0, 0, 0, 0); /* null descriptor */
|
|
|
|
loflags = SD_CODE | SD_CD | SD_DPL0 | SD_PRESENT;
|
|
gdt_set_entry(KERNEL_CS, 0, 0xFFFFFFFF, loflags, SD_OPSIZE32 | SD_PAGE4KB);
|
|
loflags = SD_DATA | SD_CD | SD_DPL0 | SD_PRESENT;
|
|
gdt_set_entry(KERNEL_DS, 0, 0xFFFFFFFF, loflags, SD_OPSIZE32 | SD_PAGE4KB);
|
|
|
|
loflags = SD_CODE | SD_CD | SD_DPL3 | SD_PRESENT;
|
|
gdt_set_entry(USER_CS, 0, 0xFFFFFFFF, loflags, SD_OPSIZE32 | SD_PAGE4KB);
|
|
loflags = SD_DATA | SD_CD | SD_DPL3 | SD_PRESENT;
|
|
gdt_set_entry(USER_DS, 0, 0xFFFFFFFF, loflags, SD_OPSIZE32 | SD_PAGE4KB);
|
|
|
|
loflags = 0x89; // P=1, DPL=0, S=0 (system), Type=0x9 (32-bit TSS)
|
|
gdt_set_entry(TSS, (uint32_t)&tss, sizeof(struct tss_entry_struct) - 1, SD_PRESENT | SD_DPL0 | SD_TSSPRESENT, 0);
|
|
|
|
load_gdt((uint32_t)&gdtr);
|
|
flush_tss();
|
|
}
|