Kernel: Unify IDT and GDT code between x86_64 and x86_32
The code is pretty much the same, so there are just couple macros differiating initialization.
This commit is contained in:
parent
af050cc729
commit
1943c3e7a1
|
@ -33,6 +33,8 @@ set(KERNEL_SOURCES
|
|||
kernel/FS/TmpFS/FileSystem.cpp
|
||||
kernel/FS/TmpFS/Inode.cpp
|
||||
kernel/FS/VirtualFileSystem.cpp
|
||||
kernel/GDT.cpp
|
||||
kernel/IDT.cpp
|
||||
kernel/Input/KeyboardLayout.cpp
|
||||
kernel/Input/KeyEvent.cpp
|
||||
kernel/Input/PS2/Controller.cpp
|
||||
|
@ -105,8 +107,6 @@ if("${BANAN_ARCH}" STREQUAL "x86_64")
|
|||
set(KERNEL_SOURCES
|
||||
${KERNEL_SOURCES}
|
||||
arch/x86_64/boot.S
|
||||
arch/x86_64/GDT.cpp
|
||||
arch/x86_64/IDT.cpp
|
||||
arch/x86_64/interrupts.S
|
||||
arch/x86_64/PageTable.cpp
|
||||
arch/x86_64/Signal.S
|
||||
|
@ -124,8 +124,7 @@ elseif("${BANAN_ARCH}" STREQUAL "i686")
|
|||
set(KERNEL_SOURCES
|
||||
${KERNEL_SOURCES}
|
||||
arch/i686/boot.S
|
||||
arch/i686/GDT.cpp
|
||||
arch/i686/IDT.cpp
|
||||
arch/i686/interrupts.S
|
||||
arch/i686/PageTable.cpp
|
||||
arch/i686/Signal.S
|
||||
arch/i686/Syscall.S
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
#include <kernel/GDT.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
GDT* GDT::create()
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
void GDT::write_entry(uint8_t, uint32_t, uint32_t, uint8_t, uint8_t)
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
void GDT::write_tss()
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
#include <kernel/IDT.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
IDT* IDT::create()
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
[[noreturn]] void IDT::force_triple_fault()
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
void IDT::register_irq_handler(uint8_t, Interruptable*)
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
void IDT::register_interrupt_handler(uint8_t, void (*)())
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
void IDT::register_syscall_handler(uint8_t, void (*)())
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
isr_stub:
|
||||
ud2
|
||||
pusha
|
||||
call cpp_isr_handler
|
||||
popa
|
||||
iret
|
||||
|
||||
irq_stub:
|
||||
ud2
|
||||
pusha
|
||||
call cpp_irq_handler
|
||||
popa
|
||||
iret
|
||||
|
||||
// arguments in EAX, EBX, ECX, EDX, ESI, EDI
|
||||
.global syscall_asm
|
||||
syscall_asm:
|
||||
ud2
|
||||
pusha
|
||||
|
||||
pushl %esp
|
||||
addl $36, (%esp)
|
||||
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
|
||||
call cpp_syscall_handler
|
||||
|
||||
addl $60, %esp
|
||||
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebp
|
||||
addl $4, %esp
|
||||
popl %ebx
|
||||
popl %edx
|
||||
popl %ecx
|
||||
addl $4, %esp
|
||||
|
||||
iret
|
||||
|
||||
.macro isr n
|
||||
.global isr\n
|
||||
isr\n:
|
||||
pushl $0
|
||||
pushl $\n
|
||||
jmp isr_stub
|
||||
.endm
|
||||
|
||||
.macro isr_err n
|
||||
.global isr\n
|
||||
isr\n:
|
||||
pushl $\n
|
||||
jmp isr_stub
|
||||
.endm
|
||||
|
||||
.macro irq n
|
||||
.global irq\n
|
||||
irq\n:
|
||||
pushl $0
|
||||
pushl $\n
|
||||
jmp irq_stub
|
||||
.endm
|
||||
|
||||
isr 0
|
||||
isr 1
|
||||
isr 2
|
||||
isr 3
|
||||
isr 4
|
||||
isr 5
|
||||
isr 6
|
||||
isr 7
|
||||
isr_err 8
|
||||
isr 9
|
||||
isr_err 10
|
||||
isr_err 11
|
||||
isr_err 12
|
||||
isr_err 13
|
||||
isr_err 14
|
||||
isr 15
|
||||
isr 16
|
||||
isr_err 17
|
||||
isr 18
|
||||
isr 19
|
||||
isr 20
|
||||
isr 21
|
||||
isr 22
|
||||
isr 23
|
||||
isr 24
|
||||
isr 25
|
||||
isr 26
|
||||
isr 27
|
||||
isr 28
|
||||
isr 29
|
||||
isr 30
|
||||
isr 31
|
||||
|
||||
irq 0
|
||||
irq 1
|
||||
irq 2
|
||||
irq 3
|
||||
irq 4
|
||||
irq 5
|
||||
irq 6
|
||||
irq 7
|
||||
irq 8
|
||||
irq 9
|
||||
irq 10
|
||||
irq 11
|
||||
irq 12
|
||||
irq 13
|
||||
irq 14
|
||||
irq 15
|
||||
irq 16
|
||||
irq 17
|
||||
irq 18
|
||||
irq 19
|
||||
irq 20
|
||||
irq 21
|
||||
irq 22
|
||||
irq 23
|
||||
irq 24
|
||||
irq 25
|
||||
irq 26
|
||||
irq 27
|
||||
irq 28
|
||||
irq 29
|
||||
irq 30
|
||||
irq 31
|
||||
irq 32
|
|
@ -1,56 +0,0 @@
|
|||
#include <kernel/GDT.h>
|
||||
#include <kernel/Debug.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
GDT* GDT::create()
|
||||
{
|
||||
auto* gdt = new GDT();
|
||||
ASSERT(gdt);
|
||||
|
||||
gdt->write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
||||
gdt->write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, 0xA); // kernel code
|
||||
gdt->write_entry(0x10, 0x00000000, 0xFFFFF, 0x92, 0xC); // kernel data
|
||||
gdt->write_entry(0x18, 0x00000000, 0xFFFFF, 0xFA, 0xA); // user code
|
||||
gdt->write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, 0xC); // user data
|
||||
gdt->write_tss();
|
||||
|
||||
return gdt;
|
||||
}
|
||||
|
||||
void GDT::write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
||||
{
|
||||
ASSERT(offset % sizeof(SegmentDescriptor) == 0);
|
||||
uint8_t idx = offset / sizeof(SegmentDescriptor);
|
||||
|
||||
auto& desc = m_gdt[idx];
|
||||
desc.base1 = (base >> 0) & 0xFFFF;
|
||||
desc.base2 = (base >> 16) & 0xFF;
|
||||
desc.base3 = (base >> 24) & 0xFF;
|
||||
|
||||
desc.limit1 = (limit >> 0) & 0xFFFF;
|
||||
desc.limit2 = (limit >> 16) & 0x0F;
|
||||
|
||||
desc.access = access & 0xFF;
|
||||
|
||||
desc.flags = flags & 0x0F;
|
||||
}
|
||||
|
||||
void GDT::write_tss()
|
||||
{
|
||||
memset(&m_tss, 0x00, sizeof(TaskStateSegment));
|
||||
m_tss.iopb = sizeof(TaskStateSegment);
|
||||
|
||||
uint64_t base = reinterpret_cast<uint64_t>(&m_tss);
|
||||
|
||||
write_entry(0x28, (uint32_t)base, sizeof(TaskStateSegment), 0x89, 0x0);
|
||||
|
||||
auto& desc = m_gdt[0x30 / sizeof(SegmentDescriptor)];
|
||||
desc.low = base >> 32;
|
||||
desc.high = 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
#include <BAN/Array.h>
|
||||
#include <BAN/NoCopyMove.h>
|
||||
#include <kernel/Arch.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
#if ARCH(x86_64)
|
||||
struct TaskStateSegment
|
||||
{
|
||||
uint32_t reserved1;
|
||||
|
@ -26,6 +28,54 @@ namespace Kernel
|
|||
uint16_t reserved4;
|
||||
uint16_t iopb;
|
||||
} __attribute__((packed));
|
||||
static_assert(sizeof(TaskStateSegment) == 104);
|
||||
#elif ARCH(i686)
|
||||
struct TaskStateSegment
|
||||
{
|
||||
uint16_t link;
|
||||
uint16_t __reserved0;
|
||||
uint32_t esp0;
|
||||
uint16_t ss0;
|
||||
uint16_t __reserved1;
|
||||
uint32_t esp1;
|
||||
uint16_t ss1;
|
||||
uint16_t __reserved2;
|
||||
uint32_t esp2;
|
||||
uint16_t ss2;
|
||||
uint16_t __reserved3;
|
||||
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 __reserved4;
|
||||
uint16_t cs;
|
||||
uint16_t __reserved5;
|
||||
uint16_t ss;
|
||||
uint16_t __reserved6;
|
||||
uint16_t ds;
|
||||
uint16_t __reserved7;
|
||||
uint16_t fs;
|
||||
uint16_t __reserved8;
|
||||
uint16_t gs;
|
||||
uint16_t __reserved9;
|
||||
uint16_t ldtr;
|
||||
uint16_t __reserved10;
|
||||
uint16_t __reserved11;
|
||||
uint16_t iopb;
|
||||
uint32_t ssp;
|
||||
};
|
||||
static_assert(sizeof(TaskStateSegment) == 108);
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
union SegmentDescriptor
|
||||
{
|
||||
|
@ -38,20 +88,20 @@ namespace Kernel
|
|||
uint8_t limit2 : 4;
|
||||
uint8_t flags : 4;
|
||||
uint8_t base3;
|
||||
} __attribute__((packed));
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t low;
|
||||
uint32_t high;
|
||||
} __attribute__((packed));
|
||||
|
||||
} __attribute__((packed));
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(SegmentDescriptor) == 8);
|
||||
|
||||
struct GDTR
|
||||
{
|
||||
uint16_t size;
|
||||
uint64_t address;
|
||||
uintptr_t address;
|
||||
} __attribute__((packed));
|
||||
|
||||
class GDT
|
||||
|
@ -60,7 +110,7 @@ namespace Kernel
|
|||
BAN_NON_MOVABLE(GDT);
|
||||
|
||||
public:
|
||||
static GDT* create();
|
||||
static GDT* create(void* processor);
|
||||
void load() { flush_gdt(); flush_tss(); }
|
||||
|
||||
static constexpr inline bool is_user_segment(uint8_t segment)
|
||||
|
@ -68,9 +118,13 @@ namespace Kernel
|
|||
return (segment & 3) == 3;
|
||||
}
|
||||
|
||||
void set_tss_stack(uintptr_t rsp)
|
||||
void set_tss_stack(uintptr_t sp)
|
||||
{
|
||||
m_tss.rsp0 = rsp;
|
||||
#if ARCH(x86_64)
|
||||
m_tss.rsp0 = sp;
|
||||
#elif ARCH(i686)
|
||||
m_tss.esp0 = sp;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -86,15 +140,21 @@ namespace Kernel
|
|||
|
||||
void flush_tss()
|
||||
{
|
||||
asm volatile("ltr %0" :: "rm"((uint16_t)0x28) : "memory");
|
||||
asm volatile("ltr %0" :: "rm"(m_tss_offset) : "memory");
|
||||
}
|
||||
|
||||
private:
|
||||
#if ARCH(x86_64)
|
||||
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
|
||||
static constexpr uint16_t m_tss_offset = 0x28;
|
||||
#elif ARCH(i686)
|
||||
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, tss
|
||||
static constexpr uint16_t m_tss_offset = 0x30;
|
||||
#endif
|
||||
TaskStateSegment m_tss;
|
||||
const GDTR m_gdtr {
|
||||
.size = m_gdt.size() * sizeof(SegmentDescriptor) - 1,
|
||||
.address = reinterpret_cast<uint64_t>(m_gdt.data())
|
||||
.address = reinterpret_cast<uintptr_t>(m_gdt.data())
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <BAN/Array.h>
|
||||
#include <BAN/NoCopyMove.h>
|
||||
#include <kernel/Arch.h>
|
||||
#include <kernel/Interruptable.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
@ -12,21 +13,36 @@ constexpr uint8_t IRQ_IPI = 32;
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
#if ARCH(x86_64)
|
||||
struct GateDescriptor
|
||||
{
|
||||
uint16_t offset1;
|
||||
uint16_t offset0;
|
||||
uint16_t selector;
|
||||
uint8_t IST;
|
||||
uint8_t flags;
|
||||
uint16_t offset2;
|
||||
uint32_t offset3;
|
||||
uint16_t offset1;
|
||||
uint32_t offset2;
|
||||
uint32_t reserved;
|
||||
} __attribute__((packed));
|
||||
};
|
||||
static_assert(sizeof(GateDescriptor) == 16);
|
||||
#elif ARCH(i686)
|
||||
struct GateDescriptor
|
||||
{
|
||||
uint16_t offset0;
|
||||
uint16_t selector;
|
||||
uint8_t reserved;
|
||||
uint8_t flags;
|
||||
uint16_t offset1;
|
||||
};
|
||||
static_assert(sizeof(GateDescriptor) == 8);
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
struct IDTR
|
||||
{
|
||||
uint16_t size;
|
||||
uint64_t offset;
|
||||
uintptr_t offset;
|
||||
} __attribute__((packed));
|
||||
|
||||
class IDT
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace Kernel
|
|||
virtual bool is_in_service(uint8_t) = 0;
|
||||
|
||||
static void initialize(bool force_pic);
|
||||
static bool is_initialized();
|
||||
static InterruptController& get();
|
||||
|
||||
virtual void initialize_multiprocessor() = 0;
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
#include <kernel/GDT.h>
|
||||
#include <kernel/Processor.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
GDT* GDT::create([[maybe_unused]] void* processor)
|
||||
{
|
||||
auto* gdt = new GDT();
|
||||
ASSERT(gdt);
|
||||
|
||||
#if ARCH(x86_64)
|
||||
constexpr uint8_t code_flags = 0xA;
|
||||
constexpr uint8_t data_flags = 0xC;
|
||||
#elif ARCH(i686)
|
||||
constexpr uint8_t code_flags = 0xC;
|
||||
constexpr uint8_t data_flags = 0xC;
|
||||
#endif
|
||||
|
||||
gdt->write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
||||
gdt->write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, code_flags); // kernel code
|
||||
gdt->write_entry(0x10, 0x00000000, 0xFFFFF, 0x92, data_flags); // kernel data
|
||||
gdt->write_entry(0x18, 0x00000000, 0xFFFFF, 0xFA, code_flags); // user code
|
||||
gdt->write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, data_flags); // user data
|
||||
#if ARCH(i686)
|
||||
gdt->write_entry(0x28, reinterpret_cast<uint32_t>(processor), sizeof(Processor), 0x92, 0x4); // processor data
|
||||
#endif
|
||||
gdt->write_tss();
|
||||
|
||||
return gdt;
|
||||
}
|
||||
|
||||
void GDT::write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
||||
{
|
||||
ASSERT(offset % sizeof(SegmentDescriptor) == 0);
|
||||
uint8_t idx = offset / sizeof(SegmentDescriptor);
|
||||
|
||||
auto& desc = m_gdt[idx];
|
||||
desc.base1 = (base >> 0) & 0xFFFF;
|
||||
desc.base2 = (base >> 16) & 0xFF;
|
||||
desc.base3 = (base >> 24) & 0xFF;
|
||||
|
||||
desc.limit1 = (limit >> 0) & 0xFFFF;
|
||||
desc.limit2 = (limit >> 16) & 0x0F;
|
||||
|
||||
desc.access = access & 0xFF;
|
||||
|
||||
desc.flags = flags & 0x0F;
|
||||
}
|
||||
|
||||
void GDT::write_tss()
|
||||
{
|
||||
memset(&m_tss, 0x00, sizeof(TaskStateSegment));
|
||||
m_tss.iopb = sizeof(TaskStateSegment);
|
||||
|
||||
uintptr_t base = reinterpret_cast<uintptr_t>(&m_tss);
|
||||
|
||||
write_entry(m_tss_offset, (uint32_t)base, sizeof(TaskStateSegment), 0x89, 0x0);
|
||||
|
||||
#if ARCH(x86_64)
|
||||
auto& desc = m_gdt[(m_tss_offset + 8) / sizeof(SegmentDescriptor)];
|
||||
desc.low = base >> 32;
|
||||
desc.high = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
|
@ -141,21 +141,16 @@ namespace Kernel
|
|||
"Unkown Exception 0x1F",
|
||||
};
|
||||
|
||||
extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, InterruptStack& interrupt_stack, const Registers* regs)
|
||||
extern "C" void cpp_isr_handler(uint32_t isr, uint32_t error, InterruptStack& interrupt_stack, const Registers* regs)
|
||||
{
|
||||
if (g_paniced)
|
||||
{
|
||||
dprintln("Processor {} halted", Processor::current_id());
|
||||
InterruptController::get().broadcast_ipi();
|
||||
if (InterruptController::is_initialized())
|
||||
InterruptController::get().broadcast_ipi();
|
||||
asm volatile("cli; 1: hlt; jmp 1b");
|
||||
}
|
||||
|
||||
#if __enable_sse
|
||||
bool from_userspace = (interrupt_stack.cs & 0b11) == 0b11;
|
||||
if (from_userspace)
|
||||
Thread::current().save_sse();
|
||||
#endif
|
||||
|
||||
pid_t tid = Scheduler::current_tid();
|
||||
pid_t pid = tid ? Process::current().pid() : 0;
|
||||
|
||||
|
@ -209,11 +204,19 @@ namespace Kernel
|
|||
#if __enable_sse
|
||||
else if (isr == ISR::DeviceNotAvailable)
|
||||
{
|
||||
#if ARCH(x86_64)
|
||||
asm volatile(
|
||||
"movq %cr0, %rax;"
|
||||
"andq $~(1 << 3), %rax;"
|
||||
"movq %rax, %cr0;"
|
||||
);
|
||||
#elif ARCH(i686)
|
||||
asm volatile(
|
||||
"movl %cr0, %eax;"
|
||||
"andl $~(1 << 3), %eax;"
|
||||
"movl %eax, %cr0;"
|
||||
);
|
||||
#endif
|
||||
if (auto* current = &Thread::current(); current != Thread::sse_thread())
|
||||
{
|
||||
if (auto* sse = Thread::sse_thread())
|
||||
|
@ -302,7 +305,8 @@ done:
|
|||
if (g_paniced)
|
||||
{
|
||||
dprintln("Processor {} halted", Processor::current_id());
|
||||
InterruptController::get().broadcast_ipi();
|
||||
if (InterruptController::is_initialized())
|
||||
InterruptController::get().broadcast_ipi();
|
||||
asm volatile("cli; 1: hlt; jmp 1b");
|
||||
}
|
||||
|
||||
|
@ -332,14 +336,17 @@ done:
|
|||
|
||||
void IDT::register_interrupt_handler(uint8_t index, void (*handler)())
|
||||
{
|
||||
auto& descriptor = m_idt[index];
|
||||
descriptor.offset1 = (uint16_t)((uint64_t)handler >> 0);
|
||||
descriptor.offset2 = (uint16_t)((uint64_t)handler >> 16);
|
||||
descriptor.offset3 = (uint32_t)((uint64_t)handler >> 32);
|
||||
auto& desc = m_idt[index];
|
||||
memset(&desc, 0, sizeof(GateDescriptor));
|
||||
|
||||
descriptor.selector = 0x08;
|
||||
descriptor.IST = 0;
|
||||
descriptor.flags = 0x8E;
|
||||
desc.offset0 = (uint16_t)((uintptr_t)handler >> 0);
|
||||
desc.offset1 = (uint16_t)((uintptr_t)handler >> 16);
|
||||
#if ARCH(x86_64)
|
||||
desc.offset2 = (uint32_t)((uintptr_t)handler >> 32);
|
||||
#endif
|
||||
|
||||
desc.selector = 0x08;
|
||||
desc.flags = 0x8E;
|
||||
}
|
||||
|
||||
void IDT::register_syscall_handler(uint8_t index, void (*handler)())
|
|
@ -40,6 +40,11 @@ namespace Kernel
|
|||
s_instance->m_using_apic = false;
|
||||
}
|
||||
|
||||
bool InterruptController::is_initialized()
|
||||
{
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
void InterruptController::enter_acpi_mode()
|
||||
{
|
||||
#if ARCH(x86_64)
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace Kernel
|
|||
processor.m_stack = kmalloc(s_stack_size, 4096, true);
|
||||
ASSERT(processor.m_stack);
|
||||
|
||||
processor.m_gdt = GDT::create();
|
||||
processor.m_gdt = GDT::create(&processor);
|
||||
ASSERT(processor.m_gdt);
|
||||
|
||||
processor.m_idt = IDT::create();
|
||||
|
@ -52,14 +52,19 @@ namespace Kernel
|
|||
auto id = read_processor_id();
|
||||
auto& processor = s_processors[id];
|
||||
|
||||
ASSERT(processor.m_gdt);
|
||||
processor.m_gdt->load();
|
||||
|
||||
// initialize GS
|
||||
#if ARCH(x86_64)
|
||||
// set gs base to pointer to this processor
|
||||
uint64_t ptr = reinterpret_cast<uint64_t>(&processor);
|
||||
uint32_t ptr_hi = ptr >> 32;
|
||||
uint32_t ptr_lo = ptr & 0xFFFFFFFF;
|
||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_GS_BASE));
|
||||
|
||||
ASSERT(processor.m_gdt);
|
||||
processor.gdt().load();
|
||||
#elif ARCH(i686)
|
||||
asm volatile("movw $0x28, %%ax; movw %%ax, %%gs" ::: "ax");
|
||||
#endif
|
||||
|
||||
ASSERT(processor.m_idt);
|
||||
processor.idt().load();
|
||||
|
|
Loading…
Reference in New Issue