Kernel: Initialize GDT in kernel code
We dont use the boot GDT only while booting
This commit is contained in:
parent
7f8cad83b1
commit
7fcbb869e1
|
@ -0,0 +1,142 @@
|
||||||
|
#include <BAN/Assert.h>
|
||||||
|
#include <kernel/GDT.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
extern "C" uintptr_t g_boot_stack_top[0];
|
||||||
|
|
||||||
|
namespace Kernel::GDT
|
||||||
|
{
|
||||||
|
|
||||||
|
struct TaskStateSegment
|
||||||
|
{
|
||||||
|
uint16_t link;
|
||||||
|
uint16_t reserved1;
|
||||||
|
uint32_t esp0;
|
||||||
|
uint16_t ss0;
|
||||||
|
uint16_t reserved2;
|
||||||
|
uint32_t esp1;
|
||||||
|
uint16_t ss1;
|
||||||
|
uint16_t reserved3;
|
||||||
|
uint32_t esp2;
|
||||||
|
uint16_t ss2;
|
||||||
|
uint16_t reserved4;
|
||||||
|
uint32_t cr3;
|
||||||
|
uint32_t eip;
|
||||||
|
uint32_t eflags;
|
||||||
|
uint32_t eax;
|
||||||
|
uint32_t ecx;
|
||||||
|
uint32_t edx;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t esp;
|
||||||
|
uint32_t ebp;
|
||||||
|
uint32_t esi;
|
||||||
|
uint32_t edi;
|
||||||
|
uint16_t es;
|
||||||
|
uint16_t reserved5;
|
||||||
|
uint16_t cs;
|
||||||
|
uint16_t reserved6;
|
||||||
|
uint16_t ss;
|
||||||
|
uint16_t reserved7;
|
||||||
|
uint16_t ds;
|
||||||
|
uint16_t reserved8;
|
||||||
|
uint16_t fs;
|
||||||
|
uint16_t reserved9;
|
||||||
|
uint16_t gs;
|
||||||
|
uint16_t reserved10;
|
||||||
|
uint16_t ldtr;
|
||||||
|
uint16_t reserved11;
|
||||||
|
uint16_t reserved12;
|
||||||
|
uint16_t iopb;
|
||||||
|
uint32_t ssp;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
union SegmentDescriptor
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t limit1;
|
||||||
|
uint16_t base1;
|
||||||
|
uint8_t base2;
|
||||||
|
uint8_t access;
|
||||||
|
uint8_t limit2 : 4;
|
||||||
|
uint8_t flags : 4;
|
||||||
|
uint8_t base3;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t low;
|
||||||
|
uint32_t high;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct GDTR
|
||||||
|
{
|
||||||
|
uint16_t size;
|
||||||
|
uint32_t address;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
static TaskStateSegment* s_tss = nullptr;
|
||||||
|
static SegmentDescriptor* s_gdt = nullptr;
|
||||||
|
static GDTR s_gdtr;
|
||||||
|
|
||||||
|
static void write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
||||||
|
{
|
||||||
|
SegmentDescriptor& desc = *(SegmentDescriptor*)((uintptr_t)s_gdt + offset);
|
||||||
|
desc.base1 = base;
|
||||||
|
desc.base2 = base >> 16;
|
||||||
|
desc.base3 = base >> 24;
|
||||||
|
|
||||||
|
desc.limit1 = limit;
|
||||||
|
desc.limit2 = limit >> 16;
|
||||||
|
|
||||||
|
desc.access = access;
|
||||||
|
|
||||||
|
desc.flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_tss(uint8_t offset)
|
||||||
|
{
|
||||||
|
s_tss = new TaskStateSegment();
|
||||||
|
ASSERT(s_tss);
|
||||||
|
|
||||||
|
memset(s_tss, 0x00, sizeof(TaskStateSegment));
|
||||||
|
s_tss->ss0 = 0x10;
|
||||||
|
s_tss->esp0 = (uintptr_t)g_boot_stack_top;
|
||||||
|
|
||||||
|
write_entry(offset, (uint32_t)s_tss, sizeof(TaskStateSegment), 0x89, 0x0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush_gdt()
|
||||||
|
{
|
||||||
|
asm volatile("lgdt %0" :: "m"(s_gdtr));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void flush_tss(uint16_t offset)
|
||||||
|
{
|
||||||
|
asm volatile("ltr %0" :: "m"(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
constexpr uint32_t descriptor_count = 6;
|
||||||
|
s_gdt = new SegmentDescriptor[descriptor_count];
|
||||||
|
ASSERT(s_gdt);
|
||||||
|
|
||||||
|
s_gdtr.address = (uint64_t)s_gdt;
|
||||||
|
s_gdtr.size = descriptor_count * sizeof(SegmentDescriptor) - 1;
|
||||||
|
|
||||||
|
write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
||||||
|
write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, 0xC); // kernel code
|
||||||
|
write_entry(0x10, 0x00000000, 0xFFFFF, 0x92, 0xC); // kernel data
|
||||||
|
write_entry(0x18, 0x00000000, 0xFFFFF, 0xFA, 0xC); // user code
|
||||||
|
write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, 0xC); // user data
|
||||||
|
write_tss(0x28);
|
||||||
|
|
||||||
|
flush_gdt();
|
||||||
|
flush_tss(0x28);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,37 +20,27 @@
|
||||||
.long 32
|
.long 32
|
||||||
|
|
||||||
.section .bss, "aw", @nobits
|
.section .bss, "aw", @nobits
|
||||||
# Create stack
|
# Create stack
|
||||||
stack_bottom:
|
.global g_boot_stack_bottom
|
||||||
|
g_boot_stack_bottom:
|
||||||
.skip 16384
|
.skip 16384
|
||||||
stack_top:
|
.global g_boot_stack_top
|
||||||
|
g_boot_stack_top:
|
||||||
|
|
||||||
.global g_kernel_cmdline
|
# 0 MiB -> 1 MiB: bootloader stuff
|
||||||
g_kernel_cmdline:
|
# 1 MiB -> 2 MiB: kernel
|
||||||
.skip 4096
|
# 2 MiB -> 3 MiB: kmalloc
|
||||||
|
# 3 MiB -> 4 Mib: kmalloc_fixed
|
||||||
.global g_gdtr
|
.align 32
|
||||||
g_gdtr:
|
boot_page_directory_pointer_table:
|
||||||
.skip 2 + 4
|
|
||||||
.global g_gdt
|
|
||||||
g_gdt:
|
|
||||||
.skip 5 * 8
|
|
||||||
|
|
||||||
# Reserve memory for paging structures,
|
|
||||||
# we will identity map first 4 MiB
|
|
||||||
|
|
||||||
# 0 MiB -> 1 MiB: bootloader stuff
|
|
||||||
# 1 MiB -> 2 MiB: kernel
|
|
||||||
# 2 MiB -> 3 MiB: kmalloc
|
|
||||||
# 3 MiB -> 4 Mib: kmalloc_eternal
|
|
||||||
.align 32
|
|
||||||
boot_page_directory_pointer_table:
|
|
||||||
.skip 4 * 8
|
.skip 4 * 8
|
||||||
.align 4096
|
.align 4096
|
||||||
boot_page_directory1:
|
boot_page_directory1:
|
||||||
.skip 512 * 8
|
.skip 512 * 8
|
||||||
|
|
||||||
.section .text, "a"
|
.global g_kernel_cmdline
|
||||||
|
g_kernel_cmdline:
|
||||||
|
.skip 4096
|
||||||
|
|
||||||
.global g_multiboot_info
|
.global g_multiboot_info
|
||||||
g_multiboot_info:
|
g_multiboot_info:
|
||||||
|
@ -59,6 +49,16 @@ g_multiboot_info:
|
||||||
g_multiboot_magic:
|
g_multiboot_magic:
|
||||||
.skip 4
|
.skip 4
|
||||||
|
|
||||||
|
.section .text, "a"
|
||||||
|
|
||||||
|
boot_gdt:
|
||||||
|
.quad 0x0000000000000000 # null
|
||||||
|
.quad 0x00CF9A000000FFFF # kernel code
|
||||||
|
.quad 0x00CF92000000FFFF # kernel data
|
||||||
|
boot_gdtr:
|
||||||
|
.short . - boot_gdt - 1
|
||||||
|
.long boot_gdt
|
||||||
|
|
||||||
has_cpuid:
|
has_cpuid:
|
||||||
pushfl
|
pushfl
|
||||||
pushfl
|
pushfl
|
||||||
|
@ -140,18 +140,7 @@ initialize_paging:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
initialize_gdt:
|
initialize_gdt:
|
||||||
# setup gdt
|
lgdt boot_gdtr
|
||||||
movw $(5 * 8 - 1), g_gdtr
|
|
||||||
movl $(g_gdt), g_gdtr + 2
|
|
||||||
movl $(0x0000FFFF), g_gdt + 0x08
|
|
||||||
movl $(0x00CF9A00), g_gdt + 0x08 + 4
|
|
||||||
movl $(0x0000FFFF), g_gdt + 0x10
|
|
||||||
movl $(0x00CF9200), g_gdt + 0x10 + 4
|
|
||||||
movl $(0x0000FFFF), g_gdt + 0x18
|
|
||||||
movl $(0x00CFFA00), g_gdt + 0x18 + 4
|
|
||||||
movl $(0x0000FFFF), g_gdt + 0x20
|
|
||||||
movl $(0x00CFF200), g_gdt + 0x20 + 4
|
|
||||||
lgdt g_gdtr
|
|
||||||
|
|
||||||
# flush gdt
|
# flush gdt
|
||||||
movw $0x10, %ax
|
movw $0x10, %ax
|
||||||
|
@ -164,12 +153,11 @@ initialize_gdt:
|
||||||
flush:
|
flush:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
.global _start
|
.global _start
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
_start:
|
_start:
|
||||||
# Initialize stack and multiboot info
|
# Initialize stack and multiboot info
|
||||||
movl $stack_top, %esp
|
movl $g_boot_stack_top, %esp
|
||||||
movl %eax, g_multiboot_magic
|
movl %eax, g_multiboot_magic
|
||||||
movl %ebx, g_multiboot_info
|
movl %ebx, g_multiboot_info
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ ELF_FORMAT=elf32-i386
|
||||||
|
|
||||||
KERNEL_ARCH_OBJS= \
|
KERNEL_ARCH_OBJS= \
|
||||||
$(ARCHDIR)/boot.o \
|
$(ARCHDIR)/boot.o \
|
||||||
|
$(ARCHDIR)/GDT.o \
|
||||||
$(ARCHDIR)/IDT.o \
|
$(ARCHDIR)/IDT.o \
|
||||||
$(ARCHDIR)/MMU.o \
|
$(ARCHDIR)/MMU.o \
|
||||||
$(ARCHDIR)/SpinLock.o \
|
$(ARCHDIR)/SpinLock.o \
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
#include <BAN/Assert.h>
|
||||||
|
#include <kernel/GDT.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
extern "C" uintptr_t g_boot_stack_top[0];
|
||||||
|
|
||||||
|
namespace Kernel::GDT
|
||||||
|
{
|
||||||
|
|
||||||
|
struct TaskStateSegment
|
||||||
|
{
|
||||||
|
uint32_t reserved1;
|
||||||
|
uint64_t rsp0;
|
||||||
|
uint64_t rsp1;
|
||||||
|
uint64_t rsp2;
|
||||||
|
uint64_t reserved2;
|
||||||
|
uint64_t ist1;
|
||||||
|
uint64_t ist2;
|
||||||
|
uint64_t ist3;
|
||||||
|
uint64_t ist4;
|
||||||
|
uint64_t ist5;
|
||||||
|
uint64_t ist6;
|
||||||
|
uint64_t ist7;
|
||||||
|
uint64_t reserved3;
|
||||||
|
uint16_t reserved4;
|
||||||
|
uint16_t iopb;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
union SegmentDescriptor
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t limit1;
|
||||||
|
uint16_t base1;
|
||||||
|
uint8_t base2;
|
||||||
|
uint8_t access;
|
||||||
|
uint8_t limit2 : 4;
|
||||||
|
uint8_t flags : 4;
|
||||||
|
uint8_t base3;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t low;
|
||||||
|
uint32_t high;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct GDTR
|
||||||
|
{
|
||||||
|
uint16_t size;
|
||||||
|
uint64_t address;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
static TaskStateSegment* s_tss = nullptr;
|
||||||
|
static SegmentDescriptor* s_gdt = nullptr;
|
||||||
|
static GDTR s_gdtr;
|
||||||
|
|
||||||
|
static void write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
||||||
|
{
|
||||||
|
SegmentDescriptor& desc = *(SegmentDescriptor*)((uintptr_t)s_gdt + offset);
|
||||||
|
desc.base1 = base;
|
||||||
|
desc.base2 = base >> 16;
|
||||||
|
desc.base3 = base >> 24;
|
||||||
|
|
||||||
|
desc.limit1 = limit;
|
||||||
|
desc.limit2 = limit >> 16;
|
||||||
|
|
||||||
|
desc.access = access;
|
||||||
|
|
||||||
|
desc.flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_tss(uint8_t offset)
|
||||||
|
{
|
||||||
|
s_tss = new TaskStateSegment();
|
||||||
|
ASSERT(s_tss);
|
||||||
|
|
||||||
|
memset(s_tss, 0x00, sizeof(TaskStateSegment));
|
||||||
|
s_tss->rsp0 = (uintptr_t)g_boot_stack_top;
|
||||||
|
|
||||||
|
uintptr_t base = (uintptr_t)s_tss;
|
||||||
|
|
||||||
|
write_entry(offset, (uint32_t)base, sizeof(TaskStateSegment), 0x89, 0x0);
|
||||||
|
SegmentDescriptor& desc = *(SegmentDescriptor*)((uintptr_t)s_gdt + offset + 0x08);
|
||||||
|
desc.low = base >> 32;
|
||||||
|
desc.high = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush_gdt()
|
||||||
|
{
|
||||||
|
asm volatile("lgdt %0" :: "m"(s_gdtr));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void flush_tss(uint16_t offset)
|
||||||
|
{
|
||||||
|
asm volatile("ltr %0" :: "m"(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
constexpr uint32_t descriptor_count = 6 + 1; // tss takes 2
|
||||||
|
s_gdt = new SegmentDescriptor[descriptor_count];
|
||||||
|
ASSERT(s_gdt);
|
||||||
|
|
||||||
|
s_gdtr.address = (uint64_t)s_gdt;
|
||||||
|
s_gdtr.size = descriptor_count * sizeof(SegmentDescriptor) - 1;
|
||||||
|
|
||||||
|
write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
||||||
|
write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, 0xA); // kernel code
|
||||||
|
write_entry(0x10, 0x00000000, 0xFFFFF, 0x92, 0xC); // kernel data
|
||||||
|
write_entry(0x18, 0x00000000, 0xFFFFF, 0xFA, 0xA); // user code
|
||||||
|
write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, 0xC); // user data
|
||||||
|
write_tss(0x28);
|
||||||
|
|
||||||
|
flush_gdt();
|
||||||
|
flush_tss(0x28);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -43,7 +43,7 @@
|
||||||
# 0 MiB -> 1 MiB: bootloader stuff
|
# 0 MiB -> 1 MiB: bootloader stuff
|
||||||
# 1 MiB -> 2 MiB: kernel
|
# 1 MiB -> 2 MiB: kernel
|
||||||
# 2 MiB -> 3 MiB: kmalloc
|
# 2 MiB -> 3 MiB: kmalloc
|
||||||
# 3 MiB -> 4 MiB: kmalloc_eternal
|
# 3 MiB -> 4 MiB: kmalloc_fixed
|
||||||
.align 4096
|
.align 4096
|
||||||
boot_pml4:
|
boot_pml4:
|
||||||
.skip 512 * 8
|
.skip 512 * 8
|
||||||
|
@ -52,8 +52,6 @@
|
||||||
boot_pd1:
|
boot_pd1:
|
||||||
.skip 512 * 8
|
.skip 512 * 8
|
||||||
|
|
||||||
.section .text, "a"
|
|
||||||
|
|
||||||
.global g_multiboot_info
|
.global g_multiboot_info
|
||||||
g_multiboot_info:
|
g_multiboot_info:
|
||||||
.skip 8
|
.skip 8
|
||||||
|
@ -61,6 +59,8 @@ g_multiboot_info:
|
||||||
g_multiboot_magic:
|
g_multiboot_magic:
|
||||||
.skip 8
|
.skip 8
|
||||||
|
|
||||||
|
.section .text, "a"
|
||||||
|
|
||||||
boot_gdt:
|
boot_gdt:
|
||||||
.quad 0x0000000000000000 # null descriptor
|
.quad 0x0000000000000000 # null descriptor
|
||||||
.quad 0x00AF9A000000FFFF # kernel code
|
.quad 0x00AF9A000000FFFF # kernel code
|
||||||
|
|
|
@ -7,6 +7,7 @@ ELF_FORMAT=elf64-x86-64
|
||||||
|
|
||||||
KERNEL_ARCH_OBJS= \
|
KERNEL_ARCH_OBJS= \
|
||||||
$(ARCHDIR)/boot.o \
|
$(ARCHDIR)/boot.o \
|
||||||
|
$(ARCHDIR)/GDT.o \
|
||||||
$(ARCHDIR)/IDT.o \
|
$(ARCHDIR)/IDT.o \
|
||||||
$(ARCHDIR)/interrupts.o \
|
$(ARCHDIR)/interrupts.o \
|
||||||
$(ARCHDIR)/MMU.o \
|
$(ARCHDIR)/MMU.o \
|
||||||
|
|
|
@ -2,43 +2,9 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace GDT
|
namespace Kernel::GDT
|
||||||
{
|
{
|
||||||
|
|
||||||
union SegmentDesriptor
|
void initialize();
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint16_t limit_lo;
|
|
||||||
uint16_t base_lo;
|
|
||||||
uint8_t base_hi1;
|
|
||||||
|
|
||||||
uint8_t type : 4;
|
|
||||||
uint8_t system : 1;
|
|
||||||
uint8_t DPL : 2;
|
|
||||||
uint8_t present : 1;
|
|
||||||
|
|
||||||
uint8_t limit_hi : 4;
|
|
||||||
uint8_t flags : 4;
|
|
||||||
|
|
||||||
uint8_t base_hi2;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint32_t low;
|
|
||||||
uint32_t high;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
struct GDTR
|
|
||||||
{
|
|
||||||
uint16_t size;
|
|
||||||
void* address;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
extern "C" GDTR g_gdtr[];
|
|
||||||
extern "C" SegmentDesriptor g_gdt[];
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
#include <kernel/Debug.h>
|
#include <kernel/Debug.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
|
#include <kernel/GDT.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/Input.h>
|
#include <kernel/Input.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
|
@ -76,6 +77,9 @@ extern "C" void kernel_main()
|
||||||
kmalloc_initialize();
|
kmalloc_initialize();
|
||||||
dprintln("kmalloc initialized");
|
dprintln("kmalloc initialized");
|
||||||
|
|
||||||
|
GDT::initialize();
|
||||||
|
dprintln("GDT initialized");
|
||||||
|
|
||||||
IDT::initialize();
|
IDT::initialize();
|
||||||
dprintln("IDT initialized");
|
dprintln("IDT initialized");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue