// 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 #include #include #include #include // 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); }