forked from Bananymous/banan-os
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/FileSystem.cpp
|
||||||
kernel/FS/TmpFS/Inode.cpp
|
kernel/FS/TmpFS/Inode.cpp
|
||||||
kernel/FS/VirtualFileSystem.cpp
|
kernel/FS/VirtualFileSystem.cpp
|
||||||
|
kernel/GDT.cpp
|
||||||
|
kernel/IDT.cpp
|
||||||
kernel/Input/KeyboardLayout.cpp
|
kernel/Input/KeyboardLayout.cpp
|
||||||
kernel/Input/KeyEvent.cpp
|
kernel/Input/KeyEvent.cpp
|
||||||
kernel/Input/PS2/Controller.cpp
|
kernel/Input/PS2/Controller.cpp
|
||||||
|
@ -105,8 +107,6 @@ if("${BANAN_ARCH}" STREQUAL "x86_64")
|
||||||
set(KERNEL_SOURCES
|
set(KERNEL_SOURCES
|
||||||
${KERNEL_SOURCES}
|
${KERNEL_SOURCES}
|
||||||
arch/x86_64/boot.S
|
arch/x86_64/boot.S
|
||||||
arch/x86_64/GDT.cpp
|
|
||||||
arch/x86_64/IDT.cpp
|
|
||||||
arch/x86_64/interrupts.S
|
arch/x86_64/interrupts.S
|
||||||
arch/x86_64/PageTable.cpp
|
arch/x86_64/PageTable.cpp
|
||||||
arch/x86_64/Signal.S
|
arch/x86_64/Signal.S
|
||||||
|
@ -124,8 +124,7 @@ elseif("${BANAN_ARCH}" STREQUAL "i686")
|
||||||
set(KERNEL_SOURCES
|
set(KERNEL_SOURCES
|
||||||
${KERNEL_SOURCES}
|
${KERNEL_SOURCES}
|
||||||
arch/i686/boot.S
|
arch/i686/boot.S
|
||||||
arch/i686/GDT.cpp
|
arch/i686/interrupts.S
|
||||||
arch/i686/IDT.cpp
|
|
||||||
arch/i686/PageTable.cpp
|
arch/i686/PageTable.cpp
|
||||||
arch/i686/Signal.S
|
arch/i686/Signal.S
|
||||||
arch/i686/Syscall.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/Array.h>
|
||||||
#include <BAN/NoCopyMove.h>
|
#include <BAN/NoCopyMove.h>
|
||||||
|
#include <kernel/Arch.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if ARCH(x86_64)
|
||||||
struct TaskStateSegment
|
struct TaskStateSegment
|
||||||
{
|
{
|
||||||
uint32_t reserved1;
|
uint32_t reserved1;
|
||||||
|
@ -26,6 +28,54 @@ namespace Kernel
|
||||||
uint16_t reserved4;
|
uint16_t reserved4;
|
||||||
uint16_t iopb;
|
uint16_t iopb;
|
||||||
} __attribute__((packed));
|
} __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
|
union SegmentDescriptor
|
||||||
{
|
{
|
||||||
|
@ -38,20 +88,20 @@ namespace Kernel
|
||||||
uint8_t limit2 : 4;
|
uint8_t limit2 : 4;
|
||||||
uint8_t flags : 4;
|
uint8_t flags : 4;
|
||||||
uint8_t base3;
|
uint8_t base3;
|
||||||
} __attribute__((packed));
|
};
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint32_t low;
|
uint32_t low;
|
||||||
uint32_t high;
|
uint32_t high;
|
||||||
} __attribute__((packed));
|
};
|
||||||
|
};
|
||||||
} __attribute__((packed));
|
static_assert(sizeof(SegmentDescriptor) == 8);
|
||||||
|
|
||||||
struct GDTR
|
struct GDTR
|
||||||
{
|
{
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint64_t address;
|
uintptr_t address;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
class GDT
|
class GDT
|
||||||
|
@ -60,7 +110,7 @@ namespace Kernel
|
||||||
BAN_NON_MOVABLE(GDT);
|
BAN_NON_MOVABLE(GDT);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static GDT* create();
|
static GDT* create(void* processor);
|
||||||
void load() { flush_gdt(); flush_tss(); }
|
void load() { flush_gdt(); flush_tss(); }
|
||||||
|
|
||||||
static constexpr inline bool is_user_segment(uint8_t segment)
|
static constexpr inline bool is_user_segment(uint8_t segment)
|
||||||
|
@ -68,9 +118,13 @@ namespace Kernel
|
||||||
return (segment & 3) == 3;
|
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:
|
private:
|
||||||
|
@ -86,15 +140,21 @@ namespace Kernel
|
||||||
|
|
||||||
void flush_tss()
|
void flush_tss()
|
||||||
{
|
{
|
||||||
asm volatile("ltr %0" :: "rm"((uint16_t)0x28) : "memory");
|
asm volatile("ltr %0" :: "rm"(m_tss_offset) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#if ARCH(x86_64)
|
||||||
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
|
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;
|
TaskStateSegment m_tss;
|
||||||
const GDTR m_gdtr {
|
const GDTR m_gdtr {
|
||||||
.size = m_gdt.size() * sizeof(SegmentDescriptor) - 1,
|
.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/Array.h>
|
||||||
#include <BAN/NoCopyMove.h>
|
#include <BAN/NoCopyMove.h>
|
||||||
|
#include <kernel/Arch.h>
|
||||||
#include <kernel/Interruptable.h>
|
#include <kernel/Interruptable.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -12,21 +13,36 @@ constexpr uint8_t IRQ_IPI = 32;
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if ARCH(x86_64)
|
||||||
struct GateDescriptor
|
struct GateDescriptor
|
||||||
{
|
{
|
||||||
uint16_t offset1;
|
uint16_t offset0;
|
||||||
uint16_t selector;
|
uint16_t selector;
|
||||||
uint8_t IST;
|
uint8_t IST;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint16_t offset2;
|
uint16_t offset1;
|
||||||
uint32_t offset3;
|
uint32_t offset2;
|
||||||
uint32_t reserved;
|
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
|
struct IDTR
|
||||||
{
|
{
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint64_t offset;
|
uintptr_t offset;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
class IDT
|
class IDT
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Kernel
|
||||||
virtual bool is_in_service(uint8_t) = 0;
|
virtual bool is_in_service(uint8_t) = 0;
|
||||||
|
|
||||||
static void initialize(bool force_pic);
|
static void initialize(bool force_pic);
|
||||||
|
static bool is_initialized();
|
||||||
static InterruptController& get();
|
static InterruptController& get();
|
||||||
|
|
||||||
virtual void initialize_multiprocessor() = 0;
|
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",
|
"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)
|
if (g_paniced)
|
||||||
{
|
{
|
||||||
dprintln("Processor {} halted", Processor::current_id());
|
dprintln("Processor {} halted", Processor::current_id());
|
||||||
|
if (InterruptController::is_initialized())
|
||||||
InterruptController::get().broadcast_ipi();
|
InterruptController::get().broadcast_ipi();
|
||||||
asm volatile("cli; 1: hlt; jmp 1b");
|
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 tid = Scheduler::current_tid();
|
||||||
pid_t pid = tid ? Process::current().pid() : 0;
|
pid_t pid = tid ? Process::current().pid() : 0;
|
||||||
|
|
||||||
|
@ -209,11 +204,19 @@ namespace Kernel
|
||||||
#if __enable_sse
|
#if __enable_sse
|
||||||
else if (isr == ISR::DeviceNotAvailable)
|
else if (isr == ISR::DeviceNotAvailable)
|
||||||
{
|
{
|
||||||
|
#if ARCH(x86_64)
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"movq %cr0, %rax;"
|
"movq %cr0, %rax;"
|
||||||
"andq $~(1 << 3), %rax;"
|
"andq $~(1 << 3), %rax;"
|
||||||
"movq %rax, %cr0;"
|
"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* current = &Thread::current(); current != Thread::sse_thread())
|
||||||
{
|
{
|
||||||
if (auto* sse = Thread::sse_thread())
|
if (auto* sse = Thread::sse_thread())
|
||||||
|
@ -302,6 +305,7 @@ done:
|
||||||
if (g_paniced)
|
if (g_paniced)
|
||||||
{
|
{
|
||||||
dprintln("Processor {} halted", Processor::current_id());
|
dprintln("Processor {} halted", Processor::current_id());
|
||||||
|
if (InterruptController::is_initialized())
|
||||||
InterruptController::get().broadcast_ipi();
|
InterruptController::get().broadcast_ipi();
|
||||||
asm volatile("cli; 1: hlt; jmp 1b");
|
asm volatile("cli; 1: hlt; jmp 1b");
|
||||||
}
|
}
|
||||||
|
@ -332,14 +336,17 @@ done:
|
||||||
|
|
||||||
void IDT::register_interrupt_handler(uint8_t index, void (*handler)())
|
void IDT::register_interrupt_handler(uint8_t index, void (*handler)())
|
||||||
{
|
{
|
||||||
auto& descriptor = m_idt[index];
|
auto& desc = m_idt[index];
|
||||||
descriptor.offset1 = (uint16_t)((uint64_t)handler >> 0);
|
memset(&desc, 0, sizeof(GateDescriptor));
|
||||||
descriptor.offset2 = (uint16_t)((uint64_t)handler >> 16);
|
|
||||||
descriptor.offset3 = (uint32_t)((uint64_t)handler >> 32);
|
|
||||||
|
|
||||||
descriptor.selector = 0x08;
|
desc.offset0 = (uint16_t)((uintptr_t)handler >> 0);
|
||||||
descriptor.IST = 0;
|
desc.offset1 = (uint16_t)((uintptr_t)handler >> 16);
|
||||||
descriptor.flags = 0x8E;
|
#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)())
|
void IDT::register_syscall_handler(uint8_t index, void (*handler)())
|
|
@ -40,6 +40,11 @@ namespace Kernel
|
||||||
s_instance->m_using_apic = false;
|
s_instance->m_using_apic = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InterruptController::is_initialized()
|
||||||
|
{
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
void InterruptController::enter_acpi_mode()
|
void InterruptController::enter_acpi_mode()
|
||||||
{
|
{
|
||||||
#if ARCH(x86_64)
|
#if ARCH(x86_64)
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Kernel
|
||||||
processor.m_stack = kmalloc(s_stack_size, 4096, true);
|
processor.m_stack = kmalloc(s_stack_size, 4096, true);
|
||||||
ASSERT(processor.m_stack);
|
ASSERT(processor.m_stack);
|
||||||
|
|
||||||
processor.m_gdt = GDT::create();
|
processor.m_gdt = GDT::create(&processor);
|
||||||
ASSERT(processor.m_gdt);
|
ASSERT(processor.m_gdt);
|
||||||
|
|
||||||
processor.m_idt = IDT::create();
|
processor.m_idt = IDT::create();
|
||||||
|
@ -52,14 +52,19 @@ namespace Kernel
|
||||||
auto id = read_processor_id();
|
auto id = read_processor_id();
|
||||||
auto& processor = s_processors[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
|
// set gs base to pointer to this processor
|
||||||
uint64_t ptr = reinterpret_cast<uint64_t>(&processor);
|
uint64_t ptr = reinterpret_cast<uint64_t>(&processor);
|
||||||
uint32_t ptr_hi = ptr >> 32;
|
uint32_t ptr_hi = ptr >> 32;
|
||||||
uint32_t ptr_lo = ptr & 0xFFFFFFFF;
|
uint32_t ptr_lo = ptr & 0xFFFFFFFF;
|
||||||
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_GS_BASE));
|
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_GS_BASE));
|
||||||
|
#elif ARCH(i686)
|
||||||
ASSERT(processor.m_gdt);
|
asm volatile("movw $0x28, %%ax; movw %%ax, %%gs" ::: "ax");
|
||||||
processor.gdt().load();
|
#endif
|
||||||
|
|
||||||
ASSERT(processor.m_idt);
|
ASSERT(processor.m_idt);
|
||||||
processor.idt().load();
|
processor.idt().load();
|
||||||
|
|
Loading…
Reference in New Issue