mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-28 15:34:33 +00:00
Add implementation for GDT & IDT on x32 and QoL fixes
This commit is contained in:
parent
f3044ceb5f
commit
d527121883
@ -22,14 +22,15 @@
|
|||||||
|
|
||||||
#include "../../kernel.h"
|
#include "../../kernel.h"
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
|
|
||||||
|
|
||||||
namespace ACPI
|
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++)
|
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?
|
// TODO: Should I be concerned about unaligned memory access?
|
||||||
ACPI::ACPIHeader *SDTHdr = nullptr;
|
ACPI::ACPIHeader *SDTHdr = nullptr;
|
||||||
if (XSDTSupported)
|
if (XSDTSupported)
|
||||||
@ -37,6 +38,8 @@ namespace ACPI
|
|||||||
else
|
else
|
||||||
SDTHdr = (ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 4)));
|
SDTHdr = (ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 4)));
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (SDTHdr->Signature[i] != Signature[i])
|
if (SDTHdr->Signature[i] != Signature[i])
|
||||||
|
@ -27,17 +27,18 @@ namespace GlobalDescriptorTable
|
|||||||
static GlobalDescriptorTableEntries GDTEntriesTemplate = {
|
static GlobalDescriptorTableEntries GDTEntriesTemplate = {
|
||||||
.Null =
|
.Null =
|
||||||
{
|
{
|
||||||
.Length = 0x0,
|
.Limit0 = 0x0,
|
||||||
.BaseLow = 0x0,
|
.BaseLow = 0x0,
|
||||||
.BaseMiddle = 0x0,
|
.BaseMiddle = 0x0,
|
||||||
.Access = {.Raw = 0x0},
|
.Access = {.Raw = 0x0},
|
||||||
|
// .Limit1 = 0x0,
|
||||||
.Flags = {.Raw = 0x0},
|
.Flags = {.Raw = 0x0},
|
||||||
.BaseHigh = 0x0,
|
.BaseHigh = 0x0,
|
||||||
},
|
},
|
||||||
|
|
||||||
.Code =
|
.Code =
|
||||||
{
|
{
|
||||||
.Length = 0x0,
|
.Limit0 = 0xFFFF,
|
||||||
.BaseLow = 0x0,
|
.BaseLow = 0x0,
|
||||||
.BaseMiddle = 0x0,
|
.BaseMiddle = 0x0,
|
||||||
.Access = {
|
.Access = {
|
||||||
@ -49,15 +50,20 @@ namespace GlobalDescriptorTable
|
|||||||
.DPL = 0,
|
.DPL = 0,
|
||||||
.P = 1,
|
.P = 1,
|
||||||
},
|
},
|
||||||
|
// .Limit1 = 0xF,
|
||||||
.Flags = {
|
.Flags = {
|
||||||
.Unknown = 0x0,
|
.Reserved = 0xF, /* Workaround for Limit1 */
|
||||||
|
|
||||||
|
.AVL = 0,
|
||||||
.L = 1,
|
.L = 1,
|
||||||
|
.DB = 0,
|
||||||
|
.G = 1,
|
||||||
},
|
},
|
||||||
.BaseHigh = 0x0,
|
.BaseHigh = 0x0,
|
||||||
},
|
},
|
||||||
|
|
||||||
.Data = {
|
.Data = {
|
||||||
.Length = 0x0,
|
.Limit0 = 0xFFFF,
|
||||||
.BaseLow = 0x0,
|
.BaseLow = 0x0,
|
||||||
.BaseMiddle = 0x0,
|
.BaseMiddle = 0x0,
|
||||||
.Access = {
|
.Access = {
|
||||||
@ -69,12 +75,20 @@ namespace GlobalDescriptorTable
|
|||||||
.DPL = 0,
|
.DPL = 0,
|
||||||
.P = 1,
|
.P = 1,
|
||||||
},
|
},
|
||||||
.Flags = {.Raw = 0x0},
|
// .Limit1 = 0xF,
|
||||||
|
.Flags = {
|
||||||
|
.Reserved = 0xF, /* Workaround for Limit1 */
|
||||||
|
|
||||||
|
.AVL = 0,
|
||||||
|
.L = 0,
|
||||||
|
.DB = 1,
|
||||||
|
.G = 1,
|
||||||
|
},
|
||||||
.BaseHigh = 0x0,
|
.BaseHigh = 0x0,
|
||||||
},
|
},
|
||||||
|
|
||||||
.UserData = {
|
.UserData = {
|
||||||
.Length = 0x0,
|
.Limit0 = 0xFFFF,
|
||||||
.BaseLow = 0x0,
|
.BaseLow = 0x0,
|
||||||
.BaseMiddle = 0x0,
|
.BaseMiddle = 0x0,
|
||||||
.Access = {
|
.Access = {
|
||||||
@ -86,14 +100,20 @@ namespace GlobalDescriptorTable
|
|||||||
.DPL = 3,
|
.DPL = 3,
|
||||||
.P = 1,
|
.P = 1,
|
||||||
},
|
},
|
||||||
|
// .Limit1 = 0xF,
|
||||||
.Flags = {
|
.Flags = {
|
||||||
.Raw = 0x0,
|
.Reserved = 0xF, /* Workaround for Limit1 */
|
||||||
|
|
||||||
|
.AVL = 0,
|
||||||
|
.L = 0,
|
||||||
|
.DB = 1,
|
||||||
|
.G = 1,
|
||||||
},
|
},
|
||||||
.BaseHigh = 0x0,
|
.BaseHigh = 0x0,
|
||||||
},
|
},
|
||||||
|
|
||||||
.UserCode = {
|
.UserCode = {
|
||||||
.Length = 0x0,
|
.Limit0 = 0xFFFF,
|
||||||
.BaseLow = 0x0,
|
.BaseLow = 0x0,
|
||||||
.BaseMiddle = 0x0,
|
.BaseMiddle = 0x0,
|
||||||
.Access = {
|
.Access = {
|
||||||
@ -105,9 +125,14 @@ namespace GlobalDescriptorTable
|
|||||||
.DPL = 3,
|
.DPL = 3,
|
||||||
.P = 1,
|
.P = 1,
|
||||||
},
|
},
|
||||||
|
// .Limit1 = 0xF,
|
||||||
.Flags = {
|
.Flags = {
|
||||||
.Unknown = 0x0,
|
.Reserved = 0xF, /* Workaround for Limit1 */
|
||||||
|
|
||||||
|
.AVL = 0,
|
||||||
.L = 1,
|
.L = 1,
|
||||||
|
.DB = 0,
|
||||||
|
.G = 1,
|
||||||
},
|
},
|
||||||
.BaseHigh = 0x0,
|
.BaseHigh = 0x0,
|
||||||
},
|
},
|
||||||
@ -135,10 +160,47 @@ namespace GlobalDescriptorTable
|
|||||||
memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries));
|
memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries));
|
||||||
gdt[Core] = {.Length = sizeof(GlobalDescriptorTableEntries) - 1, .Entries = &GDTEntries[Core]};
|
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("GDT: %#lx", &gdt[Core]);
|
||||||
debug("Kernel: Code Flags: %ld; Data Flags: %ld", GDTEntries[Core].Code.Flags.Raw, GDTEntries[Core].Data.Flags.Raw);
|
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",
|
||||||
debug("User: Code Access: %ld; Data Access: %ld", GDTEntries[Core].UserCode.Access.Raw, GDTEntries[Core].UserData.Access.Raw);
|
GDT_KERNEL_CODE,
|
||||||
debug("User: Code Flags: %ld; Data Flags: %ld", GDTEntries[Core].UserCode.Flags.Raw, GDTEntries[Core].UserData.Flags.Raw);
|
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]);
|
CPU::x64::lgdt(&gdt[Core]);
|
||||||
|
|
||||||
asmv("movq %%rsp, %%rax\n"
|
asmv("movq %%rsp, %%rax\n"
|
||||||
@ -162,16 +224,18 @@ namespace GlobalDescriptorTable
|
|||||||
|
|
||||||
uintptr_t Base = (uintptr_t)&tss[Core];
|
uintptr_t Base = (uintptr_t)&tss[Core];
|
||||||
size_t Limit = Base + sizeof(TaskStateSegment);
|
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.BaseLow = Base & 0xFFFF;
|
||||||
gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF;
|
gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF;
|
||||||
gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 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.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);
|
gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF);
|
||||||
|
|
||||||
tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment);
|
tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment);
|
||||||
tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE;
|
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++)
|
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);
|
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");
|
debug("Global Descriptor Table initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,88 +22,66 @@
|
|||||||
|
|
||||||
namespace GlobalDescriptorTable
|
namespace GlobalDescriptorTable
|
||||||
{
|
{
|
||||||
/** @brief The GDT Access Table
|
struct TaskStateSegmentEntry
|
||||||
* @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
|
|
||||||
{
|
{
|
||||||
/* LOW */
|
/* LOW */
|
||||||
uint16_t Length;
|
uint16_t Limit;
|
||||||
uint16_t BaseLow;
|
uint16_t BaseLow;
|
||||||
uint8_t BaseMiddle;
|
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 Granularity;
|
||||||
uint8_t BaseHigh;
|
uint8_t BaseHigh;
|
||||||
/* HIGH */
|
/* HIGH */
|
||||||
uint32_t BaseUpper;
|
uint32_t BaseUpper;
|
||||||
uint32_t Reserved;
|
uint32_t Reserved;
|
||||||
} __packed TaskStateSegmentEntry;
|
} __packed;
|
||||||
|
|
||||||
typedef struct _TaskStateSegment
|
struct TaskStateSegment
|
||||||
{
|
{
|
||||||
uint32_t Reserved0 __aligned(16);
|
uint32_t Reserved0 __aligned(16);
|
||||||
uint64_t StackPointer[3];
|
uint64_t StackPointer[3];
|
||||||
@ -112,25 +90,107 @@ namespace GlobalDescriptorTable
|
|||||||
uint64_t Reserved2;
|
uint64_t Reserved2;
|
||||||
uint16_t Reserved3;
|
uint16_t Reserved3;
|
||||||
uint16_t IOMapBaseAddressOffset;
|
uint16_t IOMapBaseAddressOffset;
|
||||||
} __packed TaskStateSegment;
|
} __packed;
|
||||||
|
|
||||||
typedef struct _GlobalDescriptorTableEntry
|
struct GlobalDescriptorTableEntry
|
||||||
{
|
{
|
||||||
/** @brief Length */
|
/** @brief Limit 0:15 */
|
||||||
uint16_t Length;
|
uint16_t Limit0 : 16;
|
||||||
/** @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;
|
|
||||||
|
|
||||||
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 Null;
|
||||||
GlobalDescriptorTableEntry Code;
|
GlobalDescriptorTableEntry Code;
|
||||||
@ -138,15 +198,15 @@ namespace GlobalDescriptorTable
|
|||||||
GlobalDescriptorTableEntry UserData;
|
GlobalDescriptorTableEntry UserData;
|
||||||
GlobalDescriptorTableEntry UserCode;
|
GlobalDescriptorTableEntry UserCode;
|
||||||
TaskStateSegmentEntry TaskStateSegment;
|
TaskStateSegmentEntry TaskStateSegment;
|
||||||
} __packed GlobalDescriptorTableEntries;
|
} __packed;
|
||||||
|
|
||||||
typedef struct _GlobalDescriptorTableDescriptor
|
struct GlobalDescriptorTableDescriptor
|
||||||
{
|
{
|
||||||
/** @brief GDT entries length */
|
/** @brief GDT entries length */
|
||||||
uint16_t Length;
|
uint16_t Length;
|
||||||
/** @brief GDT entries address */
|
/** @brief GDT entries address */
|
||||||
GlobalDescriptorTableEntries *Entries;
|
GlobalDescriptorTableEntries *Entries;
|
||||||
} __packed GlobalDescriptorTableDescriptor;
|
} __packed;
|
||||||
|
|
||||||
extern void *CPUStackPointer[];
|
extern void *CPUStackPointer[];
|
||||||
extern TaskStateSegment tss[];
|
extern TaskStateSegment tss[];
|
||||||
|
@ -25,75 +25,123 @@
|
|||||||
namespace GlobalDescriptorTable
|
namespace GlobalDescriptorTable
|
||||||
{
|
{
|
||||||
static GlobalDescriptorTableEntries GDTEntriesTemplate = {
|
static GlobalDescriptorTableEntries GDTEntriesTemplate = {
|
||||||
// null
|
.Null =
|
||||||
{.Length = 0x0,
|
{
|
||||||
.BaseLow = 0x0,
|
.Limit0 = 0x0,
|
||||||
.BaseMiddle = 0x0,
|
.BaseLow = 0x0,
|
||||||
.Access = {.Raw = 0x0},
|
.BaseMiddle = 0x0,
|
||||||
.Flags = {.Raw = 0x0},
|
.Access = {.Raw = 0x0},
|
||||||
.BaseHigh = 0x0},
|
// .Limit1 = 0x0,
|
||||||
|
.Flags = {.Raw = 0x0},
|
||||||
|
.BaseHigh = 0x0,
|
||||||
|
},
|
||||||
|
|
||||||
// kernel code
|
.Code =
|
||||||
{.Length = 0x0,
|
{
|
||||||
.BaseLow = 0x0,
|
.Limit0 = 0xFFFF,
|
||||||
.BaseMiddle = 0x0,
|
.BaseLow = 0x0,
|
||||||
.Access = {.A = 0,
|
.BaseMiddle = 0x0,
|
||||||
|
.Access = {
|
||||||
|
.A = 0,
|
||||||
.RW = 1,
|
.RW = 1,
|
||||||
.DC = 0,
|
.DC = 0,
|
||||||
.E = 1,
|
.E = 1,
|
||||||
.S = 1,
|
.S = 1,
|
||||||
.DPL = 0,
|
.DPL = 0,
|
||||||
.P = 1},
|
.P = 1,
|
||||||
.Flags = {.Unknown = 0x0, .L = 1},
|
},
|
||||||
.BaseHigh = 0x0},
|
// .Limit1 = 0xF,
|
||||||
|
.Flags = {
|
||||||
|
.Reserved = 0xF, /* Workaround for Limit1 */
|
||||||
|
|
||||||
// kernel data
|
.AVL = 0,
|
||||||
{.Length = 0x0,
|
.L = 0,
|
||||||
.BaseLow = 0x0,
|
.DB = 1,
|
||||||
.BaseMiddle = 0x0,
|
.G = 1,
|
||||||
.Access = {.A = 0,
|
},
|
||||||
.RW = 1,
|
.BaseHigh = 0x0,
|
||||||
.DC = 0,
|
},
|
||||||
.E = 0,
|
|
||||||
.S = 1,
|
|
||||||
.DPL = 0,
|
|
||||||
.P = 1},
|
|
||||||
.Flags = {.Raw = 0x0},
|
|
||||||
.BaseHigh = 0x0},
|
|
||||||
|
|
||||||
// user data
|
.Data = {
|
||||||
{.Length = 0x0,
|
.Limit0 = 0xFFFF,
|
||||||
.BaseLow = 0x0,
|
.BaseLow = 0x0,
|
||||||
.BaseMiddle = 0x0,
|
.BaseMiddle = 0x0,
|
||||||
.Access = {.A = 0,
|
.Access = {
|
||||||
.RW = 1,
|
.A = 0,
|
||||||
.DC = 0,
|
.RW = 1,
|
||||||
.E = 0,
|
.DC = 0,
|
||||||
.S = 1,
|
.E = 0,
|
||||||
.DPL = 3,
|
.S = 1,
|
||||||
.P = 1},
|
.DPL = 0,
|
||||||
.Flags = {.Raw = 0x0},
|
.P = 1,
|
||||||
.BaseHigh = 0x0},
|
},
|
||||||
|
// .Limit1 = 0xF,
|
||||||
|
.Flags = {
|
||||||
|
.Reserved = 0xF, /* Workaround for Limit1 */
|
||||||
|
|
||||||
// user code
|
.AVL = 0,
|
||||||
{.Length = 0x0,
|
.L = 0,
|
||||||
.BaseLow = 0x0,
|
.DB = 1,
|
||||||
.BaseMiddle = 0x0,
|
.G = 1,
|
||||||
.Access = {.A = 0,
|
},
|
||||||
.RW = 1,
|
.BaseHigh = 0x0,
|
||||||
.DC = 0,
|
},
|
||||||
.E = 1,
|
|
||||||
.S = 1,
|
|
||||||
.DPL = 3,
|
|
||||||
.P = 1},
|
|
||||||
.Flags = {.Unknown = 0x0, .L = 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];
|
.AVL = 0,
|
||||||
GlobalDescriptorTableDescriptor gdt[MAX_CPU];
|
.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] = {
|
TaskStateSegment tss[MAX_CPU] = {
|
||||||
0,
|
0,
|
||||||
@ -102,15 +150,123 @@ namespace GlobalDescriptorTable
|
|||||||
{0, 0, 0, 0, 0, 0, 0},
|
{0, 0, 0, 0, 0, 0, 0},
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
void *CPUStackPointer[MAX_CPU];
|
void *CPUStackPointer[MAX_CPU];
|
||||||
|
|
||||||
SafeFunction void Init(int Core)
|
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)
|
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]; }
|
||||||
}
|
}
|
||||||
|
727
Architecture/i386/cpu/InterruptDescriptorTable.cpp
Normal file
727
Architecture/i386/cpu/InterruptDescriptorTable.cpp
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "idt.hpp"
|
||||||
|
|
||||||
|
#include <memory.hpp>
|
||||||
|
#include <cpu.hpp>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
@ -22,114 +22,175 @@
|
|||||||
|
|
||||||
namespace GlobalDescriptorTable
|
namespace GlobalDescriptorTable
|
||||||
{
|
{
|
||||||
/** @brief The GDT Access Table
|
struct TaskStateSegmentEntry
|
||||||
* @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
|
|
||||||
{
|
{
|
||||||
/* LOW */
|
/* LOW */
|
||||||
uint16_t Length;
|
uint16_t Limit;
|
||||||
uint16_t BaseLow;
|
uint16_t BaseLow;
|
||||||
uint8_t BaseMiddle;
|
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 Granularity;
|
||||||
uint8_t BaseHigh;
|
uint8_t BaseHigh;
|
||||||
/* HIGH */
|
/* HIGH */
|
||||||
uint32_t BaseUpper;
|
uint32_t BaseUpper;
|
||||||
uint32_t Reserved;
|
uint32_t Reserved;
|
||||||
} __packed TaskStateSegmentEntry;
|
} __packed;
|
||||||
|
|
||||||
typedef struct _TaskStateSegment
|
struct TaskStateSegment
|
||||||
{
|
{
|
||||||
uint32_t Reserved0 __aligned(16);
|
uint32_t Reserved0 __aligned(16);
|
||||||
uint64_t StackPointer[3];
|
uint64_t StackPointer[3];
|
||||||
uint64_t Reserved1;
|
uint64_t Reserved1;
|
||||||
uint64_t InterruptStackTable[7];
|
uint64_t InterruptStackTable[7];
|
||||||
uint16_t Reserved2;
|
uint64_t Reserved2;
|
||||||
|
uint16_t Reserved3;
|
||||||
uint16_t IOMapBaseAddressOffset;
|
uint16_t IOMapBaseAddressOffset;
|
||||||
} __packed TaskStateSegment;
|
} __packed;
|
||||||
|
|
||||||
typedef struct _GlobalDescriptorTableEntry
|
struct GlobalDescriptorTableEntry
|
||||||
{
|
{
|
||||||
/** @brief Length */
|
/** @brief Limit 0:15 */
|
||||||
uint16_t Length;
|
uint16_t Limit0 : 16;
|
||||||
/** @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;
|
|
||||||
|
|
||||||
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 Null;
|
||||||
GlobalDescriptorTableEntry Code;
|
GlobalDescriptorTableEntry Code;
|
||||||
@ -137,20 +198,21 @@ namespace GlobalDescriptorTable
|
|||||||
GlobalDescriptorTableEntry UserData;
|
GlobalDescriptorTableEntry UserData;
|
||||||
GlobalDescriptorTableEntry UserCode;
|
GlobalDescriptorTableEntry UserCode;
|
||||||
TaskStateSegmentEntry TaskStateSegment;
|
TaskStateSegmentEntry TaskStateSegment;
|
||||||
} __packed GlobalDescriptorTableEntries;
|
} __packed;
|
||||||
|
|
||||||
typedef struct _GlobalDescriptorTableDescriptor
|
struct GlobalDescriptorTableDescriptor
|
||||||
{
|
{
|
||||||
/** @brief GDT entries length */
|
/** @brief GDT entries length */
|
||||||
uint16_t Length;
|
uint16_t Length;
|
||||||
/** @brief GDT entries address */
|
/** @brief GDT entries address */
|
||||||
GlobalDescriptorTableEntries *Entries;
|
GlobalDescriptorTableEntries *Entries;
|
||||||
} __packed GlobalDescriptorTableDescriptor;
|
} __packed;
|
||||||
|
|
||||||
extern void *CPUStackPointer[];
|
extern void *CPUStackPointer[];
|
||||||
extern TaskStateSegment tss[];
|
extern TaskStateSegment tss[];
|
||||||
void Init(int Core);
|
void Init(int Core);
|
||||||
void SetKernelStack(void *Stack);
|
void SetKernelStack(void *Stack);
|
||||||
|
void *GetKernelStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code)
|
#define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code)
|
||||||
|
@ -22,6 +22,48 @@
|
|||||||
|
|
||||||
namespace InterruptDescriptorTable
|
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);
|
void Init(int Core);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,8 +817,8 @@ namespace CrashHandler
|
|||||||
{
|
{
|
||||||
// TODO: SUPPORT SMP
|
// TODO: SUPPORT SMP
|
||||||
CPU::Interrupts(CPU::Disable);
|
CPU::Interrupts(CPU::Disable);
|
||||||
SBIdx = 255;
|
|
||||||
CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data;
|
CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data;
|
||||||
|
SBIdx = 255;
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
debug("-----------------------------------------------------------------------------------");
|
debug("-----------------------------------------------------------------------------------");
|
||||||
error("Exception: %#llx", Frame->InterruptNumber);
|
error("Exception: %#llx", Frame->InterruptNumber);
|
||||||
|
@ -57,7 +57,7 @@ static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line,
|
|||||||
case DebugLevelUbsan:
|
case DebugLevelUbsan:
|
||||||
{
|
{
|
||||||
DbgLvlString = "UBSAN";
|
DbgLvlString = "UBSAN";
|
||||||
fctprintf(uart_wrapper, nullptr, "%s|%s: ", DbgLvlString, Function);
|
fctprintf(uart_wrapper, nullptr, "%s| ", DbgLvlString);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -245,10 +245,7 @@ namespace Driver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status);
|
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status);
|
||||||
CPU::Stop();
|
|
||||||
}
|
|
||||||
vfs->Close(DriverDirectory);
|
vfs->Close(DriverDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,22 @@ namespace Interrupts
|
|||||||
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
|
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
|
||||||
InitializeSystemCalls();
|
InitializeSystemCalls();
|
||||||
#elif defined(a32)
|
#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)
|
#elif defined(aa64)
|
||||||
warn("aarch64 is not supported yet");
|
warn("aarch64 is not supported yet");
|
||||||
#endif
|
#endif
|
||||||
|
@ -120,6 +120,9 @@ namespace Memory
|
|||||||
|
|
||||||
for (size_t t = 0; t < TableSize; t++)
|
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?
|
// TODO: Should I be concerned about unaligned memory access?
|
||||||
ACPI::ACPI::ACPIHeader *SDTHdr = nullptr;
|
ACPI::ACPI::ACPIHeader *SDTHdr = nullptr;
|
||||||
if (XSDT)
|
if (XSDT)
|
||||||
@ -127,6 +130,8 @@ namespace Memory
|
|||||||
else
|
else
|
||||||
SDTHdr = (ACPI::ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIPtr + sizeof(ACPI::ACPI::ACPIHeader) + (t * 4)));
|
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));
|
this->ReservePages(SDTHdr, TO_PAGES(SDTHdr->Length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,10 @@ namespace SymbolResolver
|
|||||||
|
|
||||||
__no_sanitize("alignment") void Symbols::AddBySymbolInfo(uint64_t Num, uint64_t EntSize, uint64_t Shndx, uintptr_t Sections)
|
__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)
|
if (this->TotalEntries >= 0x10000)
|
||||||
{
|
{
|
||||||
error("Symbol table is full");
|
error("Symbol table is full");
|
||||||
|
@ -36,7 +36,7 @@ namespace SMBIOS
|
|||||||
|
|
||||||
SMBIOSEntryPoint *GetSMBIOSEntryPoint() { return (SMBIOSEntryPoint *)bInfo.SMBIOSPtr; }
|
SMBIOSEntryPoint *GetSMBIOSEntryPoint() { return (SMBIOSEntryPoint *)bInfo.SMBIOSPtr; }
|
||||||
|
|
||||||
static inline int SMBIOSTableLength(SMBIOSHeader *Hdr)
|
__no_sanitize("alignment") static inline int SMBIOSTableLength(SMBIOSHeader *Hdr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char *strtab = (char *)Hdr + Hdr->Length;
|
const char *strtab = (char *)Hdr + Hdr->Length;
|
||||||
@ -45,7 +45,7 @@ namespace SMBIOS
|
|||||||
return Hdr->Length + i + 1;
|
return Hdr->Length + i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *GetSMBIOSHeader(SMBIOSType Type)
|
__no_sanitize("alignment") void *GetSMBIOSHeader(SMBIOSType Type)
|
||||||
{
|
{
|
||||||
if (!CheckSMBIOS())
|
if (!CheckSMBIOS())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -382,216 +382,121 @@ const char *Type_Check_Kinds[] = {
|
|||||||
"Cast to virtual base of",
|
"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)
|
void __ubsan_handle_type_mismatch_v1(struct type_mismatch_v1_data *type_mismatch, uintptr_t pointer)
|
||||||
{
|
{
|
||||||
struct source_location *location = &type_mismatch->location;
|
struct source_location *location = &type_mismatch->location;
|
||||||
if (pointer == 0)
|
if (pointer == 0)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(location->file, location->line, location->column))
|
ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column);
|
||||||
{
|
ubsan("Null pointer access.");
|
||||||
ubsan("Null pointer access.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (type_mismatch->alignment != 0 && is_aligned(pointer, type_mismatch->alignment))
|
else if (type_mismatch->alignment != 0 && is_aligned(pointer, type_mismatch->alignment))
|
||||||
{
|
{
|
||||||
if (UBSANMsg(location->file, location->line, location->column))
|
ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column);
|
||||||
{
|
ubsan("Unaligned memory access %#llx.", pointer);
|
||||||
ubsan("Unaligned memory access %#llx.", pointer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (UBSANMsg(location->file, location->line, location->column))
|
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",
|
||||||
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);
|
||||||
Type_Check_Kinds[type_mismatch->type_check_kind], (void *)pointer, type_mismatch->type->name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_add_overflow(struct overflow_data *data)
|
void __ubsan_handle_add_overflow(struct overflow_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Addition overflow.");
|
||||||
ubsan("Addition overflow.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_sub_overflow(struct overflow_data *data)
|
void __ubsan_handle_sub_overflow(struct overflow_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Subtraction overflow.");
|
||||||
ubsan("Subtraction overflow.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_mul_overflow(struct overflow_data *data)
|
void __ubsan_handle_mul_overflow(struct overflow_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Multiplication overflow.");
|
||||||
ubsan("Multiplication overflow.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_divrem_overflow(struct overflow_data *data)
|
void __ubsan_handle_divrem_overflow(struct overflow_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Division overflow.");
|
||||||
ubsan("Division overflow.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_negate_overflow(struct overflow_data *data)
|
void __ubsan_handle_negate_overflow(struct overflow_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Negation overflow.");
|
||||||
ubsan("Negation overflow.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_pointer_overflow(struct overflow_data *data)
|
void __ubsan_handle_pointer_overflow(struct overflow_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Pointer overflow.");
|
||||||
ubsan("Pointer overflow.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data)
|
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("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Shift out of bounds.");
|
||||||
ubsan("Shift out of bounds.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_load_invalid_value(struct invalid_value_data *data)
|
void __ubsan_handle_load_invalid_value(struct invalid_value_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Invalid load value.");
|
||||||
ubsan("Invalid load value.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_out_of_bounds(struct array_out_of_bounds_data *data)
|
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("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Array out of bounds.");
|
||||||
ubsan("Array out of bounds.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_vla_bound_not_positive(struct negative_vla_data *data)
|
void __ubsan_handle_vla_bound_not_positive(struct negative_vla_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Variable-length argument is negative.");
|
||||||
ubsan("Variable-length argument is negative.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
|
void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Non-null return is null.");
|
||||||
ubsan("Non-null return is null.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_nonnull_return_v1(struct nonnull_return_data *data)
|
void __ubsan_handle_nonnull_return_v1(struct nonnull_return_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Non-null return is null.");
|
||||||
ubsan("Non-null return is null.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data)
|
void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Non-null argument is null.");
|
||||||
ubsan("Non-null argument is null.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
|
void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Unreachable code reached.");
|
||||||
ubsan("Unreachable code reached.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_invalid_builtin(struct invalid_builtin_data *data)
|
void __ubsan_handle_invalid_builtin(struct invalid_builtin_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Invalid builtin.");
|
||||||
ubsan("Invalid builtin.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_handle_missing_return(struct unreachable_data *data)
|
void __ubsan_handle_missing_return(struct unreachable_data *data)
|
||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Missing return.");
|
||||||
ubsan("Missing return.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ubsan_vptr_type_cache(uintptr_t *cache, uintptr_t ptr)
|
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)
|
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("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||||
{
|
ubsan("Dynamic type cache miss.");
|
||||||
ubsan("Dynamic type cache miss.");
|
|
||||||
}
|
|
||||||
UNUSED(ptr);
|
UNUSED(ptr);
|
||||||
}
|
}
|
@ -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 + 2), 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||||
NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0B); // IRQs enabled, RTS/DSR set
|
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.
|
// Check if the serial port is faulty.
|
||||||
if (NoProfiler_inportb(s_cst(uint16_t, Port + 0)) != 0xAE)
|
// if (NoProfiler_inportb(s_cst(uint16_t, Port + 0)) != 0xAE)
|
||||||
{
|
// {
|
||||||
static int once = 0;
|
// static int once = 0;
|
||||||
if (!once++)
|
// if (!once++)
|
||||||
warn("Serial port %#llx is faulty.", Port);
|
// warn("Serial port %#llx is faulty.", Port);
|
||||||
// serialports[Port] = false; // ignore for now
|
// // serialports[Port] = false; // ignore for now
|
||||||
// return;
|
// // return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Set to normal operation mode.
|
// Set to normal operation mode.
|
||||||
NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0F);
|
NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0F);
|
||||||
|
@ -536,7 +536,6 @@ EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info)
|
|||||||
TestString();
|
TestString();
|
||||||
TestMemoryAllocation();
|
TestMemoryAllocation();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EnableProfiler = true;
|
EnableProfiler = true;
|
||||||
Main();
|
Main();
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ Execute::SpawnData SpawnInit()
|
|||||||
/* Files: 0.tga 1.tga ... 26.tga */
|
/* Files: 0.tga 1.tga ... 26.tga */
|
||||||
void *Frames[27];
|
void *Frames[27];
|
||||||
uint32_t FrameSizes[27];
|
uint32_t FrameSizes[27];
|
||||||
uint32_t FrameCount = 1;
|
size_t FrameCount = 1;
|
||||||
|
|
||||||
void BootLogoAnimationThread()
|
void BootLogoAnimationThread()
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@ namespace NetworkDHCP
|
|||||||
debug("DHCP interface %#lx destroyed.", this);
|
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->Opcode = b8(DHCP_OP_BOOTREQUEST);
|
||||||
Packet->HardwareType = b8(1);
|
Packet->HardwareType = b8(1);
|
||||||
@ -153,7 +153,7 @@ namespace NetworkDHCP
|
|||||||
return nullptr;
|
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(Socket);
|
||||||
UNUSED(Length);
|
UNUSED(Length);
|
||||||
|
@ -68,7 +68,7 @@ namespace NetworkIPv4
|
|||||||
|
|
||||||
std::vector<IPv4Events *> RegisteredEvents;
|
std::vector<IPv4Events *> 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;
|
IPv4Packet *Packet = (IPv4Packet *)Data;
|
||||||
netdbg("Received %d bytes [Protocol %ld]", Length, Packet->Header.Protocol);
|
netdbg("Received %d bytes [Protocol %ld]", Length, Packet->Header.Protocol);
|
||||||
|
@ -347,15 +347,15 @@ namespace Tasking
|
|||||||
NextTID--;
|
NextTID--;
|
||||||
}
|
}
|
||||||
|
|
||||||
TCB *Task::CreateThread(PCB *Parent,
|
__no_sanitize("undefined") TCB *Task::CreateThread(PCB *Parent,
|
||||||
IP EntryPoint,
|
IP EntryPoint,
|
||||||
const char **argv,
|
const char **argv,
|
||||||
const char **envp,
|
const char **envp,
|
||||||
const std::vector<AuxiliaryVector> &auxv,
|
const std::vector<AuxiliaryVector> &auxv,
|
||||||
IPOffset Offset,
|
IPOffset Offset,
|
||||||
TaskArchitecture Architecture,
|
TaskArchitecture Architecture,
|
||||||
TaskCompatibility Compatibility,
|
TaskCompatibility Compatibility,
|
||||||
bool ThreadNotReady)
|
bool ThreadNotReady)
|
||||||
{
|
{
|
||||||
SmartLock(TaskingLock);
|
SmartLock(TaskingLock);
|
||||||
TCB *Thread = new TCB;
|
TCB *Thread = new TCB;
|
||||||
|
@ -247,7 +247,7 @@ void TestMemoryAllocation()
|
|||||||
assert(InvMlc == nullptr);
|
assert(InvMlc == nullptr);
|
||||||
kfree(InvMlc);
|
kfree(InvMlc);
|
||||||
|
|
||||||
debug("Memory Test Complete\n");
|
debug("Memory Test Complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
@ -262,21 +262,31 @@ namespace CPU
|
|||||||
|
|
||||||
typedef struct TrapFrame
|
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 edi; // Destination index for string operations
|
||||||
uint32_t esi; // Source 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 edx; // Data (commonly extends the A register)
|
||||||
uint32_t ecx; // Counter
|
uint32_t ecx; // Counter
|
||||||
uint32_t ebx; // Base
|
|
||||||
uint32_t eax; // Accumulator
|
uint32_t eax; // Accumulator
|
||||||
|
|
||||||
uint32_t InterruptNumber; // Interrupt Number
|
uint32_t InterruptNumber; // Interrupt Number
|
||||||
uint32_t ErrorCode; // Error code
|
uint32_t ErrorCode; // Error code
|
||||||
uint32_t eip; // Instruction Pointer
|
|
||||||
uint32_t cs; // Code Segment
|
uint32_t eip; // Instruction Pointer
|
||||||
EFLAGS eflags; // Register Flags
|
uint32_t cs; // Code Segment
|
||||||
uint32_t esp; // Stack Pointer
|
EFLAGS eflags; // Register Flags
|
||||||
uint32_t ss; // Stack Segment
|
// uint32_t esp; // Stack Pointer
|
||||||
|
uint32_t ss; // Stack Segment
|
||||||
} TrapFrame;
|
} TrapFrame;
|
||||||
|
|
||||||
// ! TODO: UNTESTED!
|
// ! 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)
|
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"
|
asmv("cpuid"
|
||||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||||
: "a"(Function));
|
: "a"(Function));
|
||||||
@ -372,9 +382,36 @@ namespace CPU
|
|||||||
#endif
|
#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)
|
SafeFunction static inline void invlpg(void *Address)
|
||||||
{
|
{
|
||||||
#if defined(a32)
|
#ifdef a32
|
||||||
asmv("invlpg (%0)"
|
asmv("invlpg (%0)"
|
||||||
:
|
:
|
||||||
: "r"(Address)
|
: "r"(Address)
|
||||||
@ -386,7 +423,7 @@ namespace CPU
|
|||||||
|
|
||||||
SafeFunction static inline void fxsave(void *FXSaveArea)
|
SafeFunction static inline void fxsave(void *FXSaveArea)
|
||||||
{
|
{
|
||||||
#if defined(a32)
|
#ifdef a32
|
||||||
if (!FXSaveArea)
|
if (!FXSaveArea)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -399,7 +436,7 @@ namespace CPU
|
|||||||
|
|
||||||
SafeFunction static inline void fxrstor(void *FXRstorArea)
|
SafeFunction static inline void fxrstor(void *FXRstorArea)
|
||||||
{
|
{
|
||||||
#if defined(a32)
|
#ifdef a32
|
||||||
if (!FXRstorArea)
|
if (!FXRstorArea)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -515,11 +552,12 @@ namespace CPU
|
|||||||
|
|
||||||
uint64_t InterruptNumber; // Interrupt Number
|
uint64_t InterruptNumber; // Interrupt Number
|
||||||
uint64_t ErrorCode; // Error code
|
uint64_t ErrorCode; // Error code
|
||||||
uint64_t rip; // Instruction Pointer
|
|
||||||
uint64_t cs; // Code Segment
|
uint64_t rip; // Instruction Pointer
|
||||||
RFLAGS rflags; // Register Flags
|
uint64_t cs; // Code Segment
|
||||||
uint64_t rsp; // Stack Pointer
|
RFLAGS rflags; // Register Flags
|
||||||
uint64_t ss; // Stack Segment
|
uint64_t rsp; // Stack Pointer
|
||||||
|
uint64_t ss; // Stack Segment
|
||||||
} TrapFrame;
|
} TrapFrame;
|
||||||
|
|
||||||
typedef union EFER
|
typedef union EFER
|
||||||
@ -673,7 +711,7 @@ namespace CPU
|
|||||||
|
|
||||||
SafeFunction static inline void lgdt(void *gdt)
|
SafeFunction static inline void lgdt(void *gdt)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#ifdef a64
|
||||||
asmv("lgdt (%0)"
|
asmv("lgdt (%0)"
|
||||||
:
|
:
|
||||||
: "r"(gdt));
|
: "r"(gdt));
|
||||||
@ -682,7 +720,7 @@ namespace CPU
|
|||||||
|
|
||||||
SafeFunction static inline void lidt(void *idt)
|
SafeFunction static inline void lidt(void *idt)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#ifdef a64
|
||||||
asmv("lidt (%0)"
|
asmv("lidt (%0)"
|
||||||
:
|
:
|
||||||
: "r"(idt));
|
: "r"(idt));
|
||||||
@ -691,7 +729,7 @@ namespace CPU
|
|||||||
|
|
||||||
SafeFunction static inline void ltr(uint16_t Segment)
|
SafeFunction static inline void ltr(uint16_t Segment)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#ifdef a64
|
||||||
asmv("ltr %0"
|
asmv("ltr %0"
|
||||||
:
|
:
|
||||||
: "r"(Segment));
|
: "r"(Segment));
|
||||||
@ -700,7 +738,7 @@ namespace CPU
|
|||||||
|
|
||||||
SafeFunction static inline void invlpg(void *Address)
|
SafeFunction static inline void invlpg(void *Address)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#ifdef a64
|
||||||
asmv("invlpg (%0)"
|
asmv("invlpg (%0)"
|
||||||
:
|
:
|
||||||
: "r"(Address)
|
: "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)
|
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"
|
asmv("cpuid"
|
||||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||||
: "a"(Function));
|
: "a"(Function));
|
||||||
@ -742,7 +780,7 @@ namespace CPU
|
|||||||
|
|
||||||
SafeFunction static inline void fxsave(void *FXSaveArea)
|
SafeFunction static inline void fxsave(void *FXSaveArea)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#ifdef a64
|
||||||
if (!FXSaveArea || FXSaveArea >= (char *)0xfffffffffffff000)
|
if (!FXSaveArea || FXSaveArea >= (char *)0xfffffffffffff000)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -755,7 +793,7 @@ namespace CPU
|
|||||||
|
|
||||||
SafeFunction static inline void fxrstor(void *FXRstorArea)
|
SafeFunction static inline void fxrstor(void *FXRstorArea)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#ifdef a64
|
||||||
if (!FXRstorArea || FXRstorArea >= (char *)0xfffffffffffff000)
|
if (!FXRstorArea || FXRstorArea >= (char *)0xfffffffffffff000)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user