From d527121883ff3de66b57aa35a7722fb13fe2ed6f Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 17 May 2023 03:28:57 +0300 Subject: [PATCH] Add implementation for GDT & IDT on x32 and QoL fixes --- ...AdvancedConfigurationAndPowerInterface.cpp | 9 +- .../amd64/cpu/GlobalDescriptorTable.cpp | 100 ++- Architecture/amd64/cpu/gdt.hpp | 242 +++--- .../i386/cpu/GlobalDescriptorTable.cpp | 272 +++++-- .../i386/cpu/InterruptDescriptorTable.cpp | 727 ++++++++++++++++++ Architecture/i386/cpu/gdt.hpp | 246 +++--- Architecture/i386/cpu/idt.hpp | 42 + Core/Crash/CrashHandler.cpp | 2 +- Core/Debugger.cpp | 2 +- Core/Driver/Driver.cpp | 3 - Core/InterruptsManager.cpp | 17 +- Core/Memory/ReserveEssentials.cpp | 5 + Core/Symbols.cpp | 4 + Core/SystemManagementBIOS.cpp | 4 +- Core/UndefinedBehaviorSanitization.c | 179 +---- ...iversalAsynchronousReceiverTransmitter.cpp | 19 +- Kernel.cpp | 1 - KernelThread.cpp | 2 +- Network/DynamicHostConfigurationProtocol.cpp | 4 +- Network/InternetProtocol.cpp | 2 +- Tasking/Task.cpp | 18 +- Tests/MemoryAllocation.cpp | 2 +- include/cpu.hpp | 84 +- 23 files changed, 1529 insertions(+), 457 deletions(-) create mode 100644 Architecture/i386/cpu/InterruptDescriptorTable.cpp diff --git a/Architecture/amd64/AdvancedConfigurationAndPowerInterface.cpp b/Architecture/amd64/AdvancedConfigurationAndPowerInterface.cpp index 2d6499a..046f864 100644 --- a/Architecture/amd64/AdvancedConfigurationAndPowerInterface.cpp +++ b/Architecture/amd64/AdvancedConfigurationAndPowerInterface.cpp @@ -22,14 +22,15 @@ #include "../../kernel.h" -#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" - namespace ACPI { - void *ACPI::FindTable(ACPI::ACPIHeader *ACPIHeader, char *Signature) + __no_sanitize("alignment") void *ACPI::FindTable(ACPI::ACPIHeader *ACPIHeader, char *Signature) { for (uint64_t t = 0; t < ((ACPIHeader->Length - sizeof(ACPI::ACPIHeader)) / (XSDTSupported ? 8 : 4)); t++) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" + // TODO: Should I be concerned about unaligned memory access? ACPI::ACPIHeader *SDTHdr = nullptr; if (XSDTSupported) @@ -37,6 +38,8 @@ namespace ACPI else SDTHdr = (ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 4))); +#pragma GCC diagnostic pop + for (int i = 0; i < 4; i++) { if (SDTHdr->Signature[i] != Signature[i]) diff --git a/Architecture/amd64/cpu/GlobalDescriptorTable.cpp b/Architecture/amd64/cpu/GlobalDescriptorTable.cpp index 5dc43de..b3cac84 100644 --- a/Architecture/amd64/cpu/GlobalDescriptorTable.cpp +++ b/Architecture/amd64/cpu/GlobalDescriptorTable.cpp @@ -27,17 +27,18 @@ namespace GlobalDescriptorTable static GlobalDescriptorTableEntries GDTEntriesTemplate = { .Null = { - .Length = 0x0, + .Limit0 = 0x0, .BaseLow = 0x0, .BaseMiddle = 0x0, .Access = {.Raw = 0x0}, + // .Limit1 = 0x0, .Flags = {.Raw = 0x0}, .BaseHigh = 0x0, }, .Code = { - .Length = 0x0, + .Limit0 = 0xFFFF, .BaseLow = 0x0, .BaseMiddle = 0x0, .Access = { @@ -49,15 +50,20 @@ namespace GlobalDescriptorTable .DPL = 0, .P = 1, }, + // .Limit1 = 0xF, .Flags = { - .Unknown = 0x0, + .Reserved = 0xF, /* Workaround for Limit1 */ + + .AVL = 0, .L = 1, + .DB = 0, + .G = 1, }, .BaseHigh = 0x0, }, .Data = { - .Length = 0x0, + .Limit0 = 0xFFFF, .BaseLow = 0x0, .BaseMiddle = 0x0, .Access = { @@ -69,12 +75,20 @@ namespace GlobalDescriptorTable .DPL = 0, .P = 1, }, - .Flags = {.Raw = 0x0}, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ + + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, .BaseHigh = 0x0, }, .UserData = { - .Length = 0x0, + .Limit0 = 0xFFFF, .BaseLow = 0x0, .BaseMiddle = 0x0, .Access = { @@ -86,14 +100,20 @@ namespace GlobalDescriptorTable .DPL = 3, .P = 1, }, + // .Limit1 = 0xF, .Flags = { - .Raw = 0x0, + .Reserved = 0xF, /* Workaround for Limit1 */ + + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, }, .BaseHigh = 0x0, }, .UserCode = { - .Length = 0x0, + .Limit0 = 0xFFFF, .BaseLow = 0x0, .BaseMiddle = 0x0, .Access = { @@ -105,9 +125,14 @@ namespace GlobalDescriptorTable .DPL = 3, .P = 1, }, + // .Limit1 = 0xF, .Flags = { - .Unknown = 0x0, + .Reserved = 0xF, /* Workaround for Limit1 */ + + .AVL = 0, .L = 1, + .DB = 0, + .G = 1, }, .BaseHigh = 0x0, }, @@ -135,10 +160,47 @@ namespace GlobalDescriptorTable memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries)); gdt[Core] = {.Length = sizeof(GlobalDescriptorTableEntries) - 1, .Entries = &GDTEntries[Core]}; - debug("Kernel: Code Access: %ld; Data Access: %ld", GDTEntries[Core].Code.Access.Raw, GDTEntries[Core].Data.Access.Raw); - debug("Kernel: Code Flags: %ld; Data Flags: %ld", GDTEntries[Core].Code.Flags.Raw, GDTEntries[Core].Data.Flags.Raw); - debug("User: Code Access: %ld; Data Access: %ld", GDTEntries[Core].UserCode.Access.Raw, GDTEntries[Core].UserData.Access.Raw); - debug("User: Code Flags: %ld; Data Flags: %ld", GDTEntries[Core].UserCode.Flags.Raw, GDTEntries[Core].UserData.Flags.Raw); + debug("GDT: %#lx", &gdt[Core]); + debug("GDT KERNEL: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_KERNEL_CODE, + GDTEntries[Core].Code.Limit0, + GDTEntries[Core].Code.BaseLow, + GDTEntries[Core].Code.BaseMiddle, + GDTEntries[Core].Code.Access.Raw, + GDTEntries[Core].Code.Flags.Reserved, + GDTEntries[Core].Code.Flags.Raw & ~0xF, + GDTEntries[Core].Code.BaseHigh); + + debug("GDT KERNEL: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_KERNEL_DATA, + GDTEntries[Core].Data.Limit0, + GDTEntries[Core].Data.BaseLow, + GDTEntries[Core].Data.BaseMiddle, + GDTEntries[Core].Data.Access.Raw, + GDTEntries[Core].Data.Flags.Reserved, + GDTEntries[Core].Data.Flags.Raw & ~0xF, + GDTEntries[Core].Data.BaseHigh); + + debug("GDT USER: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_USER_CODE, + GDTEntries[Core].UserCode.Limit0, + GDTEntries[Core].UserCode.BaseLow, + GDTEntries[Core].UserCode.BaseMiddle, + GDTEntries[Core].UserCode.Access.Raw, + GDTEntries[Core].UserCode.Flags.Reserved, + GDTEntries[Core].UserCode.Flags.Raw & ~0xF, + GDTEntries[Core].UserCode.BaseHigh); + + debug("GDT USER: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_USER_DATA, + GDTEntries[Core].UserData.Limit0, + GDTEntries[Core].UserData.BaseLow, + GDTEntries[Core].UserData.BaseMiddle, + GDTEntries[Core].UserData.Access.Raw, + GDTEntries[Core].UserData.Flags.Reserved, + GDTEntries[Core].UserData.Flags.Raw & ~0xF, + GDTEntries[Core].UserData.BaseHigh); + CPU::x64::lgdt(&gdt[Core]); asmv("movq %%rsp, %%rax\n" @@ -162,16 +224,18 @@ namespace GlobalDescriptorTable uintptr_t Base = (uintptr_t)&tss[Core]; size_t Limit = Base + sizeof(TaskStateSegment); - gdt[Core].Entries->TaskStateSegment.Length = Limit & 0xFFFF; + gdt[Core].Entries->TaskStateSegment.Limit = Limit & 0xFFFF; gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF; gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF; gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 0xFF; gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); - gdt[Core].Entries->TaskStateSegment.Flags = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1}; + gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1}; gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF); tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment); tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE; + tss[Core].StackPointer[1] = 0x0; + tss[Core].StackPointer[2] = 0x0; for (size_t i = 0; i < sizeof(tss[Core].InterruptStackTable) / sizeof(tss[Core].InterruptStackTable[7]); i++) { @@ -183,12 +247,6 @@ namespace GlobalDescriptorTable } CPU::x64::ltr(GDT_TSS); - - debug("GDT_KERNEL_CODE: %#lx", GDT_KERNEL_CODE); - debug("GDT_KERNEL_DATA: %#lx", GDT_KERNEL_DATA); - debug("GDT_USER_CODE: %#lx", GDT_USER_CODE); - debug("GDT_USER_DATA: %#lx", GDT_USER_DATA); - debug("GDT_TSS: %#lx", GDT_TSS); debug("Global Descriptor Table initialized"); } diff --git a/Architecture/amd64/cpu/gdt.hpp b/Architecture/amd64/cpu/gdt.hpp index 7eec05d..84b0e8b 100644 --- a/Architecture/amd64/cpu/gdt.hpp +++ b/Architecture/amd64/cpu/gdt.hpp @@ -22,88 +22,66 @@ namespace GlobalDescriptorTable { - /** @brief The GDT Access Table - * @details For more information, see https://wiki.osdev.org/Global_Descriptor_Table - */ - union GlobalDescriptorTableAccess - { - struct - { - /** @brief Access bit. - * @note The CPU sets this bit to 1 when the segment is accessed. - */ - uint64_t A : 1; - - /** @brief Readable bit for code segments, writable bit for data segments. - * @details For code segments, this bit must be 1 for the segment to be readable. - * @details For data segments, this bit must be 1 for the segment to be writable. - */ - uint64_t RW : 1; - - /** @brief Direction bit for data segments, conforming bit for code segments. - * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). - * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. - */ - uint64_t DC : 1; - - /** @brief Executable bit. - * @details This bit must be 1 for code-segment descriptors. - * @details This bit must be 0 for data-segment and system descriptors. - */ - uint64_t E : 1; - - /** @brief Descriptor type. - * @details This bit must be 0 for system descriptors. - * @details This bit must be 1 for code or data segment descriptor. - */ - uint64_t S : 1; - - /** @brief Descriptor privilege level. - * @details This field determines the privilege level of the segment. - * @details 0 = kernel mode, 3 = user mode. - */ - uint64_t DPL : 2; - - /** @brief Present bit. - * @details This bit must be 1 for all valid descriptors. - */ - uint64_t P : 1; - } __packed; - uint8_t Raw; - }; - - union GlobalDescriptorTableFlags - { - // TODO: Add more flags. - struct - { - /** @brief Unknown. */ - uint64_t Unknown : 5; - - /** @brief Long mode. - * @details If the long mode bit is clear, the segment is in 32-bit protected mode. - * @details If the long mode bit is set, the segment is in 64-bit long mode. - */ - uint64_t L : 1; - } __packed; - uint8_t Raw; - }; - - typedef struct _TaskStateSegmentEntry + struct TaskStateSegmentEntry { /* LOW */ - uint16_t Length; + uint16_t Limit; uint16_t BaseLow; uint8_t BaseMiddle; - GlobalDescriptorTableAccess Flags; + union GlobalDescriptorTableAccess + { + struct + { + /** @brief Access bit. + * @note The CPU sets this bit to 1 when the segment is accessed. + */ + uint8_t A : 1; + + /** @brief Readable bit for code segments, writable bit for data segments. + * @details For code segments, this bit must be 1 for the segment to be readable. + * @details For data segments, this bit must be 1 for the segment to be writable. + */ + uint8_t RW : 1; + + /** @brief Direction bit for data segments, conforming bit for code segments. + * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). + * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. + */ + uint8_t DC : 1; + + /** @brief Executable bit. + * @details This bit must be 1 for code-segment descriptors. + * @details This bit must be 0 for data-segment and system descriptors. + */ + uint8_t E : 1; + + /** @brief Descriptor type. + * @details This bit must be 0 for system descriptors. + * @details This bit must be 1 for code or data segment descriptor. + */ + uint8_t S : 1; + + /** @brief Descriptor privilege level. + * @details This field determines the privilege level of the segment. + * @details 0 = kernel mode, 3 = user mode. + */ + uint8_t DPL : 2; + + /** @brief Present bit. + * @details This bit must be 1 for all valid descriptors. + */ + uint8_t P : 1; + } __packed; + uint8_t Raw : 8; + } Access; uint8_t Granularity; uint8_t BaseHigh; /* HIGH */ uint32_t BaseUpper; uint32_t Reserved; - } __packed TaskStateSegmentEntry; + } __packed; - typedef struct _TaskStateSegment + struct TaskStateSegment { uint32_t Reserved0 __aligned(16); uint64_t StackPointer[3]; @@ -112,25 +90,107 @@ namespace GlobalDescriptorTable uint64_t Reserved2; uint16_t Reserved3; uint16_t IOMapBaseAddressOffset; - } __packed TaskStateSegment; + } __packed; - typedef struct _GlobalDescriptorTableEntry + struct GlobalDescriptorTableEntry { - /** @brief Length */ - uint16_t Length; - /** @brief Low Base */ - uint16_t BaseLow; - /** @brief Middle Base */ - uint8_t BaseMiddle; - /** @brief Access */ - GlobalDescriptorTableAccess Access; - /** @brief Flags */ - GlobalDescriptorTableFlags Flags; - /** @brief High Base */ - uint8_t BaseHigh; - } __packed GlobalDescriptorTableEntry; + /** @brief Limit 0:15 */ + uint16_t Limit0 : 16; - typedef struct _GlobalDescriptorTableEntries + /** @brief Low Base 0:15 */ + uint16_t BaseLow : 16; + + /** @brief Middle Base 16:23 */ + uint8_t BaseMiddle : 8; + + /** @brief Access */ + union GlobalDescriptorTableAccess + { + struct + { + /** @brief Access bit. + * @note The CPU sets this bit to 1 when the segment is accessed. + */ + uint8_t A : 1; + + /** @brief Readable bit for code segments, writable bit for data segments. + * @details For code segments, this bit must be 1 for the segment to be readable. + * @details For data segments, this bit must be 1 for the segment to be writable. + */ + uint8_t RW : 1; + + /** @brief Direction bit for data segments, conforming bit for code segments. + * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). + * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. + */ + uint8_t DC : 1; + + /** @brief Executable bit. + * @details This bit must be 1 for code-segment descriptors. + * @details This bit must be 0 for data-segment and system descriptors. + */ + uint8_t E : 1; + + /** @brief Descriptor type. + * @details This bit must be 0 for system descriptors. + * @details This bit must be 1 for code or data segment descriptor. + */ + uint8_t S : 1; + + /** @brief Descriptor privilege level. + * @details This field determines the privilege level of the segment. + * @details 0 = kernel mode, 3 = user mode. + */ + uint8_t DPL : 2; + + /** @brief Present bit. + * @details This bit must be 1 for all valid descriptors. + */ + uint8_t P : 1; + } __packed; + uint8_t Raw : 8; + } Access; + + // /** @brief Limit 16:19 */ + // uint16_t Limit1 : 4; + + /** @brief Flags */ + union GlobalDescriptorTableFlags + { + struct + { + uint8_t Reserved : 4; /* FIXME: Without this, the kernel crashes. */ + /** @brief Available bit. + * @details This bit is available for use by system software. + */ + uint8_t AVL : 1; + + /** @brief Long mode. + * @details If the long mode bit is clear, the segment is in 32-bit protected mode. + * @details If the long mode bit is set, the segment is in 64-bit long mode. + */ + uint8_t L : 1; + + /** @brief Size flag. + * @details If the size bit is clear, the segment is in 16-bit protected mode. + * @details If the size bit is set, the segment is in 32-bit protected mode. + */ + uint8_t DB : 1; + + /** @brief Granularity bit. + * @details If the granularity bit is clear, the segment limit is in 1 B blocks. + * @details If the granularity bit is set, the segment limit is in 4 KiB blocks. + */ + uint8_t G : 1; + } __packed; + uint8_t Raw : 8; + } Flags; + + /** @brief High Base 24:31 */ + uint8_t BaseHigh : 8; + } __packed; + + struct GlobalDescriptorTableEntries { GlobalDescriptorTableEntry Null; GlobalDescriptorTableEntry Code; @@ -138,15 +198,15 @@ namespace GlobalDescriptorTable GlobalDescriptorTableEntry UserData; GlobalDescriptorTableEntry UserCode; TaskStateSegmentEntry TaskStateSegment; - } __packed GlobalDescriptorTableEntries; + } __packed; - typedef struct _GlobalDescriptorTableDescriptor + struct GlobalDescriptorTableDescriptor { /** @brief GDT entries length */ uint16_t Length; /** @brief GDT entries address */ GlobalDescriptorTableEntries *Entries; - } __packed GlobalDescriptorTableDescriptor; + } __packed; extern void *CPUStackPointer[]; extern TaskStateSegment tss[]; diff --git a/Architecture/i386/cpu/GlobalDescriptorTable.cpp b/Architecture/i386/cpu/GlobalDescriptorTable.cpp index d7cb3d0..c1a4a86 100644 --- a/Architecture/i386/cpu/GlobalDescriptorTable.cpp +++ b/Architecture/i386/cpu/GlobalDescriptorTable.cpp @@ -25,75 +25,123 @@ namespace GlobalDescriptorTable { static GlobalDescriptorTableEntries GDTEntriesTemplate = { - // null - {.Length = 0x0, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = {.Raw = 0x0}, - .Flags = {.Raw = 0x0}, - .BaseHigh = 0x0}, + .Null = + { + .Limit0 = 0x0, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = {.Raw = 0x0}, + // .Limit1 = 0x0, + .Flags = {.Raw = 0x0}, + .BaseHigh = 0x0, + }, - // kernel code - {.Length = 0x0, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = {.A = 0, + .Code = + { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, .RW = 1, .DC = 0, .E = 1, .S = 1, .DPL = 0, - .P = 1}, - .Flags = {.Unknown = 0x0, .L = 1}, - .BaseHigh = 0x0}, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - // kernel data - {.Length = 0x0, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = {.A = 0, - .RW = 1, - .DC = 0, - .E = 0, - .S = 1, - .DPL = 0, - .P = 1}, - .Flags = {.Raw = 0x0}, - .BaseHigh = 0x0}, + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, + .BaseHigh = 0x0, + }, - // user data - {.Length = 0x0, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = {.A = 0, - .RW = 1, - .DC = 0, - .E = 0, - .S = 1, - .DPL = 3, - .P = 1}, - .Flags = {.Raw = 0x0}, - .BaseHigh = 0x0}, + .Data = { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 0, + .S = 1, + .DPL = 0, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - // user code - {.Length = 0x0, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = {.A = 0, - .RW = 1, - .DC = 0, - .E = 1, - .S = 1, - .DPL = 3, - .P = 1}, - .Flags = {.Unknown = 0x0, .L = 1}, - .BaseHigh = 0x0}, + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, + .BaseHigh = 0x0, + }, - // tss - {}}; + .UserData = { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 0, + .S = 1, + .DPL = 3, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ - GlobalDescriptorTableEntries GDTEntries[MAX_CPU]; - GlobalDescriptorTableDescriptor gdt[MAX_CPU]; + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, + .BaseHigh = 0x0, + }, + + .UserCode = { + .Limit0 = 0xFFFF, + .BaseLow = 0x0, + .BaseMiddle = 0x0, + .Access = { + .A = 0, + .RW = 1, + .DC = 0, + .E = 1, + .S = 1, + .DPL = 3, + .P = 1, + }, + // .Limit1 = 0xF, + .Flags = { + .Reserved = 0xF, /* Workaround for Limit1 */ + + .AVL = 0, + .L = 0, + .DB = 1, + .G = 1, + }, + .BaseHigh = 0x0, + }, + + .TaskStateSegment = {}, + }; + + GlobalDescriptorTableEntries GDTEntries[MAX_CPU] __aligned(16); + GlobalDescriptorTableDescriptor gdt[MAX_CPU] __aligned(16); TaskStateSegment tss[MAX_CPU] = { 0, @@ -102,15 +150,123 @@ namespace GlobalDescriptorTable {0, 0, 0, 0, 0, 0, 0}, 0, 0, + 0, }; void *CPUStackPointer[MAX_CPU]; SafeFunction void Init(int Core) { + memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries)); + gdt[Core] = {.Length = sizeof(GlobalDescriptorTableEntries) - 1, .Entries = &GDTEntries[Core]}; + + debug("GDT: %#lx", &gdt[Core]); + debug("GDT KERNEL: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_KERNEL_CODE, + GDTEntries[Core].Code.Limit0, + GDTEntries[Core].Code.BaseLow, + GDTEntries[Core].Code.BaseMiddle, + GDTEntries[Core].Code.Access.Raw, + GDTEntries[Core].Code.Flags.Reserved, + GDTEntries[Core].Code.Flags.Raw & ~0xF, + GDTEntries[Core].Code.BaseHigh); + + debug("GDT KERNEL: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_KERNEL_DATA, + GDTEntries[Core].Data.Limit0, + GDTEntries[Core].Data.BaseLow, + GDTEntries[Core].Data.BaseMiddle, + GDTEntries[Core].Data.Access.Raw, + GDTEntries[Core].Data.Flags.Reserved, + GDTEntries[Core].Data.Flags.Raw & ~0xF, + GDTEntries[Core].Data.BaseHigh); + + debug("GDT USER: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_USER_CODE, + GDTEntries[Core].UserCode.Limit0, + GDTEntries[Core].UserCode.BaseLow, + GDTEntries[Core].UserCode.BaseMiddle, + GDTEntries[Core].UserCode.Access.Raw, + GDTEntries[Core].UserCode.Flags.Reserved, + GDTEntries[Core].UserCode.Flags.Raw & ~0xF, + GDTEntries[Core].UserCode.BaseHigh); + + debug("GDT USER: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", + GDT_USER_DATA, + GDTEntries[Core].UserData.Limit0, + GDTEntries[Core].UserData.BaseLow, + GDTEntries[Core].UserData.BaseMiddle, + GDTEntries[Core].UserData.Access.Raw, + GDTEntries[Core].UserData.Flags.Reserved, + GDTEntries[Core].UserData.Flags.Raw & ~0xF, + GDTEntries[Core].UserData.BaseHigh); + + CPU::x32::lgdt(&gdt[Core]); + + asmv("mov %%esp, %%eax\n" + "push $16\n" + "push %%eax\n" + "pushf\n" + "push $8\n" + "push $1f\n" + "iret\n" + "1:\n" + "movw $16, %%ax\n" + "movw %%ax, %%ds\n" + "movw %%ax, %%es\n" :: + : "memory", "eax"); + + CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); + memset(CPUStackPointer[Core], 0, STACK_SIZE); + debug("CPU %d Stack Pointer: %#lx-%#lx (%d pages)", Core, + CPUStackPointer[Core], (uintptr_t)CPUStackPointer[Core] + STACK_SIZE, + TO_PAGES(STACK_SIZE + 1)); + + uintptr_t Base = (uintptr_t)&tss[Core]; + size_t Limit = Base + sizeof(TaskStateSegment); + gdt[Core].Entries->TaskStateSegment.Limit = Limit & 0xFFFF; + gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF; + gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF; + gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 0xFF; + gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); + gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1}; + gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF); + + tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment); + tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE; + tss[Core].StackPointer[1] = 0x0; + tss[Core].StackPointer[2] = 0x0; + + for (size_t i = 0; i < sizeof(tss[Core].InterruptStackTable) / sizeof(tss[Core].InterruptStackTable[7]); i++) + { + void *NewStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); + + tss[Core].InterruptStackTable[i] = (uint64_t)NewStack + STACK_SIZE; + memset((void *)(tss[Core].InterruptStackTable[i] - STACK_SIZE), 0, STACK_SIZE); + debug("IST-%d: %#lx-%#lx", i, NewStack, (uintptr_t)NewStack + STACK_SIZE); + } + + CPU::x32::ltr(GDT_TSS); + debug("Global Descriptor Table initialized"); } SafeFunction void SetKernelStack(void *Stack) { + long CPUID = GetCurrentCPU()->ID; + if (Stack != nullptr) + tss[CPUID].StackPointer[0] = (uint64_t)Stack; + else + tss[CPUID].StackPointer[0] = (uint64_t)CPUStackPointer[CPUID] + STACK_SIZE; + + /* + FIXME: There's a bug in kernel which if + we won't update "tss[CPUID].StackPointer[0]" + with the current stack pointer, the kernel + will crash. + */ + asmv("mov %%esp, %0" + : "=r"(tss[CPUID].StackPointer[0])); } + + void *GetKernelStack() { return (void *)tss[GetCurrentCPU()->ID].StackPointer[0]; } } diff --git a/Architecture/i386/cpu/InterruptDescriptorTable.cpp b/Architecture/i386/cpu/InterruptDescriptorTable.cpp new file mode 100644 index 0000000..855f6b4 --- /dev/null +++ b/Architecture/i386/cpu/InterruptDescriptorTable.cpp @@ -0,0 +1,727 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#include "idt.hpp" + +#include +#include +#include +#include + +#include "gdt.hpp" +#include "../../../kernel.h" + +/* conversion from ‘uint64_t’ {aka ‘long unsigned int’} to ‘unsigned char:2’ may change value */ +#pragma GCC diagnostic ignored "-Wconversion" + +extern "C" void MainInterruptHandler(void *Data); +extern "C" void ExceptionHandler(void *Data); + +namespace InterruptDescriptorTable +{ + static InterruptDescriptorTableEntry Entries[0x100]; + + InterruptDescriptorTableDescriptor idtd = { + .Length = sizeof(Entries) - 1, + .Entries = Entries, + }; + + void SetEntry(uint8_t Index, + void (*Base)(), + InterruptGateType Gate, + InterruptRingType Ring, + bool Present, + uint16_t SegmentSelector) + { + /* FIXME: Check "Intel Software Developer Manual, Volume 3-A" at Section 6.11: IDT Descriptors */ + Entries[Index].LowOffset = s_cst(uint16_t, ((uint32_t)Base & 0xFFFF)); + Entries[Index].SegmentSelector = SegmentSelector; + Entries[Index].Reserved0 = 0; + Entries[Index].Flags = Gate; + Entries[Index].Reserved1 = 0; + Entries[Index].Ring = Ring; + Entries[Index].Present = Present; + Entries[Index].HighOffset = s_cst(uint16_t, ((uint32_t)Base >> 16 /* & 0xFFFF */)); + } + + extern "C" __naked __used __no_stack_protector __aligned(16) void ExceptionHandlerStub() + { + asm("cld\n" + "cli\n" + + // "push %eax\n" + // "push %ebx\n" + // "push %ecx\n" + // "push %edx\n" + // "push %esi\n" + // "push %edi\n" + // "push %ebp\n" + "pusha\n" + + "push %esp\n" + "call ExceptionHandler\n" + + "popa\n" + // "pop %ebp\n" + // "pop %edi\n" + // "pop %esi\n" + // "pop %edx\n" + // "pop %ecx\n" + // "pop %ebx\n" + // "pop %eax\n" + + "add $8, %esp\n" + + "iret"); + } + + extern "C" __naked __used __no_stack_protector __aligned(16) void InterruptHandlerStub() + { + asm("cld\n" + "cli\n" + + // "push %eax\n" + // "push %ebx\n" + // "push %ecx\n" + // "push %edx\n" + // "push %esi\n" + // "push %edi\n" + // "push %ebp\n" + "pusha\n" + + "push %esp\n" + "call MainInterruptHandler\n" + + "popa\n" + // "pop %ebp\n" + // "pop %edi\n" + // "pop %esi\n" + // "pop %edx\n" + // "pop %ecx\n" + // "pop %ebx\n" + // "pop %eax\n" + + "add $8, %esp\n" + + "sti\n" + "iret"); + } + +#pragma region Exceptions + +#define EXCEPTION_HANDLER(num) \ + __naked __used __no_stack_protector __aligned(16) static void InterruptHandler_##num() \ + { \ + asm("push $0\npush $" #num "\n" \ + "jmp ExceptionHandlerStub"); \ + } + +#define EXCEPTION_ERROR_HANDLER(num) \ + __naked __used __no_stack_protector __aligned(16) static void InterruptHandler_##num() \ + { \ + asm("push $" #num "\n" \ + "jmp ExceptionHandlerStub"); \ + } + +#define INTERRUPT_HANDLER(num) \ + __naked __used __no_stack_protector __aligned(16) void InterruptHandler_##num() \ + { \ + asm("push $0\npush $" #num "\n" \ + "jmp InterruptHandlerStub\n"); \ + } + + /* ISR */ + + EXCEPTION_HANDLER(0x0); + EXCEPTION_HANDLER(0x1); + EXCEPTION_HANDLER(0x2); + EXCEPTION_HANDLER(0x3); + EXCEPTION_HANDLER(0x4); + EXCEPTION_HANDLER(0x5); + EXCEPTION_HANDLER(0x6); + EXCEPTION_HANDLER(0x7); + EXCEPTION_ERROR_HANDLER(0x8); + EXCEPTION_HANDLER(0x9); + EXCEPTION_ERROR_HANDLER(0xa); + EXCEPTION_ERROR_HANDLER(0xb); + EXCEPTION_ERROR_HANDLER(0xc); + EXCEPTION_ERROR_HANDLER(0xd); + EXCEPTION_ERROR_HANDLER(0xe); + EXCEPTION_HANDLER(0xf); + EXCEPTION_ERROR_HANDLER(0x10); + EXCEPTION_HANDLER(0x11); + EXCEPTION_HANDLER(0x12); + EXCEPTION_HANDLER(0x13); + EXCEPTION_HANDLER(0x14); + EXCEPTION_HANDLER(0x15); + EXCEPTION_HANDLER(0x16); + EXCEPTION_HANDLER(0x17); + EXCEPTION_HANDLER(0x18); + EXCEPTION_HANDLER(0x19); + EXCEPTION_HANDLER(0x1a); + EXCEPTION_HANDLER(0x1b); + EXCEPTION_HANDLER(0x1c); + EXCEPTION_HANDLER(0x1d); + EXCEPTION_HANDLER(0x1e); + EXCEPTION_HANDLER(0x1f); + + /* IRQ */ + + INTERRUPT_HANDLER(0x20) + INTERRUPT_HANDLER(0x21) + INTERRUPT_HANDLER(0x22) + INTERRUPT_HANDLER(0x23) + INTERRUPT_HANDLER(0x24) + INTERRUPT_HANDLER(0x25) + INTERRUPT_HANDLER(0x26) + INTERRUPT_HANDLER(0x27) + INTERRUPT_HANDLER(0x28) + INTERRUPT_HANDLER(0x29) + INTERRUPT_HANDLER(0x2a) + INTERRUPT_HANDLER(0x2b) + INTERRUPT_HANDLER(0x2c) + INTERRUPT_HANDLER(0x2d) + INTERRUPT_HANDLER(0x2e) + INTERRUPT_HANDLER(0x2f) + + /* Reserved by OS */ + + INTERRUPT_HANDLER(0x30) + INTERRUPT_HANDLER(0x31) + INTERRUPT_HANDLER(0x32) + INTERRUPT_HANDLER(0x33) + INTERRUPT_HANDLER(0x34) + INTERRUPT_HANDLER(0x35) + INTERRUPT_HANDLER(0x36) + INTERRUPT_HANDLER(0x37) + INTERRUPT_HANDLER(0x38) + INTERRUPT_HANDLER(0x39) + INTERRUPT_HANDLER(0x3a) + INTERRUPT_HANDLER(0x3b) + INTERRUPT_HANDLER(0x3c) + INTERRUPT_HANDLER(0x3d) + + /* Free */ + + INTERRUPT_HANDLER(0x3e) + INTERRUPT_HANDLER(0x3f) + INTERRUPT_HANDLER(0x40) + INTERRUPT_HANDLER(0x41) + INTERRUPT_HANDLER(0x42) + INTERRUPT_HANDLER(0x43) + INTERRUPT_HANDLER(0x44) + INTERRUPT_HANDLER(0x45) + INTERRUPT_HANDLER(0x46) + INTERRUPT_HANDLER(0x47) + INTERRUPT_HANDLER(0x48) + INTERRUPT_HANDLER(0x49) + INTERRUPT_HANDLER(0x4a) + INTERRUPT_HANDLER(0x4b) + INTERRUPT_HANDLER(0x4c) + INTERRUPT_HANDLER(0x4d) + INTERRUPT_HANDLER(0x4e) + INTERRUPT_HANDLER(0x4f) + INTERRUPT_HANDLER(0x50) + INTERRUPT_HANDLER(0x51) + INTERRUPT_HANDLER(0x52) + INTERRUPT_HANDLER(0x53) + INTERRUPT_HANDLER(0x54) + INTERRUPT_HANDLER(0x55) + INTERRUPT_HANDLER(0x56) + INTERRUPT_HANDLER(0x57) + INTERRUPT_HANDLER(0x58) + INTERRUPT_HANDLER(0x59) + INTERRUPT_HANDLER(0x5a) + INTERRUPT_HANDLER(0x5b) + INTERRUPT_HANDLER(0x5c) + INTERRUPT_HANDLER(0x5d) + INTERRUPT_HANDLER(0x5e) + INTERRUPT_HANDLER(0x5f) + INTERRUPT_HANDLER(0x60) + INTERRUPT_HANDLER(0x61) + INTERRUPT_HANDLER(0x62) + INTERRUPT_HANDLER(0x63) + INTERRUPT_HANDLER(0x64) + INTERRUPT_HANDLER(0x65) + INTERRUPT_HANDLER(0x66) + INTERRUPT_HANDLER(0x67) + INTERRUPT_HANDLER(0x68) + INTERRUPT_HANDLER(0x69) + INTERRUPT_HANDLER(0x6a) + INTERRUPT_HANDLER(0x6b) + INTERRUPT_HANDLER(0x6c) + INTERRUPT_HANDLER(0x6d) + INTERRUPT_HANDLER(0x6e) + INTERRUPT_HANDLER(0x6f) + INTERRUPT_HANDLER(0x70) + INTERRUPT_HANDLER(0x71) + INTERRUPT_HANDLER(0x72) + INTERRUPT_HANDLER(0x73) + INTERRUPT_HANDLER(0x74) + INTERRUPT_HANDLER(0x75) + INTERRUPT_HANDLER(0x76) + INTERRUPT_HANDLER(0x77) + INTERRUPT_HANDLER(0x78) + INTERRUPT_HANDLER(0x79) + INTERRUPT_HANDLER(0x7a) + INTERRUPT_HANDLER(0x7b) + INTERRUPT_HANDLER(0x7c) + INTERRUPT_HANDLER(0x7d) + INTERRUPT_HANDLER(0x7e) + INTERRUPT_HANDLER(0x7f) + INTERRUPT_HANDLER(0x80) + INTERRUPT_HANDLER(0x81) + INTERRUPT_HANDLER(0x82) + INTERRUPT_HANDLER(0x83) + INTERRUPT_HANDLER(0x84) + INTERRUPT_HANDLER(0x85) + INTERRUPT_HANDLER(0x86) + INTERRUPT_HANDLER(0x87) + INTERRUPT_HANDLER(0x88) + INTERRUPT_HANDLER(0x89) + INTERRUPT_HANDLER(0x8a) + INTERRUPT_HANDLER(0x8b) + INTERRUPT_HANDLER(0x8c) + INTERRUPT_HANDLER(0x8d) + INTERRUPT_HANDLER(0x8e) + INTERRUPT_HANDLER(0x8f) + INTERRUPT_HANDLER(0x90) + INTERRUPT_HANDLER(0x91) + INTERRUPT_HANDLER(0x92) + INTERRUPT_HANDLER(0x93) + INTERRUPT_HANDLER(0x94) + INTERRUPT_HANDLER(0x95) + INTERRUPT_HANDLER(0x96) + INTERRUPT_HANDLER(0x97) + INTERRUPT_HANDLER(0x98) + INTERRUPT_HANDLER(0x99) + INTERRUPT_HANDLER(0x9a) + INTERRUPT_HANDLER(0x9b) + INTERRUPT_HANDLER(0x9c) + INTERRUPT_HANDLER(0x9d) + INTERRUPT_HANDLER(0x9e) + INTERRUPT_HANDLER(0x9f) + INTERRUPT_HANDLER(0xa0) + INTERRUPT_HANDLER(0xa1) + INTERRUPT_HANDLER(0xa2) + INTERRUPT_HANDLER(0xa3) + INTERRUPT_HANDLER(0xa4) + INTERRUPT_HANDLER(0xa5) + INTERRUPT_HANDLER(0xa6) + INTERRUPT_HANDLER(0xa7) + INTERRUPT_HANDLER(0xa8) + INTERRUPT_HANDLER(0xa9) + INTERRUPT_HANDLER(0xaa) + INTERRUPT_HANDLER(0xab) + INTERRUPT_HANDLER(0xac) + INTERRUPT_HANDLER(0xad) + INTERRUPT_HANDLER(0xae) + INTERRUPT_HANDLER(0xaf) + INTERRUPT_HANDLER(0xb0) + INTERRUPT_HANDLER(0xb1) + INTERRUPT_HANDLER(0xb2) + INTERRUPT_HANDLER(0xb3) + INTERRUPT_HANDLER(0xb4) + INTERRUPT_HANDLER(0xb5) + INTERRUPT_HANDLER(0xb6) + INTERRUPT_HANDLER(0xb7) + INTERRUPT_HANDLER(0xb8) + INTERRUPT_HANDLER(0xb9) + INTERRUPT_HANDLER(0xba) + INTERRUPT_HANDLER(0xbb) + INTERRUPT_HANDLER(0xbc) + INTERRUPT_HANDLER(0xbd) + INTERRUPT_HANDLER(0xbe) + INTERRUPT_HANDLER(0xbf) + INTERRUPT_HANDLER(0xc0) + INTERRUPT_HANDLER(0xc1) + INTERRUPT_HANDLER(0xc2) + INTERRUPT_HANDLER(0xc3) + INTERRUPT_HANDLER(0xc4) + INTERRUPT_HANDLER(0xc5) + INTERRUPT_HANDLER(0xc6) + INTERRUPT_HANDLER(0xc7) + INTERRUPT_HANDLER(0xc8) + INTERRUPT_HANDLER(0xc9) + INTERRUPT_HANDLER(0xca) + INTERRUPT_HANDLER(0xcb) + INTERRUPT_HANDLER(0xcc) + INTERRUPT_HANDLER(0xcd) + INTERRUPT_HANDLER(0xce) + INTERRUPT_HANDLER(0xcf) + INTERRUPT_HANDLER(0xd0) + INTERRUPT_HANDLER(0xd1) + INTERRUPT_HANDLER(0xd2) + INTERRUPT_HANDLER(0xd3) + INTERRUPT_HANDLER(0xd4) + INTERRUPT_HANDLER(0xd5) + INTERRUPT_HANDLER(0xd6) + INTERRUPT_HANDLER(0xd7) + INTERRUPT_HANDLER(0xd8) + INTERRUPT_HANDLER(0xd9) + INTERRUPT_HANDLER(0xda) + INTERRUPT_HANDLER(0xdb) + INTERRUPT_HANDLER(0xdc) + INTERRUPT_HANDLER(0xdd) + INTERRUPT_HANDLER(0xde) + INTERRUPT_HANDLER(0xdf) + INTERRUPT_HANDLER(0xe0) + INTERRUPT_HANDLER(0xe1) + INTERRUPT_HANDLER(0xe2) + INTERRUPT_HANDLER(0xe3) + INTERRUPT_HANDLER(0xe4) + INTERRUPT_HANDLER(0xe5) + INTERRUPT_HANDLER(0xe6) + INTERRUPT_HANDLER(0xe7) + INTERRUPT_HANDLER(0xe8) + INTERRUPT_HANDLER(0xe9) + INTERRUPT_HANDLER(0xea) + INTERRUPT_HANDLER(0xeb) + INTERRUPT_HANDLER(0xec) + INTERRUPT_HANDLER(0xed) + INTERRUPT_HANDLER(0xee) + INTERRUPT_HANDLER(0xef) + INTERRUPT_HANDLER(0xf0) + INTERRUPT_HANDLER(0xf1) + INTERRUPT_HANDLER(0xf2) + INTERRUPT_HANDLER(0xf3) + INTERRUPT_HANDLER(0xf4) + INTERRUPT_HANDLER(0xf5) + INTERRUPT_HANDLER(0xf6) + INTERRUPT_HANDLER(0xf7) + INTERRUPT_HANDLER(0xf8) + INTERRUPT_HANDLER(0xf9) + INTERRUPT_HANDLER(0xfa) + INTERRUPT_HANDLER(0xfb) + INTERRUPT_HANDLER(0xfc) + INTERRUPT_HANDLER(0xfd) + INTERRUPT_HANDLER(0xfe) + INTERRUPT_HANDLER(0xff) + +#pragma endregion Exceptions + + void Init(int Core) + { + if (Core == 0) /* Remap PIC using BSP */ + { + // PIC + outb(0x20, 0x10 | 0x1); + outb(0x80, 0); + outb(0xA0, 0x10 | 0x10); + outb(0x80, 0); + + outb(0x21, 0x20); + outb(0x80, 0); + outb(0xA1, 0x28); + outb(0x80, 0); + + outb(0x21, 0x04); + outb(0x80, 0); + outb(0xA1, 0x02); + outb(0x80, 0); + + outb(0x21, 1); + outb(0x80, 0); + outb(0xA1, 1); + outb(0x80, 0); + + // Masking and disabling PIC + // outb(0x21, 0xff); + // outb(0x80, 0); + // outb(0xA1, 0xff); + } + + /* ISR */ + +#ifdef DEBUG + // if (!DebuggerIsAttached) + if (true) + { +#endif + SetEntry(0x0, InterruptHandler_0x0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x1, InterruptHandler_0x1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x2, InterruptHandler_0x2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x3, InterruptHandler_0x3, TRAP_32BIT, RING3, (!DebuggerIsAttached), GDT_KERNEL_CODE); /* Do not handle breakpoints if we are debugging the kernel. */ + SetEntry(0x4, InterruptHandler_0x4, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x5, InterruptHandler_0x5, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x6, InterruptHandler_0x6, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x7, InterruptHandler_0x7, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x8, InterruptHandler_0x8, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x9, InterruptHandler_0x9, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa, InterruptHandler_0xa, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb, InterruptHandler_0xb, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc, InterruptHandler_0xc, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd, InterruptHandler_0xd, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe, InterruptHandler_0xe, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf, InterruptHandler_0xf, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x10, InterruptHandler_0x10, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x11, InterruptHandler_0x11, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x12, InterruptHandler_0x12, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x13, InterruptHandler_0x13, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x14, InterruptHandler_0x14, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x15, InterruptHandler_0x15, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x16, InterruptHandler_0x16, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x17, InterruptHandler_0x17, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x18, InterruptHandler_0x18, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x19, InterruptHandler_0x19, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x1a, InterruptHandler_0x1a, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x1b, InterruptHandler_0x1b, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x1c, InterruptHandler_0x1c, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x1d, InterruptHandler_0x1d, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x1e, InterruptHandler_0x1e, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x1f, InterruptHandler_0x1f, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); +#ifdef DEBUG + } + else + KPrint("\eFFA500The debugger is attached, not setting up the ISR."); +#endif + + /* IRQ */ + + SetEntry(0x20, InterruptHandler_0x20, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x21, InterruptHandler_0x21, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x22, InterruptHandler_0x22, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x23, InterruptHandler_0x23, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x24, InterruptHandler_0x24, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x25, InterruptHandler_0x25, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x26, InterruptHandler_0x26, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x27, InterruptHandler_0x27, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x28, InterruptHandler_0x28, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x29, InterruptHandler_0x29, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x2a, InterruptHandler_0x2a, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x2b, InterruptHandler_0x2b, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x2c, InterruptHandler_0x2c, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x2d, InterruptHandler_0x2d, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x2e, InterruptHandler_0x2e, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x2f, InterruptHandler_0x2f, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + + /* Reserved by OS */ + + SetEntry(0x30, InterruptHandler_0x30, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x31, InterruptHandler_0x31, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x32, InterruptHandler_0x32, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x33, InterruptHandler_0x33, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x34, InterruptHandler_0x34, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x35, InterruptHandler_0x35, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x36, InterruptHandler_0x36, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x37, InterruptHandler_0x37, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x38, InterruptHandler_0x38, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x39, InterruptHandler_0x39, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x3a, InterruptHandler_0x3a, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x3b, InterruptHandler_0x3b, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x3c, InterruptHandler_0x3c, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x3d, InterruptHandler_0x3d, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + + /* Free */ + + SetEntry(0x3e, InterruptHandler_0x3e, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x3f, InterruptHandler_0x3f, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x40, InterruptHandler_0x40, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x41, InterruptHandler_0x41, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x42, InterruptHandler_0x42, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x43, InterruptHandler_0x43, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x44, InterruptHandler_0x44, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x45, InterruptHandler_0x45, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x46, InterruptHandler_0x46, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x47, InterruptHandler_0x47, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x48, InterruptHandler_0x48, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x49, InterruptHandler_0x49, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x4a, InterruptHandler_0x4a, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x4b, InterruptHandler_0x4b, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x4c, InterruptHandler_0x4c, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x4d, InterruptHandler_0x4d, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x4e, InterruptHandler_0x4e, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x4f, InterruptHandler_0x4f, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x50, InterruptHandler_0x50, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x51, InterruptHandler_0x51, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x52, InterruptHandler_0x52, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x53, InterruptHandler_0x53, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x54, InterruptHandler_0x54, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x55, InterruptHandler_0x55, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x56, InterruptHandler_0x56, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x57, InterruptHandler_0x57, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x58, InterruptHandler_0x58, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x59, InterruptHandler_0x59, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x5a, InterruptHandler_0x5a, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x5b, InterruptHandler_0x5b, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x5c, InterruptHandler_0x5c, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x5d, InterruptHandler_0x5d, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x5e, InterruptHandler_0x5e, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x5f, InterruptHandler_0x5f, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x60, InterruptHandler_0x60, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x61, InterruptHandler_0x61, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x62, InterruptHandler_0x62, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x63, InterruptHandler_0x63, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x64, InterruptHandler_0x64, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x65, InterruptHandler_0x65, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x66, InterruptHandler_0x66, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x67, InterruptHandler_0x67, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x68, InterruptHandler_0x68, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x69, InterruptHandler_0x69, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x6a, InterruptHandler_0x6a, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x6b, InterruptHandler_0x6b, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x6c, InterruptHandler_0x6c, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x6d, InterruptHandler_0x6d, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x6e, InterruptHandler_0x6e, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x6f, InterruptHandler_0x6f, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x70, InterruptHandler_0x70, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x71, InterruptHandler_0x71, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x72, InterruptHandler_0x72, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x73, InterruptHandler_0x73, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x74, InterruptHandler_0x74, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x75, InterruptHandler_0x75, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x76, InterruptHandler_0x76, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x77, InterruptHandler_0x77, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x78, InterruptHandler_0x78, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x79, InterruptHandler_0x79, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x7a, InterruptHandler_0x7a, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x7b, InterruptHandler_0x7b, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x7c, InterruptHandler_0x7c, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x7d, InterruptHandler_0x7d, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x7e, InterruptHandler_0x7e, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x7f, InterruptHandler_0x7f, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x80, InterruptHandler_0x80, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x81, InterruptHandler_0x81, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x82, InterruptHandler_0x82, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x83, InterruptHandler_0x83, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x84, InterruptHandler_0x84, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x85, InterruptHandler_0x85, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x86, InterruptHandler_0x86, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x87, InterruptHandler_0x87, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x88, InterruptHandler_0x88, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x89, InterruptHandler_0x89, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x8a, InterruptHandler_0x8a, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x8b, InterruptHandler_0x8b, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x8c, InterruptHandler_0x8c, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x8d, InterruptHandler_0x8d, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x8e, InterruptHandler_0x8e, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x8f, InterruptHandler_0x8f, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x90, InterruptHandler_0x90, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x91, InterruptHandler_0x91, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x92, InterruptHandler_0x92, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x93, InterruptHandler_0x93, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x94, InterruptHandler_0x94, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x95, InterruptHandler_0x95, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x96, InterruptHandler_0x96, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x97, InterruptHandler_0x97, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x98, InterruptHandler_0x98, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x99, InterruptHandler_0x99, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x9a, InterruptHandler_0x9a, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x9b, InterruptHandler_0x9b, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x9c, InterruptHandler_0x9c, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x9d, InterruptHandler_0x9d, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x9e, InterruptHandler_0x9e, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0x9f, InterruptHandler_0x9f, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa0, InterruptHandler_0xa0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa1, InterruptHandler_0xa1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa2, InterruptHandler_0xa2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa3, InterruptHandler_0xa3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa4, InterruptHandler_0xa4, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa5, InterruptHandler_0xa5, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa6, InterruptHandler_0xa6, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa7, InterruptHandler_0xa7, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa8, InterruptHandler_0xa8, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xa9, InterruptHandler_0xa9, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xaa, InterruptHandler_0xaa, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xab, InterruptHandler_0xab, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xac, InterruptHandler_0xac, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xad, InterruptHandler_0xad, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xae, InterruptHandler_0xae, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xaf, InterruptHandler_0xaf, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb0, InterruptHandler_0xb0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb1, InterruptHandler_0xb1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb2, InterruptHandler_0xb2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb3, InterruptHandler_0xb3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb4, InterruptHandler_0xb4, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb5, InterruptHandler_0xb5, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb6, InterruptHandler_0xb6, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb7, InterruptHandler_0xb7, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb8, InterruptHandler_0xb8, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xb9, InterruptHandler_0xb9, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xba, InterruptHandler_0xba, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xbb, InterruptHandler_0xbb, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xbc, InterruptHandler_0xbc, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xbd, InterruptHandler_0xbd, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xbe, InterruptHandler_0xbe, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xbf, InterruptHandler_0xbf, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc0, InterruptHandler_0xc0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc1, InterruptHandler_0xc1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc2, InterruptHandler_0xc2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc3, InterruptHandler_0xc3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc4, InterruptHandler_0xc4, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc5, InterruptHandler_0xc5, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc6, InterruptHandler_0xc6, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc7, InterruptHandler_0xc7, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc8, InterruptHandler_0xc8, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xc9, InterruptHandler_0xc9, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xca, InterruptHandler_0xca, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xcb, InterruptHandler_0xcb, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xcc, InterruptHandler_0xcc, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xcd, InterruptHandler_0xcd, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xce, InterruptHandler_0xce, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xcf, InterruptHandler_0xcf, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd0, InterruptHandler_0xd0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd1, InterruptHandler_0xd1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd2, InterruptHandler_0xd2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd3, InterruptHandler_0xd3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd4, InterruptHandler_0xd4, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd5, InterruptHandler_0xd5, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd6, InterruptHandler_0xd6, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd7, InterruptHandler_0xd7, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd8, InterruptHandler_0xd8, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xd9, InterruptHandler_0xd9, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xda, InterruptHandler_0xda, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xdb, InterruptHandler_0xdb, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xdc, InterruptHandler_0xdc, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xdd, InterruptHandler_0xdd, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xde, InterruptHandler_0xde, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xdf, InterruptHandler_0xdf, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe0, InterruptHandler_0xe0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe1, InterruptHandler_0xe1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe2, InterruptHandler_0xe2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe3, InterruptHandler_0xe3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe4, InterruptHandler_0xe4, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe5, InterruptHandler_0xe5, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe6, InterruptHandler_0xe6, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe7, InterruptHandler_0xe7, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe8, InterruptHandler_0xe8, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xe9, InterruptHandler_0xe9, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xea, InterruptHandler_0xea, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xeb, InterruptHandler_0xeb, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xec, InterruptHandler_0xec, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xed, InterruptHandler_0xed, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xee, InterruptHandler_0xee, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xef, InterruptHandler_0xef, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf0, InterruptHandler_0xf0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf1, InterruptHandler_0xf1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf2, InterruptHandler_0xf2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf3, InterruptHandler_0xf3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf4, InterruptHandler_0xf4, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf5, InterruptHandler_0xf5, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf6, InterruptHandler_0xf6, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf7, InterruptHandler_0xf7, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf8, InterruptHandler_0xf8, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xf9, InterruptHandler_0xf9, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xfa, InterruptHandler_0xfa, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xfb, InterruptHandler_0xfb, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xfc, InterruptHandler_0xfc, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xfd, InterruptHandler_0xfd, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xfe, InterruptHandler_0xfe, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + SetEntry(0xff, InterruptHandler_0xff, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); + CPU::x32::lidt(&idtd); + } +} diff --git a/Architecture/i386/cpu/gdt.hpp b/Architecture/i386/cpu/gdt.hpp index 92e4301..84b0e8b 100644 --- a/Architecture/i386/cpu/gdt.hpp +++ b/Architecture/i386/cpu/gdt.hpp @@ -22,114 +22,175 @@ namespace GlobalDescriptorTable { - /** @brief The GDT Access Table - * @details For more information, see https://wiki.osdev.org/Global_Descriptor_Table - */ - union GlobalDescriptorTableAccess - { - struct - { - /** @brief Access bit. - * @note The CPU sets this bit to 1 when the segment is accessed. - */ - uint8_t A : 1; - - /** @brief Readable bit for code segments, writable bit for data segments. - * @details For code segments, this bit must be 1 for the segment to be readable. - * @details For data segments, this bit must be 1 for the segment to be writable. - */ - uint8_t RW : 1; - - /** @brief Direction bit for data segments, conforming bit for code segments. - * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). - * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. - */ - uint8_t DC : 1; - - /** @brief Executable bit. - * @details This bit must be 1 for code-segment descriptors. - * @details This bit must be 0 for data-segment and system descriptors. - */ - uint8_t E : 1; - - /** @brief Descriptor type. - * @details This bit must be 0 for system descriptors. - * @details This bit must be 1 for code or data segment descriptor. - */ - uint8_t S : 1; - - /** @brief Descriptor privilege level. - * @details This field determines the privilege level of the segment. - * @details 0 = kernel mode, 3 = user mode. - */ - uint8_t DPL : 2; - - /** @brief Present bit. - * @details This bit must be 1 for all valid descriptors. - */ - uint8_t P : 1; - } __packed; - uint8_t Raw; - }; - - union GlobalDescriptorTableFlags - { - // TODO: Add more flags. - struct - { - /** @brief Unknown. */ - uint8_t Unknown : 5; - - /** @brief Long mode. - * @details If the long mode bit is clear, the segment is in 32-bit protected mode. - * @details If the long mode bit is set, the segment is in 64-bit long mode. - */ - uint8_t L : 1; - } __packed; - uint8_t Raw; - }; - - typedef struct _TaskStateSegmentEntry + struct TaskStateSegmentEntry { /* LOW */ - uint16_t Length; + uint16_t Limit; uint16_t BaseLow; uint8_t BaseMiddle; - GlobalDescriptorTableAccess Flags; + union GlobalDescriptorTableAccess + { + struct + { + /** @brief Access bit. + * @note The CPU sets this bit to 1 when the segment is accessed. + */ + uint8_t A : 1; + + /** @brief Readable bit for code segments, writable bit for data segments. + * @details For code segments, this bit must be 1 for the segment to be readable. + * @details For data segments, this bit must be 1 for the segment to be writable. + */ + uint8_t RW : 1; + + /** @brief Direction bit for data segments, conforming bit for code segments. + * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). + * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. + */ + uint8_t DC : 1; + + /** @brief Executable bit. + * @details This bit must be 1 for code-segment descriptors. + * @details This bit must be 0 for data-segment and system descriptors. + */ + uint8_t E : 1; + + /** @brief Descriptor type. + * @details This bit must be 0 for system descriptors. + * @details This bit must be 1 for code or data segment descriptor. + */ + uint8_t S : 1; + + /** @brief Descriptor privilege level. + * @details This field determines the privilege level of the segment. + * @details 0 = kernel mode, 3 = user mode. + */ + uint8_t DPL : 2; + + /** @brief Present bit. + * @details This bit must be 1 for all valid descriptors. + */ + uint8_t P : 1; + } __packed; + uint8_t Raw : 8; + } Access; uint8_t Granularity; uint8_t BaseHigh; /* HIGH */ uint32_t BaseUpper; uint32_t Reserved; - } __packed TaskStateSegmentEntry; + } __packed; - typedef struct _TaskStateSegment + struct TaskStateSegment { uint32_t Reserved0 __aligned(16); uint64_t StackPointer[3]; uint64_t Reserved1; uint64_t InterruptStackTable[7]; - uint16_t Reserved2; + uint64_t Reserved2; + uint16_t Reserved3; uint16_t IOMapBaseAddressOffset; - } __packed TaskStateSegment; + } __packed; - typedef struct _GlobalDescriptorTableEntry + struct GlobalDescriptorTableEntry { - /** @brief Length */ - uint16_t Length; - /** @brief Low Base */ - uint16_t BaseLow; - /** @brief Middle Base */ - uint8_t BaseMiddle; - /** @brief Access */ - GlobalDescriptorTableAccess Access; - /** @brief Flags */ - GlobalDescriptorTableFlags Flags; - /** @brief High Base */ - uint8_t BaseHigh; - } __packed GlobalDescriptorTableEntry; + /** @brief Limit 0:15 */ + uint16_t Limit0 : 16; - typedef struct _GlobalDescriptorTableEntries + /** @brief Low Base 0:15 */ + uint16_t BaseLow : 16; + + /** @brief Middle Base 16:23 */ + uint8_t BaseMiddle : 8; + + /** @brief Access */ + union GlobalDescriptorTableAccess + { + struct + { + /** @brief Access bit. + * @note The CPU sets this bit to 1 when the segment is accessed. + */ + uint8_t A : 1; + + /** @brief Readable bit for code segments, writable bit for data segments. + * @details For code segments, this bit must be 1 for the segment to be readable. + * @details For data segments, this bit must be 1 for the segment to be writable. + */ + uint8_t RW : 1; + + /** @brief Direction bit for data segments, conforming bit for code segments. + * @details For data segments, this bit must be 1 for the segment to grow up (higher addresses). + * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level. + */ + uint8_t DC : 1; + + /** @brief Executable bit. + * @details This bit must be 1 for code-segment descriptors. + * @details This bit must be 0 for data-segment and system descriptors. + */ + uint8_t E : 1; + + /** @brief Descriptor type. + * @details This bit must be 0 for system descriptors. + * @details This bit must be 1 for code or data segment descriptor. + */ + uint8_t S : 1; + + /** @brief Descriptor privilege level. + * @details This field determines the privilege level of the segment. + * @details 0 = kernel mode, 3 = user mode. + */ + uint8_t DPL : 2; + + /** @brief Present bit. + * @details This bit must be 1 for all valid descriptors. + */ + uint8_t P : 1; + } __packed; + uint8_t Raw : 8; + } Access; + + // /** @brief Limit 16:19 */ + // uint16_t Limit1 : 4; + + /** @brief Flags */ + union GlobalDescriptorTableFlags + { + struct + { + uint8_t Reserved : 4; /* FIXME: Without this, the kernel crashes. */ + /** @brief Available bit. + * @details This bit is available for use by system software. + */ + uint8_t AVL : 1; + + /** @brief Long mode. + * @details If the long mode bit is clear, the segment is in 32-bit protected mode. + * @details If the long mode bit is set, the segment is in 64-bit long mode. + */ + uint8_t L : 1; + + /** @brief Size flag. + * @details If the size bit is clear, the segment is in 16-bit protected mode. + * @details If the size bit is set, the segment is in 32-bit protected mode. + */ + uint8_t DB : 1; + + /** @brief Granularity bit. + * @details If the granularity bit is clear, the segment limit is in 1 B blocks. + * @details If the granularity bit is set, the segment limit is in 4 KiB blocks. + */ + uint8_t G : 1; + } __packed; + uint8_t Raw : 8; + } Flags; + + /** @brief High Base 24:31 */ + uint8_t BaseHigh : 8; + } __packed; + + struct GlobalDescriptorTableEntries { GlobalDescriptorTableEntry Null; GlobalDescriptorTableEntry Code; @@ -137,20 +198,21 @@ namespace GlobalDescriptorTable GlobalDescriptorTableEntry UserData; GlobalDescriptorTableEntry UserCode; TaskStateSegmentEntry TaskStateSegment; - } __packed GlobalDescriptorTableEntries; + } __packed; - typedef struct _GlobalDescriptorTableDescriptor + struct GlobalDescriptorTableDescriptor { /** @brief GDT entries length */ uint16_t Length; /** @brief GDT entries address */ GlobalDescriptorTableEntries *Entries; - } __packed GlobalDescriptorTableDescriptor; + } __packed; extern void *CPUStackPointer[]; extern TaskStateSegment tss[]; void Init(int Core); void SetKernelStack(void *Stack); + void *GetKernelStack(); } #define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code) diff --git a/Architecture/i386/cpu/idt.hpp b/Architecture/i386/cpu/idt.hpp index 204072a..c4bf5f0 100644 --- a/Architecture/i386/cpu/idt.hpp +++ b/Architecture/i386/cpu/idt.hpp @@ -22,6 +22,48 @@ namespace InterruptDescriptorTable { + typedef enum _InterruptGateType + { + TASK = 0b101, + INT_16BIT = 0b110, + TRAP_16BIT = 0b111, + INT_32BIT = 0b1110, + TRAP_32BIT = 0b1111, + } InterruptGateType; + + typedef enum _InterruptRingType + { + RING0 = 0b0, + RING1 = 0b1, + RING2 = 0b10, + RING3 = 0b11, + } InterruptRingType; + + typedef struct _InterruptDescriptorTableEntry + { + uint32_t LowOffset : 16; + uint32_t SegmentSelector : 16; + uint32_t Reserved0 : 5; + uint32_t Flags : 4; + uint32_t Reserved1 : 1; + uint32_t Ring : 2; + uint32_t Present : 1; + uint32_t HighOffset : 16; + } __packed InterruptDescriptorTableEntry; + + typedef struct _InterruptDescriptorTableDescriptor + { + uint16_t Length; + InterruptDescriptorTableEntry *Entries; + } __packed InterruptDescriptorTableDescriptor; + + void SetEntry(uint8_t Index, + void (*Base)(), + InterruptGateType Gate, + InterruptRingType Ring, + bool Present, + uint16_t SegmentSelector); + void Init(int Core); } diff --git a/Core/Crash/CrashHandler.cpp b/Core/Crash/CrashHandler.cpp index 175f406..2ede6ef 100644 --- a/Core/Crash/CrashHandler.cpp +++ b/Core/Crash/CrashHandler.cpp @@ -817,8 +817,8 @@ namespace CrashHandler { // TODO: SUPPORT SMP CPU::Interrupts(CPU::Disable); - SBIdx = 255; CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data; + SBIdx = 255; #if defined(a64) debug("-----------------------------------------------------------------------------------"); error("Exception: %#llx", Frame->InterruptNumber); diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 7d29c4e..8f9244f 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -57,7 +57,7 @@ static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line, case DebugLevelUbsan: { DbgLvlString = "UBSAN"; - fctprintf(uart_wrapper, nullptr, "%s|%s: ", DbgLvlString, Function); + fctprintf(uart_wrapper, nullptr, "%s| ", DbgLvlString); return; } default: diff --git a/Core/Driver/Driver.cpp b/Core/Driver/Driver.cpp index 0f392e3..613b42a 100644 --- a/Core/Driver/Driver.cpp +++ b/Core/Driver/Driver.cpp @@ -245,10 +245,7 @@ namespace Driver } } else - { KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status); - CPU::Stop(); - } vfs->Close(DriverDirectory); } diff --git a/Core/InterruptsManager.cpp b/Core/InterruptsManager.cpp index c169c0c..9fae563 100644 --- a/Core/InterruptsManager.cpp +++ b/Core/InterruptsManager.cpp @@ -77,7 +77,22 @@ namespace Interrupts debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE); InitializeSystemCalls(); #elif defined(a32) - warn("i386 is not supported yet"); + GlobalDescriptorTable::Init(Core); + InterruptDescriptorTable::Init(Core); + CPUData *CoreData = GetCPU(Core); + CoreData->Checksum = CPU_DATA_CHECKSUM; + CPU::x32::wrmsr(CPU::x32::MSR_GS_BASE, (uint64_t)CoreData); + CPU::x32::wrmsr(CPU::x32::MSR_SHADOW_GS_BASE, (uint64_t)CoreData); + CoreData->ID = Core; + CoreData->IsActive = true; + CoreData->SystemCallStack = (uint8_t *)((uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE); + CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE; + if (CoreData->Checksum != CPU_DATA_CHECKSUM) + { + KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM); + CPU::Stop(); + } + debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE); #elif defined(aa64) warn("aarch64 is not supported yet"); #endif diff --git a/Core/Memory/ReserveEssentials.cpp b/Core/Memory/ReserveEssentials.cpp index 14f7268..1041380 100644 --- a/Core/Memory/ReserveEssentials.cpp +++ b/Core/Memory/ReserveEssentials.cpp @@ -120,6 +120,9 @@ namespace Memory for (size_t t = 0; t < TableSize; t++) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" + // TODO: Should I be concerned about unaligned memory access? ACPI::ACPI::ACPIHeader *SDTHdr = nullptr; if (XSDT) @@ -127,6 +130,8 @@ namespace Memory else SDTHdr = (ACPI::ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIPtr + sizeof(ACPI::ACPI::ACPIHeader) + (t * 4))); +#pragma GCC diagnostic pop + this->ReservePages(SDTHdr, TO_PAGES(SDTHdr->Length)); } diff --git a/Core/Symbols.cpp b/Core/Symbols.cpp index e5e5402..367855d 100644 --- a/Core/Symbols.cpp +++ b/Core/Symbols.cpp @@ -49,6 +49,10 @@ namespace SymbolResolver __no_sanitize("alignment") void Symbols::AddBySymbolInfo(uint64_t Num, uint64_t EntSize, uint64_t Shndx, uintptr_t Sections) { +#ifdef a32 + fixme("Function not working on 32-bit"); + return; +#endif if (this->TotalEntries >= 0x10000) { error("Symbol table is full"); diff --git a/Core/SystemManagementBIOS.cpp b/Core/SystemManagementBIOS.cpp index a58caa4..c0ad12f 100644 --- a/Core/SystemManagementBIOS.cpp +++ b/Core/SystemManagementBIOS.cpp @@ -36,7 +36,7 @@ namespace SMBIOS SMBIOSEntryPoint *GetSMBIOSEntryPoint() { return (SMBIOSEntryPoint *)bInfo.SMBIOSPtr; } - static inline int SMBIOSTableLength(SMBIOSHeader *Hdr) + __no_sanitize("alignment") static inline int SMBIOSTableLength(SMBIOSHeader *Hdr) { int i; const char *strtab = (char *)Hdr + Hdr->Length; @@ -45,7 +45,7 @@ namespace SMBIOS return Hdr->Length + i + 1; } - void *GetSMBIOSHeader(SMBIOSType Type) + __no_sanitize("alignment") void *GetSMBIOSHeader(SMBIOSType Type) { if (!CheckSMBIOS()) return nullptr; diff --git a/Core/UndefinedBehaviorSanitization.c b/Core/UndefinedBehaviorSanitization.c index 8d19125..82303a9 100644 --- a/Core/UndefinedBehaviorSanitization.c +++ b/Core/UndefinedBehaviorSanitization.c @@ -382,216 +382,121 @@ const char *Type_Check_Kinds[] = { "Cast to virtual base of", }; -bool UBSANMsg(const char *file, uint32_t line, uint32_t column) -{ - /* This can be ignored (unaligned memory access) */ - if (strstr(file, "AdvancedConfigurationAndPowerInterface.cpp") && - ((line == 34 && column == 47) || - (line == 36 && column == 47))) - return false; - - /* This can be ignored (unaligned memory access) */ - if (strstr(file, "SystemManagementBIOS.cpp") && - ((line == 47 && column == 21) || - (line == 44 && column == 49) || - (line == 62 && column == 26))) - return false; - - /* This can be ignored (unaligned memory access) */ - if (strstr(file, "DynamicHostConfigurationProtocol.cpp") && - (line == 63 && column == 30)) - return false; - - if (strstr(file, "liballoc_1_1.c")) - return false; - - /* This can be ignored (store address x with insufficient space for object of type 'y') */ - if (strstr(file, "Task.cpp") && line > 500) - return false; - - /* This can be ignored (store address x with insufficient space for object of type 'y') */ - if (strstr(file, "InternetProtocol.cpp") && - ((line == 66 && column == 13) || - (line == 66 && column == 93) || - (line == 68 && column == 51) || - (line == 68 && column == 165) || - (line == 73 && column == 36) || - (line == 78 && column == 54) || - (line == 79 && column == 64) || - - (line == 81 && column == 126) || - (line == 81 && column == 165) || - - (line == 81 && column == 15) || - (line == 156 && column == 38) || - (line == 157 && column == 47) || - (line == 158 && column == 45))) - return false; - - /* This can be ignored (store address x with insufficient space for object of type 'y') */ - if (strstr(file, "DynamicHostConfigurationProtocol.cpp") && - ((line == 156 && column == 38) || - (line == 157 && column == 47) || - (line == 158 && column == 45))) - return false; - - ubsan("\t\tIn File: %s:%i:%i", file, line, column); - return true; -} - void __ubsan_handle_type_mismatch_v1(struct type_mismatch_v1_data *type_mismatch, uintptr_t pointer) { struct source_location *location = &type_mismatch->location; if (pointer == 0) { - if (UBSANMsg(location->file, location->line, location->column)) - { - ubsan("Null pointer access."); - } + ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column); + ubsan("Null pointer access."); } else if (type_mismatch->alignment != 0 && is_aligned(pointer, type_mismatch->alignment)) { - if (UBSANMsg(location->file, location->line, location->column)) - { - ubsan("Unaligned memory access %#llx.", pointer); - } + ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column); + ubsan("Unaligned memory access %#llx.", pointer); } else { - if (UBSANMsg(location->file, location->line, location->column)) - { - ubsan("%s address %#llx with insufficient space for object of type %s", - Type_Check_Kinds[type_mismatch->type_check_kind], (void *)pointer, type_mismatch->type->name); - } + ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column); + ubsan("%s address %#llx with insufficient space for object of type %s", + Type_Check_Kinds[type_mismatch->type_check_kind], (void *)pointer, type_mismatch->type->name); } } void __ubsan_handle_add_overflow(struct overflow_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Addition overflow."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Addition overflow."); } void __ubsan_handle_sub_overflow(struct overflow_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Subtraction overflow."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Subtraction overflow."); } void __ubsan_handle_mul_overflow(struct overflow_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Multiplication overflow."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Multiplication overflow."); } void __ubsan_handle_divrem_overflow(struct overflow_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Division overflow."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Division overflow."); } void __ubsan_handle_negate_overflow(struct overflow_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Negation overflow."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Negation overflow."); } void __ubsan_handle_pointer_overflow(struct overflow_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Pointer overflow."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Pointer overflow."); } void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Shift out of bounds."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Shift out of bounds."); } void __ubsan_handle_load_invalid_value(struct invalid_value_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Invalid load value."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Invalid load value."); } void __ubsan_handle_out_of_bounds(struct array_out_of_bounds_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Array out of bounds."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Array out of bounds."); } void __ubsan_handle_vla_bound_not_positive(struct negative_vla_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Variable-length argument is negative."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Variable-length argument is negative."); } void __ubsan_handle_nonnull_return(struct nonnull_return_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Non-null return is null."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Non-null return is null."); } void __ubsan_handle_nonnull_return_v1(struct nonnull_return_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Non-null return is null."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Non-null return is null."); } void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Non-null argument is null."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Non-null argument is null."); } void __ubsan_handle_builtin_unreachable(struct unreachable_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Unreachable code reached."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Unreachable code reached."); } void __ubsan_handle_invalid_builtin(struct invalid_builtin_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Invalid builtin."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Invalid builtin."); } void __ubsan_handle_missing_return(struct unreachable_data *data) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Missing return."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Missing return."); } void __ubsan_vptr_type_cache(uintptr_t *cache, uintptr_t ptr) @@ -602,9 +507,7 @@ void __ubsan_vptr_type_cache(uintptr_t *cache, uintptr_t ptr) void __ubsan_handle_dynamic_type_cache_miss(struct dynamic_type_cache_miss_data *data, uintptr_t ptr) { - if (UBSANMsg(data->location.file, data->location.line, data->location.column)) - { - ubsan("Dynamic type cache miss."); - } + ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column); + ubsan("Dynamic type cache miss."); UNUSED(ptr); } \ No newline at end of file diff --git a/Core/UniversalAsynchronousReceiverTransmitter.cpp b/Core/UniversalAsynchronousReceiverTransmitter.cpp index e9b7961..d18c73b 100644 --- a/Core/UniversalAsynchronousReceiverTransmitter.cpp +++ b/Core/UniversalAsynchronousReceiverTransmitter.cpp @@ -105,15 +105,18 @@ namespace UniversalAsynchronousReceiverTransmitter NoProfiler_outportb(s_cst(uint16_t, Port + 2), 0xC7); // Enable FIFO, clear them, with 14-byte threshold NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0B); // IRQs enabled, RTS/DSR set + /* FIXME https://wiki.osdev.org/Serial_Ports */ + // NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0x1E); + // NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0xAE); // Check if the serial port is faulty. - if (NoProfiler_inportb(s_cst(uint16_t, Port + 0)) != 0xAE) - { - static int once = 0; - if (!once++) - warn("Serial port %#llx is faulty.", Port); - // serialports[Port] = false; // ignore for now - // return; - } + // if (NoProfiler_inportb(s_cst(uint16_t, Port + 0)) != 0xAE) + // { + // static int once = 0; + // if (!once++) + // warn("Serial port %#llx is faulty.", Port); + // // serialports[Port] = false; // ignore for now + // // return; + // } // Set to normal operation mode. NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0F); diff --git a/Kernel.cpp b/Kernel.cpp index 0dace43..30337c3 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -536,7 +536,6 @@ EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info) TestString(); TestMemoryAllocation(); #endif - EnableProfiler = true; Main(); } diff --git a/KernelThread.cpp b/KernelThread.cpp index 5ee9d94..de9beb6 100644 --- a/KernelThread.cpp +++ b/KernelThread.cpp @@ -276,7 +276,7 @@ Execute::SpawnData SpawnInit() /* Files: 0.tga 1.tga ... 26.tga */ void *Frames[27]; uint32_t FrameSizes[27]; -uint32_t FrameCount = 1; +size_t FrameCount = 1; void BootLogoAnimationThread() { diff --git a/Network/DynamicHostConfigurationProtocol.cpp b/Network/DynamicHostConfigurationProtocol.cpp index 6471285..3f0380a 100644 --- a/Network/DynamicHostConfigurationProtocol.cpp +++ b/Network/DynamicHostConfigurationProtocol.cpp @@ -50,7 +50,7 @@ namespace NetworkDHCP debug("DHCP interface %#lx destroyed.", this); } - void DHCP::CreatePacket(DHCPHeader *Packet, uint8_t MessageType, uint32_t RequestIP) + __no_sanitize("alignment") void DHCP::CreatePacket(DHCPHeader *Packet, uint8_t MessageType, uint32_t RequestIP) { Packet->Opcode = b8(DHCP_OP_BOOTREQUEST); Packet->HardwareType = b8(1); @@ -153,7 +153,7 @@ namespace NetworkDHCP return nullptr; } - void DHCP::OnUDPPacketReceived(NetworkUDP::Socket *Socket, uint8_t *Data, size_t Length) + __no_sanitize("alignment") void DHCP::OnUDPPacketReceived(NetworkUDP::Socket *Socket, uint8_t *Data, size_t Length) { UNUSED(Socket); UNUSED(Length); diff --git a/Network/InternetProtocol.cpp b/Network/InternetProtocol.cpp index ccd3f9d..ae897c7 100644 --- a/Network/InternetProtocol.cpp +++ b/Network/InternetProtocol.cpp @@ -68,7 +68,7 @@ namespace NetworkIPv4 std::vector RegisteredEvents; - bool IPv4::OnEthernetPacketReceived(uint8_t *Data, size_t Length) + __no_sanitize("alignment") bool IPv4::OnEthernetPacketReceived(uint8_t *Data, size_t Length) { IPv4Packet *Packet = (IPv4Packet *)Data; netdbg("Received %d bytes [Protocol %ld]", Length, Packet->Header.Protocol); diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index 9e204d6..ec079d3 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -347,15 +347,15 @@ namespace Tasking NextTID--; } - TCB *Task::CreateThread(PCB *Parent, - IP EntryPoint, - const char **argv, - const char **envp, - const std::vector &auxv, - IPOffset Offset, - TaskArchitecture Architecture, - TaskCompatibility Compatibility, - bool ThreadNotReady) + __no_sanitize("undefined") TCB *Task::CreateThread(PCB *Parent, + IP EntryPoint, + const char **argv, + const char **envp, + const std::vector &auxv, + IPOffset Offset, + TaskArchitecture Architecture, + TaskCompatibility Compatibility, + bool ThreadNotReady) { SmartLock(TaskingLock); TCB *Thread = new TCB; diff --git a/Tests/MemoryAllocation.cpp b/Tests/MemoryAllocation.cpp index b61c188..1810a42 100644 --- a/Tests/MemoryAllocation.cpp +++ b/Tests/MemoryAllocation.cpp @@ -247,7 +247,7 @@ void TestMemoryAllocation() assert(InvMlc == nullptr); kfree(InvMlc); - debug("Memory Test Complete\n"); + debug("Memory Test Complete"); } #endif // DEBUG diff --git a/include/cpu.hpp b/include/cpu.hpp index 9b6b9a2..160534f 100644 --- a/include/cpu.hpp +++ b/include/cpu.hpp @@ -262,21 +262,31 @@ namespace CPU typedef struct TrapFrame { - uint32_t ebp; // Base Pointer (meant for stack frames) + // uint32_t ebp; // Base Pointer (meant for stack frames) + // uint32_t edi; // Destination index for string operations + // uint32_t esi; // Source index for string operations + // uint32_t edx; // Data (commonly extends the A register) + // uint32_t ecx; // Counter + // uint32_t ebx; // Base + // uint32_t eax; // Accumulator + uint32_t edi; // Destination index for string operations uint32_t esi; // Source index for string operations + uint32_t ebp; // Base Pointer (meant for stack frames) + uint32_t esp; // Stack Pointer + uint32_t ebx; // Base uint32_t edx; // Data (commonly extends the A register) uint32_t ecx; // Counter - uint32_t ebx; // Base uint32_t eax; // Accumulator uint32_t InterruptNumber; // Interrupt Number uint32_t ErrorCode; // Error code - uint32_t eip; // Instruction Pointer - uint32_t cs; // Code Segment - EFLAGS eflags; // Register Flags - uint32_t esp; // Stack Pointer - uint32_t ss; // Stack Segment + + uint32_t eip; // Instruction Pointer + uint32_t cs; // Code Segment + EFLAGS eflags; // Register Flags + // uint32_t esp; // Stack Pointer + uint32_t ss; // Stack Segment } TrapFrame; // ! TODO: UNTESTED! @@ -359,7 +369,7 @@ namespace CPU */ static inline void cpuid(uint32_t Function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { -#if defined(a32) +#ifdef a32 asmv("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(Function)); @@ -372,9 +382,36 @@ namespace CPU #endif } + SafeFunction static inline void lgdt(void *gdt) + { +#ifdef a32 + asmv("lgdt (%0)" + : + : "r"(gdt)); +#endif + } + + SafeFunction static inline void lidt(void *idt) + { +#ifdef a32 + asmv("lidt (%0)" + : + : "r"(idt)); +#endif + } + + SafeFunction static inline void ltr(uint16_t Segment) + { +#ifdef a32 + asmv("ltr %0" + : + : "r"(Segment)); +#endif + } + SafeFunction static inline void invlpg(void *Address) { -#if defined(a32) +#ifdef a32 asmv("invlpg (%0)" : : "r"(Address) @@ -386,7 +423,7 @@ namespace CPU SafeFunction static inline void fxsave(void *FXSaveArea) { -#if defined(a32) +#ifdef a32 if (!FXSaveArea) return; @@ -399,7 +436,7 @@ namespace CPU SafeFunction static inline void fxrstor(void *FXRstorArea) { -#if defined(a32) +#ifdef a32 if (!FXRstorArea) return; @@ -515,11 +552,12 @@ namespace CPU uint64_t InterruptNumber; // Interrupt Number uint64_t ErrorCode; // Error code - uint64_t rip; // Instruction Pointer - uint64_t cs; // Code Segment - RFLAGS rflags; // Register Flags - uint64_t rsp; // Stack Pointer - uint64_t ss; // Stack Segment + + uint64_t rip; // Instruction Pointer + uint64_t cs; // Code Segment + RFLAGS rflags; // Register Flags + uint64_t rsp; // Stack Pointer + uint64_t ss; // Stack Segment } TrapFrame; typedef union EFER @@ -673,7 +711,7 @@ namespace CPU SafeFunction static inline void lgdt(void *gdt) { -#if defined(a64) +#ifdef a64 asmv("lgdt (%0)" : : "r"(gdt)); @@ -682,7 +720,7 @@ namespace CPU SafeFunction static inline void lidt(void *idt) { -#if defined(a64) +#ifdef a64 asmv("lidt (%0)" : : "r"(idt)); @@ -691,7 +729,7 @@ namespace CPU SafeFunction static inline void ltr(uint16_t Segment) { -#if defined(a64) +#ifdef a64 asmv("ltr %0" : : "r"(Segment)); @@ -700,7 +738,7 @@ namespace CPU SafeFunction static inline void invlpg(void *Address) { -#if defined(a64) +#ifdef a64 asmv("invlpg (%0)" : : "r"(Address) @@ -719,7 +757,7 @@ namespace CPU */ SafeFunction static inline void cpuid(uint32_t Function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { -#if defined(a64) +#ifdef a64 asmv("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(Function)); @@ -742,7 +780,7 @@ namespace CPU SafeFunction static inline void fxsave(void *FXSaveArea) { -#if defined(a64) +#ifdef a64 if (!FXSaveArea || FXSaveArea >= (char *)0xfffffffffffff000) return; @@ -755,7 +793,7 @@ namespace CPU SafeFunction static inline void fxrstor(void *FXRstorArea) { -#if defined(a64) +#ifdef a64 if (!FXRstorArea || FXRstorArea >= (char *)0xfffffffffffff000) return;