Files
2026-10-27 09:28:31 +01:00

544 lines
16 KiB
C

// Kernel descriptor-table setup. This file owns GDT, IDT, and TSS initialization.
// GDT layout (matches segment selectors in ke_switch.asm / ke_syscall.asm):
// 0x00 null
// 0x08 ring-0 code (64-bit)
// 0x10 ring-0 data
// 0x18 ring-3 code (64-bit, DPL=3)
// 0x20 ring-3 data (DPL=3) - note: 0x1B/0x23 = 0x18|3 / 0x20|3
// 0x28 TSS low
// 0x30 TSS high.
#include <stdint.h>
#include <string.h>
#include <kernel/ke_idt.h>
#include <kernel/ke_cpu.h>
#include <kernel/ke_vectors.h>
// External assembly procedures.
extern void KeFlushGdt(void* pGdtr, uint16_t codeSel, uint16_t dataSel, uint16_t tssSel);
extern void KeFlushIdt(void* pIdtr);
extern void KeIrqStub0(void);
extern void KeIrqStub1(void);
extern void KeIrqStub2(void);
extern void KeIrqStub3(void);
extern void KeIrqStub4(void);
extern void KeIrqStub5(void);
extern void KeIrqStub6(void);
extern void KeIrqStub7(void);
extern void KeIrqStub8(void);
extern void KeIrqStub9(void);
extern void KeIrqStub10(void);
extern void KeIrqStub11(void);
extern void KeIrqStub12(void);
extern void KeIrqStub13(void);
extern void KeIrqStub14(void);
extern void KeIrqStub15(void);
extern void KeIrqStub16(void);
extern void KeIrqStub17(void);
extern void KeIrqStub18(void);
extern void KeIrqStub19(void);
extern void KeIrqStub20(void);
extern void KeIrqStub21(void);
extern void KeIrqStub22(void);
extern void KeIrqStub23(void);
extern void KeIrqStub24(void);
extern void KeIrqStub25(void);
extern void KeIrqStub26(void);
extern void KeIrqStub27(void);
extern void KeIrqStub28(void);
extern void KeIrqStub29(void);
extern void KeIrqStub30(void);
extern void KeIrqStub31(void);
extern void KeIrqStub32(void);
extern void KeIrqStub33(void);
extern void KeIrqStub34(void);
extern void KeIrqStub35(void);
extern void KeIrqStub36(void);
extern void KeIrqStub37(void);
extern void KeIrqStub38(void);
extern void KeIrqStub39(void);
extern void KeIrqStub40(void);
extern void KeIrqStub41(void);
extern void KeIrqStub42(void);
extern void KeIrqStub43(void);
extern void KeIrqStub44(void);
extern void KeIrqStub45(void);
extern void KeIrqStub46(void);
extern void KeIrqStub47(void);
extern void KeIrqStub48(void);
extern void KeIrqStub49(void);
extern void KeIrqStub50(void);
extern void KeIrqStub51(void);
extern void KeIrqStub52(void);
extern void KeIrqStub53(void);
extern void KeIrqStub54(void);
extern void KeIrqStub55(void);
extern void KeIrqStub56(void);
extern void KeIrqStub57(void);
extern void KeIrqStub58(void);
extern void KeIrqStub59(void);
extern void KeIrqStub60(void);
extern void KeIrqStub61(void);
extern void KeIrqStub62(void);
extern void KeIrqStub63(void);
extern void KeIrqStub64(void);
extern void KeIrqStub65(void);
extern void KeIrqStub66(void);
extern void KeIrqStub67(void);
extern void KeIrqStub68(void);
extern void KeIrqStub69(void);
extern void KeIrqStub70(void);
extern void KeIrqStub71(void);
extern void KeIrqStub72(void);
extern void KeIrqStub73(void);
extern void KeIrqStub74(void);
extern void KeIrqStub75(void);
extern void KeIrqStub76(void);
extern void KeIrqStub77(void);
extern void KeIrqStub78(void);
extern void KeIrqStub79(void);
extern void KeIrqStub80(void);
extern void KeIrqStub81(void);
extern void KeIrqStub82(void);
extern void KeIrqStub83(void);
extern void KeIrqStub84(void);
extern void KeIrqStub85(void);
extern void KeIrqStub86(void);
extern void KeIrqStub87(void);
extern void KeIrqStub88(void);
extern void KeIrqStub89(void);
extern void KeIrqStub90(void);
extern void KeIrqStub91(void);
extern void KeIrqStub92(void);
extern void KeIrqStub93(void);
extern void KeIrqStub94(void);
extern void KeIrqStub95(void);
extern void KeIrqStub96(void);
extern void KeIrqStub97(void);
extern void KeIrqStub98(void);
extern void KeIrqStub99(void);
extern void KeIrqStub100(void);
extern void KeIrqStub101(void);
extern void KeIrqStub102(void);
extern void KeIrqStub103(void);
extern void KeIrqStub104(void);
extern void KeIrqStub105(void);
extern void KeIrqStub106(void);
extern void KeIrqStub107(void);
extern void KeIrqStub108(void);
extern void KeIrqStub109(void);
extern void KeIrqStub110(void);
extern void KeIrqStub111(void);
extern void KeIrqStub112(void);
extern void KeIrqStub113(void);
extern void KeIrqStub114(void);
extern void KeIrqStub115(void);
extern void KeIrqStub116(void);
extern void KeIrqStub117(void);
extern void KeIrqStub118(void);
extern void KeIrqStub119(void);
extern void KeIrqStub120(void);
extern void KeIrqStub121(void);
extern void KeIrqStub122(void);
extern void KeIrqStub123(void);
extern void KeIrqStub124(void);
extern void KeIrqStub125(void);
extern void KeIrqStub126(void);
extern void KeIrqStub127(void);
extern void KeIrqStub128(void);
extern void KeIrqStub129(void);
extern void KeIrqStub130(void);
extern void KeIrqStub131(void);
extern void KeIrqStub132(void);
extern void KeIrqStub133(void);
extern void KeIrqStub134(void);
extern void KeIrqStub135(void);
extern void KeIrqStub136(void);
extern void KeIrqStub137(void);
extern void KeIrqStub138(void);
extern void KeIrqStub139(void);
extern void KeIrqStub140(void);
extern void KeIrqStub141(void);
extern void KeIrqStub142(void);
extern void KeIrqStub143(void);
extern void KeIrqStub144(void);
extern void KeIrqStub145(void);
extern void KeIrqStub146(void);
extern void KeIrqStub147(void);
extern void KeIrqStub148(void);
extern void KeIrqStub149(void);
extern void KeIrqStub150(void);
extern void KeIrqStub151(void);
extern void KeIrqStub152(void);
extern void KeIrqStub153(void);
extern void KeIrqStub154(void);
extern void KeIrqStub155(void);
extern void KeIrqStub156(void);
extern void KeIrqStub157(void);
extern void KeIrqStub158(void);
extern void KeIrqStub159(void);
extern void KeRescheduleIpiStub(void);
extern void KeLocalTimerStub(void);
extern void KeSpuriousStub(void);
extern void KeFaultDB(void);
extern void KeFaultNMI(void);
extern void KeNmiIpiStub(void);
extern void KeFaultBP(void);
extern void KeFaultOF(void);
extern void KeFaultBR(void);
extern void KeFaultUD(void);
extern void KeFaultNM(void);
extern void KeFaultDF(void);
extern void KeFaultCSO(void);
extern void KeFaultTS(void);
extern void KeFaultNP(void);
extern void KeFaultSS(void);
extern void KeFaultRSV15(void);
extern void KeFaultMF(void);
extern void KeFaultAC(void);
extern void KeFaultMC(void);
extern void KeFaultXM(void);
extern void KeFaultVE(void);
extern void KeFaultCP(void);
extern void KeFaultRSV22(void);
extern void KeFaultRSV23(void);
extern void KeFaultRSV24(void);
extern void KeFaultRSV25(void);
extern void KeFaultRSV26(void);
extern void KeFaultRSV27(void);
extern void KeFaultHV(void);
extern void KeFaultVC(void);
extern void KeFaultSX(void);
extern void KeFaultRSV31(void);
#define NUM_DEVICE_VECTORS (KE_VECTOR_DEVICE_LAST - KE_VECTOR_DEVICE_FIRST + 1u)
// GDT.
static void KiGdtSetEntry(uint64_t* gdt, int idx, uint32_t base, uint32_t limit,
uint8_t access, uint8_t flags) {
gdt[idx] =
((uint64_t)(limit & 0xFFFF)) |
((uint64_t)(base & 0xFFFFFF) << 16) |
((uint64_t)access << 40) |
((uint64_t)(limit >> 16 & 0xF)<< 48) |
((uint64_t)(flags & 0xF) << 52) |
((uint64_t)(base >> 24 & 0xFF)<< 56);
}
// Implements the gdt Set Tss operation.
static void KiGdtSetTss(uint64_t* gdt, int idx, uintptr_t base, uint32_t limit) {
// TSS descriptor is 16 bytes (two GDT slots).
gdt[idx] = 0;
gdt[idx+1] = 0;
gdt[idx] =
((uint64_t)(limit & 0xFFFF)) |
((uint64_t)(base & 0xFFFFFF) << 16) |
(0x89ULL << 40) | // P=1,DPL=0,type=TSS64 avail
((uint64_t)((limit>>16)&0xF) << 48) |
((uint64_t)(base>>24 & 0xFF) << 56);
gdt[idx+1] = (base >> 32);
}
// Initializes gdt For Cpu.
void KeInitializeGdtForCpu(KCPU* cpu) {
if (!cpu) return;
TSS64* tss = &cpu->Tss;
uint64_t* gdt = cpu->Gdt;
memset(gdt, 0, sizeof(cpu->Gdt));
// 0x00: Null.
KiGdtSetEntry(gdt, 0, 0, 0, 0, 0);
// 0x08: Ring-0 Code (Access 0x9A, Flags 0xA for 64-bit).
KiGdtSetEntry(gdt, 1, 0, 0xFFFFF, 0x9A, 0xA);
// 0x10: Ring-0 Data.
KiGdtSetEntry(gdt, 2, 0, 0xFFFFF, 0x92, 0xC);
// 0x18: Ring-3 Code.
KiGdtSetEntry(gdt, 3, 0, 0xFFFFF, 0xFA, 0xA);
// 0x20: Ring-3 Data.
KiGdtSetEntry(gdt, 4, 0, 0xFFFFF, 0xF2, 0xC);
// 0x28: CPU-local TSS (occupies slots 0x28 and 0x30).
tss->IoMapBase = sizeof(TSS64);
if (!tss->RSP0)
tss->RSP0 = cpu->KernelStackTop;
KiGdtSetTss(gdt, 5, (uintptr_t)tss, sizeof(TSS64) - 1);
cpu->Gdtr.Limit = sizeof(cpu->Gdt) - 1;
cpu->Gdtr.Base = (uint64_t)cpu->Gdt;
}
// Loads gdt For Current Cpu.
void KeLoadGdtForCurrentCpu(KCPU* cpu) {
if (!cpu) cpu = KeGetCurrentCpu();
KeFlushGdt(&cpu->Gdtr, 0x08, 0x10, 0x28);
// Reloading GS as a segment register during GDT reload can disturb the
// hidden GS base. Reinstall the kernel per-CPU base immediately after
// the descriptor reload so KeGetCurrentCpu() remains GS-backed.
KeLoadKernelGsBase(cpu);
}
// Initializes gdt.
void KeInitializeGdt(void) {
KCPU* cpu = KeGetCurrentCpu();
KeInitializeGdtForCpu(cpu);
KeLoadGdtForCurrentCpu(cpu);
}
// Updates current Tss Rsp0.
void KeSetCurrentTssRsp0(uintptr_t rsp0) {
TSS64* tss = KeGetCurrentTss();
if (tss)
tss->RSP0 = rsp0;
}
// IDT.
#define IDT_ENTRIES 256
#define KI_IDT_TYPE_INTERRUPT_GATE 0x8Eu
#define KI_IDT_TYPE_USER_INTERRUPT_GATE 0xEEu
#pragma pack(push, 1)
typedef struct {
uint16_t OffsetLow;
uint16_t Selector;
uint8_t Ist;
uint8_t TypeAttr;
uint16_t OffsetMid;
uint32_t OffsetHigh;
uint32_t MustBeZero;
} IDT_ENTRY;
#pragma pack(pop)
static IDT_ENTRY gIdt[IDT_ENTRIES];
#pragma pack(push, 1)
typedef struct { uint16_t Limit; uint64_t Base; } IDTR;
#pragma pack(pop)
static void KiIdtSetGate(int vec, uintptr_t handler,
uint8_t typeAttr, uint8_t ist) {
gIdt[vec].OffsetLow = (uint16_t)(handler & 0xFFFF);
gIdt[vec].Selector = 0x08; // ring-0 code segment
gIdt[vec].Ist = ist;
gIdt[vec].TypeAttr = typeAttr;
gIdt[vec].OffsetMid = (uint16_t)((handler >> 16) & 0xFFFF);
gIdt[vec].OffsetHigh = (uint32_t)((handler >> 32) & 0xFFFFFFFF);
gIdt[vec].MustBeZero = 0;
}
// Initializes idt.
void KeInitializeIdt(void) {
memset(gIdt, 0, sizeof(gIdt));
static void* faultStubs[32] = {
(void*)KeFaultDE, (void*)KeFaultDB, (void*)KeNmiIpiStub,
(void*)KeFaultBP, (void*)KeFaultOF, (void*)KeFaultBR,
(void*)KeFaultUD, (void*)KeFaultNM, (void*)KeFaultDF,
(void*)KeFaultCSO, (void*)KeFaultTS, (void*)KeFaultNP,
(void*)KeFaultSS, (void*)KeFaultGP, (void*)KeFaultPF,
(void*)KeFaultRSV15, (void*)KeFaultMF, (void*)KeFaultAC,
(void*)KeFaultMC, (void*)KeFaultXM, (void*)KeFaultVE,
(void*)KeFaultCP, (void*)KeFaultRSV22, (void*)KeFaultRSV23,
(void*)KeFaultRSV24, (void*)KeFaultRSV25, (void*)KeFaultRSV26,
(void*)KeFaultRSV27, (void*)KeFaultHV, (void*)KeFaultVC,
(void*)KeFaultSX, (void*)KeFaultRSV31,
};
for (int i = 0; i < 32; i++)
KiIdtSetGate(i, (uintptr_t)faultStubs[i], KI_IDT_TYPE_INTERRUPT_GATE, 0);
// User-mode INT3 must enter #BP, not fail the gate-DPL check and become #GP.
KiIdtSetGate(3, (uintptr_t)KeFaultBP, KI_IDT_TYPE_USER_INTERRUPT_GATE, 0);
KiIdtSetGate(KE_VECTOR_SYSCALL, (uintptr_t)KeSyscallEntry, KI_IDT_TYPE_USER_INTERRUPT_GATE, 0);
static void* irqStubs[NUM_DEVICE_VECTORS] = {
(void*)KeIrqStub0,
(void*)KeIrqStub1,
(void*)KeIrqStub2,
(void*)KeIrqStub3,
(void*)KeIrqStub4,
(void*)KeIrqStub5,
(void*)KeIrqStub6,
(void*)KeIrqStub7,
(void*)KeIrqStub8,
(void*)KeIrqStub9,
(void*)KeIrqStub10,
(void*)KeIrqStub11,
(void*)KeIrqStub12,
(void*)KeIrqStub13,
(void*)KeIrqStub14,
(void*)KeIrqStub15,
(void*)KeIrqStub16,
(void*)KeIrqStub17,
(void*)KeIrqStub18,
(void*)KeIrqStub19,
(void*)KeIrqStub20,
(void*)KeIrqStub21,
(void*)KeIrqStub22,
(void*)KeIrqStub23,
(void*)KeIrqStub24,
(void*)KeIrqStub25,
(void*)KeIrqStub26,
(void*)KeIrqStub27,
(void*)KeIrqStub28,
(void*)KeIrqStub29,
(void*)KeIrqStub30,
(void*)KeIrqStub31,
(void*)KeIrqStub32,
(void*)KeIrqStub33,
(void*)KeIrqStub34,
(void*)KeIrqStub35,
(void*)KeIrqStub36,
(void*)KeIrqStub37,
(void*)KeIrqStub38,
(void*)KeIrqStub39,
(void*)KeIrqStub40,
(void*)KeIrqStub41,
(void*)KeIrqStub42,
(void*)KeIrqStub43,
(void*)KeIrqStub44,
(void*)KeIrqStub45,
(void*)KeIrqStub46,
(void*)KeIrqStub47,
(void*)KeIrqStub48,
(void*)KeIrqStub49,
(void*)KeIrqStub50,
(void*)KeIrqStub51,
(void*)KeIrqStub52,
(void*)KeIrqStub53,
(void*)KeIrqStub54,
(void*)KeIrqStub55,
(void*)KeIrqStub56,
(void*)KeIrqStub57,
(void*)KeIrqStub58,
(void*)KeIrqStub59,
(void*)KeIrqStub60,
(void*)KeIrqStub61,
(void*)KeIrqStub62,
(void*)KeIrqStub63,
(void*)KeIrqStub64,
(void*)KeIrqStub65,
(void*)KeIrqStub66,
(void*)KeIrqStub67,
(void*)KeIrqStub68,
(void*)KeIrqStub69,
(void*)KeIrqStub70,
(void*)KeIrqStub71,
(void*)KeIrqStub72,
(void*)KeIrqStub73,
(void*)KeIrqStub74,
(void*)KeIrqStub75,
(void*)KeIrqStub76,
(void*)KeIrqStub77,
(void*)KeIrqStub78,
(void*)KeIrqStub79,
(void*)KeIrqStub80,
(void*)KeIrqStub81,
(void*)KeIrqStub82,
(void*)KeIrqStub83,
(void*)KeIrqStub84,
(void*)KeIrqStub85,
(void*)KeIrqStub86,
(void*)KeIrqStub87,
(void*)KeIrqStub88,
(void*)KeIrqStub89,
(void*)KeIrqStub90,
(void*)KeIrqStub91,
(void*)KeIrqStub92,
(void*)KeIrqStub93,
(void*)KeIrqStub94,
(void*)KeIrqStub95,
(void*)KeIrqStub96,
(void*)KeIrqStub97,
(void*)KeIrqStub98,
(void*)KeIrqStub99,
(void*)KeIrqStub100,
(void*)KeIrqStub101,
(void*)KeIrqStub102,
(void*)KeIrqStub103,
(void*)KeIrqStub104,
(void*)KeIrqStub105,
(void*)KeIrqStub106,
(void*)KeIrqStub107,
(void*)KeIrqStub108,
(void*)KeIrqStub109,
(void*)KeIrqStub110,
(void*)KeIrqStub111,
(void*)KeIrqStub112,
(void*)KeIrqStub113,
(void*)KeIrqStub114,
(void*)KeIrqStub115,
(void*)KeIrqStub116,
(void*)KeIrqStub117,
(void*)KeIrqStub118,
(void*)KeIrqStub119,
(void*)KeIrqStub120,
(void*)KeIrqStub121,
(void*)KeIrqStub122,
(void*)KeIrqStub123,
(void*)KeIrqStub124,
(void*)KeIrqStub125,
(void*)KeIrqStub126,
(void*)KeIrqStub127,
(void*)KeIrqStub128,
(void*)KeIrqStub129,
(void*)KeIrqStub130,
(void*)KeIrqStub131,
(void*)KeIrqStub132,
(void*)KeIrqStub133,
(void*)KeIrqStub134,
(void*)KeIrqStub135,
(void*)KeIrqStub136,
(void*)KeIrqStub137,
(void*)KeIrqStub138,
(void*)KeIrqStub139,
(void*)KeIrqStub140,
(void*)KeIrqStub141,
(void*)KeIrqStub142,
(void*)KeIrqStub143,
(void*)KeIrqStub144,
(void*)KeIrqStub145,
(void*)KeIrqStub146,
(void*)KeIrqStub147,
(void*)KeIrqStub148,
(void*)KeIrqStub149,
(void*)KeIrqStub150,
(void*)KeIrqStub151,
(void*)KeIrqStub152,
(void*)KeIrqStub153,
(void*)KeIrqStub154,
(void*)KeIrqStub155,
(void*)KeIrqStub156,
(void*)KeIrqStub157,
(void*)KeIrqStub158,
(void*)KeIrqStub159,
};
for (uint32_t i = 0; i < NUM_DEVICE_VECTORS; i++)
KiIdtSetGate(KE_VECTOR_DEVICE_FIRST + i, (uintptr_t)irqStubs[i],
KI_IDT_TYPE_INTERRUPT_GATE, 0);
KiIdtSetGate(KE_VECTOR_CPU_TIMER, (uintptr_t)KeLocalTimerStub,
KI_IDT_TYPE_INTERRUPT_GATE, 0);
KiIdtSetGate(KE_VECTOR_RESCHEDULE_IPI, (uintptr_t)KeRescheduleIpiStub,
KI_IDT_TYPE_INTERRUPT_GATE, 0);
KiIdtSetGate(KE_VECTOR_SPURIOUS, (uintptr_t)KeSpuriousStub,
KI_IDT_TYPE_INTERRUPT_GATE, 0);
KeLoadIdtForCurrentCpu();
}
// Loads idt For Current Cpu.
void KeLoadIdtForCurrentCpu(void) {
IDTR idtr = { sizeof(gIdt) - 1, (uint64_t)gIdt };
KeFlushIdt(&idtr);
}