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:
2024-03-26 13:59:09 +02:00
parent af050cc729
commit 1943c3e7a1
12 changed files with 335 additions and 147 deletions

View File

@@ -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())
};
};

View File

@@ -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

View File

@@ -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;