Kernel/tasking-test

This commit is contained in:
EnderIce2 2024-11-20 05:18:19 +02:00
parent 4a8e6eec5f
commit 9b49f670bd
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
190 changed files with 37142 additions and 0 deletions

38
Kernel/.github/workflows/flawfinder.yml vendored Normal file
View File

@ -0,0 +1,38 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: flawfinder
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '21 1 * * 1'
jobs:
flawfinder:
name: Flawfinder
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: flawfinder_scan
uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c
with:
arguments: '--sarif ./'
output: 'flawfinder_results.sarif'
- name: Upload analysis results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ${{github.workspace}}/flawfinder_results.sarif

8
Kernel/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
*.o
*.su
*.gcno
*.map
*.fsys
*.log
Files/*.psf
.dccache

View File

@ -0,0 +1,28 @@
{
"Fennix Kernel Header": {
"prefix": [
"head",
],
"body": [
"#ifndef __FENNIX_KERNEL_${2:header}_H__",
"#define __FENNIX_KERNEL_${2:header}_H__",
"",
"#include <types.h>",
"",
"$0",
"",
"#endif // !__FENNIX_KERNEL_${2:header}_H__",
""
],
"description": "Create kernel header."
},
"Fennix Kernel brief": {
"prefix": [
"brief",
],
"body": [
"/** @brief $0 */"
],
"description": "Create kernel documentation brief."
}
}

49
Kernel/.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,49 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/include/**"
],
"defines": [
"__debug_vscode__",
"KERNEL_NAME=\"Fennix\"",
"KERNEL_VERSION=\"1.0\"",
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"DEBUG=\"1\""
],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "gcc-x64",
"configurationProvider": "ms-vscode.makefile-tools",
"compilerArgs": [
// "-m32",
"-mcmodel=kernel", /* 64-bit only */
"-fno-rtti",
"-fexceptions",
"-fno-pic",
"-fno-pie",
"-mno-80387",
"-mno-mmx",
"-mno-3dnow",
"-mno-red-zone",
"-mno-sse",
"-mno-sse2",
"-march=nehalem",
"-pipe",
"-msoft-float",
"-fno-builtin",
"-ffreestanding",
"-nostdinc",
"-Wl,-static,--no-dynamic-linker,-ztext",
"-shared",
"-zmax-page-size=0x1000",
"-nostdinc++",
"-fsanitize=undefined"
]
}
],
"version": 4
}

16
Kernel/.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
"recommendations": [
"pejmannikram.vscode-auto-scroll",
"aaron-bond.better-comments",
"ms-vscode.cpptools",
"streetsidesoftware.code-spell-checker",
"naumovs.color-highlight",
"cschlosser.doxdocgen",
"ferrierbenjamin.fold-unfold-all-icone",
"ajshort.include-autocomplete",
"zixuanwang.linkerscript",
"ibm.output-colorizer",
"christian-kohler.path-intellisense",
"Gruntfuggly.todo-tree"
]
}

40
Kernel/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,40 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to a running QEMU instance",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/kernel.fsys",
"cwd": "${workspaceRoot}",
"args": [],
"targetArchitecture": "x64",
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"miDebuggerArgs": "",
"externalConsole": false,
"additionalSOLibSearchPath": "${workspaceRoot}",
"customLaunchSetupCommands": [
{
"text": "target remote localhost:1234",
"description": "Connect to QEMU remote debugger"
}
],
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"text": "set breakpoint pending on",
"description": "Make breakpoint pending on future shared library load."
},
{
"text": "file ${workspaceRoot}/kernel.fsys",
"description": "Load binary."
},
]
}
]
}

18
Kernel/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,18 @@
{
"C_Cpp.errorSquiggles": "Enabled",
"C_Cpp.autocompleteAddParentheses": true,
"C_Cpp.codeAnalysis.clangTidy.enabled": true,
"C_Cpp.clang_format_style": "Visual Studio",
"C_Cpp.default.intelliSenseMode": "gcc-x64",
"C_Cpp.default.cStandard": "c17",
"C_Cpp.default.cppStandard": "c++20",
"C_Cpp.intelliSenseMemoryLimit": 16384,
"editor.smoothScrolling": true,
"editor.cursorSmoothCaretAnimation": true,
"C_Cpp.codeAnalysis.clangTidy.checks.disabled": [
"clang-analyzer-security.insecureAPI.strcpy",
"clang-diagnostic-unknown-warning-option",
"clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling",
"clang-diagnostic-implicit-exception-spec-mismatch"
]
}

View File

@ -0,0 +1,10 @@
#include <types.h>
#include <debug.h>
#include <cpu.hpp>
EXTERNC void arm64Entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3)
{
trace("Hello, World!");
CPU::Halt(true);
}

View File

@ -0,0 +1,14 @@
#include <syscalls.hpp>
#include <cpu.hpp>
extern "C" __attribute__((naked, used, no_stack_protector)) void SystemCallHandlerStub()
{
}
extern "C" uint64_t SystemCallsHandler(SyscallsFrame *regs);
void InitializeSystemCalls()
{
}

View File

@ -0,0 +1,40 @@
#include <smp.hpp>
#include <interrupts.hpp>
#include <memory.hpp>
#include <cpu.hpp>
#include "../../../kernel.h"
volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
CPUData *GetCurrentCPU()
{
uint64_t ret = 0;
if (!CPUs[ret].IsActive)
{
error("CPU %d is not active!", ret);
return &CPUs[0];
}
if (CPUs[ret].Checksum != CPU_DATA_CHECKSUM)
{
error("CPU %d data is corrupted!", ret);
return &CPUs[0];
}
return &CPUs[ret];
}
namespace SMP
{
void Initialize(void *madt)
{
fixme("SMP::Initialize() is not implemented!");
}
}

View File

@ -0,0 +1,42 @@
ENTRY(_start)
SECTIONS
{
. = 0x80000;
_kernel_start = .;
.text :
{
KEEP(*(.text.boot))
*(.text .text.*)
}
. = ALIGN(4096);
_kernel_text_end = .;
.data :
{
*(.data .data.*)
}
. = ALIGN(4096);
_kernel_data_end = .;
.rodata :
{
*(.rodata .rodata.*)
}
. = ALIGN(4096);
_kernel_rodata_end = .;
.bss :
{
*(.bss .bss.*)
}
. = ALIGN(4096);
_kernel_end = .;
_bss_size = _kernel_end - _kernel_rodata_end;
/DISCARD/ :
{
*(.comment*)
*(.note*)
}
}

View File

@ -0,0 +1,17 @@
// .section ".text.boot"
//
// .global _start
// .org 0x80000
// _start:
// ldr x5, =_start
// mov sp, x5
// ldr x5, =_kernel_rodata_end
// ldr w6, =_bss_size
// 1: cbz w6, 2f
// str xzr, [x5], #8
// sub w6, w6, #1
// cbnz w6, 1b
// 2: bl arm64Entry
// Halt:
// wfe
// b Halt

View File

@ -0,0 +1,17 @@
.section ".text.boot"
.global _start
.org 0x80000
_start:
ldr x5, =_start
mov sp, x5
ldr x5, =_kernel_rodata_end
ldr w6, =_bss_size
1: cbz w6, 2f
str xzr, [x5], #8
sub w6, w6, #1
cbnz w6, 1b
2: bl arm64Entry
Halt:
wfe
b Halt

View File

@ -0,0 +1 @@
// C++ constructor/destructor stuff

View File

@ -0,0 +1 @@
// C++ constructor/destructor stuff

View File

@ -0,0 +1,13 @@
.section .init
.global _init
.type _init, @function
_init:
// push %rbp
// movq %rsp, %rbp
.section .fini
.global _fini
.type _fini, @function
_fini:
// push %rbp
// movq %rsp, %rbp

View File

@ -0,0 +1,7 @@
.section .init
// popq %rbp
ret
.section .fini
// popq %rbp
ret

View File

@ -0,0 +1,130 @@
#include "acpi.hpp"
#include <debug.h>
#include <io.h>
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
namespace ACPI
{
void *ACPI::FindTable(ACPI::ACPIHeader *ACPIHeader, char *Signature)
{
for (uint64_t t = 0; t < ((ACPIHeader->Length - sizeof(ACPI::ACPIHeader)) / (XSDTSupported ? 8 : 4)); t++)
{
// Should I be concerned about unaligned memory access?
ACPI::ACPIHeader *SDTHdr = nullptr;
if (XSDTSupported)
SDTHdr = (ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 8)));
else
SDTHdr = (ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 4)));
for (uint64_t i = 0; i < 4; i++)
{
if (SDTHdr->Signature[i] != Signature[i])
break;
if (i == 3)
{
trace("%s found!", Signature);
return SDTHdr;
}
}
}
// warn("%s not found!", Signature);
return nullptr;
}
void ACPI::SearchTables(ACPIHeader *Header)
{
if (!Header)
return;
HPET = (HPETHeader *)FindTable(XSDT, (char *)"HPET");
FADT = (FADTHeader *)FindTable(XSDT, (char *)"FACP");
MCFG = (MCFGHeader *)FindTable(XSDT, (char *)"MCFG");
BGRT = (BGRTHeader *)FindTable(XSDT, (char *)"BGRT");
SRAT = (SRATHeader *)FindTable(XSDT, (char *)"SRAT");
TPM2 = (TPM2Header *)FindTable(XSDT, (char *)"TPM2");
TCPA = (TCPAHeader *)FindTable(XSDT, (char *)"TCPA");
WAET = (WAETHeader *)FindTable(XSDT, (char *)"WAET");
MADT = (MADTHeader *)FindTable(XSDT, (char *)"APIC");
HEST = (HESTHeader *)FindTable(XSDT, (char *)"HEST");
FindTable(XSDT, (char *)"BERT");
FindTable(XSDT, (char *)"CPEP");
FindTable(XSDT, (char *)"DSDT");
FindTable(XSDT, (char *)"ECDT");
FindTable(XSDT, (char *)"EINJ");
FindTable(XSDT, (char *)"ERST");
FindTable(XSDT, (char *)"FACS");
FindTable(XSDT, (char *)"MSCT");
FindTable(XSDT, (char *)"MPST");
FindTable(XSDT, (char *)"OEMx");
FindTable(XSDT, (char *)"PMTT");
FindTable(XSDT, (char *)"PSDT");
FindTable(XSDT, (char *)"RASF");
FindTable(XSDT, (char *)"RSDT");
FindTable(XSDT, (char *)"SBST");
FindTable(XSDT, (char *)"SLIT");
FindTable(XSDT, (char *)"SSDT");
FindTable(XSDT, (char *)"XSDT");
FindTable(XSDT, (char *)"DRTM");
FindTable(XSDT, (char *)"FPDT");
FindTable(XSDT, (char *)"GTDT");
FindTable(XSDT, (char *)"PCCT");
FindTable(XSDT, (char *)"S3PT");
FindTable(XSDT, (char *)"MATR");
FindTable(XSDT, (char *)"MSDM");
FindTable(XSDT, (char *)"WPBT");
FindTable(XSDT, (char *)"OSDT");
FindTable(XSDT, (char *)"RSDP");
FindTable(XSDT, (char *)"NFIT");
FindTable(XSDT, (char *)"ASF!");
FindTable(XSDT, (char *)"BOOT");
FindTable(XSDT, (char *)"CSRT");
FindTable(XSDT, (char *)"DBG2");
FindTable(XSDT, (char *)"DBGP");
FindTable(XSDT, (char *)"DMAR");
FindTable(XSDT, (char *)"IBFT");
FindTable(XSDT, (char *)"IORT");
FindTable(XSDT, (char *)"IVRS");
FindTable(XSDT, (char *)"LPIT");
FindTable(XSDT, (char *)"MCHI");
FindTable(XSDT, (char *)"MTMR");
FindTable(XSDT, (char *)"SLIC");
FindTable(XSDT, (char *)"SPCR");
FindTable(XSDT, (char *)"SPMI");
FindTable(XSDT, (char *)"UEFI");
FindTable(XSDT, (char *)"VRTC");
FindTable(XSDT, (char *)"WDAT");
FindTable(XSDT, (char *)"WDDT");
FindTable(XSDT, (char *)"WDRT");
}
ACPI::ACPI(BootInfo *Info)
{
trace("Initializing ACPI");
if (Info->RSDP->Revision >= 2 && Info->RSDP->XSDTAddress)
{
debug("XSDT supported");
XSDTSupported = true;
XSDT = (ACPIHeader *)(Info->RSDP->XSDTAddress);
}
else
{
debug("RSDT supported");
XSDT = (ACPIHeader *)(uintptr_t)Info->RSDP->RSDTAddress;
}
this->SearchTables(XSDT);
if (FADT)
{
outb(FADT->SMI_CommandPort, FADT->AcpiEnable);
while (!(inw(FADT->PM1aControlBlock) & 1))
;
}
}
ACPI::~ACPI()
{
}
}

View File

@ -0,0 +1,213 @@
#include "acpi.hpp"
#include <time.hpp>
#include <debug.h>
#include <smp.hpp>
#include <io.h>
#include "cpu/apic.hpp"
#define ACPI_TIMER 0x0001
#define ACPI_BUSMASTER 0x0010
#define ACPI_GLOBAL 0x0020
#define ACPI_POWER_BUTTON 0x0100
#define ACPI_SLEEP_BUTTON 0x0200
#define ACPI_RTC_ALARM 0x0400
#define ACPI_PCIE_WAKE 0x4000
#define ACPI_WAKE 0x8000
namespace ACPI
{
__attribute__((always_inline)) inline bool IsCanonical(uint64_t Address)
{
return ((Address <= 0x00007FFFFFFFFFFF) || ((Address >= 0xFFFF800000000000) && (Address <= 0xFFFFFFFFFFFFFFFF)));
}
#define ACPI_ENABLED 0x0001
#define ACPI_SLEEP 0x2000
#define ACPI_GAS_MMIO 0
#define ACPI_GAS_IO 1
#define ACPI_GAS_PCI 2
void DSDT::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
{
debug("SCI Handle Triggered");
uint16_t Event = 0;
{
uint16_t a = 0, b = 0;
if (acpi->FADT->PM1aEventBlock)
{
a = inw(acpi->FADT->PM1aEventBlock);
outw(acpi->FADT->PM1aEventBlock, a);
}
if (acpi->FADT->PM1bEventBlock)
{
b = inw(acpi->FADT->PM1bEventBlock);
outw(acpi->FADT->PM1bEventBlock, b);
}
Event = a | b;
}
debug("SCI Event: %#lx", Event);
if (Event & ACPI_BUSMASTER)
{
fixme("ACPI Busmaster");
}
else if (Event & ACPI_GLOBAL)
{
fixme("ACPI Global");
}
else if (Event & ACPI_POWER_BUTTON)
{
this->Shutdown();
Time::Clock tm = Time::ReadClock();
while (tm.Second == Time::ReadClock().Second)
;
outw(0xB004, 0x2000);
outw(0x604, 0x2000);
outw(0x4004, 0x3400);
CPU::Stop();
}
else if (Event & ACPI_SLEEP_BUTTON)
{
fixme("ACPI Sleep Button");
}
else if (Event & ACPI_RTC_ALARM)
{
fixme("ACPI RTC Alarm");
}
else if (Event & ACPI_PCIE_WAKE)
{
fixme("ACPI PCIe Wake");
}
else if (Event & ACPI_WAKE)
{
fixme("ACPI Wake");
}
else if (Event & ACPI_TIMER)
{
fixme("ACPI Timer");
}
else
{
error("ACPI unknown event %#lx on CPU %d", Event, GetCurrentCPU()->ID);
CPU::Stop();
}
UNUSED(Frame);
}
void DSDT::Shutdown()
{
trace("Shutting down...");
if (SCI_EN == 1)
{
outw(acpi->FADT->PM1aControlBlock, (inw(acpi->FADT->PM1aControlBlock) & 0xE3FF) | ((SLP_TYPa << 10) | ACPI_SLEEP));
if (acpi->FADT->PM1bControlBlock)
outw(acpi->FADT->PM1bControlBlock, (inw(acpi->FADT->PM1bControlBlock) & 0xE3FF) | ((SLP_TYPb << 10) | ACPI_SLEEP));
outw(PM1a_CNT, SLP_TYPa | SLP_EN);
if (PM1b_CNT)
outw(PM1b_CNT, SLP_TYPb | SLP_EN);
}
}
void DSDT::Reboot()
{
trace("Rebooting...");
switch (acpi->FADT->ResetReg.AddressSpace)
{
case ACPI_GAS_MMIO:
*(uint8_t *)(acpi->FADT->ResetReg.Address) = acpi->FADT->ResetValue;
break;
case ACPI_GAS_IO:
outb(acpi->FADT->ResetReg.Address, acpi->FADT->ResetValue);
break;
case ACPI_GAS_PCI:
fixme("ACPI_GAS_PCI not supported.");
/*
seg - 0
bus - 0
dev - (FADT->ResetReg.Address >> 32) & 0xFFFF
function - (FADT->ResetReg.Address >> 16) & 0xFFFF
offset - FADT->ResetReg.Address & 0xFFFF
value - FADT->ResetValue
*/
break;
}
}
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt + CPU::x64::IRQ0)
{
this->acpi = acpi;
uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt);
uint8_t *S5Address = (uint8_t *)(Address) + 36;
ACPI::ACPI::ACPIHeader *Header = (ACPI::ACPI::ACPIHeader *)Address;
uint64_t Length = Header->Length;
while (Length-- > 0)
{
if (!memcmp(S5Address, "_S5_", 4))
break;
S5Address++;
}
if (Length <= 0)
{
warn("_S5 not present in ACPI");
return;
}
if ((*(S5Address - 1) == 0x08 || (*(S5Address - 2) == 0x08 && *(S5Address - 1) == '\\')) && *(S5Address + 4) == 0x12)
{
S5Address += 5;
S5Address += ((*S5Address & 0xC0) >> 6) + 2;
if (*S5Address == 0x0A)
S5Address++;
SLP_TYPa = *(S5Address) << 10;
S5Address++;
if (*S5Address == 0x0A)
S5Address++;
SLP_TYPb = *(S5Address) << 10;
SMI_CMD = acpi->FADT->SMI_CommandPort;
ACPI_ENABLE = acpi->FADT->AcpiEnable;
ACPI_DISABLE = acpi->FADT->AcpiDisable;
PM1a_CNT = acpi->FADT->PM1aControlBlock;
PM1b_CNT = acpi->FADT->PM1bControlBlock;
PM1_CNT_LEN = acpi->FADT->PM1ControlLength;
SLP_EN = 1 << 13;
SCI_EN = 1;
trace("ACPI Shutdown is supported");
ACPIShutdownSupported = true;
uint16_t value = ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE;
{
uint16_t a = acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2);
uint16_t b = acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2);
debug("SCI Event: %#llx [a:%#x b:%#x]", value, a, b);
if (acpi->FADT->PM1aEventBlock)
outw(a, value);
if (acpi->FADT->PM1bEventBlock)
outw(b, value);
}
{
uint16_t a = 0, b = 0;
if (acpi->FADT->PM1aEventBlock)
{
a = inw(acpi->FADT->PM1aEventBlock);
outw(acpi->FADT->PM1aEventBlock, a);
}
if (acpi->FADT->PM1bEventBlock)
{
b = inw(acpi->FADT->PM1bEventBlock);
outw(acpi->FADT->PM1bEventBlock, b);
}
}
((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1);
return;
}
warn("Failed to parse _S5 in ACPI");
SCI_EN = 0;
}
DSDT::~DSDT()
{
}
}

View File

@ -0,0 +1,257 @@
#include <boot/binfo.h>
#include <types.h>
#include <debug.h>
#include <convert.h>
#include "../../../tools/limine/limine.h"
#include "../../kernel.h"
void init_limine();
static volatile struct limine_entry_point_request EntryPointRequest = {
.id = LIMINE_ENTRY_POINT_REQUEST,
.revision = 0,
.response = NULL,
.entry = init_limine};
static volatile struct limine_bootloader_info_request BootloaderInfoRequest = {
.id = LIMINE_BOOTLOADER_INFO_REQUEST,
.revision = 0};
static volatile struct limine_terminal_request TerminalRequest = {
.id = LIMINE_TERMINAL_REQUEST,
.revision = 0};
static volatile struct limine_framebuffer_request FramebufferRequest = {
.id = LIMINE_FRAMEBUFFER_REQUEST,
.revision = 0};
static volatile struct limine_memmap_request MemmapRequest = {
.id = LIMINE_MEMMAP_REQUEST,
.revision = 0};
static volatile struct limine_kernel_address_request KernelAddressRequest = {
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
.revision = 0};
static volatile struct limine_rsdp_request RsdpRequest = {
.id = LIMINE_RSDP_REQUEST,
.revision = 0};
static volatile struct limine_kernel_file_request KernelFileRequest = {
.id = LIMINE_KERNEL_FILE_REQUEST,
.revision = 0};
static volatile struct limine_module_request ModuleRequest = {
.id = LIMINE_MODULE_REQUEST,
.revision = 0};
static volatile struct limine_smbios_request SmbiosRequest = {
.id = LIMINE_SMBIOS_REQUEST,
.revision = 0};
SafeFunction __no_instrument_function void init_limine()
{
struct BootInfo binfo;
struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response;
info("Bootloader: %s %s", BootloaderInfoResponse->name, BootloaderInfoResponse->version);
struct limine_terminal_response *TerminalResponse = TerminalRequest.response;
if (TerminalResponse == NULL || TerminalResponse->terminal_count < 1)
{
warn("No terminal available.");
while (1)
asmv("hlt");
}
TerminalResponse->write(TerminalResponse->terminals[0], "\033[37mPlease wait... ", 20);
struct limine_framebuffer_response *FrameBufferResponse = FramebufferRequest.response;
struct limine_memmap_response *MemmapResponse = MemmapRequest.response;
struct limine_kernel_address_response *KernelAddressResponse = KernelAddressRequest.response;
struct limine_rsdp_response *RsdpResponse = RsdpRequest.response;
struct limine_kernel_file_response *KernelFileResponse = KernelFileRequest.response;
struct limine_module_response *ModuleResponse = ModuleRequest.response;
struct limine_smbios_response *SmbiosResponse = SmbiosRequest.response;
if (FrameBufferResponse == NULL || FrameBufferResponse->framebuffer_count < 1)
{
error("No framebuffer available [%p;%ld]", FrameBufferResponse,
(FrameBufferResponse == NULL) ? 0 : FrameBufferResponse->framebuffer_count);
TerminalResponse->write(TerminalResponse->terminals[0], "No framebuffer available", 24);
while (1)
asmv("hlt");
}
if (MemmapResponse == NULL || MemmapResponse->entry_count < 1)
{
error("No memory map available [%p;%ld]", MemmapResponse,
(MemmapResponse == NULL) ? 0 : MemmapResponse->entry_count);
TerminalResponse->write(TerminalResponse->terminals[0], "No memory map available", 23);
while (1)
asmv("hlt");
}
if (KernelAddressResponse == NULL)
{
error("No kernel address available [%p]", KernelAddressResponse);
TerminalResponse->write(TerminalResponse->terminals[0], "No kernel address available", 27);
while (1)
asmv("hlt");
}
if (RsdpResponse == NULL || RsdpResponse->address == 0)
{
error("No RSDP address available [%p;%p]", RsdpResponse,
(RsdpResponse == NULL) ? 0 : RsdpResponse->address);
TerminalResponse->write(TerminalResponse->terminals[0], "No RSDP address available", 25);
while (1)
asmv("hlt");
}
if (KernelFileResponse == NULL || KernelFileResponse->kernel_file == NULL)
{
error("No kernel file available [%p;%p]", KernelFileResponse,
(KernelFileResponse == NULL) ? 0 : KernelFileResponse->kernel_file);
TerminalResponse->write(TerminalResponse->terminals[0], "No kernel file available", 24);
while (1)
asmv("hlt");
}
if (ModuleResponse == NULL || ModuleResponse->module_count < 1)
{
error("No module information available [%p;%ld]", ModuleResponse,
(ModuleResponse == NULL) ? 0 : ModuleResponse->module_count);
TerminalResponse->write(TerminalResponse->terminals[0], "No module information available", 31);
while (1)
asmv("hlt");
}
for (uint64_t i = 0; i < FrameBufferResponse->framebuffer_count; i++)
{
struct limine_framebuffer *framebuffer = FrameBufferResponse->framebuffers[i];
binfo.Framebuffer[i].BaseAddress = (void *)((uint64_t)framebuffer->address - 0xffff800000000000);
binfo.Framebuffer[i].Width = framebuffer->width;
binfo.Framebuffer[i].Height = framebuffer->height;
binfo.Framebuffer[i].Pitch = framebuffer->pitch;
binfo.Framebuffer[i].BitsPerPixel = framebuffer->bpp;
binfo.Framebuffer[i].MemoryModel = framebuffer->memory_model;
binfo.Framebuffer[i].RedMaskSize = framebuffer->red_mask_size;
binfo.Framebuffer[i].RedMaskShift = framebuffer->red_mask_shift;
binfo.Framebuffer[i].GreenMaskSize = framebuffer->green_mask_size;
binfo.Framebuffer[i].GreenMaskShift = framebuffer->green_mask_shift;
binfo.Framebuffer[i].BlueMaskSize = framebuffer->blue_mask_size;
binfo.Framebuffer[i].BlueMaskShift = framebuffer->blue_mask_shift;
binfo.Framebuffer[i].ExtendedDisplayIdentificationData = framebuffer->edid;
binfo.Framebuffer[i].EDIDSize = framebuffer->edid_size;
debug("Framebuffer %d: %dx%d %d bpp", i, framebuffer->width, framebuffer->height, framebuffer->bpp);
debug("More info:\nAddress: %p\nPitch: %ld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d\nEDID: %p\nEDIDSize: %d",
(uint64_t)framebuffer->address - 0xffff800000000000, framebuffer->pitch, framebuffer->memory_model, framebuffer->red_mask_size, framebuffer->red_mask_shift, framebuffer->green_mask_size, framebuffer->green_mask_shift, framebuffer->blue_mask_size, framebuffer->blue_mask_shift, framebuffer->edid, framebuffer->edid_size);
}
binfo.Memory.Entries = MemmapResponse->entry_count;
for (uint64_t i = 0; i < MemmapResponse->entry_count; i++)
{
if (MemmapResponse->entry_count > MAX_MEMORY_ENTRIES)
{
warn("Too many memory entries, skipping the rest...");
break;
}
struct limine_memmap_entry *entry = MemmapResponse->entries[i];
binfo.Memory.Size += entry->length;
switch (entry->type)
{
case LIMINE_MEMMAP_USABLE:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = Usable;
break;
case LIMINE_MEMMAP_RESERVED:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = Reserved;
break;
case LIMINE_MEMMAP_ACPI_RECLAIMABLE:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = ACPIReclaimable;
break;
case LIMINE_MEMMAP_ACPI_NVS:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = ACPINVS;
break;
case LIMINE_MEMMAP_BAD_MEMORY:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = BadMemory;
break;
case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = BootloaderReclaimable;
break;
case LIMINE_MEMMAP_KERNEL_AND_MODULES:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = KernelAndModules;
break;
case LIMINE_MEMMAP_FRAMEBUFFER:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = Framebuffer;
break;
default:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = Unknown;
break;
}
}
for (uint64_t i = 0; i < ModuleResponse->module_count; i++)
{
if (i > MAX_MODULES)
{
warn("Too many modules, skipping the rest...");
break;
}
binfo.Modules[i].Address = (void *)((uint64_t)ModuleResponse->modules[i]->address - 0xffff800000000000);
strncpy(binfo.Modules[i].Path,
ModuleResponse->modules[i]->path,
strlen(ModuleResponse->modules[i]->path) + 1);
strncpy(binfo.Modules[i].CommandLine,
ModuleResponse->modules[i]->cmdline,
strlen(ModuleResponse->modules[i]->cmdline) + 1);
binfo.Modules[i].Size = ModuleResponse->modules[i]->size;
debug("Module %d:\nAddress: %p\nPath: %s\nCommand Line: %s\nSize: %ld", i,
(uint64_t)ModuleResponse->modules[i]->address - 0xffff800000000000, ModuleResponse->modules[i]->path,
ModuleResponse->modules[i]->cmdline, ModuleResponse->modules[i]->size);
}
binfo.RSDP = (struct RSDPInfo *)((uint64_t)RsdpResponse->address - 0xffff800000000000);
trace("RSDP: %p(%p) [Signature: %.8s] [OEM: %.6s]",
RsdpResponse->address, binfo.RSDP, binfo.RSDP->Signature, binfo.RSDP->OEMID);
debug("SMBIOS: %p %p", SmbiosResponse->entry_32, SmbiosResponse->entry_64);
if (SmbiosResponse->entry_32 != NULL)
binfo.SMBIOSPtr = (void *)((uint64_t)SmbiosResponse->entry_32 - 0xffff800000000000);
else if (SmbiosResponse->entry_64 != NULL)
binfo.SMBIOSPtr = (void *)((uint64_t)SmbiosResponse->entry_64 - 0xffff800000000000);
else
binfo.SMBIOSPtr = NULL;
binfo.Kernel.PhysicalBase = (void *)KernelAddressResponse->physical_base;
binfo.Kernel.VirtualBase = (void *)KernelAddressResponse->virtual_base;
binfo.Kernel.FileBase = KernelFileResponse->kernel_file->address;
strncpy(binfo.Kernel.CommandLine,
KernelFileResponse->kernel_file->cmdline,
strlen(KernelFileResponse->kernel_file->cmdline) + 1);
binfo.Kernel.Size = KernelFileResponse->kernel_file->size;
trace("Kernel physical address: %p", KernelAddressResponse->physical_base);
trace("Kernel virtual address: %p", KernelAddressResponse->virtual_base);
strncpy(binfo.Bootloader.Name,
BootloaderInfoResponse->name,
strlen(BootloaderInfoResponse->name) + 1);
strncpy(binfo.Bootloader.Version,
BootloaderInfoResponse->version,
strlen(BootloaderInfoResponse->version) + 1);
// Call kernel entry point
Entry(&binfo);
}

View File

@ -0,0 +1,69 @@
#include "acpi.hpp"
#include <memory.hpp>
#include <debug.h>
#include "../../kernel.h"
namespace ACPI
{
MADT::MADT(ACPI::MADTHeader *madt)
{
trace("Initializing MADT");
CPUCores = 0;
LAPICAddress = (LAPIC *)(uintptr_t)madt->LocalControllerAddress;
for (uint8_t *ptr = (uint8_t *)(madt->Entries);
(uintptr_t)(ptr) < (uintptr_t)(madt) + madt->Header.Length;
ptr += *(ptr + 1))
{
switch (*(ptr))
{
case 0:
{
if (ptr[4] & 1)
{
lapic.push_back((LocalAPIC *)ptr);
KPrint("Local APIC \e8888FF%d\eCCCCCC (APIC \e8888FF%d\eCCCCCC) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId);
CPUCores++;
}
break;
}
case 1:
{
ioapic.push_back((MADTIOApic *)ptr);
KPrint("I/O APIC \e8888FF%d\eCCCCCC (Address \e8888FF%#lx\eCCCCCC) found.", ioapic.back()->APICID, ioapic.back()->Address);
Memory::Virtual().Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped.
break;
}
case 2:
{
iso.push_back((MADTIso *)ptr);
KPrint("ISO (IRQ:\e8888FF%#lx\eCCCCCC, BUS:\e8888FF%#lx\eCCCCCC, GSI:\e8888FF%#lx\eCCCCCC, %s\eCCCCCC/%s\eCCCCCC) found.",
iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI,
iso.back()->Flags & 0x00000004 ? "\e1770FFActive High" : "\e475EFFActive Low",
iso.back()->Flags & 0x00000100 ? "\e00962DEdge Triggered" : "\e008F58Level Triggered");
break;
}
case 4:
{
nmi.push_back((MADTNmi *)ptr);
KPrint("NMI \e8888FF%#lx\eCCCCCC (lint:\e8888FF%#lx\eCCCCCC) found.", nmi.back()->processor, nmi.back()->lint);
break;
}
case 5:
{
LAPICAddress = (LAPIC *)ptr;
KPrint("APIC found at \e8888FF%#lx\eCCCCCC", LAPICAddress);
break;
}
}
Memory::Virtual().Map((void *)LAPICAddress, (void *)LAPICAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page?
}
CPUCores--; // We start at 0 (BSP) and end at 11 (APs), so we have 12 cores.
KPrint("Total CPU cores: %d", CPUCores + 1);
}
MADT::~MADT()
{
}
}

View File

@ -0,0 +1,85 @@
#include <syscalls.hpp>
#include <cpu.hpp>
#include "cpu/gdt.hpp"
// https://supercip971.github.io/02-wingos-syscalls.html
using namespace CPU::x64;
// "Core/SystemCalls.cpp"
extern "C" uint64_t SystemCallsHandler(SyscallsFrame *regs);
extern "C" void SystemCallHandlerStub();
extern "C" __attribute__((naked, used, no_stack_protector)) void SystemCallHandlerStub_broken()
{
// asmv(
// // "cmp $0x08, 0x8(%rsp)\n"
// // "je 1f\n"
// "swapgs\n"
// // "1:\n"
// "mov %rsp, 0x8(%gs)\n" // CPUData->TempStack
// "mov 0x0(%gs), %rsp\n" // CPUData->SystemCallStack
// "push $0x1b\n" // user data segment
// "push 0x8(%gs)\n" // saved stack
// "push %r11\n" // saved rflags
// "push $0x23\n" // user code segment
// "push %rcx\n" // Current RIP
// "push %rax\n"
// "push %rbx\n"
// "push %rcx\n"
// "push %rdx\n"
// "push %rsi\n"
// "push %rdi\n"
// "push %rbp\n"
// "push %r8\n"
// "push %r9\n"
// "push %r10\n"
// "push %r11\n"
// "push %r12\n"
// "push %r13\n"
// "push %r14\n"
// "push %r15\n"
// "mov %rsp, %rdi\n"
// "mov $0, %rbp\n"
// "call SystemCallsHandler\n"
// "pop %r15\n"
// "pop %r14\n"
// "pop %r13\n"
// "pop %r12\n"
// "pop %r11\n"
// "pop %r10\n"
// "pop %r9\n"
// "pop %r8\n"
// "pop %rbp\n"
// "pop %rdi\n"
// "pop %rsi\n"
// "pop %rdx\n"
// "pop %rcx\n"
// "pop %rbx\n"
// /* "pop %rax\n" */
// "mov 0x8(%gs), %rsp\n" // CPUData->TempStack
// // "cmp $0x08, 0x8(%rsp)\n"
// // "je 1f\n"
// "swapgs\n"
// // "1:\n"
// "sti\n"
// "sysretq\n");
}
void InitializeSystemCalls()
{
wrmsr(MSR_EFER, rdmsr(MSR_EFER) | 1);
wrmsr(MSR_STAR, ((uint64_t)(GDT_KERNEL_CODE) << 32) | ((uint64_t)(GDT_KERNEL_DATA | 3) << 48));
wrmsr(MSR_LSTAR, (uint64_t)SystemCallHandlerStub);
wrmsr(MSR_SYSCALL_MASK, (uint64_t)(1 << 9));
}

View File

@ -0,0 +1,59 @@
[BITS 64]
%macro PushAllSC 0
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
%endmacro
%macro PopAllSC 0
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
%endmacro
ALIGN 4096
extern SystemCallsHandler
global SystemCallHandlerStub
SystemCallHandlerStub:
swapgs ; Swap gs and kernelgs
mov [gs:0x8], rsp ; CPUData->TempStack
mov rsp, [gs:0x0] ; CPUData->SystemCallStack
push qword 0x1b ; User data segment
push qword [gs:0x8] ; Saved stack
push r11 ; Saved rflags
push qword 0x23 ; User code segment
push rcx ; Current instruction pointer
cld ; Clear direction flag
PushAllSC ; Push all registers
mov rdi, rsp ; Pass pointer to registers
mov rbp, 0 ; Pass 0 as return address
call SystemCallsHandler ; Call system call handler
PopAllSC ; Pop all registers except rax
mov rsp, [gs:0x8] ; Restore stack
swapgs ; Swap back gs and kernelgs
sti ; Enable interrupts
o64 sysret ; Return to user mode

View File

@ -0,0 +1,277 @@
#ifndef __FENNIX_KERNEL_ACPI_H__
#define __FENNIX_KERNEL_ACPI_H__
#include <types.h>
#include <boot/binfo.h>
#include <interrupts.hpp>
#include <vector.hpp>
#include <cpu.hpp>
namespace ACPI
{
class ACPI
{
public:
struct ACPIHeader
{
unsigned char Signature[4];
uint32_t Length;
uint8_t Revision;
uint8_t Checksum;
uint8_t OEMID[6];
uint8_t OEMTableID[8];
uint32_t OEMRevision;
uint32_t CreatorID;
uint32_t CreatorRevision;
} __attribute__((packed));
struct GenericAddressStructure
{
uint8_t AddressSpace;
uint8_t BitWidth;
uint8_t BitOffset;
uint8_t AccessSize;
uint64_t Address;
} __attribute__((packed));
struct MCFGHeader
{
struct ACPIHeader Header;
uint64_t Reserved;
} __attribute__((packed));
struct HPETHeader
{
ACPIHeader Header;
uint8_t HardwareRevID;
uint8_t ComparatorCount : 5;
uint8_t CounterSize : 1;
uint8_t Reserved : 1;
uint8_t LegacyReplacement : 1;
uint16_t PCIVendorID;
struct GenericAddressStructure Address;
uint8_t HPETNumber;
uint16_t MinimumTick;
uint8_t PageProtection;
} __attribute__((packed));
struct FADTHeader
{
ACPIHeader Header;
uint32_t FirmwareCtrl;
uint32_t Dsdt;
uint8_t Reserved;
uint8_t PreferredPowerManagementProfile;
uint16_t SCI_Interrupt;
uint32_t SMI_CommandPort;
uint8_t AcpiEnable;
uint8_t AcpiDisable;
uint8_t S4BIOS_REQ;
uint8_t PSTATE_Control;
uint32_t PM1aEventBlock;
uint32_t PM1bEventBlock;
uint32_t PM1aControlBlock;
uint32_t PM1bControlBlock;
uint32_t PM2ControlBlock;
uint32_t PMTimerBlock;
uint32_t GPE0Block;
uint32_t GPE1Block;
uint8_t PM1EventLength;
uint8_t PM1ControlLength;
uint8_t PM2ControlLength;
uint8_t PMTimerLength;
uint8_t GPE0Length;
uint8_t GPE1Length;
uint8_t GPE1Base;
uint8_t CStateControl;
uint16_t WorstC2Latency;
uint16_t WorstC3Latency;
uint16_t FlushSize;
uint16_t FlushStride;
uint8_t DutyOffset;
uint8_t DutyWidth;
uint8_t DayAlarm;
uint8_t MonthAlarm;
uint8_t Century;
uint16_t BootArchitectureFlags;
uint8_t Reserved2;
uint32_t Flags;
struct GenericAddressStructure ResetReg;
uint8_t ResetValue;
uint8_t Reserved3[3];
uint64_t X_FirmwareControl;
uint64_t X_Dsdt;
struct GenericAddressStructure X_PM1aEventBlock;
struct GenericAddressStructure X_PM1bEventBlock;
struct GenericAddressStructure X_PM1aControlBlock;
struct GenericAddressStructure X_PM1bControlBlock;
struct GenericAddressStructure X_PM2ControlBlock;
struct GenericAddressStructure X_PMTimerBlock;
struct GenericAddressStructure X_GPE0Block;
struct GenericAddressStructure X_GPE1Block;
} __attribute__((packed));
struct BGRTHeader
{
ACPIHeader Header;
uint16_t Version;
uint8_t Status;
uint8_t ImageType;
uint64_t ImageAddress;
uint32_t ImageOffsetX;
uint32_t ImageOffsetY;
};
struct SRATHeader
{
ACPIHeader Header;
uint32_t TableRevision; // Must be value 1
uint64_t Reserved; // Reserved, must be zero
};
struct TPM2Header
{
ACPIHeader Header;
uint32_t Flags;
uint64_t ControlAddress;
uint32_t StartMethod;
};
struct TCPAHeader
{
ACPIHeader Header;
uint16_t Reserved;
uint32_t MaxLogLength;
uint64_t LogAddress;
};
struct WAETHeader
{
ACPIHeader Header;
uint32_t Flags;
};
struct HESTHeader
{
ACPIHeader Header;
uint32_t ErrorSourceCount;
};
struct MADTHeader
{
ACPIHeader Header;
uint32_t LocalControllerAddress;
uint32_t Flags;
char Entries[];
} __attribute__((packed));
ACPIHeader *XSDT = nullptr;
MCFGHeader *MCFG = nullptr;
HPETHeader *HPET = nullptr;
FADTHeader *FADT = nullptr;
BGRTHeader *BGRT = nullptr;
SRATHeader *SRAT = nullptr;
TPM2Header *TPM2 = nullptr;
TCPAHeader *TCPA = nullptr;
WAETHeader *WAET = nullptr;
MADTHeader *MADT = nullptr;
HESTHeader *HEST = nullptr;
bool XSDTSupported = false;
void *FindTable(ACPIHeader *ACPIHeader, char *Signature);
void SearchTables(ACPIHeader *Header);
ACPI(BootInfo *Info);
~ACPI();
};
class MADT
{
public:
struct APICHeader
{
uint8_t Type;
uint8_t Length;
} __attribute__((packed));
struct MADTIOApic
{
struct APICHeader Header;
uint8_t APICID;
uint8_t reserved;
uint32_t Address;
uint32_t GSIBase;
} __attribute__((packed));
struct MADTIso
{
struct APICHeader Header;
uint8_t BuSSource;
uint8_t IRQSource;
uint32_t GSI;
uint16_t Flags;
} __attribute__((packed));
struct MADTNmi
{
struct APICHeader Header;
uint8_t processor;
uint16_t flags;
uint8_t lint;
} __attribute__((packed));
struct LocalAPIC
{
struct APICHeader Header;
uint8_t ACPIProcessorId;
uint8_t APICId;
uint32_t Flags;
} __attribute__((packed));
struct LAPIC
{
uint8_t id;
uintptr_t PhysicalAddress;
void *VirtualAddress;
};
Vector<MADTIOApic *> ioapic;
Vector<MADTIso *> iso;
Vector<MADTNmi *> nmi;
Vector<LocalAPIC *> lapic;
struct LAPIC *LAPICAddress;
uint16_t CPUCores;
MADT(ACPI::MADTHeader *madt);
~MADT();
};
class DSDT : public Interrupts::Handler
{
private:
uint32_t SMI_CMD = 0;
uint8_t ACPI_ENABLE = 0;
uint8_t ACPI_DISABLE = 0;
uint32_t PM1a_CNT = 0;
uint32_t PM1b_CNT = 0;
uint16_t SLP_TYPa = 0;
uint16_t SLP_TYPb = 0;
uint16_t SLP_EN = 0;
uint16_t SCI_EN = 0;
uint8_t PM1_CNT_LEN = 0;
ACPI *acpi;
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
public:
bool ACPIShutdownSupported = false;
void Reboot();
void Shutdown();
DSDT(ACPI *acpi);
~DSDT();
};
}
#endif // !__FENNIX_KERNEL_ACPI_H__

View File

@ -0,0 +1,354 @@
#include "apic.hpp"
#include <memory.hpp>
#include <uart.hpp>
#include <lock.hpp>
#include <cpu.hpp>
#include <smp.hpp>
#include <io.h>
#include "../../../kernel.h"
#include "../acpi.hpp"
NewLock(APICLock);
using namespace CPU::x64;
/*
In constructor APIC::APIC::APIC(int):
warning: left shift count >= width of type
| APICBaseAddress = BaseStruct.ApicBaseLo << 12u | BaseStruct.ApicBaseHi << 32u;
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~
*/
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
namespace APIC
{
// headache
// https://www.amd.com/system/files/TechDocs/24593.pdf
// https://www.naic.edu/~phil/software/intel/318148.pdf
uint32_t APIC::Read(uint32_t Register)
{
if (Register != APIC_ICRLO &&
Register != APIC_ICRHI &&
Register != APIC_ID)
debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0);
if (x2APICSupported)
{
if (Register != APIC_ICRHI)
return rdmsr((Register >> 4) + 0x800);
else
return rdmsr(0x30 + 0x800);
}
else
{
CPU::MemBar::Barrier();
uint32_t ret = *((volatile uint32_t *)((uintptr_t)APICBaseAddress + Register));
CPU::MemBar::Barrier();
return ret;
}
}
void APIC::Write(uint32_t Register, uint32_t Value)
{
if (Register != APIC_EOI &&
Register != APIC_TDCR &&
Register != APIC_TIMER &&
Register != APIC_TICR &&
Register != APIC_ICRLO &&
Register != APIC_ICRHI)
debug("APIC::Write(%#lx, %#lx) [x2=%d]", Register, Value, x2APICSupported ? 1 : 0);
if (x2APICSupported)
{
if (Register != APIC_ICRHI)
wrmsr((Register >> 4) + 0x800, Value);
else
wrmsr(MSR_X2APIC_ICR, Value);
}
else
{
CPU::MemBar::Barrier();
*((volatile uint32_t *)(((uintptr_t)APICBaseAddress) + Register)) = Value;
CPU::MemBar::Barrier();
}
}
void APIC::IOWrite(uint64_t Base, uint32_t Register, uint32_t Value)
{
debug("APIC::IOWrite(%#lx, %#lx, %#lx)", Base, Register, Value);
CPU::MemBar::Barrier();
*((volatile uint32_t *)(((uintptr_t)Base))) = Register;
CPU::MemBar::Barrier();
*((volatile uint32_t *)(((uintptr_t)Base + 16))) = Value;
CPU::MemBar::Barrier();
}
uint32_t APIC::IORead(uint64_t Base, uint32_t Register)
{
debug("APIC::IORead(%#lx, %#lx)", Base, Register);
CPU::MemBar::Barrier();
*((volatile uint32_t *)(((uintptr_t)Base))) = Register;
CPU::MemBar::Barrier();
uint32_t ret = *((volatile uint32_t *)(((uintptr_t)Base + 16)));
CPU::MemBar::Barrier();
return ret;
}
void APIC::EOI() { this->Write(APIC_EOI, 0); }
void APIC::WaitForIPI()
{
InterruptCommandRegisterLow icr = {.raw = 0};
do
{
icr.raw = this->Read(APIC_ICRLO);
} while (icr.DeliveryStatus != Idle);
}
void APIC::IPI(uint8_t CPU, InterruptCommandRegisterLow icr)
{
SmartCriticalSection(APICLock);
if (x2APICSupported)
{
fixme("Not implemented for x2APIC");
// wrmsr(MSR_X2APIC_ICR, ((uint64_t)CPU) << 32);
}
else
{
this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, icr.raw);
this->WaitForIPI();
}
}
void APIC::SendInitIPI(uint8_t CPU)
{
SmartCriticalSection(APICLock);
if (x2APICSupported)
{
fixme("Not implemented for x2APIC");
// wrmsr(MSR_X2APIC_ICR, ((uint64_t)CPU) << 32);
}
else
{
InterruptCommandRegisterLow icr = {.raw = 0};
icr.DeliveryMode = INIT;
icr.Level = Assert;
this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, icr.raw);
this->WaitForIPI();
}
}
void APIC::SendStartupIPI(uint8_t CPU, uint64_t StartupAddress)
{
SmartCriticalSection(APICLock);
if (x2APICSupported)
{
warn("Not tested for x2APIC");
wrmsr(MSR_X2APIC_ICR, ((uint64_t)CPU) << 32 | StartupAddress);
}
else
{
InterruptCommandRegisterLow icr = {.raw = 0};
icr.Vector = StartupAddress >> 12;
icr.DeliveryMode = Startup;
icr.Level = Assert;
this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, icr.raw);
this->WaitForIPI();
}
}
uint32_t APIC::IOGetMaxRedirect(uint32_t APICID)
{
uint32_t TableAddress = (this->IORead((((ACPI::MADT *)PowerManager->GetMADT())->ioapic[APICID]->Address), GetIOAPICVersion));
return ((IOAPICVersion *)&TableAddress)->MaximumRedirectionEntry;
}
void APIC::RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status)
{
uint64_t Value = Vector;
int64_t IOAPICTarget = -1;
for (uint64_t i = 0; ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i] != 0; i++)
if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase <= GSI)
if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase + IOGetMaxRedirect(i) > GSI)
{
IOAPICTarget = i;
break;
}
if (IOAPICTarget == -1)
{
error("No ISO table found for I/O APIC");
return;
}
// TODO: IOAPICRedirectEntry Entry = {.raw = 0};
if (Flags & ActiveHighLow)
Value |= (1 << 13);
if (Flags & EdgeLevel)
Value |= (1 << 15);
if (!Status)
Value |= (1 << 16);
Value |= (((uintptr_t)CPU) << 56);
uint32_t IORegister = (GSI - ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->GSIBase) * 2 + 16;
this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister, (uint32_t)Value);
this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister + 1, (uint32_t)(Value >> 32));
}
void APIC::RedirectIRQ(int CPU, uint8_t IRQ, int Status)
{
for (uint64_t i = 0; i < ((ACPI::MADT *)PowerManager->GetMADT())->iso.size(); i++)
if (((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource == IRQ)
{
debug("[ISO %d] Mapping to source IRQ%#d GSI:%#lx on CPU %d",
i, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->GSI, CPU);
this->RawRedirectIRQ(((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource + 0x20, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->GSI, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->Flags, CPU, Status);
return;
}
debug("Mapping IRQ%d on CPU %d", IRQ, CPU);
this->RawRedirectIRQ(IRQ + 0x20, IRQ, 0, CPU, Status);
}
void APIC::RedirectIRQs(int CPU)
{
SmartCriticalSection(APICLock);
debug("Redirecting IRQs...");
for (int i = 0; i < 16; i++)
this->RedirectIRQ(CPU, i, 1);
debug("Redirecting IRQs completed.");
}
APIC::APIC(int Core)
{
SmartCriticalSection(APICLock);
APIC_BASE BaseStruct = {.raw = rdmsr(MSR_APIC_BASE)};
uint64_t BaseLow = BaseStruct.ApicBaseLo;
uint64_t BaseHigh = BaseStruct.ApicBaseHi;
this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u;
trace("APIC Address: %#lx", this->APICBaseAddress);
uint32_t rcx;
cpuid(1, 0, 0, &rcx, 0);
if (rcx & CPUID_FEAT_RCX_x2APIC)
{
// this->x2APICSupported = true;
warn("x2APIC not supported yet.");
// wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
BaseStruct.EN = 1;
wrmsr(MSR_APIC_BASE, BaseStruct.raw);
}
else
{
BaseStruct.EN = 1;
wrmsr(MSR_APIC_BASE, BaseStruct.raw);
}
this->Write(APIC_TPR, 0x0);
// this->Write(APIC_SVR, this->Read(APIC_SVR) | 0x100); // 0x1FF or 0x100 ? on https://wiki.osdev.org/APIC is 0x100
if (!this->x2APICSupported)
{
this->Write(APIC_DFR, 0xF0000000);
this->Write(APIC_LDR, this->Read(APIC_ID));
}
ACPI::MADT *madt = (ACPI::MADT *)PowerManager->GetMADT();
for (size_t i = 0; i < madt->nmi.size(); i++)
{
if (madt->nmi[i]->processor != 0xFF && Core != madt->nmi[i]->processor)
return;
uint32_t nmi = 0x402;
if (madt->nmi[i]->flags & 2)
nmi |= 1 << 13;
if (madt->nmi[i]->flags & 8)
nmi |= 1 << 15;
if (madt->nmi[i]->lint == 0)
this->Write(APIC_LINT0, nmi);
else if (madt->nmi[i]->lint == 1)
this->Write(APIC_LINT1, nmi);
}
// Setup the spurrious interrupt vector
Spurious Spurious = {.raw = this->Read(APIC_SVR)};
Spurious.Vector = IRQ223; // TODO: Should I map the IRQ to something?
Spurious.Software = 1;
this->Write(APIC_SVR, Spurious.raw);
static int once = 0;
if (!once++)
{
// Disable PIT
outb(0x43, 0x28);
outb(0x40, 0x0);
// Disable PIC
outb(0x21, 0xFF);
outb(0xA1, 0xFF);
}
}
APIC::~APIC() {}
void Timer::OnInterruptReceived(TrapFrame *Frame) {}
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
{
SmartCriticalSection(APICLock);
LVTTimer timer = {.raw = 0};
timer.Vector = Vector;
timer.TimerMode = 0;
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
this->lapic->Write(APIC_TDCR, DivideBy128);
else
this->lapic->Write(APIC_TDCR, DivideBy16);
this->lapic->Write(APIC_TICR, Ticks * Miliseconds);
this->lapic->Write(APIC_TIMER, timer.raw);
}
Timer::Timer(APIC *apic) : Interrupts::Handler(IRQ0)
{
SmartCriticalSection(APICLock);
this->lapic = apic;
LVTTimerDivide Divider = DivideBy16;
trace("Initializing APIC timer on CPU %d", GetCurrentCPU()->ID);
this->lapic->Write(APIC_TDCR, Divider);
this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
TimeManager->Sleep(10);
// Mask the timer
this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);
Ticks = 0xFFFFFFFF - this->lapic->Read(APIC_TCCR);
// Config for IRQ0 timer
LVTTimer timer = {.raw = 0};
timer.Vector = IRQ0;
timer.Mask = Unmasked;
timer.TimerMode = LVTTimerMode::OneShot;
// Initialize APIC timer
this->lapic->Write(APIC_TDCR, Divider);
this->lapic->Write(APIC_TICR, Ticks);
this->lapic->Write(APIC_TIMER, timer.raw);
trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks);
KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks);
}
Timer::~Timer()
{
}
}

View File

@ -0,0 +1,153 @@
#include "gdt.hpp"
#include <memory.hpp>
#include <smp.hpp>
#include <cpu.hpp>
#include <debug.h>
namespace GlobalDescriptorTable
{
static GlobalDescriptorTableEntries GDTEntriesTemplate = {
// null
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.Raw = 0x0},
.Flags = {.Raw = 0x0},
.BaseHigh = 0x0},
// kernel code
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.A = 0,
.RW = 1,
.DC = 0,
.E = 1,
.S = 1,
.DPL = 0,
.P = 1},
.Flags = {.Unknown = 0x0, .L = 1},
.BaseHigh = 0x0},
// kernel data
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.A = 0,
.RW = 1,
.DC = 0,
.E = 0,
.S = 1,
.DPL = 0,
.P = 1},
.Flags = {.Raw = 0x0},
.BaseHigh = 0x0},
// user data
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.A = 0,
.RW = 1,
.DC = 0,
.E = 0,
.S = 1,
.DPL = 3,
.P = 1},
.Flags = {.Raw = 0x0},
.BaseHigh = 0x0},
// user code
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.A = 0,
.RW = 1,
.DC = 0,
.E = 1,
.S = 1,
.DPL = 3,
.P = 1},
.Flags = {.Unknown = 0x0, .L = 1},
.BaseHigh = 0x0},
// tss
{}};
static GlobalDescriptorTableEntries GDTEntries[MAX_CPU];
GlobalDescriptorTableDescriptor gdt[MAX_CPU];
TaskStateSegment tss[MAX_CPU] = {
0,
{0, 0, 0},
0,
{0, 0, 0, 0, 0, 0, 0},
0,
0,
};
void *CPUStackPointer[MAX_CPU];
SafeFunction void Init(int Core)
{
memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries));
gdt[Core] = {.Length = sizeof(GlobalDescriptorTableEntries) - 1, .Entries = &GDTEntries[Core]};
debug("Kernel: Code Access: %ld; Data Access: %ld", GDTEntries[Core].Code.Access.Raw, GDTEntries[Core].Data.Access.Raw);
debug("Kernel: Code Flags: %ld; Data Flags: %ld", GDTEntries[Core].Code.Flags.Raw, GDTEntries[Core].Data.Flags.Raw);
debug("User: Code Access: %ld; Data Access: %ld", GDTEntries[Core].UserCode.Access.Raw, GDTEntries[Core].UserData.Access.Raw);
debug("User: Code Flags: %ld; Data Flags: %ld", GDTEntries[Core].UserCode.Flags.Raw, GDTEntries[Core].UserData.Flags.Raw);
CPU::x64::lgdt(&gdt[Core]);
asmv("movq %%rsp, %%rax\n"
"pushq $16\n"
"pushq %%rax\n"
"pushfq\n"
"pushq $8\n"
"pushq $1f\n"
"iretq\n"
"1:\n"
"movw $16, %%ax\n"
"movw %%ax, %%ds\n"
"movw %%ax, %%es\n" ::
: "memory", "rax");
CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
uint64_t Base = (uint64_t)&tss[Core];
uint64_t Limit = Base + sizeof(TaskStateSegment);
gdt[Core].Entries->TaskStateSegment.Length = 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 = (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.Granularity = (0 << 4) | ((Limit >> 16) & 0xF);
tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment);
tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE;
tss[Core].InterruptStackTable[0] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
tss[Core].InterruptStackTable[1] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
tss[Core].InterruptStackTable[2] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
CPU::x64::ltr(GDT_TSS);
asmv("mov %%rsp, %0"
: "=r"(tss[Core].StackPointer[0]));
trace("GDT_KERNEL_CODE: %#lx", GDT_KERNEL_CODE);
trace("GDT_KERNEL_DATA: %#lx", GDT_KERNEL_DATA);
trace("GDT_USER_CODE: %#lx", GDT_USER_CODE);
trace("GDT_USER_DATA: %#lx", GDT_USER_DATA);
trace("GDT_TSS: %#lx", GDT_TSS);
trace("Global Descriptor Table initialized");
}
SafeFunction void SetKernelStack(void *Stack)
{
if (Stack)
tss[GetCurrentCPU()->ID].StackPointer[0] = (uint64_t)Stack;
else
tss[GetCurrentCPU()->ID].StackPointer[0] = (uint64_t)CPUStackPointer[GetCurrentCPU()->ID] + STACK_SIZE;
}
}

View File

@ -0,0 +1,755 @@
#include "idt.hpp"
#include <cpu.hpp>
#include <debug.h>
#include <io.h>
#include "gdt.hpp"
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)(),
InterruptDescriptorTableFlags Attribute,
uint8_t InterruptStackTable,
InterruptDescriptorTableFlags Ring,
uint16_t SegmentSelector)
{
Entries[Index].BaseLow = (uint16_t)((uint64_t)Base & 0xFFFF);
Entries[Index].BaseHigh = (uint64_t)((uint64_t)Base >> 16 /* & 0xFFFF */);
Entries[Index].SegmentSelector = SegmentSelector;
Entries[Index].Flags = Attribute;
Entries[Index].Reserved1 = 0;
Entries[Index].Reserved2 = 0;
Entries[Index].Reserved3 = 0;
Entries[Index].InterruptStackTable = InterruptStackTable;
Entries[Index].Ring = Ring;
Entries[Index].Present = 1;
}
extern "C" __attribute__((naked, used, no_stack_protector)) void ExceptionHandlerStub()
{
asm(
// "cmp $0x1000, %rsp\n" // Just in case the stack is corrupted
// "jng .skip_swap_check_1\n" /* if is not greater than */
// "cmpw $0x8, 0x8(%rsp)\n"
// "je .skip_swap_check_1\n"
// "swapgs\n"
// ".skip_swap_check_1:\n"
"cld\n" // clear direction flag
// push all registers
"pushq %rax\n"
"pushq %rbx\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"pushq %rbp\n"
"pushq %r8\n"
"pushq %r9\n"
"pushq %r10\n"
"pushq %r11\n"
"pushq %r12\n"
"pushq %r13\n"
"pushq %r14\n"
"pushq %r15\n"
"movq %rsp, %rdi\n"
"call ExceptionHandler\n"
// pop all registers
"popq %r15\n"
"popq %r14\n"
"popq %r13\n"
"popq %r12\n"
"popq %r11\n"
"popq %r10\n"
"popq %r9\n"
"popq %r8\n"
"popq %rbp\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n"
"popq %rbx\n"
"popq %rax\n"
"addq $16, %rsp\n"
// "cmp $0x1000, %rsp\n"
// "jng .skip_swap_check_2\n"
// "cmpw $0x8, 0x8(%rsp)\n"
// "je .skip_swap_check_2\n"
// "swapgs\n"
// ".skip_swap_check_2:\n"
"iretq"); // pop CS RIP RFLAGS SS ESP
}
extern "C" void WarnSwapgs() { warn("swapgs"); }
extern "C" __attribute__((naked, used, no_stack_protector)) void InterruptHandlerStub()
{
asm(
// "cmp $0x1000, %rsp\n"
// "jng .skip_swap_check__1\n"
// "cmpw $0x8, 0x8(%rsp)\n"
// "je .skip_swap_check__1\n"
// "swapgs\n"
// "call WarnSwapgs\n"
// ".skip_swap_check__1:\n"
"cld\n"
"pushq %rax\n"
"pushq %rbx\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"pushq %rbp\n"
"pushq %r8\n"
"pushq %r9\n"
"pushq %r10\n"
"pushq %r11\n"
"pushq %r12\n"
"pushq %r13\n"
"pushq %r14\n"
"pushq %r15\n"
"movq %rsp, %rdi\n"
"call MainInterruptHandler\n"
"popq %r15\n"
"popq %r14\n"
"popq %r13\n"
"popq %r12\n"
"popq %r11\n"
"popq %r10\n"
"popq %r9\n"
"popq %r8\n"
"popq %rbp\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n"
"popq %rbx\n"
"popq %rax\n"
"addq $16, %rsp\n"
// "cmp $0x1000, %rsp\n"
// "jng .skip_swap_check__2\n"
// "cmpw $0x8, 0x8(%rsp)\n"
// "je .skip_swap_check__2\n"
// "call WarnSwapgs\n"
// "swapgs\n"
// ".skip_swap_check__2:\n"
"iretq");
}
#pragma region Exceptions
#define EXCEPTION_HANDLER(num) \
__attribute__((naked, no_stack_protector)) static void InterruptHandler_##num() \
{ \
asm("pushq $0\npushq $" #num "\n" \
"jmp ExceptionHandlerStub"); \
}
#define EXCEPTION_ERROR_HANDLER(num) \
__attribute__((naked, no_stack_protector)) static void InterruptHandler_##num() \
{ \
asm("pushq $" #num "\n" \
"jmp ExceptionHandlerStub"); \
}
#define INTERRUPT_HANDLER(num) \
__attribute__((naked, used, no_stack_protector)) void InterruptHandler_##num() \
{ \
asm("pushq $0\npushq $" #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)
{
static int once = 0;
if (!once++)
{
// 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 */
SetEntry(0x0, InterruptHandler_0x0, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1, InterruptHandler_0x1, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2, InterruptHandler_0x2, FlagGate_32BIT_TRAP, 2, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3, InterruptHandler_0x3, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4, InterruptHandler_0x4, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5, InterruptHandler_0x5, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6, InterruptHandler_0x6, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7, InterruptHandler_0x7, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8, InterruptHandler_0x8, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9, InterruptHandler_0x9, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa, InterruptHandler_0xa, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb, InterruptHandler_0xb, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc, InterruptHandler_0xc, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd, InterruptHandler_0xd, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe, InterruptHandler_0xe, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf, InterruptHandler_0xf, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x10, InterruptHandler_0x10, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x11, InterruptHandler_0x11, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x12, InterruptHandler_0x12, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x13, InterruptHandler_0x13, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x14, InterruptHandler_0x14, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x15, InterruptHandler_0x15, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x16, InterruptHandler_0x16, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x17, InterruptHandler_0x17, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x18, InterruptHandler_0x18, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x19, InterruptHandler_0x19, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1a, InterruptHandler_0x1a, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1b, InterruptHandler_0x1b, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1c, InterruptHandler_0x1c, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1d, InterruptHandler_0x1d, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1e, InterruptHandler_0x1e, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1f, InterruptHandler_0x1f, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
/* IRQ */
SetEntry(0x20, InterruptHandler_0x20, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x21, InterruptHandler_0x21, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x22, InterruptHandler_0x22, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x23, InterruptHandler_0x23, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x24, InterruptHandler_0x24, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x25, InterruptHandler_0x25, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x26, InterruptHandler_0x26, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x27, InterruptHandler_0x27, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x28, InterruptHandler_0x28, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x29, InterruptHandler_0x29, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2a, InterruptHandler_0x2a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2b, InterruptHandler_0x2b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2c, InterruptHandler_0x2c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2d, InterruptHandler_0x2d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2e, InterruptHandler_0x2e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2f, InterruptHandler_0x2f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
/* Reserved by OS */
SetEntry(0x30, InterruptHandler_0x30, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x31, InterruptHandler_0x31, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x32, InterruptHandler_0x32, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x33, InterruptHandler_0x33, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x34, InterruptHandler_0x34, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x35, InterruptHandler_0x35, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x36, InterruptHandler_0x36, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x37, InterruptHandler_0x37, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x38, InterruptHandler_0x38, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x39, InterruptHandler_0x39, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3a, InterruptHandler_0x3a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3b, InterruptHandler_0x3b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3c, InterruptHandler_0x3c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3d, InterruptHandler_0x3d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
/* Free */
SetEntry(0x3e, InterruptHandler_0x3e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3f, InterruptHandler_0x3f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x40, InterruptHandler_0x40, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x41, InterruptHandler_0x41, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x42, InterruptHandler_0x42, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x43, InterruptHandler_0x43, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x44, InterruptHandler_0x44, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x45, InterruptHandler_0x45, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x46, InterruptHandler_0x46, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x47, InterruptHandler_0x47, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x48, InterruptHandler_0x48, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x49, InterruptHandler_0x49, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4a, InterruptHandler_0x4a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4b, InterruptHandler_0x4b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4c, InterruptHandler_0x4c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4d, InterruptHandler_0x4d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4e, InterruptHandler_0x4e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4f, InterruptHandler_0x4f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x50, InterruptHandler_0x50, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x51, InterruptHandler_0x51, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x52, InterruptHandler_0x52, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x53, InterruptHandler_0x53, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x54, InterruptHandler_0x54, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x55, InterruptHandler_0x55, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x56, InterruptHandler_0x56, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x57, InterruptHandler_0x57, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x58, InterruptHandler_0x58, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x59, InterruptHandler_0x59, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5a, InterruptHandler_0x5a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5b, InterruptHandler_0x5b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5c, InterruptHandler_0x5c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5d, InterruptHandler_0x5d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5e, InterruptHandler_0x5e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5f, InterruptHandler_0x5f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x60, InterruptHandler_0x60, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x61, InterruptHandler_0x61, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x62, InterruptHandler_0x62, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x63, InterruptHandler_0x63, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x64, InterruptHandler_0x64, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x65, InterruptHandler_0x65, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x66, InterruptHandler_0x66, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x67, InterruptHandler_0x67, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x68, InterruptHandler_0x68, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x69, InterruptHandler_0x69, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6a, InterruptHandler_0x6a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6b, InterruptHandler_0x6b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6c, InterruptHandler_0x6c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6d, InterruptHandler_0x6d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6e, InterruptHandler_0x6e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6f, InterruptHandler_0x6f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x70, InterruptHandler_0x70, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x71, InterruptHandler_0x71, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x72, InterruptHandler_0x72, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x73, InterruptHandler_0x73, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x74, InterruptHandler_0x74, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x75, InterruptHandler_0x75, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x76, InterruptHandler_0x76, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x77, InterruptHandler_0x77, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x78, InterruptHandler_0x78, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x79, InterruptHandler_0x79, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7a, InterruptHandler_0x7a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7b, InterruptHandler_0x7b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7c, InterruptHandler_0x7c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7d, InterruptHandler_0x7d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7e, InterruptHandler_0x7e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7f, InterruptHandler_0x7f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x80, InterruptHandler_0x80, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x81, InterruptHandler_0x81, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x82, InterruptHandler_0x82, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x83, InterruptHandler_0x83, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x84, InterruptHandler_0x84, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x85, InterruptHandler_0x85, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x86, InterruptHandler_0x86, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x87, InterruptHandler_0x87, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x88, InterruptHandler_0x88, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x89, InterruptHandler_0x89, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8a, InterruptHandler_0x8a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8b, InterruptHandler_0x8b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8c, InterruptHandler_0x8c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8d, InterruptHandler_0x8d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8e, InterruptHandler_0x8e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8f, InterruptHandler_0x8f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x90, InterruptHandler_0x90, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x91, InterruptHandler_0x91, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x92, InterruptHandler_0x92, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x93, InterruptHandler_0x93, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x94, InterruptHandler_0x94, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x95, InterruptHandler_0x95, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x96, InterruptHandler_0x96, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x97, InterruptHandler_0x97, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x98, InterruptHandler_0x98, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x99, InterruptHandler_0x99, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9a, InterruptHandler_0x9a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9b, InterruptHandler_0x9b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9c, InterruptHandler_0x9c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9d, InterruptHandler_0x9d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9e, InterruptHandler_0x9e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9f, InterruptHandler_0x9f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa0, InterruptHandler_0xa0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa1, InterruptHandler_0xa1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa2, InterruptHandler_0xa2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa3, InterruptHandler_0xa3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa4, InterruptHandler_0xa4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa5, InterruptHandler_0xa5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa6, InterruptHandler_0xa6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa7, InterruptHandler_0xa7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa8, InterruptHandler_0xa8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa9, InterruptHandler_0xa9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xaa, InterruptHandler_0xaa, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xab, InterruptHandler_0xab, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xac, InterruptHandler_0xac, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xad, InterruptHandler_0xad, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xae, InterruptHandler_0xae, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xaf, InterruptHandler_0xaf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb0, InterruptHandler_0xb0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb1, InterruptHandler_0xb1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb2, InterruptHandler_0xb2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb3, InterruptHandler_0xb3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb4, InterruptHandler_0xb4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb5, InterruptHandler_0xb5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb6, InterruptHandler_0xb6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb7, InterruptHandler_0xb7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb8, InterruptHandler_0xb8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb9, InterruptHandler_0xb9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xba, InterruptHandler_0xba, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbb, InterruptHandler_0xbb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbc, InterruptHandler_0xbc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbd, InterruptHandler_0xbd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbe, InterruptHandler_0xbe, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbf, InterruptHandler_0xbf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc0, InterruptHandler_0xc0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc1, InterruptHandler_0xc1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc2, InterruptHandler_0xc2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc3, InterruptHandler_0xc3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc4, InterruptHandler_0xc4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc5, InterruptHandler_0xc5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc6, InterruptHandler_0xc6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc7, InterruptHandler_0xc7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc8, InterruptHandler_0xc8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc9, InterruptHandler_0xc9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xca, InterruptHandler_0xca, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcb, InterruptHandler_0xcb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcc, InterruptHandler_0xcc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcd, InterruptHandler_0xcd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xce, InterruptHandler_0xce, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcf, InterruptHandler_0xcf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd0, InterruptHandler_0xd0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd1, InterruptHandler_0xd1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd2, InterruptHandler_0xd2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd3, InterruptHandler_0xd3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd4, InterruptHandler_0xd4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd5, InterruptHandler_0xd5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd6, InterruptHandler_0xd6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd7, InterruptHandler_0xd7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd8, InterruptHandler_0xd8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd9, InterruptHandler_0xd9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xda, InterruptHandler_0xda, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdb, InterruptHandler_0xdb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdc, InterruptHandler_0xdc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdd, InterruptHandler_0xdd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xde, InterruptHandler_0xde, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdf, InterruptHandler_0xdf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe0, InterruptHandler_0xe0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe1, InterruptHandler_0xe1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe2, InterruptHandler_0xe2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe3, InterruptHandler_0xe3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe4, InterruptHandler_0xe4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe5, InterruptHandler_0xe5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe6, InterruptHandler_0xe6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe7, InterruptHandler_0xe7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe8, InterruptHandler_0xe8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe9, InterruptHandler_0xe9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xea, InterruptHandler_0xea, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xeb, InterruptHandler_0xeb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xec, InterruptHandler_0xec, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xed, InterruptHandler_0xed, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xee, InterruptHandler_0xee, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xef, InterruptHandler_0xef, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf0, InterruptHandler_0xf0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf1, InterruptHandler_0xf1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf2, InterruptHandler_0xf2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf3, InterruptHandler_0xf3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf4, InterruptHandler_0xf4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf5, InterruptHandler_0xf5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf6, InterruptHandler_0xf6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf7, InterruptHandler_0xf7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf8, InterruptHandler_0xf8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf9, InterruptHandler_0xf9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfa, InterruptHandler_0xfa, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfb, InterruptHandler_0xfb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfc, InterruptHandler_0xfc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfd, InterruptHandler_0xfd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfe, InterruptHandler_0xfe, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xff, InterruptHandler_0xff, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
CPU::x64::lidt(&idtd);
}
}

View File

@ -0,0 +1,113 @@
[bits 16]
TRAMPOLINE_BASE equ 0x2000
extern StartCPU
global _trampoline_start
_trampoline_start:
cli
mov ax, 0x0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
o32 lgdt [ProtectedMode_gdtr - _trampoline_start + TRAMPOLINE_BASE]
mov eax, cr0
or al, 0x1
mov cr0, eax
jmp 0x8:(Trampoline32 - _trampoline_start + TRAMPOLINE_BASE)
[bits 32]
section .text
Trampoline32:
mov bx, 0x10
mov ds, bx
mov es, bx
mov ss, bx
mov eax, dword [0x500]
mov cr3, eax
mov eax, cr4
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
or eax, 1 << 7
mov cr4, eax
mov ecx, 0xc0000080
rdmsr
or eax,1 << 8 ; LME
wrmsr
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
lgdt [LongMode_gdtr - _trampoline_start + TRAMPOLINE_BASE]
jmp 0x8:(Trampoline64 - _trampoline_start + TRAMPOLINE_BASE)
[bits 64]
Trampoline64:
mov ax, 0x10
mov ds, ax
mov es, ax
mov ss, ax
mov ax, 0x0
mov fs, ax
mov gs, ax
lgdt [0x580]
lidt [0x590]
mov rsp, [0x570]
mov rbp, 0x0 ; Terminate stack traces here.
; Reset RFLAGS.
push 0x0
popf
mov rax, qword vcode64
call vcode64
vcode64:
push rbp
; Set up SSE
mov rax, cr0
; btr eax, 2
; bts eax, 1
; mov cr0, rax
mov rax, cr4
bts eax, 9
bts eax, 10
mov cr4, rax
mov rax, qword TrampolineExit
call rax
align 16
LongMode_gdtr:
dw LongModeGDTEnd - LongModeGDTStart - 1
dq LongModeGDTStart - _trampoline_start + TRAMPOLINE_BASE
align 16
LongModeGDTStart:
dq 0 ; NULL segment
dq 0x00AF98000000FFFF ; Code segment
dq 0x00CF92000000FFFF ; Data segment
LongModeGDTEnd:
align 16
ProtectedMode_gdtr:
dw ProtectedModeGDTEnd - ProtectedModeGDTStart - 1
dd ProtectedModeGDTStart - _trampoline_start + TRAMPOLINE_BASE
align 16
ProtectedModeGDTStart:
dq 0 ; NULL segment
dq 0x00CF9A000000FFFF ; Code segment
dq 0x00CF92000000FFFF ; Data segment
ProtectedModeGDTEnd:
align 16
ProtectedMode_idtr:
dw 0
dd 0
dd 0
align 16
global _trampoline_end
_trampoline_end:
TrampolineExit:
call StartCPU
times 512 - ($-$$) db 0

View File

@ -0,0 +1,129 @@
#include <smp.hpp>
#include <interrupts.hpp>
#include <memory.hpp>
#include <assert.h>
#include <cpu.hpp>
#include "../../../kernel.h"
#include "../acpi.hpp"
#include "apic.hpp"
extern "C" uint64_t _trampoline_start, _trampoline_end;
enum SMPTrampolineAddress
{
PAGE_TABLE = 0x500,
START_ADDR = 0x520,
STACK = 0x570,
GDT = 0x580,
IDT = 0x590,
CORE = 0x600,
TRAMPOLINE_START = 0x2000
};
volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
CPUData *GetCPU(long id) { return &CPUs[id]; }
CPUData *GetCurrentCPU()
{
CPUData *data = (CPUData *)CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE);
if (data == nullptr && Interrupts::apic[0])
data = &CPUs[((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24];
if (data == nullptr)
return nullptr; // The caller should handle this.
if (!data->IsActive)
{
error("CPU %d is not active!", data->ID);
if ((&CPUs[0])->IsActive)
return &CPUs[0];
else
return nullptr; // We are in trouble.
}
assert(data->Checksum == CPU_DATA_CHECKSUM); // This should never happen.
return data;
}
extern "C" void StartCPU()
{
CPU::Interrupts(CPU::Disable);
CPU::InitializeFeatures();
uint64_t CoreID = (int)*reinterpret_cast<int *>(CORE);
// Initialize GDT and IDT
Interrupts::Initialize(CoreID);
Interrupts::Enable(CoreID);
Interrupts::InitializeTimer(CoreID);
CPU::Interrupts(CPU::Enable);
KPrint("\e058C19CPU \e8888FF%d \e058C19is online", CoreID);
CPUEnabled = true;
CPU::Halt(true);
}
namespace SMP
{
int CPUCores = 0;
void Initialize(void *madt)
{
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) == 0)
{
KPrint("VirtualBox detected, disabling SMP");
return;
}
int Cores = ((ACPI::MADT *)madt)->CPUCores + 1;
if (Config.Cores > ((ACPI::MADT *)madt)->CPUCores + 1)
KPrint("More cores requested than available. Using %d cores", ((ACPI::MADT *)madt)->CPUCores + 1);
else if (Config.Cores != 0)
Cores = Config.Cores;
CPUCores = Cores;
for (int i = 0; i < Cores; i++)
{
debug("Initializing CPU %d", i);
if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24) != ((ACPI::MADT *)madt)->lapic[i]->ACPIProcessorId)
{
((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24));
((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRLO, 0x500);
Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW | Memory::PTFlag::US);
uint64_t TrampolineLength = (uintptr_t)&_trampoline_end - (uintptr_t)&_trampoline_start;
for (uint64_t i = 0; i < (TrampolineLength / PAGE_SIZE) + 2; i++)
Memory::Virtual().Map((void *)(TRAMPOLINE_START + (i * PAGE_SIZE)), (void *)(TRAMPOLINE_START + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
memcpy((void *)TRAMPOLINE_START, &_trampoline_start, TrampolineLength);
POKE(volatile uint64_t, PAGE_TABLE) = CPU::x64::readcr3().raw;
POKE(volatile uint64_t, STACK) = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
POKE(volatile uint64_t, CORE) = i;
asmv("sgdt [0x580]\n"
"sidt [0x590]\n");
POKE(volatile uint64_t, START_ADDR) = (uintptr_t)&StartCPU;
((APIC::APIC *)Interrupts::apic[0])->SendInitIPI(((ACPI::MADT *)madt)->lapic[i]->APICId);
((APIC::APIC *)Interrupts::apic[0])->SendStartupIPI(((ACPI::MADT *)madt)->lapic[i]->APICId, TRAMPOLINE_START);
while (!CPUEnabled)
CPU::Pause();
trace("CPU %d loaded.", ((ACPI::MADT *)madt)->lapic[i]->APICId);
KernelAllocator.FreePages((void *)*reinterpret_cast<long *>(STACK), TO_PAGES(STACK_SIZE));
CPUEnabled = false;
}
else
KPrint("\e058C19CPU \e8888FF%d \e058C19is the BSP", ((ACPI::MADT *)madt)->lapic[i]->APICId);
}
}
}

View File

@ -0,0 +1,337 @@
#ifndef __FENNIX_KERNEL_APIC_H__
#define __FENNIX_KERNEL_APIC_H__
#include <types.h>
#include <interrupts.hpp>
#include <cpu.hpp>
namespace APIC
{
enum APICRegisters
{
// source from: https://github.com/pdoane/osdev/blob/master/intr/local_apic.c
APIC_ID = 0x20, // Local APIC ID
APIC_VER = 0x30, // Local APIC Version
APIC_TPR = 0x80, // Task Priority
APIC_APR = 0x90, // Arbitration Priority
APIC_PPR = 0xA0, // Processor Priority
APIC_EOI = 0xB0, // EOI
APIC_RRD = 0xC0, // Remote Read
APIC_LDR = 0xD0, // Logical Destination
APIC_DFR = 0xE0, // Destination Format
APIC_SVR = 0xF0, // Spurious Interrupt Vector
APIC_ISR = 0x100, // In-Service (8 registers)
APIC_TMR = 0x180, // Trigger Mode (8 registers)
APIC_IRR = 0x200, // Interrupt Request (8 registers)
APIC_ESR = 0x280, // Error Status
APIC_ICRLO = 0x300, // Interrupt Command
APIC_ICRHI = 0x310, // Interrupt Command [63:32]
APIC_TIMER = 0x320, // LVT Timer
APIC_THERMAL = 0x330, // LVT Thermal Sensor
APIC_PERF = 0x340, // LVT Performance Counter
APIC_LINT0 = 0x350, // LVT LINT0
APIC_LINT1 = 0x360, // LVT LINT1
APIC_ERROR = 0x370, // LVT Error
APIC_TICR = 0x380, // Initial Count (for Timer)
APIC_TCCR = 0x390, // Current Count (for Timer)
APIC_TDCR = 0x3E0, // Divide Configuration (for Timer)
};
enum IOAPICRegisters
{
GetIOAPICVersion = 0x1
};
enum IOAPICFlags
{
ActiveHighLow = 2,
EdgeLevel = 8
};
enum APICDeliveryMode
{
Fixed = 0b000,
LowestPriority = 0b001, /* Reserved */
SMI = 0b010,
APIC_DELIVERY_MODE_RESERVED0 = 0b011, /* Reserved */
NMI = 0b100,
INIT = 0b101,
Startup = 0b110,
ExtINT = 0b111 /* Reserved */
};
enum APICDestinationMode
{
Physical = 0b0,
Logical = 0b1
};
enum APICDeliveryStatus
{
Idle = 0b0,
SendPending = 0b1
};
enum APICLevel
{
DeAssert = 0b0,
Assert = 0b1
};
enum APICTriggerMode
{
Edge = 0b0,
Level = 0b1
};
enum APICDestinationShorthand
{
NoShorthand = 0b00,
Self = 0b01,
AllIncludingSelf = 0b10,
AllExcludingSelf = 0b11
};
enum LVTTimerDivide
{
DivideBy2 = 0b000,
DivideBy4 = 0b001,
DivideBy8 = 0b010,
DivideBy16 = 0b011,
DivideBy32 = 0b100,
DivideBy64 = 0b101,
DivideBy128 = 0b110,
DivideBy1 = 0b111
};
enum LVTTimerMask
{
Unmasked = 0b0,
Masked = 0b1
};
enum LVTTimerMode
{
OneShot = 0b00,
Periodic = 0b01,
TSCDeadline = 0b10
};
typedef union
{
struct
{
/** @brief Interrupt Vector */
uint64_t Vector : 8;
/** @brief Reserved */
uint64_t Reserved0 : 4;
/**
* @brief Delivery Status
*
* 0: Idle
* 1: Send Pending
*/
uint64_t DeliveryStatus : 1;
/** @brief Reserved */
uint64_t Reserved1 : 3;
/**
* @brief Mask
*
* 0: Not masked
* 1: Masked
*/
uint64_t Mask : 1;
/** @brief Timer Mode
*
* 0: One-shot
* 1: Periodic
* 2: TSC-Deadline
*/
uint64_t TimerMode : 1;
/** @brief Reserved */
uint64_t Reserved2 : 14;
};
uint64_t raw;
} __attribute__((packed)) LVTTimer;
typedef union
{
struct
{
/** @brief Spurious Vector */
uint64_t Vector : 8;
/** @brief Enable or disable APIC software */
uint64_t Software : 1;
/** @brief Focus Processor Checking */
uint64_t FocusProcessorChecking : 1;
/** @brief Reserved */
uint64_t Reserved : 2;
/** @brief Disable EOI Broadcast */
uint64_t DisableEOIBroadcast : 1;
/** @brief Reserved */
uint64_t Reserved1 : 19;
};
uint64_t raw;
} __attribute__((packed)) Spurious;
typedef union
{
struct
{
/** @brief Interrupt Vector */
uint64_t Vector : 8;
/** @brief Delivery Mode */
uint64_t DeliveryMode : 3;
/** @brief Destination Mode
*
* 0: Physical
* 1: Logical
*/
uint64_t DestinationMode : 1;
/** @brief Delivery Status
*
* @note Reserved when in x2APIC mode
*/
uint64_t DeliveryStatus : 1;
/** @brief Reserved */
uint64_t Reserved0 : 1;
/** @brief Level
*
* 0: Deassert
* 1: Assert
*/
uint64_t Level : 1;
/** @brief Trigger Mode
*
* 0: Edge
* 1: Level
*/
uint64_t TriggerMode : 1;
/** @brief Reserved */
uint64_t Reserved1 : 2;
/** @brief Destination Shorthand
*
* 0: No shorthand
* 1: Self
* 2: All including self
* 3: All excluding self
*/
uint64_t DestinationShorthand : 2;
/** @brief Reserved */
uint64_t Reserved2 : 12;
};
uint64_t raw;
} __attribute__((packed)) InterruptCommandRegisterLow;
typedef union
{
struct
{
/** @brief Reserved */
uint64_t Reserved0 : 24;
/** @brief Destination */
uint64_t Destination : 8;
};
uint64_t raw;
} __attribute__((packed)) InterruptCommandRegisterHigh;
typedef union
{
struct
{
/** @brief Interrupt Vector */
uint64_t Vector : 8;
/** @brief Delivery Mode */
uint64_t DeliveryMode : 3;
/** @brief Destination Mode
*
* 0: Physical
* 1: Logical
*/
uint64_t DestinationMode : 1;
/** @brief Delivery Status */
uint64_t DeliveryStatus : 1;
/** @brief Interrupt Input Pin Polarity
*
* 0: Active High
* 1: Active Low
*/
uint64_t Polarity : 1;
/** @brief Remote IRR */
uint64_t RemoteIRR : 1;
/** @brief Trigger Mode
*
* 0: Edge
* 1: Level
*/
uint64_t TriggerMode : 1;
/** @brief Mask */
uint64_t Mask : 1;
/** @brief Reserved */
uint64_t Reserved0 : 15;
/** @brief Reserved */
uint64_t Reserved1 : 24;
/** @brief Destination */
uint64_t DestinationID : 8;
};
struct
{
uint64_t Low;
uint64_t High;
} split;
uint64_t raw;
} __attribute__((packed)) IOAPICRedirectEntry;
typedef union
{
struct
{
uint64_t Version : 8;
uint64_t Reserved : 8;
uint64_t MaximumRedirectionEntry : 8;
uint64_t Reserved2 : 8;
};
uint64_t raw;
} __attribute__((packed)) IOAPICVersion;
class APIC
{
private:
bool x2APICSupported = false;
uint64_t APICBaseAddress = 0;
public:
uint32_t Read(uint32_t Register);
void Write(uint32_t Register, uint32_t Value);
void IOWrite(uint64_t Base, uint32_t Register, uint32_t Value);
uint32_t IORead(uint64_t Base, uint32_t Register);
void EOI();
void RedirectIRQs(int CPU = 0);
void WaitForIPI();
void IPI(uint8_t CPU, InterruptCommandRegisterLow icr);
void SendInitIPI(uint8_t CPU);
void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress);
uint32_t IOGetMaxRedirect(uint32_t APICID);
void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
void RedirectIRQ(int CPU, uint8_t IRQ, int Status);
APIC(int Core);
~APIC();
};
class Timer : public Interrupts::Handler
{
private:
APIC *lapic;
uint64_t Ticks = 0;
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
public:
uint64_t GetTicks() { return Ticks; }
void OneShot(uint32_t Vector, uint64_t Miliseconds);
Timer(APIC *apic);
~Timer();
};
}
#endif // !__FENNIX_KERNEL_APIC_H__

View File

@ -0,0 +1,11 @@
[bits 64]
[global _amd64_fxsave]
_amd64_fxsave:
fxsave [rdi]
ret
[global _amd64_fxrstor]
_amd64_fxrstor:
fxrstor [rdi]
ret

View File

@ -0,0 +1,144 @@
#ifndef __FENNIX_KERNEL_GDT_H__
#define __FENNIX_KERNEL_GDT_H__
#include <types.h>
namespace GlobalDescriptorTable
{
/** @brief The GDT Access Table
* @details For more information, see https://wiki.osdev.org/Global_Descriptor_Table
*/
union GlobalDescriptorTableAccess
{
struct
{
/** @brief Access bit.
* @note The CPU sets this bit to 1 when the segment is accessed.
*/
uint8_t A : 1;
/** @brief Readable bit for code segments, writable bit for data segments.
* @details For code segments, this bit must be 1 for the segment to be readable.
* @details For data segments, this bit must be 1 for the segment to be writable.
*/
uint8_t RW : 1;
/** @brief Direction bit for data segments, conforming bit for code segments.
* @details For data segments, this bit must be 1 for the segment to grow up (higher addresses).
* @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level.
*/
uint8_t DC : 1;
/** @brief Executable bit.
* @details This bit must be 1 for code-segment descriptors.
* @details This bit must be 0 for data-segment and system descriptors.
*/
uint8_t E : 1;
/** @brief Descriptor type.
* @details This bit must be 0 for system descriptors.
* @details This bit must be 1 for code or data segment descriptor.
*/
uint8_t S : 1;
/** @brief Descriptor privilege level.
* @details This field determines the privilege level of the segment.
* @details 0 = kernel mode, 3 = user mode.
*/
uint8_t DPL : 2;
/** @brief Present bit.
* @details This bit must be 1 for all valid descriptors.
*/
uint8_t P : 1;
} __attribute__((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;
} __attribute__((packed));
uint8_t Raw;
};
typedef struct _TaskStateSegmentEntry
{
/* LOW */
uint16_t Length;
uint16_t BaseLow;
uint8_t BaseMiddle;
GlobalDescriptorTableAccess Flags;
uint8_t Granularity;
uint8_t BaseHigh;
/* HIGH */
uint32_t BaseUpper;
uint32_t Reserved;
} __attribute__((packed)) TaskStateSegmentEntry;
typedef struct _TaskStateSegment
{
uint32_t Reserved0 __attribute__((aligned(16)));
uint64_t StackPointer[3];
uint64_t Reserved1;
uint64_t InterruptStackTable[7];
uint16_t Reserved2;
uint16_t IOMapBaseAddressOffset;
} __attribute__((packed)) TaskStateSegment;
typedef struct _GlobalDescriptorTableEntry
{
/** @brief Length */
uint16_t Length;
/** @brief Low Base */
uint16_t BaseLow;
/** @brief Middle Base */
uint8_t BaseMiddle;
/** @brief Access */
GlobalDescriptorTableAccess Access;
/** @brief Flags */
GlobalDescriptorTableFlags Flags;
/** @brief High Base */
uint8_t BaseHigh;
} __attribute__((packed)) GlobalDescriptorTableEntry;
typedef struct _GlobalDescriptorTableEntries
{
GlobalDescriptorTableEntry Null;
GlobalDescriptorTableEntry Code;
GlobalDescriptorTableEntry Data;
GlobalDescriptorTableEntry UserData;
GlobalDescriptorTableEntry UserCode;
TaskStateSegmentEntry TaskStateSegment;
} __attribute__((packed)) GlobalDescriptorTableEntries;
typedef struct _GlobalDescriptorTableDescriptor
{
/** @brief GDT entries length */
uint16_t Length;
/** @brief GDT entries address */
GlobalDescriptorTableEntries *Entries;
} __attribute__((packed)) GlobalDescriptorTableDescriptor;
extern void *CPUStackPointer[];
void Init(int Core);
void SetKernelStack(void *Stack);
}
#define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code)
#define GDT_KERNEL_DATA offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Data)
#define GDT_USER_CODE (offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, UserCode) | 3)
#define GDT_USER_DATA (offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, UserData) | 3)
#define GDT_TSS (offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, TaskStateSegment) | 3)
#endif // !__FENNIX_KERNEL_GDT_H__

View File

@ -0,0 +1,46 @@
#ifndef __FENNIX_KERNEL_IDT_H__
#define __FENNIX_KERNEL_IDT_H__
#include <types.h>
namespace InterruptDescriptorTable
{
typedef enum _InterruptDescriptorTableFlags
{
FlagGate_TASK = 0b101,
FlagGate_16BIT_INT = 0b110,
FlagGate_16BIT_TRAP = 0b111,
FlagGate_32BIT_INT = 0b1110,
FlagGate_32BIT_TRAP = 0b1111,
FlagGate_RING0 = 0b0,
FlagGate_RING1 = 0b1,
FlagGate_RING2 = 0b10,
FlagGate_RING3 = 0b11,
FlagGate_PRESENT = 0b1, // Not sure if this is correct.
} InterruptDescriptorTableFlags;
typedef struct _InterruptDescriptorTableEntry
{
uint64_t BaseLow : 16;
uint64_t SegmentSelector : 16;
uint64_t InterruptStackTable : 3;
uint64_t Reserved1 : 5;
InterruptDescriptorTableFlags Flags : 4;
uint64_t Reserved2 : 1;
uint64_t Ring : 2;
uint64_t Present : 1;
uint64_t BaseHigh : 48;
uint64_t Reserved3 : 32;
} __attribute__((packed)) InterruptDescriptorTableEntry;
typedef struct _InterruptDescriptorTableDescriptor
{
uint16_t Length;
InterruptDescriptorTableEntry *Entries;
} __attribute__((packed)) InterruptDescriptorTableDescriptor;
void SetEntry(uint8_t Index, void (*Base)(), InterruptDescriptorTableFlags Attribute, uint8_t InterruptStackTable, InterruptDescriptorTableFlags Ring, uint16_t SegmentSelector);
void Init(int Core);
}
#endif // !__FENNIX_KERNEL_IDT_H__

View File

@ -0,0 +1,63 @@
OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SECTIONS
{
. = 0xffffffff80000000;
_kernel_start = .;
.text :
{
*(.text .text.*)
}
_kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.data :
{
*(.data .data.*)
}
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.rodata :
{
*(.rodata .rodata.*)
}
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.init_array :
{
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(.init_array .ctors))
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP(*(.fini_array .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
. += CONSTANT(MAXPAGESIZE);
.bss :
{
*(COMMON)
*(.bss .bss.*)
}
. += CONSTANT(MAXPAGESIZE);
_kernel_end = ALIGN(CONSTANT(MAXPAGESIZE));
/DISCARD/ :
{
*(.comment*)
*(.note*)
}
}

View File

@ -0,0 +1,15 @@
// #include <types.h>
// #include <debug.h>
// int Entry(void *Info);
// void _start(void *Raw)
// {
// error("Todo");
// while (1)
// asmv("hlt");
// Entry(NULL);
// return;
// }
// C stuff

View File

@ -0,0 +1,15 @@
#include <types.h>
#include <debug.h>
int Entry(void *Info);
void _start(void *Raw)
{
error("ERROR! INVALID BOOT PROTOCOL!");
while (1)
asmv("hlt");
Entry(NULL);
return;
}
// C stuff

View File

@ -0,0 +1 @@
// C++ constructor/destructor stuff

View File

@ -0,0 +1 @@
// C++ constructor/destructor stuff

View File

@ -0,0 +1,13 @@
.section .init
.global _init
.type _init, @function
_init:
push %rbp
movq %rsp, %rbp
.section .fini
.global _fini
.type _fini, @function
_fini:
push %rbp
movq %rsp, %rbp

View File

@ -0,0 +1,7 @@
.section .init
popq %rbp
ret
.section .fini
popq %rbp
ret

View File

@ -0,0 +1,21 @@
{
"llvm-target": "x86_64-unknown-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"cpu": "x86-64",
"arch": "x86_64",
"features": "-mmx,-sse,+soft-float",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"linker-flavor": "ld",
"pre-link-args": {
"ld": [
"-m64"
]
},
"no-compiler-rt": true,
"disable-redzone": true,
"eliminate-frame-pointer": false,
"morestack": false
}

View File

@ -0,0 +1,285 @@
/* Source: https://github.com/glitchub/arith64 */
#define arith64_u64 unsigned long long int
#define arith64_s64 signed long long int
#define arith64_u32 unsigned int
#define arith64_s32 int
typedef union
{
arith64_u64 u64;
arith64_s64 s64;
struct
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
arith64_u32 hi;
arith64_u32 lo;
#else
arith64_u32 lo;
arith64_u32 hi;
#endif
} u32;
struct
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
arith64_s32 hi;
arith64_s32 lo;
#else
arith64_s32 lo;
arith64_s32 hi;
#endif
} s32;
} arith64_word;
#define arith64_hi(n) (arith64_word){.u64 = n}.u32.hi
#define arith64_lo(n) (arith64_word){.u64 = n}.u32.lo
#define arith64_neg(a, b) (((a) ^ ((((arith64_s64)(b)) >= 0) - 1)) + (((arith64_s64)(b)) < 0))
#define arith64_abs(a) arith64_neg(a, a)
arith64_s64 __absvdi2(arith64_s64 a)
{
return arith64_abs(a);
}
arith64_s64 __ashldi3(arith64_s64 a, int b)
{
arith64_word w = {.s64 = a};
b &= 63;
if (b >= 32)
{
w.u32.hi = w.u32.lo << (b - 32);
w.u32.lo = 0;
}
else if (b)
{
w.u32.hi = (w.u32.lo >> (32 - b)) | (w.u32.hi << b);
w.u32.lo <<= b;
}
return w.s64;
}
arith64_s64 __ashrdi3(arith64_s64 a, int b)
{
arith64_word w = {.s64 = a};
b &= 63;
if (b >= 32)
{
w.s32.lo = w.s32.hi >> (b - 32);
w.s32.hi >>= 31; // 0xFFFFFFFF or 0
}
else if (b)
{
w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
w.s32.hi >>= b;
}
return w.s64;
}
int __clzsi2(arith64_u32 a)
{
int b, n = 0;
b = !(a & 0xffff0000) << 4;
n += b;
a <<= b;
b = !(a & 0xff000000) << 3;
n += b;
a <<= b;
b = !(a & 0xf0000000) << 2;
n += b;
a <<= b;
b = !(a & 0xc0000000) << 1;
n += b;
a <<= b;
return n + !(a & 0x80000000);
}
int __clzdi2(arith64_u64 a)
{
int b, n = 0;
b = !(a & 0xffffffff00000000ULL) << 5;
n += b;
a <<= b;
b = !(a & 0xffff000000000000ULL) << 4;
n += b;
a <<= b;
b = !(a & 0xff00000000000000ULL) << 3;
n += b;
a <<= b;
b = !(a & 0xf000000000000000ULL) << 2;
n += b;
a <<= b;
b = !(a & 0xc000000000000000ULL) << 1;
n += b;
a <<= b;
return n + !(a & 0x8000000000000000ULL);
}
int __ctzsi2(arith64_u32 a)
{
int b, n = 0;
b = !(a & 0x0000ffff) << 4;
n += b;
a >>= b;
b = !(a & 0x000000ff) << 3;
n += b;
a >>= b;
b = !(a & 0x0000000f) << 2;
n += b;
a >>= b;
b = !(a & 0x00000003) << 1;
n += b;
a >>= b;
return n + !(a & 0x00000001);
}
int __ctzdi2(arith64_u64 a)
{
int b, n = 0;
b = !(a & 0x00000000ffffffffULL) << 5;
n += b;
a >>= b;
b = !(a & 0x000000000000ffffULL) << 4;
n += b;
a >>= b;
b = !(a & 0x00000000000000ffULL) << 3;
n += b;
a >>= b;
b = !(a & 0x000000000000000fULL) << 2;
n += b;
a >>= b;
b = !(a & 0x0000000000000003ULL) << 1;
n += b;
a >>= b;
return n + !(a & 0x0000000000000001ULL);
}
arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c)
{
if (b > a) //
{
if (c)
*c = a;
return 0;
}
if (!arith64_hi(b))
{
if (b == 0)
{
volatile char x = 0;
x = 1 / x;
}
if (b == 1)
{
if (c)
*c = 0;
return a;
}
if (!arith64_hi(a))
{
if (c)
*c = arith64_lo(a) % arith64_lo(b);
return arith64_lo(a) / arith64_lo(b);
}
}
char bits = __clzdi2(b) - __clzdi2(a) + 1;
arith64_u64 rem = a >> bits;
a <<= 64 - bits;
arith64_u64 wrap = 0;
while (bits-- > 0)
{
rem = (rem << 1) | (a >> 63);
a = (a << 1) | (wrap & 1);
wrap = ((arith64_s64)(b - rem - 1) >> 63);
rem -= b & wrap;
}
if (c)
*c = rem;
return (a << 1) | (wrap & 1);
}
arith64_s64 __divdi3(arith64_s64 a, arith64_s64 b)
{
arith64_u64 q = __divmoddi4(arith64_abs(a), arith64_abs(b), (void *)0);
return arith64_neg(q, a ^ b);
}
int __ffsdi2(arith64_u64 a) { return a ? __ctzdi2(a) + 1 : 0; }
arith64_u64 __lshrdi3(arith64_u64 a, int b)
{
arith64_word w = {.u64 = a};
b &= 63;
if (b >= 32)
{
w.u32.lo = w.u32.hi >> (b - 32);
w.u32.hi = 0;
}
else if (b)
{
w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
w.u32.hi >>= b;
}
return w.u64;
}
arith64_s64 __moddi3(arith64_s64 a, arith64_s64 b)
{
arith64_u64 r;
__divmoddi4(arith64_abs(a), arith64_abs(b), &r);
return arith64_neg(r, a);
}
int __popcountsi2(arith64_u32 a)
{
a = a - ((a >> 1) & 0x55555555);
a = ((a >> 2) & 0x33333333) + (a & 0x33333333);
a = (a + (a >> 4)) & 0x0F0F0F0F;
a = (a + (a >> 16));
return (a + (a >> 8)) & 63;
}
int __popcountdi2(arith64_u64 a)
{
a = a - ((a >> 1) & 0x5555555555555555ULL);
a = ((a >> 2) & 0x3333333333333333ULL) + (a & 0x3333333333333333ULL);
a = (a + (a >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
a = (a + (a >> 32));
a = (a + (a >> 16));
return (a + (a >> 8)) & 127;
}
arith64_u64 __udivdi3(arith64_u64 a, arith64_u64 b) { return __divmoddi4(a, b, (void *)0); }
arith64_u64 __umoddi3(arith64_u64 a, arith64_u64 b)
{
arith64_u64 r;
__divmoddi4(a, b, &r);
return r;
}
/* Good documentation: https://splichal.eu/scripts/sphinx/gccint/_build/html/the-gcc-low-level-runtime-library/routines-for-floating-point-emulation.html */
double __adddf3(double a, double b) { return a + b; }
double __muldf3(double a, double b) { return a * b; }
double __floatsidf(int i) { return (double)i; }
int __ltdf2(double a, double b) { return a < b; }
int __gtdf2(double a, double b) { return a > b; }
int __nedf2(double a, double b) { return a != b; }
int __eqdf2(double a, double b) { return a == b; }
double __floatdidf(long i) { return (double)i; }
double __divdf3(double a, double b) { return a / b; }
double __subdf3(double a, double b) { return a - b; }
int __gedf2(double a, double b) { return a >= b; }
int __fixdfsi(double a) { return (int)a; }
long __fixdfdi(double a) { return (long)a; }
int __ledf2(double a, double b) { return a <= b; }

View File

@ -0,0 +1,123 @@
#include "pic.hpp"
#include <io.h>
namespace PIC
{
PIC::PIC(uint8_t MasterCommandPort, uint8_t MasterDataPort, uint8_t SlaveCommandPort, uint8_t SlaveDataPort, uint8_t MasterOffset, uint8_t SlaveOffset)
{
this->MasterCommandPort = MasterCommandPort;
this->MasterDataPort = MasterDataPort;
this->SlaveCommandPort = SlaveCommandPort;
this->SlaveDataPort = SlaveDataPort;
this->MasterOffset = MasterOffset;
this->SlaveOffset = SlaveOffset;
MasterMask = 0xFF;
SlaveMask = 0xFF;
// ICW1
outb(MasterCommandPort, 0x11);
outb(SlaveCommandPort, 0x11);
// ICW2
outb(MasterDataPort, MasterOffset);
outb(SlaveDataPort, SlaveOffset);
// ICW3
outb(MasterDataPort, 0x04);
outb(SlaveDataPort, 0x02);
// ICW4
outb(MasterDataPort, 0x01);
outb(SlaveDataPort, 0x01);
// OCW1
outb(MasterDataPort, MasterMask);
outb(SlaveDataPort, SlaveMask);
}
PIC::~PIC()
{
outb(MasterDataPort, 0xFF);
outb(SlaveDataPort, 0xFF);
}
void PIC::Mask(uint8_t IRQ)
{
uint16_t Port;
uint8_t Value;
if (IRQ < 8)
{
Port = MasterDataPort;
Value = MasterMask & ~(1 << IRQ);
MasterMask = Value;
}
else
{
Port = SlaveDataPort;
Value = SlaveMask & ~(1 << (IRQ - 8));
SlaveMask = Value;
}
outb(Port, Value);
}
void PIC::Unmask(uint8_t IRQ)
{
uint16_t Port;
uint8_t Value;
if (IRQ < 8)
{
Port = MasterDataPort;
Value = MasterMask | (1 << IRQ);
MasterMask = Value;
}
else
{
Port = SlaveDataPort;
Value = SlaveMask | (1 << (IRQ - 8));
SlaveMask = Value;
}
outb(Port, Value);
}
void PIC::SendEOI(uint8_t IRQ)
{
if (IRQ >= 8)
outb(SlaveCommandPort, 0x20);
outb(MasterCommandPort, 0x20);
}
PIT::PIT(uint16_t Port, uint16_t Frequency)
{
this->Port = Port;
this->Frequency = Frequency;
}
PIT::~PIT()
{
}
void PIT::PrepareSleep(uint32_t Milliseconds)
{
uint16_t Divisor = 1193182 / Frequency;
uint8_t Low = (uint8_t)(Divisor & 0xFF);
uint8_t High = (uint8_t)((Divisor >> 8) & 0xFF);
outb(Port + 3, 0x36);
outb(Port + 0, Low);
outb(Port + 1, High);
}
void PIT::PerformSleep()
{
uint8_t Value = inb(Port + 0);
while (Value != 0)
Value = inb(Port + 0);
}
}

View File

@ -0,0 +1,42 @@
#ifndef __FENNIX_KERNEL_8259PIC_H__
#define __FENNIX_KERNEL_8259PIC_H__
#include <types.h>
namespace PIC
{
class PIC
{
private:
uint8_t MasterCommandPort;
uint8_t MasterDataPort;
uint8_t SlaveCommandPort;
uint8_t SlaveDataPort;
uint8_t MasterOffset;
uint8_t SlaveOffset;
uint8_t MasterMask;
uint8_t SlaveMask;
public:
PIC(uint8_t MasterCommandPort, uint8_t MasterDataPort, uint8_t SlaveCommandPort, uint8_t SlaveDataPort, uint8_t MasterOffset, uint8_t SlaveOffset);
~PIC();
void Mask(uint8_t IRQ);
void Unmask(uint8_t IRQ);
void SendEOI(uint8_t IRQ);
};
class PIT
{
private:
uint16_t Port;
uint16_t Frequency;
public:
PIT(uint16_t Port, uint16_t Frequency);
~PIT();
void PrepareSleep(uint32_t Milliseconds);
void PerformSleep();
};
}
#endif // !__FENNIX_KERNEL_8259PIC_H__

View File

@ -0,0 +1,343 @@
#include <types.h>
#include <boot/protocols/multiboot2.h>
#include <io.h>
#include "../../kernel.h"
enum VideoType
{
VIDEO_TYPE_NONE = 0x00,
VIDEO_TYPE_COLOUR = 0x20,
VIDEO_TYPE_MONOCHROME = 0x30,
};
uint16_t GetBiosAreaHardware()
{
const uint16_t *BIOSDataAreaDetectedHardware = (const uint16_t *)0x410;
return *BIOSDataAreaDetectedHardware;
}
enum VideoType GetVideoType() { return (enum VideoType)(GetBiosAreaHardware() & 0x30); }
void GetSMBIOS()
{
unsigned char *SMBIOSAddress = (unsigned char *)0xF0000;
while ((unsigned int)(unsigned long)SMBIOSAddress < 0x100000)
{
if (SMBIOSAddress[0] == '_' &&
SMBIOSAddress[1] == 'S' &&
SMBIOSAddress[2] == 'M' &&
SMBIOSAddress[3] == '_')
{
unsigned char Checksum = 0;
int Length = SMBIOSAddress[5];
for (int i = 0; i < Length; i++)
Checksum += SMBIOSAddress[i];
if (Checksum == 0)
break;
}
SMBIOSAddress += 16;
}
if ((unsigned int)(unsigned long)SMBIOSAddress == 0x100000)
{
// No SMBIOS found
}
}
struct multiboot_info
{
multiboot_uint32_t Size;
multiboot_uint32_t Reserved;
struct multiboot_tag *Tag;
};
EXTERNC void x32Multiboot2Entry(multiboot_info *Info, unsigned int Magic)
{
if (Info == NULL || Magic == NULL)
{
if (Magic == NULL)
error("Multiboot magic is NULL");
if (Info == NULL)
error("Multiboot info is NULL");
CPU::Stop();
}
else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC)
{
error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC);
trace("Hello, World!");
CPU::Stop();
}
uint64_t div = 1193180 / 1000;
outb(0x43, 0xB6);
outb(0x42, (uint8_t)div);
outb(0x42, (uint8_t)(div >> 8));
uint8_t tmp = inb(0x61);
if (tmp != (tmp | 3))
outb(0x61, tmp | 3);
BootInfo binfo;
uint32_t Itr = 0;
for (uint32_t i = 8; i < Info->Size; i += Itr)
{
multiboot_tag *Tag = (multiboot_tag *)((uint8_t *)Info + i);
if (Tag->type == MULTIBOOT_TAG_TYPE_END)
break;
switch (Tag->type)
{
case MULTIBOOT_TAG_TYPE_CMDLINE:
{
strncpy(binfo.Kernel.CommandLine,
((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string));
break;
}
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
{
strncpy(binfo.Bootloader.Name,
((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string));
break;
}
case MULTIBOOT_TAG_TYPE_MODULE:
{
multiboot_tag_module *module = (multiboot_tag_module *)Tag;
static int module_count = 0;
binfo.Modules[module_count++].Address = (void *)module->mod_start;
binfo.Modules[module_count++].Size = module->size;
strncpy(binfo.Modules[module_count++].Path, "(null)", 6);
strncpy(binfo.Modules[module_count++].CommandLine, module->cmdline,
strlen(module->cmdline));
break;
}
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
{
multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag;
fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]",
meminfo->mem_lower, meminfo->mem_upper);
break;
}
case MULTIBOOT_TAG_TYPE_BOOTDEV:
{
multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag;
fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]",
bootdev->biosdev, bootdev->slice, bootdev->part);
break;
}
case MULTIBOOT_TAG_TYPE_MMAP:
{
multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag;
uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry);
binfo.Memory.Entries = EntryCount;
for (uint32_t i = 0; i < EntryCount; i++)
{
if (EntryCount > MAX_MEMORY_ENTRIES)
{
warn("Too many memory entries, skipping the rest...");
break;
}
multiboot_mmap_entry entry = mmap->entries[i];
binfo.Memory.Size += entry.len;
switch (entry.type)
{
case MULTIBOOT_MEMORY_AVAILABLE:
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.Memory.Entry[i].Type = Usable;
break;
case MULTIBOOT_MEMORY_RESERVED:
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.Memory.Entry[i].Type = Reserved;
break;
case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.Memory.Entry[i].Type = ACPIReclaimable;
break;
case MULTIBOOT_MEMORY_NVS:
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.Memory.Entry[i].Type = ACPINVS;
break;
case MULTIBOOT_MEMORY_BADRAM:
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.Memory.Entry[i].Type = BadMemory;
break;
default:
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.Memory.Entry[i].Type = Unknown;
break;
}
}
break;
}
case MULTIBOOT_TAG_TYPE_VBE:
{
multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag;
fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]",
vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len);
break;
}
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
{
multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag;
static int fb_count = 0;
binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width;
binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height;
binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch;
binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp;
binfo.Framebuffer[fb_count].MemoryModel = fb->common.framebuffer_type;
switch (fb->common.framebuffer_type)
{
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
{
fixme("indexed");
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
{
binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size;
binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position;
binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size;
binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position;
binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size;
binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
{
fixme("ega_text");
break;
}
}
debug("Framebuffer %d: %dx%d %d bpp", i, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp);
debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d",
fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type,
fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size,
fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position);
fb_count++;
break;
}
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
{
multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag;
fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]",
elf->num, elf->size, elf->entsize, elf->shndx);
break;
}
case MULTIBOOT_TAG_TYPE_APM:
{
multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag;
fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]",
apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len);
break;
}
case MULTIBOOT_TAG_TYPE_EFI32:
{
multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag;
fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size);
break;
}
case MULTIBOOT_TAG_TYPE_EFI64:
{
multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag;
fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size);
break;
}
case MULTIBOOT_TAG_TYPE_SMBIOS:
{
multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag;
fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor);
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_OLD:
{
binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_NEW:
{
binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
break;
}
case MULTIBOOT_TAG_TYPE_NETWORK:
{
multiboot_tag_network *net = (multiboot_tag_network *)Tag;
fixme("network->[dhcpack: %p]", net->dhcpack);
break;
}
case MULTIBOOT_TAG_TYPE_EFI_MMAP:
{
multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag;
fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]",
efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap);
break;
}
case MULTIBOOT_TAG_TYPE_EFI_BS:
{
fixme("efi_bs->[%p] (unknown structure)", Tag);
break;
}
case MULTIBOOT_TAG_TYPE_EFI32_IH:
{
multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag;
fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer);
break;
}
case MULTIBOOT_TAG_TYPE_EFI64_IH:
{
multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag;
fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer);
break;
}
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
{
multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag;
binfo.Kernel.PhysicalBase = (void *)load_base_addr->load_base_addr;
binfo.Kernel.VirtualBase = (void *)(load_base_addr->load_base_addr + 0xC0000000);
break;
}
}
Itr = Tag->size;
if ((Itr % 8) != 0)
Itr += (8 - Itr % 8);
}
tmp = inb(0x61) & 0xFC;
outb(0x61, tmp);
int *vm = (int *)0xb8000;
// "Not supported yet"
vm[0] = 0x054E;
vm[1] = 0x056F;
vm[2] = 0x0574;
vm[3] = 0x0520;
vm[4] = 0x0573;
vm[5] = 0x0575;
vm[6] = 0x0570;
vm[7] = 0x0570;
vm[8] = 0x0572;
vm[9] = 0x056F;
vm[10] = 0x0574;
vm[11] = 0x0520;
vm[12] = 0x0579;
vm[13] = 0x0565;
vm[14] = 0x0574;
CPU::Stop();
// Entry(&binfo);
}

View File

@ -0,0 +1,13 @@
#include <syscalls.hpp>
#include <cpu.hpp>
#include "cpu/gdt.hpp"
using namespace CPU::x32;
extern "C" uint32_t SystemCallsHandler(SyscallsFrame *regs);
void InitializeSystemCalls()
{
}

View File

@ -0,0 +1,37 @@
#include <smp.hpp>
#include <interrupts.hpp>
#include <memory.hpp>
#include <assert.h>
#include <cpu.hpp>
#include "../../../kernel.h"
volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
CPUData *GetCurrentCPU()
{
uint64_t ret = 0;
if (!(&CPUs[ret])->IsActive)
{
error("CPU %d is not active!", ret);
return &CPUs[0];
}
assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM);
return &CPUs[ret];
}
namespace SMP
{
int CPUCores = 0;
void Initialize(void *madt)
{
fixme("SMP::Initialize() is not implemented!");
}
}

View File

@ -0,0 +1,337 @@
#ifndef __FENNIX_KERNEL_APIC_H__
#define __FENNIX_KERNEL_APIC_H__
#include <types.h>
#include <interrupts.hpp>
#include <cpu.hpp>
namespace APIC
{
enum APICRegisters
{
// source from: https://github.com/pdoane/osdev/blob/master/intr/local_apic.c
APIC_ID = 0x20, // Local APIC ID
APIC_VER = 0x30, // Local APIC Version
APIC_TPR = 0x80, // Task Priority
APIC_APR = 0x90, // Arbitration Priority
APIC_PPR = 0xA0, // Processor Priority
APIC_EOI = 0xB0, // EOI
APIC_RRD = 0xC0, // Remote Read
APIC_LDR = 0xD0, // Logical Destination
APIC_DFR = 0xE0, // Destination Format
APIC_SVR = 0xF0, // Spurious Interrupt Vector
APIC_ISR = 0x100, // In-Service (8 registers)
APIC_TMR = 0x180, // Trigger Mode (8 registers)
APIC_IRR = 0x200, // Interrupt Request (8 registers)
APIC_ESR = 0x280, // Error Status
APIC_ICRLO = 0x300, // Interrupt Command
APIC_ICRHI = 0x310, // Interrupt Command [63:32]
APIC_TIMER = 0x320, // LVT Timer
APIC_THERMAL = 0x330, // LVT Thermal Sensor
APIC_PERF = 0x340, // LVT Performance Counter
APIC_LINT0 = 0x350, // LVT LINT0
APIC_LINT1 = 0x360, // LVT LINT1
APIC_ERROR = 0x370, // LVT Error
APIC_TICR = 0x380, // Initial Count (for Timer)
APIC_TCCR = 0x390, // Current Count (for Timer)
APIC_TDCR = 0x3E0, // Divide Configuration (for Timer)
};
enum IOAPICRegisters
{
GetIOAPICVersion = 0x1
};
enum IOAPICFlags
{
ActiveHighLow = 2,
EdgeLevel = 8
};
enum APICDeliveryMode
{
Fixed = 0b000,
LowestPriority = 0b001, /* Reserved */
SMI = 0b010,
APIC_DELIVERY_MODE_RESERVED0 = 0b011, /* Reserved */
NMI = 0b100,
INIT = 0b101,
Startup = 0b110,
ExtINT = 0b111 /* Reserved */
};
enum APICDestinationMode
{
Physical = 0b0,
Logical = 0b1
};
enum APICDeliveryStatus
{
Idle = 0b0,
SendPending = 0b1
};
enum APICLevel
{
DeAssert = 0b0,
Assert = 0b1
};
enum APICTriggerMode
{
Edge = 0b0,
Level = 0b1
};
enum APICDestinationShorthand
{
NoShorthand = 0b00,
Self = 0b01,
AllIncludingSelf = 0b10,
AllExcludingSelf = 0b11
};
enum LVTTimerDivide
{
DivideBy2 = 0b000,
DivideBy4 = 0b001,
DivideBy8 = 0b010,
DivideBy16 = 0b011,
DivideBy32 = 0b100,
DivideBy64 = 0b101,
DivideBy128 = 0b110,
DivideBy1 = 0b111
};
enum LVTTimerMask
{
Unmasked = 0b0,
Masked = 0b1
};
enum LVTTimerMode
{
OneShot = 0b00,
Periodic = 0b01,
TSCDeadline = 0b10
};
typedef union
{
struct
{
/** @brief Interrupt Vector */
uint64_t Vector : 8;
/** @brief Reserved */
uint64_t Reserved0 : 4;
/**
* @brief Delivery Status
*
* 0: Idle
* 1: Send Pending
*/
uint64_t DeliveryStatus : 1;
/** @brief Reserved */
uint64_t Reserved1 : 3;
/**
* @brief Mask
*
* 0: Not masked
* 1: Masked
*/
uint64_t Mask : 1;
/** @brief Timer Mode
*
* 0: One-shot
* 1: Periodic
* 2: TSC-Deadline
*/
uint64_t TimerMode : 1;
/** @brief Reserved */
uint64_t Reserved2 : 14;
};
uint64_t raw;
} __attribute__((packed)) LVTTimer;
typedef union
{
struct
{
/** @brief Spurious Vector */
uint64_t Vector : 8;
/** @brief Enable or disable APIC software */
uint64_t Software : 1;
/** @brief Focus Processor Checking */
uint64_t FocusProcessorChecking : 1;
/** @brief Reserved */
uint64_t Reserved : 2;
/** @brief Disable EOI Broadcast */
uint64_t DisableEOIBroadcast : 1;
/** @brief Reserved */
uint64_t Reserved1 : 19;
};
uint64_t raw;
} __attribute__((packed)) Spurious;
typedef union
{
struct
{
/** @brief Interrupt Vector */
uint64_t Vector : 8;
/** @brief Delivery Mode */
uint64_t DeliveryMode : 3;
/** @brief Destination Mode
*
* 0: Physical
* 1: Logical
*/
uint64_t DestinationMode : 1;
/** @brief Delivery Status
*
* @note Reserved when in x2APIC mode
*/
uint64_t DeliveryStatus : 1;
/** @brief Reserved */
uint64_t Reserved0 : 1;
/** @brief Level
*
* 0: Deassert
* 1: Assert
*/
uint64_t Level : 1;
/** @brief Trigger Mode
*
* 0: Edge
* 1: Level
*/
uint64_t TriggerMode : 1;
/** @brief Reserved */
uint64_t Reserved1 : 2;
/** @brief Destination Shorthand
*
* 0: No shorthand
* 1: Self
* 2: All including self
* 3: All excluding self
*/
uint64_t DestinationShorthand : 2;
/** @brief Reserved */
uint64_t Reserved2 : 12;
};
uint64_t raw;
} __attribute__((packed)) InterruptCommandRegisterLow;
typedef union
{
struct
{
/** @brief Reserved */
uint64_t Reserved0 : 24;
/** @brief Destination */
uint64_t Destination : 8;
};
uint64_t raw;
} __attribute__((packed)) InterruptCommandRegisterHigh;
typedef union
{
struct
{
/** @brief Interrupt Vector */
uint64_t Vector : 8;
/** @brief Delivery Mode */
uint64_t DeliveryMode : 3;
/** @brief Destination Mode
*
* 0: Physical
* 1: Logical
*/
uint64_t DestinationMode : 1;
/** @brief Delivery Status */
uint64_t DeliveryStatus : 1;
/** @brief Interrupt Input Pin Polarity
*
* 0: Active High
* 1: Active Low
*/
uint64_t Polarity : 1;
/** @brief Remote IRR */
uint64_t RemoteIRR : 1;
/** @brief Trigger Mode
*
* 0: Edge
* 1: Level
*/
uint64_t TriggerMode : 1;
/** @brief Mask */
uint64_t Mask : 1;
/** @brief Reserved */
uint64_t Reserved0 : 15;
/** @brief Reserved */
uint64_t Reserved1 : 24;
/** @brief Destination */
uint64_t DestinationID : 8;
};
struct
{
uint64_t Low;
uint64_t High;
} split;
uint64_t raw;
} __attribute__((packed)) IOAPICRedirectEntry;
typedef union
{
struct
{
uint64_t Version : 8;
uint64_t Reserved : 8;
uint64_t MaximumRedirectionEntry : 8;
uint64_t Reserved2 : 8;
};
uint64_t raw;
} __attribute__((packed)) IOAPICVersion;
class APIC
{
private:
bool x2APICSupported = false;
uint64_t APICBaseAddress = 0;
public:
uint32_t Read(uint32_t Register);
void Write(uint32_t Register, uint32_t Value);
void IOWrite(uint64_t Base, uint32_t Register, uint32_t Value);
uint32_t IORead(uint64_t Base, uint32_t Register);
void EOI();
void RedirectIRQs(int CPU = 0);
void WaitForIPI();
void IPI(uint8_t CPU, InterruptCommandRegisterLow icr);
void SendInitIPI(uint8_t CPU);
void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress);
uint32_t IOGetMaxRedirect(uint32_t APICID);
void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
void RedirectIRQ(int CPU, uint8_t IRQ, int Status);
APIC(int Core);
~APIC();
};
class Timer : public Interrupts::Handler
{
private:
APIC *lapic;
uint64_t Ticks = 0;
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
public:
uint64_t GetTicks() { return Ticks; }
void OneShot(uint32_t Vector, uint64_t Miliseconds);
Timer(APIC *apic);
~Timer();
};
}
#endif // !__FENNIX_KERNEL_APIC_H__

View File

@ -0,0 +1,11 @@
[bits 64]
[global _i386_fxsave]
_i386_fxsave:
fxsave [edi]
ret
[global _i386_fxrstor]
_i386_fxrstor:
fxrstor [edi]
ret

View File

@ -0,0 +1,11 @@
#ifndef __FENNIX_KERNEL_GDT_H__
#define __FENNIX_KERNEL_GDT_H__
#include <types.h>
namespace GlobalDescriptorTable
{
void Init(int Core);
}
#endif // !__FENNIX_KERNEL_GDT_H__

View File

@ -0,0 +1,11 @@
#ifndef __FENNIX_KERNEL_IDT_H__
#define __FENNIX_KERNEL_IDT_H__
#include <types.h>
namespace InterruptDescriptorTable
{
void Init(int Core);
}
#endif // !__FENNIX_KERNEL_IDT_H__

View File

@ -0,0 +1,42 @@
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386)
ENTRY(_start)
SECTIONS
{
. = 0xC0100000;
_kernel_start = .;
.text ALIGN(4096) : AT(ADDR(.text) - 0xC0000000)
{
*(.multiboot2)
*(.text .text.*)
}
_kernel_text_end = .;
.data ALIGN (4096) : AT(ADDR(.data) - 0xC0000000)
{
*(.data .data.*)
}
_kernel_data_end = .;
.rodata ALIGN (4096) : AT(ADDR(.rodata) - 0xC0000000)
{
*(.rodata .rodata.*)
}
_kernel_rodata_end = .;
.bss ALIGN (4096) : AT(ADDR(.bss) - 0xC0000000)
{
*(COMMON)
*(.bss .bss.*)
}
_kernel_end = .;
/DISCARD/ :
{
*(.comment*)
*(.note*)
}
}

View File

@ -0,0 +1,15 @@
// #include <types.h>
// #include <debug.h>
// int Entry(void *Info);
// void _start(void *Raw)
// {
// error("Todo");
// while (1)
// asmv("hlt");
// Entry(NULL);
// return;
// }
// C stuff

View File

@ -0,0 +1,69 @@
; Inspired From: https://github.com/MQuy/mos/blob/master/src/kernel/boot.asm
section .multiboot2
align 4096
HEADER_START:
dd 0xE85250D6
dd 0
dd (HEADER_END - HEADER_START)
dd 0x100000000 - (HEADER_END - HEADER_START) - 0 - 0xE85250D6
align 8
MB2_TAG_START:
dw 0
dw 0
dd MB2_TAG_END - MB2_TAG_START
MB2_TAG_END:
HEADER_END:
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB
KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; 768
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
extern x32Multiboot2Entry
global _start
section .data
align 0x1000
BootPageTable:
dd 0x00000083
times ((KERNEL_PAGE_NUMBER) - 1) dd 0
dd 0x00000083
times (1024 - KERNEL_PAGE_NUMBER - 1) dd 0
section .text
_start:
mov word [0xb8000], 0x074C ; L
mov word [0xb8002], 0x076F ; o
mov word [0xb8004], 0x0761 ; a
mov word [0xb8006], 0x0764 ; d
mov word [0xb8008], 0x0769 ; i
mov word [0xb800a], 0x076E ; n
mov word [0xb800c], 0x0767 ; g
mov word [0xb800e], 0x072E ; .
mov word [0xb8010], 0x072E ; .
mov word [0xb8012], 0x072E ; .
mov ecx, (BootPageTable - KERNEL_VIRTUAL_BASE)
mov cr3, ecx
mov ecx, cr4
or ecx, 0x00000010 ; Set PSE in CR4
mov cr4, ecx
mov ecx, cr0
or ecx, 0x80000000 ; Set PG in CR0
mov cr0, ecx
lea ecx, [HigherHalfStart]
jmp ecx
HigherHalfStart:
mov esp, KernelStack + KERNEL_STACK_SIZE
push eax ; Multiboot2 Magic
add ebx, KERNEL_VIRTUAL_BASE
push ebx ; Multiboot2 Header
call x32Multiboot2Entry
Loop:
hlt
jmp Loop
section .bss
align 16
KernelStack :
resb KERNEL_STACK_SIZE

View File

@ -0,0 +1 @@
// C++ constructor/destructor stuff

View File

@ -0,0 +1 @@
// C++ constructor/destructor stuff

View File

@ -0,0 +1,13 @@
.section .init
.global _init
.type _init, @function
_init:
push %ebp
mov %esp, %ebp
.section .fini
.global _fini
.type _fini, @function
_fini:
push %ebp
mov %esp, %ebp

View File

@ -0,0 +1,7 @@
.section .init
pop %ebp
ret
.section .fini
pop %ebp
ret

274
Kernel/Core/CPU.cpp Normal file
View File

@ -0,0 +1,274 @@
#include <cpu.hpp>
#include <memory.hpp>
#include <convert.h>
#include <debug.h>
#include "../kernel.h"
namespace CPU
{
char *Vendor()
{
static char Vendor[13];
#if defined(__amd64__)
uint32_t rax, rbx, rcx, rdx;
x64::cpuid(0x0, &rax, &rbx, &rcx, &rdx);
memcpy(Vendor + 0, &rbx, 4);
memcpy(Vendor + 4, &rdx, 4);
memcpy(Vendor + 8, &rcx, 4);
#elif defined(__i386__)
uint32_t rax, rbx, rcx, rdx;
x32::cpuid(0x0, &rax, &rbx, &rcx, &rdx);
memcpy(Vendor + 0, &rbx, 4);
memcpy(Vendor + 4, &rdx, 4);
memcpy(Vendor + 8, &rcx, 4);
#elif defined(__aarch64__)
asmv("mrs %0, MIDR_EL1"
: "=r"(Vendor[0]));
#endif
return Vendor;
}
char *Name()
{
static char Name[49];
#if defined(__amd64__)
uint32_t rax, rbx, rcx, rdx;
x64::cpuid(0x80000002, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 0, &rax, 4);
memcpy(Name + 4, &rbx, 4);
memcpy(Name + 8, &rcx, 4);
memcpy(Name + 12, &rdx, 4);
x64::cpuid(0x80000003, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 16, &rax, 4);
memcpy(Name + 20, &rbx, 4);
memcpy(Name + 24, &rcx, 4);
memcpy(Name + 28, &rdx, 4);
x64::cpuid(0x80000004, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 32, &rax, 4);
memcpy(Name + 36, &rbx, 4);
memcpy(Name + 40, &rcx, 4);
memcpy(Name + 44, &rdx, 4);
#elif defined(__i386__)
uint32_t rax, rbx, rcx, rdx;
x32::cpuid(0x80000002, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 0, &rax, 4);
memcpy(Name + 4, &rbx, 4);
memcpy(Name + 8, &rcx, 4);
memcpy(Name + 12, &rdx, 4);
x32::cpuid(0x80000003, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 16, &rax, 4);
memcpy(Name + 20, &rbx, 4);
memcpy(Name + 24, &rcx, 4);
memcpy(Name + 28, &rdx, 4);
x32::cpuid(0x80000004, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 32, &rax, 4);
memcpy(Name + 36, &rbx, 4);
memcpy(Name + 40, &rcx, 4);
memcpy(Name + 44, &rdx, 4);
#elif defined(__aarch64__)
asmv("mrs %0, MIDR_EL1"
: "=r"(Name[0]));
#endif
return Name;
}
char *Hypervisor()
{
static char Hypervisor[13];
#if defined(__amd64__)
uint32_t rax, rbx, rcx, rdx;
x64::cpuid(0x40000000, &rax, &rbx, &rcx, &rdx);
memcpy(Hypervisor + 0, &rbx, 4);
memcpy(Hypervisor + 4, &rcx, 4);
memcpy(Hypervisor + 8, &rdx, 4);
#elif defined(__i386__)
uint32_t rax, rbx, rcx, rdx;
x64::cpuid(0x40000000, &rax, &rbx, &rcx, &rdx);
memcpy(Hypervisor + 0, &rbx, 4);
memcpy(Hypervisor + 4, &rcx, 4);
memcpy(Hypervisor + 8, &rdx, 4);
#elif defined(__aarch64__)
asmv("mrs %0, MIDR_EL1"
: "=r"(Hypervisor[0]));
#endif
return Hypervisor;
}
bool Interrupts(InterruptsType Type)
{
switch (Type)
{
case Check:
{
#if defined(__amd64__)
uint64_t rflags;
asmv("pushfq");
asmv("popq %0"
: "=r"(rflags));
return rflags & (1 << 9);
#elif defined(__i386__)
uint32_t rflags;
asmv("pushfl");
asmv("popl %0"
: "=r"(rflags));
return rflags & (1 << 9);
#elif defined(__aarch64__)
uint64_t daif;
asmv("mrs %0, daif"
: "=r"(daif));
return !(daif & (1 << 2));
#endif
}
case Enable:
{
#if defined(__amd64__) || defined(__i386__)
asmv("sti");
#elif defined(__aarch64__)
asmv("msr daifclr, #2");
#endif
return true;
}
case Disable:
{
#if defined(__amd64__) || defined(__i386__)
asmv("cli");
#elif defined(__aarch64__)
asmv("msr daifset, #2");
#endif
return true;
}
}
return false;
}
void *PageTable(void *PT)
{
#if defined(__amd64__)
if (PT)
asmv("movq %0, %%cr3"
:
: "r"(PT));
else
asmv("movq %%cr3, %0"
: "=r"(PT));
#elif defined(__i386__)
if (PT)
asmv("movl %0, %%cr3"
:
: "r"(PT));
else
asmv("movl %%cr3, %0"
: "=r"(PT));
#elif defined(__aarch64__)
if (PT)
asmv("msr ttbr0_el1, %0"
:
: "r"(PT));
else
asmv("mrs %0, ttbr0_el1"
: "=r"(PT));
#endif
return PT;
}
void InitializeFeatures()
{
#if defined(__amd64__)
static int BSP = 0;
x64::CR0 cr0 = x64::readcr0();
x64::CR4 cr4 = x64::readcr4();
uint32_t rax, rbx, rcx, rdx;
x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx);
if (rdx & x64::CPUID_FEAT_RDX_PGE)
{
debug("Enabling global pages support...");
if (!BSP)
KPrint("Global Pages is supported.");
cr4.PGE = 1;
}
if (rdx & x64::CPUID_FEAT_RDX_SSE)
{
debug("Enabling SSE support...");
if (!BSP)
KPrint("SSE is supported.");
cr0.EM = 0;
cr0.MP = 1;
cr4.OSFXSR = 1;
cr4.OSXMMEXCPT = 1;
}
if (!BSP)
KPrint("Enabling CPU cache.");
cr0.NW = 0;
cr0.CD = 0;
cr0.WP = 1;
x64::writecr0(cr0);
debug("Enabling UMIP, SMEP & SMAP support...");
x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx);
if (rdx & x64::CPUID_FEAT_RDX_UMIP)
{
if (!BSP)
KPrint("UMIP is supported.");
fixme("Not going to enable UMIP.");
// cr4.UMIP = 1;
}
if (rdx & x64::CPUID_FEAT_RDX_SMEP)
{
if (!BSP)
KPrint("SMEP is supported.");
fixme("Not going to enable SMEP.");
// cr4.SMEP = 1;
}
if (rdx & x64::CPUID_FEAT_RDX_SMAP)
{
if (!BSP)
KPrint("SMAP is supported.");
fixme("Not going to enable SMAP.");
// cr4.SMAP = 1;
}
if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0 &&
strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
x64::writecr4(cr4);
else
{
if (!BSP)
{
if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0)
KPrint("VirtualBox detected. Not using UMIP, SMEP & SMAP");
else if (strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
KPrint("QEMU (TCG) detected. Not using UMIP, SMEP & SMAP");
}
}
debug("Enabling PAT support...");
x64::wrmsr(x64::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16));
if (!BSP++)
trace("Features for BSP initialized.");
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
}
uint64_t Counter()
{
// TODO: Get the counter from the x2APIC or any other timer that is available. (TSC is not available on all CPUs)
#if defined(__amd64__)
uint64_t counter;
asmv("rdtsc"
: "=A"(counter));
return counter;
#elif defined(__i386__)
return 0;
#elif defined(__aarch64__)
uint64_t counter;
asmv("mrs %0, cntvct_el0"
: "=r"(counter));
return counter;
#endif
}
}

View File

@ -0,0 +1,129 @@
#include "../crashhandler.hpp"
#include "chfcts.hpp"
#include <display.hpp>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../kernel.h"
static const char *PagefaultDescriptions[8] = {
"Supervisory process tried to read a non-present page entry\n",
"Supervisory process tried to read a page and caused a protection fault\n",
"Supervisory process tried to write to a non-present page entry\n",
"Supervisory process tried to write a page and caused a protection fault\n",
"User process tried to read a non-present page entry\n",
"User process tried to read a page and caused a protection fault\n",
"User process tried to write to a non-present page entry\n",
"User process tried to write a page and caused a protection fault\n"};
SafeFunction void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Divide by zero exception\n");
}
SafeFunction void DebugExceptionHandler(CHArchTrapFrame *Frame)
{
CrashHandler::EHPrint("\eDD2920System crashed!\n");
CrashHandler::EHPrint("Kernel triggered debug exception.\n");
}
SafeFunction void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame) { fixme("NMI exception"); }
SafeFunction void BreakpointExceptionHandler(CHArchTrapFrame *Frame) { fixme("Breakpoint exception"); }
SafeFunction void OverflowExceptionHandler(CHArchTrapFrame *Frame) { fixme("Overflow exception"); }
SafeFunction void BoundRangeExceptionHandler(CHArchTrapFrame *Frame) { fixme("Bound range exception"); }
SafeFunction void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame)
{
CrashHandler::EHPrint("\eDD2920System crashed!\n");
CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n");
}
SafeFunction void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame) { fixme("Device not available exception"); }
SafeFunction void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame) { fixme("Double fault exception"); }
SafeFunction void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame) { fixme("Coprocessor segment overrun exception"); }
SafeFunction void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame) { fixme("Invalid TSS exception"); }
SafeFunction void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame) { fixme("Segment not present exception"); }
SafeFunction void StackFaultExceptionHandler(CHArchTrapFrame *Frame)
{
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
CrashHandler::EHPrint("\eDD2920System crashed!\n");
CrashHandler::EHPrint("More info about the exception:\n");
#if defined(__amd64__)
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->rip);
#elif defined(__i386__)
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->eip);
#elif defined(__aarch64__)
#endif
CrashHandler::EHPrint("External: %d\n", SelCode.External);
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
CrashHandler::EHPrint("Error code: %#lx\n", Frame->ErrorCode);
}
SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame)
{
// staticbuffer(descbuf);
// staticbuffer(desc_ext);
// staticbuffer(desc_table);
// staticbuffer(desc_idx);
// staticbuffer(desc_tmp);
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
// switch (SelCode.Table)
// {
// case CPU::x64::0b00:
// memcpy(desc_tmp, "GDT", 3);
// break;
// case CPU::x64::0b01:
// memcpy(desc_tmp, "IDT", 3);
// break;
// case CPU::x64::0b10:
// memcpy(desc_tmp, "LDT", 3);
// break;
// case CPU::x64::0b11:
// memcpy(desc_tmp, "IDT", 3);
// break;
// default:
// memcpy(desc_tmp, "Unknown", 7);
// break;
// }
CrashHandler::EHPrint("\eDD2920System crashed!\n");
CrashHandler::EHPrint("Kernel performed an illegal operation.\n");
CrashHandler::EHPrint("More info about the exception:\n");
CrashHandler::EHPrint("External: %d\n", SelCode.External);
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
}
SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
{
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
CrashHandler::EHPrint("\eDD2920System crashed!\n\eFFFFFF");
#if defined(__amd64__)
CrashHandler::EHPrint("An exception occurred at %#lx by %#lx\n", CPU::x64::readcr2().PFLA, Frame->rip);
#elif defined(__i386__)
CrashHandler::EHPrint("An exception occurred at %#lx by %#lx\n", CPU::x64::readcr2().PFLA, Frame->eip);
#elif defined(__aarch64__)
#endif
CrashHandler::EHPrint("Page: %s\n", params.P ? "Present" : "Not Present");
CrashHandler::EHPrint("Write Operation: %s\n", params.W ? "Read-Only" : "Read-Write");
CrashHandler::EHPrint("Processor Mode: %s\n", params.U ? "User-Mode" : "Kernel-Mode");
CrashHandler::EHPrint("CPU Reserved Bits: %s\n", params.R ? "Reserved" : "Unreserved");
CrashHandler::EHPrint("Caused By An Instruction Fetch: %s\n", params.I ? "Yes" : "No");
CrashHandler::EHPrint("Caused By A Protection-Key Violation: %s\n", params.PK ? "Yes" : "No");
CrashHandler::EHPrint("Caused By A Shadow Stack Access: %s\n", params.SS ? "Yes" : "No");
CrashHandler::EHPrint("Caused By An SGX Violation: %s\n", params.SGX ? "Yes" : "No");
if (Frame->ErrorCode & 0x00000008)
CrashHandler::EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n");
else
CrashHandler::EHPrint(PagefaultDescriptions[Frame->ErrorCode & 0b111]);
}
SafeFunction void x87FloatingPointExceptionHandler(CHArchTrapFrame *Frame) { fixme("x87 floating point exception"); }
SafeFunction void AlignmentCheckExceptionHandler(CHArchTrapFrame *Frame) { fixme("Alignment check exception"); }
SafeFunction void MachineCheckExceptionHandler(CHArchTrapFrame *Frame) { fixme("Machine check exception"); }
SafeFunction void SIMDFloatingPointExceptionHandler(CHArchTrapFrame *Frame) { fixme("SIMD floating point exception"); }
SafeFunction void VirtualizationExceptionHandler(CHArchTrapFrame *Frame) { fixme("Virtualization exception"); }
SafeFunction void SecurityExceptionHandler(CHArchTrapFrame *Frame) { fixme("Security exception"); }
SafeFunction void UnknownExceptionHandler(CHArchTrapFrame *Frame) { fixme("Unknown exception"); }

View File

@ -0,0 +1,691 @@
#include "../crashhandler.hpp"
#include "chfcts.hpp"
#include <display.hpp>
#include <bitmap.hpp>
#include <convert.h>
#include <printf.h>
#include <lock.hpp>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#include <io.h>
#if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../kernel.h"
NewLock(UserInputLock);
#define TRACE_PAGE_TABLE(x, itr, depth) \
EHPrint("\e888888#%s\eAABBCC%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PS:%s G:%s Address:\e888888%#lx\n", \
depth, \
itr, \
x.Value.Present ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.ReadWrite ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.UserSupervisor ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.WriteThrough ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.CacheDisable ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.Accessed ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.Dirty ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.PageSize ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.Global ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.GetAddress() << 12); \
Display->SetBuffer(SBIdx);
namespace CrashHandler
{
void *EHIntFrames[INT_FRAMES_MAX];
static bool ExceptionOccurred = false;
int SBIdx = 255;
SafeFunction void printfWrapper(char c, void *unused)
{
Display->Print(c, SBIdx, true);
UNUSED(unused);
}
SafeFunction void EHPrint(const char *Format, ...)
{
va_list args;
va_start(args, Format);
vfctprintf(printfWrapper, NULL, Format, args);
va_end(args);
}
SafeFunction char *TrimWhiteSpace(char *str)
{
char *end;
while (*str == ' ')
str++;
if (*str == 0)
return str;
end = str + strlen(str) - 1;
while (end > str && *end == ' ')
end--;
*(end + 1) = 0;
return str;
}
CRData crashdata = {};
SafeFunction void DisplayTopOverlay()
{
Video::ScreenBuffer *sb = Display->GetBuffer(SBIdx);
Video::Font *f = Display->GetCurrentFont();
Video::FontInfo fi = f->GetInfo();
for (uint32_t i = 0; i < sb->Width; i++)
for (uint32_t j = 0; j < fi.Height + 8; j++)
Display->SetPixel(i, j, 0x282828, SBIdx);
Display->SetBufferCursor(SBIdx, 8, (fi.Height + 8) / 6);
switch (SBIdx)
{
case 255:
{
EHPrint("\eAAAAAAMAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE");
break;
}
case 254:
{
EHPrint("\e606060MAIN \eAAAAAADETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE");
break;
}
case 253:
{
EHPrint("\e606060MAIN \e606060DETAILS \eAAAAAAFRAMES \e606060TASKS \e606060CONSOLE");
break;
}
case 252:
{
EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \eAAAAAATASKS \e606060CONSOLE");
break;
}
case 251:
{
EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \eAAAAAACONSOLE");
break;
}
default:
{
EHPrint("\e606060MAIN \e606060DETAILS \e606060FRAMES \e606060TASKS \e606060CONSOLE");
break;
}
}
EHPrint(" \e00AAFF%ldMB / %ldMB (%ldMB Reserved)",
TO_MB(KernelAllocator.GetUsedMemory()),
TO_MB(KernelAllocator.GetTotalMemory()),
TO_MB(KernelAllocator.GetReservedMemory()));
EHPrint(" \eAA0F0F%s", CPU::Hypervisor());
EHPrint(" \eAAF00F%s", CPU::Vendor());
EHPrint(" \eAA00FF%s", CPU::Name());
Display->SetBufferCursor(SBIdx, 0, fi.Height + 10);
}
SafeFunction void DisplayBottomOverlay()
{
Video::ScreenBuffer *sb = Display->GetBuffer(SBIdx);
Video::Font *f = Display->GetCurrentFont();
Video::FontInfo fi = f->GetInfo();
for (uint32_t i = 0; i < sb->Width; i++)
for (uint32_t j = sb->Height - fi.Height - 8; j < sb->Height; j++)
Display->SetPixel(i, j, 0x282828, SBIdx);
Display->SetBufferCursor(SBIdx, 8, sb->Height - fi.Height - 4);
EHPrint("\eAAAAAA> \eFAFAFA");
}
SafeFunction void ArrowInput(uint8_t key)
{
switch (key)
{
case KEY_D_UP:
if (SBIdx < 255)
SBIdx++;
else
return;
break;
case KEY_D_LEFT:
if (SBIdx < 255)
SBIdx++;
else
return;
break;
case KEY_D_RIGHT:
if (SBIdx > 251)
SBIdx--;
else
return;
break;
case KEY_D_DOWN:
if (SBIdx > 251)
SBIdx--;
else
return;
break;
default:
break;
}
Display->ClearBuffer(SBIdx);
DisplayTopOverlay();
EHPrint("\eFAFAFA");
switch (SBIdx)
{
case 255:
{
DisplayMainScreen(crashdata);
break;
}
case 254:
{
DisplayDetailsScreen(crashdata);
break;
}
case 253:
{
DisplayStackFrameScreen(crashdata);
break;
}
case 252:
{
DisplayTasksScreen(crashdata);
break;
}
case 251:
{
DisplayConsoleScreen(crashdata);
break;
}
default:
{
break;
}
}
DisplayBottomOverlay();
Display->SetBuffer(SBIdx);
}
SafeFunction void UserInput(char *Input)
{
SmartCriticalSection(UserInputLock);
Display->ClearBuffer(SBIdx);
DisplayTopOverlay();
EHPrint("\eFAFAFA");
if (strcmp(Input, "help") == 0)
{
EHPrint("Available commands are:\n");
EHPrint("exit - Shutdown the OS.\n");
EHPrint("reboot - Reboot the OS.\n");
EHPrint("help - Display this help message.\n");
EHPrint("showbuf <INDEX> - Display the contents of a screen buffer.\n");
EHPrint(" - A sleep timer will be enabled. This will cause the OS to sleep for an unknown amount of time.\n");
EHPrint(" - \eFF4400WARNING: This can crash the system if a wrong buffer is selected.\eFAFAFA\n");
EHPrint("ifr <COUNT> - Show interrupt frames.\n");
EHPrint("tlb <ADDRESS> - Print the page table entries\n");
EHPrint("bitmap - Print the memory bitmap\n");
EHPrint("main - Show the main screen.\n");
EHPrint("details - Show the details screen.\n");
EHPrint("frames - Show the stack frame screen.\n");
EHPrint("tasks - Show the tasks screen.\n");
EHPrint("console - Show the console screen.\n");
EHPrint("Also, you can use the arrow keys to navigate the menu.\n");
EHPrint("=========================================================================\n");
EHPrint("Kernel Compiled at: %s %s with C++ Standard: %d\n", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
EHPrint("C++ Language Version (__cplusplus): %ld\n", __cplusplus);
}
else if (strcmp(Input, "exit") == 0)
{
PowerManager->Shutdown();
EHPrint("\eFFFFFFNow it's safe to turn off your computer.");
Display->SetBuffer(SBIdx);
CPU::Stop();
}
else if (strcmp(Input, "reboot") == 0)
{
PowerManager->Reboot();
EHPrint("\eFFFFFFNow it's safe to reboot your computer.");
Display->SetBuffer(SBIdx);
CPU::Stop();
}
else if (strncmp(Input, "showbuf", 7) == 0)
{
char *arg = TrimWhiteSpace(Input + 7);
int tmpidx = SBIdx;
SBIdx = atoi(arg);
Display->SetBuffer(SBIdx);
for (int i = 0; i < 5000000; i++)
inb(0x80);
SBIdx = tmpidx;
Display->SetBuffer(SBIdx);
}
else if (strncmp(Input, "ifr", 3) == 0)
{
char *arg = TrimWhiteSpace(Input + 3);
uint64_t CountI = atoi(arg);
uint64_t TotalCount = sizeof(EHIntFrames) / sizeof(EHIntFrames[0]);
debug("Printing %ld interrupt frames.", CountI);
if (CountI > TotalCount)
{
EHPrint("eFF4400Count too big! Maximum allowed is %ld\eFAFAFA\n", TotalCount);
Display->SetBuffer(SBIdx);
}
else
{
for (uint64_t i = 0; i < CountI; i++)
{
if (EHIntFrames[i])
{
if (!Memory::Virtual().Check(EHIntFrames[i]))
continue;
EHPrint("\n\e2565CC%p", EHIntFrames[i]);
EHPrint("\e7925CC-");
#if defined(__amd64__)
if ((uint64_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(__i386__)
if ((uint64_t)EHIntFrames[i] >= 0xC0000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(__aarch64__)
#endif
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uint64_t)EHIntFrames[i]));
else
EHPrint("\eFF4CA9Outside Kernel");
for (int i = 0; i < 20000; i++)
inb(0x80);
Display->SetBuffer(SBIdx);
}
}
}
}
else if (strncmp(Input, "tlb", 3) == 0)
{
char *arg = TrimWhiteSpace(Input + 3);
uint64_t Address = NULL;
Address = strtol(arg, NULL, 16);
debug("Converted %s to %#lx", arg, Address);
Memory::PageTable *BasePageTable = (Memory::PageTable *)Address;
if (Memory::Virtual().Check(BasePageTable))
for (int Index = 0; Index < 512; Index++)
{
if (BasePageTable->Entries[Index].Value.raw == 0)
continue;
TRACE_PAGE_TABLE(BasePageTable->Entries[Index], Index, "");
for (int i = 0; i < 10000; i++)
inb(0x80);
if (BasePageTable->Entries[Index].GetFlag(Memory::PTFlag::P))
{
Memory::PageTable *PDP = (Memory::PageTable *)((uint64_t)BasePageTable->Entries[Index].GetAddress() << 12);
for (int PDPIndex = 0; PDPIndex < 512; PDPIndex++)
{
if (PDP->Entries[PDPIndex].Value.raw == 0)
continue;
TRACE_PAGE_TABLE(PDP->Entries[PDPIndex], PDPIndex, " ");
for (int i = 0; i < 10000; i++)
inb(0x80);
if (PDP->Entries[PDPIndex].GetFlag(Memory::PTFlag::P))
{
Memory::PageTable *PD = (Memory::PageTable *)((uint64_t)PDP->Entries[PDPIndex].GetAddress() << 12);
for (int PDIndex = 0; PDIndex < 512; PDIndex++)
{
if (PD->Entries[PDIndex].Value.raw == 0)
continue;
TRACE_PAGE_TABLE(PD->Entries[PDIndex], PDIndex, " ");
for (int i = 0; i < 10000; i++)
inb(0x80);
if (PD->Entries[PDIndex].GetFlag(Memory::PTFlag::P))
{
Memory::PageTable *PT = (Memory::PageTable *)((uint64_t)PD->Entries[PDIndex].GetAddress() << 12);
for (int PIndex = 0; PIndex < 512; PIndex++)
{
if (PT->Entries[PIndex].Value.raw == 0)
continue;
TRACE_PAGE_TABLE(PT->Entries[PIndex], PIndex, " ");
for (int i = 0; i < 10000; i++)
inb(0x80);
}
}
}
}
}
}
}
}
else if (strncmp(Input, "bitmap", 6) == 0)
{
Bitmap bm = KernelAllocator.GetPageBitmap();
EHPrint("\n\eFAFAFA%08ld: ", 0);
for (uint64_t i = 0; i < bm.Size; i++)
{
if (bm.Get(i))
EHPrint("\eFF00001");
else
EHPrint("\e00FF000");
if (i % 128 == 127)
{
EHPrint("\n\eFAFAFA%08ld: ", i);
Display->SetBuffer(SBIdx);
}
}
EHPrint("\n\e22AA44--- END OF BITMAP ---\nBitmap size: %ld\n", bm.Size);
Display->SetBuffer(SBIdx);
}
else if (strcmp(Input, "main") == 0)
{
SBIdx = 255;
DisplayTopOverlay();
DisplayMainScreen(crashdata);
Display->SetBuffer(SBIdx);
}
else if (strcmp(Input, "details") == 0)
{
SBIdx = 254;
DisplayTopOverlay();
DisplayDetailsScreen(crashdata);
Display->SetBuffer(SBIdx);
}
else if (strcmp(Input, "frames") == 0)
{
SBIdx = 253;
DisplayTopOverlay();
DisplayStackFrameScreen(crashdata);
Display->SetBuffer(SBIdx);
}
else if (strcmp(Input, "tasks") == 0)
{
SBIdx = 252;
DisplayTopOverlay();
DisplayTasksScreen(crashdata);
Display->SetBuffer(SBIdx);
}
else if (strcmp(Input, "console") == 0)
{
SBIdx = 251;
DisplayTopOverlay();
DisplayConsoleScreen(crashdata);
Display->SetBuffer(SBIdx);
}
else
{
if (strlen(Input) > 0)
EHPrint("Unknown command: %s", Input);
}
DisplayBottomOverlay();
Display->SetBuffer(SBIdx);
}
SafeFunction void Handle(void *Data)
{
// TODO: SUPPORT SMP
CPU::Interrupts(CPU::Disable);
error("An exception occurred!");
for (size_t i = 0; i < INT_FRAMES_MAX; i++)
EHIntFrames[i] = Interrupts::InterruptFrames[i];
SBIdx = 255;
CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data;
#if defined(__amd64__)
error("Exception: %#llx", Frame->InterruptNumber);
if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA)
{
debug("Exception in kernel mode");
if (TaskManager)
TaskManager->Panic();
debug("ePanicSchedStop");
Display->CreateBuffer(0, 0, SBIdx);
debug("e0");
}
else
{
debug("Exception in user mode");
CPUData *data = GetCurrentCPU();
if (!data)
{
Display->CreateBuffer(0, 0, SBIdx);
EHPrint("\eFF0000Cannot get CPU data! This results in a kernel crash!");
error("Cannot get CPU data! This results in a kernel crash!");
error("This should never happen!");
}
else
{
debug("CPU %ld data is valid", data->ID);
if (data->CurrentThread)
{
debug("Current thread is valid %#lx", data->CurrentThread);
UserModeExceptionHandler(Frame);
return;
}
}
}
if (ExceptionOccurred)
{
SBIdx = 255;
Display->ClearBuffer(SBIdx);
debug("e0-1");
Display->SetBufferCursor(SBIdx, 0, 0);
debug("e0-2");
CPU::x64::CR0 cr0 = CPU::x64::readcr0();
CPU::x64::CR2 cr2 = CPU::x64::readcr2();
CPU::x64::CR3 cr3 = CPU::x64::readcr3();
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
CPU::x64::CR8 cr8 = CPU::x64::readcr8();
CPU::x64::EFER efer;
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
uint64_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
EHPrint("\eFF0000FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
Frame->ss, Frame->cs, ds);
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
EHPrint("R12=%#llx R13=%#llx R14=%#llx R15=%#llx\n", Frame->r12, Frame->r13, Frame->r14, Frame->r15);
EHPrint("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx\n", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
EHPrint("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx\n", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
EHPrint("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
EHPrint("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx\n", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw);
EHPrint("CR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n R0:%#x R1:%#x R2:%#x\n",
cr0.PE ? "True " : "False", cr0.MP ? "True " : "False", cr0.EM ? "True " : "False", cr0.TS ? "True " : "False",
cr0.ET ? "True " : "False", cr0.NE ? "True " : "False", cr0.WP ? "True " : "False", cr0.AM ? "True " : "False",
cr0.NW ? "True " : "False", cr0.CD ? "True " : "False", cr0.PG ? "True " : "False",
cr0.Reserved0, cr0.Reserved1, cr0.Reserved2);
EHPrint("CR2: PFLA: %#llx\n",
cr2.PFLA);
EHPrint("CR3: PWT:%s PCD:%s PDBR:%#llx\n",
cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR);
EHPrint("CR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n R0:%#x R1:%#x R2:%#x\n",
cr4.VME ? "True " : "False", cr4.PVI ? "True " : "False", cr4.TSD ? "True " : "False", cr4.DE ? "True " : "False",
cr4.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False",
cr4.PCE ? "True " : "False", cr4.UMIP ? "True " : "False", cr4.OSFXSR ? "True " : "False", cr4.OSXMMEXCPT ? "True " : "False",
cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False",
cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False",
cr4.Reserved0, cr4.Reserved1, cr4.Reserved2);
EHPrint("CR8: TPL:%d\n", cr8.TPL);
EHPrint("RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n",
Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False",
Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False",
Frame->rflags.OF ? "True " : "False", Frame->rflags.IOPL ? "True " : "False", Frame->rflags.NT ? "True " : "False", Frame->rflags.RF ? "True " : "False",
Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False",
Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne,
Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3);
EHPrint("EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n R0:%#x R1:%#x R2:%#x\n",
efer.SCE ? "True " : "False", efer.LME ? "True " : "False", efer.LMA ? "True " : "False", efer.NXE ? "True " : "False",
efer.SVME ? "True " : "False", efer.LMSLE ? "True " : "False", efer.FFXSR ? "True " : "False", efer.TCE ? "True " : "False",
efer.Reserved0, efer.Reserved1, efer.Reserved2);
EHPrint("\nException occurred while handling exception! HALTED!");
Display->SetBuffer(SBIdx);
CPU::Stop();
}
ExceptionOccurred = true;
Interrupts::RemoveAll();
debug("Reading control registers...");
crashdata.Frame = Frame;
crashdata.cr0 = CPU::x64::readcr0();
crashdata.cr2 = CPU::x64::readcr2();
crashdata.cr3 = CPU::x64::readcr3();
crashdata.cr4 = CPU::x64::readcr4();
crashdata.cr8 = CPU::x64::readcr8();
crashdata.efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
uint64_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
// Get debug registers
asmv("movq %%dr0, %0"
: "=r"(crashdata.dr0));
asmv("movq %%dr1, %0"
: "=r"(crashdata.dr1));
asmv("movq %%dr2, %0"
: "=r"(crashdata.dr2));
asmv("movq %%dr3, %0"
: "=r"(crashdata.dr3));
asmv("movq %%dr6, %0"
: "=r"(crashdata.dr6));
asmv("movq %%dr7, %0"
: "=r"(crashdata.dr7));
CPUData *cpudata = GetCurrentCPU();
if (cpudata == nullptr)
{
EHPrint("\eFFA500Invalid CPU data!\n");
for (long i = 0; i < MAX_CPU; i++)
{
cpudata = GetCPU(i);
if (cpudata != nullptr)
break;
if (i == MAX_CPU - 1)
{
EHPrint("\eFF0000No CPU data found!\n");
cpudata = nullptr;
}
}
debug("CPU ptr %#lx", cpudata);
}
if (cpudata != nullptr)
{
crashdata.ID = cpudata->ID;
crashdata.CPUData = cpudata;
error("Technical Informations on CPU %lld:", cpudata->ID);
}
if (TaskManager && cpudata != nullptr)
{
crashdata.Process = cpudata->CurrentProcess;
crashdata.Thread = cpudata->CurrentThread;
error("Current Process: %s(%ld)",
cpudata->CurrentProcess->Name,
cpudata->CurrentProcess->ID);
error("Current Thread: %s(%ld)",
cpudata->CurrentThread->Name,
cpudata->CurrentThread->ID);
}
{
error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx",
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
Frame->ss, Frame->cs, ds);
error("R8=%#llx R9=%#llx R10=%#llx R11=%#llx", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
error("R12=%#llx R13=%#llx R14=%#llx R15=%#llx", Frame->r12, Frame->r13, Frame->r14, Frame->r15);
error("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, crashdata.efer.raw);
error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", crashdata.cr0.raw, crashdata.cr2.raw, crashdata.cr3.raw, crashdata.cr4.raw, crashdata.cr8.raw);
error("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx", crashdata.dr0, crashdata.dr1, crashdata.dr2, crashdata.dr3, crashdata.dr6, crashdata.dr7.raw);
error("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x",
crashdata.cr0.PE ? "True " : "False", crashdata.cr0.MP ? "True " : "False", crashdata.cr0.EM ? "True " : "False", crashdata.cr0.TS ? "True " : "False",
crashdata.cr0.ET ? "True " : "False", crashdata.cr0.NE ? "True " : "False", crashdata.cr0.WP ? "True " : "False", crashdata.cr0.AM ? "True " : "False",
crashdata.cr0.NW ? "True " : "False", crashdata.cr0.CD ? "True " : "False", crashdata.cr0.PG ? "True " : "False",
crashdata.cr0.Reserved0, crashdata.cr0.Reserved1, crashdata.cr0.Reserved2);
error("CR2: PFLA: %#llx",
crashdata.cr2.PFLA);
error("CR3: PWT:%s PCD:%s PDBR:%#llx",
crashdata.cr3.PWT ? "True " : "False", crashdata.cr3.PCD ? "True " : "False", crashdata.cr3.PDBR);
error("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x R2:%#x",
crashdata.cr4.VME ? "True " : "False", crashdata.cr4.PVI ? "True " : "False", crashdata.cr4.TSD ? "True " : "False", crashdata.cr4.DE ? "True " : "False",
crashdata.cr4.PSE ? "True " : "False", crashdata.cr4.PAE ? "True " : "False", crashdata.cr4.MCE ? "True " : "False", crashdata.cr4.PGE ? "True " : "False",
crashdata.cr4.PCE ? "True " : "False", crashdata.cr4.UMIP ? "True " : "False", crashdata.cr4.OSFXSR ? "True " : "False", crashdata.cr4.OSXMMEXCPT ? "True " : "False",
crashdata.cr4.LA57 ? "True " : "False", crashdata.cr4.VMXE ? "True " : "False", crashdata.cr4.SMXE ? "True " : "False", crashdata.cr4.PCIDE ? "True " : "False",
crashdata.cr4.OSXSAVE ? "True " : "False", crashdata.cr4.SMEP ? "True " : "False", crashdata.cr4.SMAP ? "True " : "False", crashdata.cr4.PKE ? "True " : "False",
crashdata.cr4.Reserved0, crashdata.cr4.Reserved1, crashdata.cr4.Reserved2);
error("CR8: TPL:%d", crashdata.cr8.TPL);
error("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x R3:%#x",
Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False",
Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False",
Frame->rflags.OF ? "True " : "False", Frame->rflags.IOPL ? "True " : "False", Frame->rflags.NT ? "True " : "False", Frame->rflags.RF ? "True " : "False",
Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False",
Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne,
Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3);
error("DR7: LDR0:%s GDR0:%s LDR1:%s GDR1:%s LDR2:%s GDR2:%s LDR3:%s GDR3:%s CDR0:%s SDR0:%s CDR1:%s SDR1:%s CDR2:%s SDR2:%s CDR3:%s SDR3:%s R:%#x",
crashdata.dr7.LocalDR0 ? "True " : "False", crashdata.dr7.GlobalDR0 ? "True " : "False", crashdata.dr7.LocalDR1 ? "True " : "False", crashdata.dr7.GlobalDR1 ? "True " : "False",
crashdata.dr7.LocalDR2 ? "True " : "False", crashdata.dr7.GlobalDR2 ? "True " : "False", crashdata.dr7.LocalDR3 ? "True " : "False", crashdata.dr7.GlobalDR3 ? "True " : "False",
crashdata.dr7.ConditionsDR0 ? "True " : "False", crashdata.dr7.SizeDR0 ? "True " : "False", crashdata.dr7.ConditionsDR1 ? "True " : "False", crashdata.dr7.SizeDR1 ? "True " : "False",
crashdata.dr7.ConditionsDR2 ? "True " : "False", crashdata.dr7.SizeDR2 ? "True " : "False", crashdata.dr7.ConditionsDR3 ? "True " : "False", crashdata.dr7.SizeDR3 ? "True " : "False",
crashdata.dr7.Reserved);
error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x",
crashdata.efer.SCE ? "True " : "False", crashdata.efer.LME ? "True " : "False", crashdata.efer.LMA ? "True " : "False", crashdata.efer.NXE ? "True " : "False",
crashdata.efer.SVME ? "True " : "False", crashdata.efer.LMSLE ? "True " : "False", crashdata.efer.FFXSR ? "True " : "False", crashdata.efer.TCE ? "True " : "False",
crashdata.efer.Reserved0, crashdata.efer.Reserved1, crashdata.efer.Reserved2);
}
goto CrashEnd;
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
CrashEnd:
if (Config.InterruptsOnCrash)
{
// 255 // Main
Display->CreateBuffer(0, 0, 254); // Details
Display->CreateBuffer(0, 0, 253); // Frames
Display->CreateBuffer(0, 0, 252); // Tasks
Display->CreateBuffer(0, 0, 251); // Console
Display->CreateBuffer(0, 0, 250); // Empty
DisplayTopOverlay();
DisplayMainScreen(crashdata);
DisplayBottomOverlay();
Display->SetBuffer(255);
debug("Interrupts are enabled, waiting for user input");
CPU::Interrupts(CPU::Enable);
HookKeyboard();
}
else
{
/*
TODO: Stuff that should be done when IOC is disabled.
*/
Display->SetBuffer(255);
}
CPU::Halt(true);
}
}

164
Kernel/Core/Crash/KBDrv.cpp Normal file
View File

@ -0,0 +1,164 @@
#include "../crashhandler.hpp"
#include "chfcts.hpp"
#include <display.hpp>
#include <convert.h>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#include <io.h>
#if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../kernel.h"
const char sc_ascii_low[] = {'?', '?', '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', '?', '?', 'q', 'w', 'e', 'r', 't', 'y',
'u', 'i', 'o', 'p', '[', ']', '?', '?', 'a', 's', 'd', 'f', 'g',
'h', 'j', 'k', 'l', ';', '\'', '`', '?', '\\', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', '?', '?', '?', ' '};
const char sc_ascii_high[] = {'?', '?', '!', '@', '#', '$', '%', '^',
'&', '*', '(', ')', '_', '+', '?', '?', 'Q', 'W', 'E', 'R', 'T', 'Y',
'U', 'I', 'O', 'P', '{', '}', '?', '?', 'A', 'S', 'D', 'F', 'G',
'H', 'J', 'K', 'L', ';', '\"', '~', '?', '|', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', '<', '>', '?', '?', '?', '?', ' '};
static int LowerCase = true;
static inline int GetLetterFromScanCode(uint8_t ScanCode)
{
if (ScanCode & 0x80)
{
switch (ScanCode)
{
case KEY_U_LSHIFT:
LowerCase = true;
return KEY_INVALID;
case KEY_U_RSHIFT:
LowerCase = true;
return KEY_INVALID;
default:
return KEY_INVALID;
}
}
else
{
switch (ScanCode)
{
case KEY_D_RETURN:
return '\n';
case KEY_D_LSHIFT:
LowerCase = false;
return KEY_INVALID;
case KEY_D_RSHIFT:
LowerCase = false;
return KEY_INVALID;
case KEY_D_BACKSPACE:
return ScanCode;
default:
{
if (ScanCode > 0x39)
break;
if (LowerCase)
return sc_ascii_low[ScanCode];
else
return sc_ascii_high[ScanCode];
}
}
}
return KEY_INVALID;
}
namespace CrashHandler
{
CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(CPU::x64::IRQ1)
{
while (inb(0x64) & 0x1)
inb(0x60);
outb(0x64, 0xAE);
outb(0x64, 0x20);
uint8_t ret = (inb(0x60) | 1) & ~0x10;
outb(0x64, 0x60);
outb(0x60, ret);
outb(0x60, 0xF4);
outb(0x21, 0xFD);
outb(0xA1, 0xFF);
CPU::Interrupts(CPU::Enable); // Just to be sure.
}
CrashKeyboardDriver::~CrashKeyboardDriver()
{
error("CrashKeyboardDriver::~CrashKeyboardDriver() called!");
}
int BackSpaceLimit = 0;
static char UserInputBuffer[1024];
#if defined(__amd64__)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
#elif defined(__i386__)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(void *Frame)
#elif defined(__aarch64__)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(void *Frame)
#endif
{
uint8_t scanCode = inb(0x60);
if (scanCode == KEY_D_TAB ||
scanCode == KEY_D_LCTRL ||
scanCode == KEY_D_LALT ||
scanCode == KEY_U_LCTRL ||
scanCode == KEY_U_LALT)
return;
switch (scanCode)
{
case KEY_D_UP:
case KEY_D_LEFT:
case KEY_D_RIGHT:
case KEY_D_DOWN:
ArrowInput(scanCode);
}
int key = GetLetterFromScanCode(scanCode);
if (key != KEY_INVALID)
{
if (key == KEY_D_BACKSPACE)
{
if (BackSpaceLimit > 0)
{
Display->Print('\b', SBIdx);
backspace(UserInputBuffer);
BackSpaceLimit--;
}
}
else if (key == '\n')
{
UserInput(UserInputBuffer);
BackSpaceLimit = 0;
UserInputBuffer[0] = '\0';
}
else
{
append(UserInputBuffer, key);
Display->Print(key, SBIdx);
BackSpaceLimit++;
}
Display->SetBuffer(SBIdx); // Update as we type.
}
}
SafeFunction void HookKeyboard()
{
CrashKeyboardDriver kbd; // We don't want to allocate memory.
asmv("KeyboardHookLoop: nop; jmp KeyboardHookLoop;");
// CPU::Halt(true); // This is an infinite loop.
}
}

View File

@ -0,0 +1,96 @@
#include "../crashhandler.hpp"
#include "chfcts.hpp"
#include <display.hpp>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../kernel.h"
namespace CrashHandler
{
struct StackFrame
{
struct StackFrame *rbp;
uint64_t rip;
};
SafeFunction void TraceFrames(CHArchTrapFrame *Frame, int Count)
{
#if defined(__amd64__)
struct StackFrame *frames = (struct StackFrame *)Frame->rbp; // (struct StackFrame *)__builtin_frame_address(0);
#elif defined(__i386__)
struct StackFrame *frames = (struct StackFrame *)Frame->ebp; // (struct StackFrame *)__builtin_frame_address(0);
#elif defined(__aarch64__)
#endif
debug("Stack tracing...");
EHPrint("\e7981FC\nStack Trace:\n");
if (!frames || !frames->rip || !frames->rbp)
{
#if defined(__amd64__)
EHPrint("\e2565CC%p", (void *)Frame->rip);
#elif defined(__i386__)
EHPrint("\e2565CC%p", (void *)Frame->eip);
#elif defined(__aarch64__)
#endif
EHPrint("\e7925CC-");
#if defined(__amd64__)
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
#elif defined(__i386__)
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->eip));
#elif defined(__aarch64__)
#endif
EHPrint("\e7981FC <- Exception");
EHPrint("\eFF0000\n< No stack trace available. >\n");
}
else
{
#if defined(__amd64__)
EHPrint("\e2565CC%p", (void *)Frame->rip);
EHPrint("\e7925CC-");
if (Frame->rip >= 0xFFFFFFFF80000000 && Frame->rip <= (uint64_t)&_kernel_end)
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
else
EHPrint("Outside Kernel");
#elif defined(__i386__)
EHPrint("\e2565CC%p", (void *)Frame->eip);
EHPrint("\e7925CC-");
if (Frame->eip >= 0xC0000000 && Frame->eip <= (uint64_t)&_kernel_end)
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->eip));
else
EHPrint("Outside Kernel");
#elif defined(__aarch64__)
#endif
EHPrint("\e7981FC <- Exception");
for (int frame = 0; frame < Count; ++frame)
{
if (!frames->rip)
break;
EHPrint("\n\e2565CC%p", (void *)frames->rip);
EHPrint("\e7925CC-");
#if defined(__amd64__)
if (frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uint64_t)&_kernel_end)
#elif defined(__i386__)
if (frames->rip >= 0xC0000000 && frames->rip <= (uint64_t)&_kernel_end)
#elif defined(__aarch64__)
#endif
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress(frames->rip));
else
EHPrint("\eFF4CA9Outside Kernel");
if (!Memory::Virtual().Check(frames->rbp))
return;
frames = frames->rbp;
}
}
}
}

View File

@ -0,0 +1,24 @@
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
#include <display.hpp>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../../kernel.h"
namespace CrashHandler
{
SafeFunction void DisplayConsoleScreen(CRData data)
{
EHPrint("TODO");
}
}

View File

@ -0,0 +1,249 @@
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
#include <display.hpp>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../../kernel.h"
namespace CrashHandler
{
SafeFunction void DisplayDetailsScreen(CRData data)
{
if (data.Process)
EHPrint("\e7981FCCurrent Process: %s(%ld)\n",
data.Process->Name,
data.Process->ID);
if (data.Thread)
EHPrint("\e7981FCCurrent Thread: %s(%ld)\n",
data.Thread->Name,
data.Thread->ID);
EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", data.ID);
#if defined(__amd64__)
CPUData *cpu = (CPUData *)data.CPUData;
if (cpu)
{
EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu);
EHPrint("Syscalls Stack: %#lx\n", cpu->SystemCallStack);
EHPrint("TempStack: %#lx\n", cpu->TempStack);
EHPrint("Core Stack: %#lx\n", cpu->Stack);
EHPrint("Core ID: %ld\n", cpu->ID);
EHPrint("Error Code: %ld\n", cpu->ErrorCode);
EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false");
EHPrint("Current Process: %#lx\n", cpu->CurrentProcess);
EHPrint("Current Thread: %#lx\n", cpu->CurrentThread);
EHPrint("Arch Specific Data: %#lx\n", cpu->Data);
EHPrint("Checksum: 0x%X\n", cpu->Checksum);
}
uint64_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
#elif defined(__i386__)
uint32_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
#elif defined(__aarch64__)
#endif
EHPrint("\e7981FCFS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
data.Frame->ss, data.Frame->cs, ds);
#if defined(__amd64__)
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", data.Frame->r8, data.Frame->r9, data.Frame->r10, data.Frame->r11);
EHPrint("R12=%#llx R13=%#llx R14=%#llx R15=%#llx\n", data.Frame->r12, data.Frame->r13, data.Frame->r14, data.Frame->r15);
EHPrint("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx\n", data.Frame->rax, data.Frame->rbx, data.Frame->rcx, data.Frame->rdx);
EHPrint("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx\n", data.Frame->rsi, data.Frame->rdi, data.Frame->rbp, data.Frame->rsp);
EHPrint("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", data.Frame->rip, data.Frame->rflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw);
#elif defined(__i386__)
EHPrint("EAX=%#llx EBX=%#llx ECX=%#llx EDX=%#llx\n", data.Frame->eax, data.Frame->ebx, data.Frame->ecx, data.Frame->edx);
EHPrint("ESI=%#llx EDI=%#llx EBP=%#llx ESP=%#llx\n", data.Frame->esi, data.Frame->edi, data.Frame->ebp, data.Frame->esp);
EHPrint("EIP=%#llx EFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", data.Frame->eip, data.Frame->eflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw);
#elif defined(__aarch64__)
#endif
EHPrint("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx\n", data.cr0.raw, data.cr2.raw, data.cr3.raw, data.cr4.raw, data.cr8.raw);
EHPrint("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx\n", data.dr0, data.dr1, data.dr2, data.dr3, data.dr6, data.dr7.raw);
EHPrint("\eFC797BCR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n R0:%#x R1:%#x R2:%#x\n",
data.cr0.PE ? "True " : "False", data.cr0.MP ? "True " : "False", data.cr0.EM ? "True " : "False", data.cr0.TS ? "True " : "False",
data.cr0.ET ? "True " : "False", data.cr0.NE ? "True " : "False", data.cr0.WP ? "True " : "False", data.cr0.AM ? "True " : "False",
data.cr0.NW ? "True " : "False", data.cr0.CD ? "True " : "False", data.cr0.PG ? "True " : "False",
data.cr0.Reserved0, data.cr0.Reserved1, data.cr0.Reserved2);
EHPrint("\eFCBD79CR2: PFLA: %#llx\n",
data.cr2.PFLA);
EHPrint("\e79FC84CR3: PWT:%s PCD:%s PDBR:%#llx\n",
data.cr3.PWT ? "True " : "False", data.cr3.PCD ? "True " : "False", data.cr3.PDBR);
EHPrint("\eBD79FCCR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n R0:%#x R1:%#x R2:%#x\n",
data.cr4.VME ? "True " : "False", data.cr4.PVI ? "True " : "False", data.cr4.TSD ? "True " : "False", data.cr4.DE ? "True " : "False",
data.cr4.PSE ? "True " : "False", data.cr4.PAE ? "True " : "False", data.cr4.MCE ? "True " : "False", data.cr4.PGE ? "True " : "False",
data.cr4.PCE ? "True " : "False", data.cr4.UMIP ? "True " : "False", data.cr4.OSFXSR ? "True " : "False", data.cr4.OSXMMEXCPT ? "True " : "False",
data.cr4.LA57 ? "True " : "False", data.cr4.VMXE ? "True " : "False", data.cr4.SMXE ? "True " : "False", data.cr4.PCIDE ? "True " : "False",
data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False",
#if defined(__amd64__)
data.cr4.Reserved0, data.cr4.Reserved1, data.cr4.Reserved2);
#elif defined(__i386__)
data.cr4.Reserved0, data.cr4.Reserved1, 0);
#elif defined(__aarch64__)
#endif
EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL);
#if defined(__amd64__)
EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n",
data.Frame->rflags.CF ? "True " : "False", data.Frame->rflags.PF ? "True " : "False", data.Frame->rflags.AF ? "True " : "False", data.Frame->rflags.ZF ? "True " : "False",
data.Frame->rflags.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False",
data.Frame->rflags.OF ? "True " : "False", data.Frame->rflags.IOPL ? "True " : "False", data.Frame->rflags.NT ? "True " : "False", data.Frame->rflags.RF ? "True " : "False",
data.Frame->rflags.VM ? "True " : "False", data.Frame->rflags.AC ? "True " : "False", data.Frame->rflags.VIF ? "True " : "False", data.Frame->rflags.VIP ? "True " : "False",
data.Frame->rflags.ID ? "True " : "False", data.Frame->rflags.AlwaysOne,
data.Frame->rflags.Reserved0, data.Frame->rflags.Reserved1, data.Frame->rflags.Reserved2, data.Frame->rflags.Reserved3);
#elif defined(__i386__)
EHPrint("\eFCFC02EFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x\n",
data.Frame->eflags.CF ? "True " : "False", data.Frame->eflags.PF ? "True " : "False", data.Frame->eflags.AF ? "True " : "False", data.Frame->eflags.ZF ? "True " : "False",
data.Frame->eflags.SF ? "True " : "False", data.Frame->eflags.TF ? "True " : "False", data.Frame->eflags.IF ? "True " : "False", data.Frame->eflags.DF ? "True " : "False",
data.Frame->eflags.OF ? "True " : "False", data.Frame->eflags.IOPL ? "True " : "False", data.Frame->eflags.NT ? "True " : "False", data.Frame->eflags.RF ? "True " : "False",
data.Frame->eflags.VM ? "True " : "False", data.Frame->eflags.AC ? "True " : "False", data.Frame->eflags.VIF ? "True " : "False", data.Frame->eflags.VIP ? "True " : "False",
data.Frame->eflags.ID ? "True " : "False", data.Frame->eflags.AlwaysOne,
data.Frame->eflags.Reserved0, data.Frame->eflags.Reserved1, data.Frame->eflags.Reserved2);
#elif defined(__aarch64__)
#endif
EHPrint("\eA0F0F0DR7: LDR0:%s GDR0:%s LDR1:%s GDR1:%s\n LDR2:%s GDR2:%s LDR3:%s GDR3:%s\n CDR0:%s SDR0:%s CDR1:%s SDR1:%s\n CDR2:%s SDR2:%s CDR3:%s SDR3:%s\n R:%#x\n",
data.dr7.LocalDR0 ? "True " : "False", data.dr7.GlobalDR0 ? "True " : "False", data.dr7.LocalDR1 ? "True " : "False", data.dr7.GlobalDR1 ? "True " : "False",
data.dr7.LocalDR2 ? "True " : "False", data.dr7.GlobalDR2 ? "True " : "False", data.dr7.LocalDR3 ? "True " : "False", data.dr7.GlobalDR3 ? "True " : "False",
data.dr7.ConditionsDR0 ? "True " : "False", data.dr7.SizeDR0 ? "True " : "False", data.dr7.ConditionsDR1 ? "True " : "False", data.dr7.SizeDR1 ? "True " : "False",
data.dr7.ConditionsDR2 ? "True " : "False", data.dr7.SizeDR2 ? "True " : "False", data.dr7.ConditionsDR3 ? "True " : "False", data.dr7.SizeDR3 ? "True " : "False",
data.dr7.Reserved);
EHPrint("\e009FF0EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n R0:%#x R1:%#x R2:%#x\n",
data.efer.SCE ? "True " : "False", data.efer.LME ? "True " : "False", data.efer.LMA ? "True " : "False", data.efer.NXE ? "True " : "False",
data.efer.SVME ? "True " : "False", data.efer.LMSLE ? "True " : "False", data.efer.FFXSR ? "True " : "False", data.efer.TCE ? "True " : "False",
data.efer.Reserved0, data.efer.Reserved1, data.efer.Reserved2);
switch (data.Frame->InterruptNumber)
{
case CPU::x64::DivideByZero:
{
DivideByZeroExceptionHandler(data.Frame);
break;
}
case CPU::x64::Debug:
{
DebugExceptionHandler(data.Frame);
break;
}
case CPU::x64::NonMaskableInterrupt:
{
NonMaskableInterruptExceptionHandler(data.Frame);
break;
}
case CPU::x64::Breakpoint:
{
BreakpointExceptionHandler(data.Frame);
break;
}
case CPU::x64::Overflow:
{
OverflowExceptionHandler(data.Frame);
break;
}
case CPU::x64::BoundRange:
{
BoundRangeExceptionHandler(data.Frame);
break;
}
case CPU::x64::InvalidOpcode:
{
InvalidOpcodeExceptionHandler(data.Frame);
break;
}
case CPU::x64::DeviceNotAvailable:
{
DeviceNotAvailableExceptionHandler(data.Frame);
break;
}
case CPU::x64::DoubleFault:
{
DoubleFaultExceptionHandler(data.Frame);
break;
}
case CPU::x64::CoprocessorSegmentOverrun:
{
CoprocessorSegmentOverrunExceptionHandler(data.Frame);
break;
}
case CPU::x64::InvalidTSS:
{
InvalidTSSExceptionHandler(data.Frame);
break;
}
case CPU::x64::SegmentNotPresent:
{
SegmentNotPresentExceptionHandler(data.Frame);
break;
}
case CPU::x64::StackSegmentFault:
{
StackFaultExceptionHandler(data.Frame);
break;
}
case CPU::x64::GeneralProtectionFault:
{
GeneralProtectionExceptionHandler(data.Frame);
break;
}
case CPU::x64::PageFault:
{
PageFaultExceptionHandler(data.Frame);
break;
}
case CPU::x64::x87FloatingPoint:
{
x87FloatingPointExceptionHandler(data.Frame);
break;
}
case CPU::x64::AlignmentCheck:
{
AlignmentCheckExceptionHandler(data.Frame);
break;
}
case CPU::x64::MachineCheck:
{
MachineCheckExceptionHandler(data.Frame);
break;
}
case CPU::x64::SIMDFloatingPoint:
{
SIMDFloatingPointExceptionHandler(data.Frame);
break;
}
case CPU::x64::Virtualization:
{
VirtualizationExceptionHandler(data.Frame);
break;
}
case CPU::x64::Security:
{
SecurityExceptionHandler(data.Frame);
break;
}
default:
{
UnknownExceptionHandler(data.Frame);
break;
}
}
}
}

View File

@ -0,0 +1,345 @@
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
#include <display.hpp>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../../kernel.h"
static const char *PagefaultDescriptions[8] = {
"Supervisory process tried to read a non-present page entry\n",
"Supervisory process tried to read a page and caused a protection fault\n",
"Supervisory process tried to write to a non-present page entry\n",
"Supervisory process tried to write a page and caused a protection fault\n",
"User process tried to read a non-present page entry\n",
"User process tried to read a page and caused a protection fault\n",
"User process tried to write to a non-present page entry\n",
"User process tried to write a page and caused a protection fault\n"};
namespace CrashHandler
{
SafeFunction void DisplayMainScreen(CRData data)
{
CHArchTrapFrame *Frame = data.Frame;
/*
_______ ___ ___ _______ _______ _______ _______ ______ ______ _______ _______ _______ _______ _____
| __| | | __|_ _| ___| | | | | __ \ _ | __| | | ___| \
|__ |\ /|__ | | | | ___| | | ---| < |__ | | ___| -- |
|_______| |___| |_______| |___| |_______|__|_|__| |______|___|__|___|___|_______|___|___|_______|_____/
*/
EHPrint("\eFF5500 _______ ___ ___ _______ _______ _______ _______ ______ ______ _______ _______ _______ _______ _____ \n");
EHPrint("| __| | | __|_ _| ___| | | | | __ \\ _ | __| | | ___| \\ \n");
EHPrint("|__ |\\ /|__ | | | | ___| | | ---| < |__ | | ___| -- |\n");
EHPrint("|_______| |___| |_______| |___| |_______|__|_|__| |______|___|__|___|___|_______|___|___|_______|_____/ \n\eFAFAFA");
switch (Frame->InterruptNumber)
{
case CPU::x64::DivideByZero:
{
EHPrint("Exception: Divide By Zero\n");
EHPrint("The processor attempted to divide a number by zero.\n");
break;
}
case CPU::x64::Debug:
{
EHPrint("Exception: Debug\n");
EHPrint("A debug exception has occurred.\n");
break;
}
case CPU::x64::NonMaskableInterrupt:
{
EHPrint("Exception: Non-Maskable Interrupt\n");
EHPrint("A non-maskable interrupt was received.\n");
break;
}
case CPU::x64::Breakpoint:
{
EHPrint("Exception: Breakpoint\n");
EHPrint("The processor encountered a breakpoint.\n");
break;
}
case CPU::x64::Overflow:
{
EHPrint("Exception: Overflow\n");
EHPrint("The processor attempted to add a number to a number that was too large.\n");
break;
}
case CPU::x64::BoundRange:
{
EHPrint("Exception: Bound Range\n");
EHPrint("The processor attempted to access an array element that is out of bounds.\n");
break;
}
case CPU::x64::InvalidOpcode:
{
EHPrint("Exception: Invalid Opcode\n");
EHPrint("The processor attempted to execute an invalid opcode.\n");
break;
}
case CPU::x64::DeviceNotAvailable:
{
EHPrint("Exception: Device Not Available\n");
EHPrint("The processor attempted to use a device that is not available.\n");
break;
}
case CPU::x64::DoubleFault:
{
EHPrint("Exception: Double Fault\n");
EHPrint("The processor encountered a double fault.\n");
break;
}
case CPU::x64::CoprocessorSegmentOverrun:
{
EHPrint("Exception: Coprocessor Segment Overrun\n");
EHPrint("The processor attempted to access a segment that is not available.\n");
break;
}
case CPU::x64::InvalidTSS:
{
EHPrint("Exception: Invalid TSS\n");
EHPrint("The processor attempted to access a task state segment that is not available or valid.\n");
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
EHPrint("GDT IDT LDT IDT\n");
switch (SelCode.Table)
{
case 0b00:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b01:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b10:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b11:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
}
break;
}
case CPU::x64::SegmentNotPresent:
{
EHPrint("Exception: Segment Not Present\n");
EHPrint("The processor attempted to access a segment that is not present.\n");
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
EHPrint("GDT IDT LDT IDT\n");
switch (SelCode.Table)
{
case 0b00:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b01:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b10:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b11:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
}
break;
}
case CPU::x64::StackSegmentFault:
{
EHPrint("Exception: Stack Segment Fault\n");
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
EHPrint("GDT IDT LDT IDT\n");
switch (SelCode.Table)
{
case 0b00:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b01:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b10:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b11:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
}
break;
}
case CPU::x64::GeneralProtectionFault:
{
EHPrint("Exception: General Protection Fault\n");
EHPrint("Kernel performed an illegal operation.\n");
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
EHPrint("GDT IDT LDT IDT\n");
switch (SelCode.Table)
{
case 0b00:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b01:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b10:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
case 0b11:
{
EHPrint(" ^ \n");
EHPrint(" | \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
}
break;
}
case CPU::x64::PageFault:
{
EHPrint("Exception: Page Fault\n");
EHPrint("The processor attempted to access a page that is not present.\n");
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
#if defined(__amd64__)
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", CPU::x64::readcr2().PFLA, Frame->rip);
#elif defined(__i386__)
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", CPU::x64::readcr2().PFLA, Frame->eip);
#elif defined(__aarch64__)
#endif
EHPrint("Page: %s\eFAFAFA\n", params.P ? "\e058C19Present" : "\eE85230Not Present");
EHPrint("Write Operation: \e8888FF%s\eFAFAFA\n", params.W ? "Read-Only" : "Read-Write");
EHPrint("Processor Mode: \e8888FF%s\eFAFAFA\n", params.U ? "User-Mode" : "Kernel-Mode");
EHPrint("CPU Reserved Bits: %s\eFAFAFA\n", params.R ? "\eE85230Reserved" : "\e058C19Unreserved");
EHPrint("Caused By An Instruction Fetch: %s\eFAFAFA\n", params.I ? "\eE85230Yes" : "\e058C19No");
EHPrint("Caused By A Protection-Key Violation: %s\eFAFAFA\n", params.PK ? "\eE85230Yes" : "\e058C19No");
EHPrint("Caused By A Shadow Stack Access: %s\eFAFAFA\n", params.SS ? "\eE85230Yes" : "\e058C19No");
EHPrint("Caused By An SGX Violation: %s\eFAFAFA\n", params.SGX ? "\eE85230Yes" : "\e058C19No");
EHPrint("More Info: \e8888FF");
if (Frame->ErrorCode & 0x00000008)
EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n");
else
EHPrint(PagefaultDescriptions[Frame->ErrorCode & 0b111]);
EHPrint("\eFAFAFA");
break;
}
case CPU::x64::x87FloatingPoint:
{
EHPrint("Exception: x87 Floating Point\n");
EHPrint("The x87 FPU generated an error.\n");
break;
}
case CPU::x64::AlignmentCheck:
{
EHPrint("Exception: Alignment Check\n");
EHPrint("The CPU detected an unaligned memory access.\n");
break;
}
case CPU::x64::MachineCheck:
{
EHPrint("Exception: Machine Check\n");
EHPrint("The CPU detected a hardware error.\n");
break;
}
case CPU::x64::SIMDFloatingPoint:
{
EHPrint("Exception: SIMD Floating Point\n");
EHPrint("The CPU detected an error in the SIMD unit.\n");
break;
}
case CPU::x64::Virtualization:
{
EHPrint("Exception: Virtualization\n");
EHPrint("The CPU detected a virtualization error.\n");
break;
}
case CPU::x64::Security:
{
EHPrint("Exception: Security\n");
EHPrint("The CPU detected a security violation.\n");
break;
}
default:
{
EHPrint("Exception: Unknown\n");
EHPrint("The CPU generated an unknown exception.\n");
break;
}
}
#if defined(__amd64__)
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->rip);
#elif defined(__i386__)
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->eip);
#elif defined(__aarch64__)
#endif
}
}

View File

@ -0,0 +1,46 @@
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
#include <interrupts.hpp>
#include <display.hpp>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../../kernel.h"
namespace CrashHandler
{
SafeFunction void DisplayStackFrameScreen(CRData data)
{
EHPrint("\eFAFAFATracing 40 frames...\n");
TraceFrames(data.Frame, 40);
EHPrint("\n\n\eFAFAFATracing interrupt frames...\n");
for (uint64_t i = 0; i < 8; i++)
{
if (EHIntFrames[i])
{
if (!Memory::Virtual().Check(EHIntFrames[i]))
continue;
EHPrint("\n\e2565CC%p", EHIntFrames[i]);
EHPrint("\e7925CC-");
#if defined(__amd64__)
if ((uint64_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(__i386__)
if ((uint64_t)EHIntFrames[i] >= 0xC0000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(__aarch64__)
#endif
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uint64_t)EHIntFrames[i]));
else
EHPrint("\eFF4CA9Outside Kernel");
}
}
}
}

View File

@ -0,0 +1,70 @@
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
#include <display.hpp>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../../kernel.h"
namespace CrashHandler
{
SafeFunction void DisplayTasksScreen(CRData data)
{
const char *StatusColor[7] = {
"FF0000", // Unknown
"AAFF00", // Ready
"00AA00", // Running
"FFAA00", // Sleeping
"FFAA00", // Waiting
"FF0088", // Stopped
"FF0000", // Terminated
};
const char *StatusString[7] = {
"Unknown", // Unknown
"Ready", // Ready
"Running", // Running
"Sleeping", // Sleeping
"Waiting", // Waiting
"Stopped", // Stopped
"Terminated", // Terminated
};
Vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
if (TaskManager)
{
if (data.Thread)
#if defined(__amd64__)
EHPrint("\eFAFAFACrash occured in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip);
#elif defined(__i386__)
EHPrint("\eFAFAFACrash occured in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->eip);
#elif defined(__aarch64__)
#endif
EHPrint("\eFAFAFAProcess list (%ld):\n", Plist.size());
foreach (auto Process in Plist)
{
EHPrint("\e%s-> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA PT:\e00AAAA%#lx\n",
StatusColor[Process->Status], Process->Name, Process->ID, StatusString[Process->Status],
Process->PageTable);
foreach (auto Thread in Process->Threads)
EHPrint("\e%s -> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA Stack:\e00AAAA%#lx\n",
StatusColor[Thread->Status], Thread->Name, Thread->ID, StatusString[Thread->Status],
Thread->Stack);
}
}
else
EHPrint("\eFAFAFATaskManager is not initialized!\n");
}
}

View File

@ -0,0 +1,278 @@
#include "../crashhandler.hpp"
#include "chfcts.hpp"
#include <display.hpp>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../kernel.h"
static const char *PageFaultDescriptions[8] = {
"Supervisory process tried to read a non-present page entry\n",
"Supervisory process tried to read a page and caused a protection fault\n",
"Supervisory process tried to write to a non-present page entry\n",
"Supervisory process tried to write a page and caused a protection fault\n",
"User process tried to read a non-present page entry\n",
"User process tried to read a page and caused a protection fault\n",
"User process tried to write to a non-present page entry\n",
"User process tried to write a page and caused a protection fault\n"};
SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
{
CriticalSection cs;
debug("Interrupts? %s.", cs.IsInterruptsEnabled() ? "Yes" : "No");
fixme("Handling user mode exception");
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Stopped;
CPUData *CurCPU = GetCurrentCPU();
{
CPU::x64::CR0 cr0 = CPU::x64::readcr0();
CPU::x64::CR2 cr2 = CPU::x64::readcr2();
CPU::x64::CR3 cr3 = CPU::x64::readcr3();
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
CPU::x64::CR8 cr8 = CPU::x64::readcr8();
CPU::x64::EFER efer;
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
error("Technical Informations on CPU %lld:", CurCPU->ID);
#if defined(__amd64__)
uint64_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
#elif defined(__i386__)
uint32_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
#elif defined(__aarch64__)
#endif
error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx",
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
Frame->ss, Frame->cs, ds);
#if defined(__amd64__)
error("R8=%#llx R9=%#llx R10=%#llx R11=%#llx", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
error("R12=%#llx R13=%#llx R14=%#llx R15=%#llx", Frame->r12, Frame->r13, Frame->r14, Frame->r15);
error("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
#elif defined(__i386__)
error("EAX=%#llx EBX=%#llx ECX=%#llx EDX=%#llx", Frame->eax, Frame->ebx, Frame->ecx, Frame->edx);
error("ESI=%#llx EDI=%#llx EBP=%#llx ESP=%#llx", Frame->esi, Frame->edi, Frame->ebp, Frame->esp);
error("EIP=%#llx EFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
#elif defined(__aarch64__)
#endif
error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw);
error("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x",
cr0.PE ? "True " : "False", cr0.MP ? "True " : "False", cr0.EM ? "True " : "False", cr0.TS ? "True " : "False",
cr0.ET ? "True " : "False", cr0.NE ? "True " : "False", cr0.WP ? "True " : "False", cr0.AM ? "True " : "False",
cr0.NW ? "True " : "False", cr0.CD ? "True " : "False", cr0.PG ? "True " : "False",
cr0.Reserved0, cr0.Reserved1, cr0.Reserved2);
error("CR2: PFLA: %#llx",
cr2.PFLA);
error("CR3: PWT:%s PCD:%s PDBR:%#llx",
cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR);
error("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x R2:%#x",
cr4.VME ? "True " : "False", cr4.PVI ? "True " : "False", cr4.TSD ? "True " : "False", cr4.DE ? "True " : "False",
cr4.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False",
cr4.PCE ? "True " : "False", cr4.UMIP ? "True " : "False", cr4.OSFXSR ? "True " : "False", cr4.OSXMMEXCPT ? "True " : "False",
cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False",
cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False",
cr4.Reserved0, cr4.Reserved1, cr4.Reserved2);
error("CR8: TPL:%d", cr8.TPL);
#if defined(__amd64__)
error("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x R3:%#x",
Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False",
Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False",
Frame->rflags.OF ? "True " : "False", Frame->rflags.IOPL ? "True " : "False", Frame->rflags.NT ? "True " : "False", Frame->rflags.RF ? "True " : "False",
Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False",
Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne,
Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3);
#elif defined(__i386__)
error("EFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x",
Frame->eflags.CF ? "True " : "False", Frame->eflags.PF ? "True " : "False", Frame->eflags.AF ? "True " : "False", Frame->eflags.ZF ? "True " : "False",
Frame->eflags.SF ? "True " : "False", Frame->eflags.TF ? "True " : "False", Frame->eflags.IF ? "True " : "False", Frame->eflags.DF ? "True " : "False",
Frame->eflags.OF ? "True " : "False", Frame->eflags.IOPL ? "True " : "False", Frame->eflags.NT ? "True " : "False", Frame->eflags.RF ? "True " : "False",
Frame->eflags.VM ? "True " : "False", Frame->eflags.AC ? "True " : "False", Frame->eflags.VIF ? "True " : "False", Frame->eflags.VIP ? "True " : "False",
Frame->eflags.ID ? "True " : "False", Frame->eflags.AlwaysOne,
Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2);
#elif defined(__aarch64__)
#endif
error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x",
efer.SCE ? "True " : "False", efer.LME ? "True " : "False", efer.LMA ? "True " : "False", efer.NXE ? "True " : "False",
efer.SVME ? "True " : "False", efer.LMSLE ? "True " : "False", efer.FFXSR ? "True " : "False", efer.TCE ? "True " : "False",
efer.Reserved0, efer.Reserved1, efer.Reserved2);
}
switch (Frame->InterruptNumber)
{
case CPU::x64::DivideByZero:
{
break;
}
case CPU::x64::Debug:
{
break;
}
case CPU::x64::NonMaskableInterrupt:
{
break;
}
case CPU::x64::Breakpoint:
{
break;
}
case CPU::x64::Overflow:
{
break;
}
case CPU::x64::BoundRange:
{
break;
}
case CPU::x64::InvalidOpcode:
{
break;
}
case CPU::x64::DeviceNotAvailable:
{
break;
}
case CPU::x64::DoubleFault:
{
break;
}
case CPU::x64::CoprocessorSegmentOverrun:
{
break;
}
case CPU::x64::InvalidTSS:
{
break;
}
case CPU::x64::SegmentNotPresent:
{
break;
}
case CPU::x64::StackSegmentFault:
{
break;
}
case CPU::x64::GeneralProtectionFault:
{
break;
}
case CPU::x64::PageFault:
{
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
#if defined(__amd64__)
error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->rip);
#elif defined(__i386__)
error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->eip);
#elif defined(__aarch64__)
#endif
error("Page: %s", params.P ? "Present" : "Not Present");
error("Write Operation: %s", params.W ? "Read-Only" : "Read-Write");
error("Processor Mode: %s", params.U ? "User-Mode" : "Kernel-Mode");
error("CPU Reserved Bits: %s", params.R ? "Reserved" : "Unreserved");
error("Caused By An Instruction Fetch: %s", params.I ? "Yes" : "No");
error("Caused By A Protection-Key Violation: %s", params.PK ? "Yes" : "No");
error("Caused By A Shadow Stack Access: %s", params.SS ? "Yes" : "No");
error("Caused By An SGX Violation: %s", params.SGX ? "Yes" : "No");
if (Frame->ErrorCode & 0x00000008)
error("One or more page directory entries contain reserved bits which are set to 1.");
else
error(PageFaultDescriptions[Frame->ErrorCode & 0b111]);
#ifdef DEBUG
if (CurCPU)
{
Memory::Virtual vma = Memory::Virtual(CurCPU->CurrentProcess->PageTable);
bool PageAvailable = vma.Check((void *)CPU::x64::readcr2().PFLA);
debug("Page available (Check(...)): %s. %s",
PageAvailable ? "Yes" : "No",
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
if (PageAvailable)
{
bool Present = vma.Check((void *)CPU::x64::readcr2().PFLA);
bool ReadWrite = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::RW);
bool User = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::US);
bool WriteThrough = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PWT);
bool CacheDisabled = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PCD);
bool Accessed = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::A);
bool Dirty = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::D);
bool Global = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::G);
/* ... */
debug("Page available: %s", Present ? "Yes" : "No");
debug("Page read/write: %s", ReadWrite ? "Yes" : "No");
debug("Page user/kernel: %s", User ? "User" : "Kernel");
debug("Page write-through: %s", WriteThrough ? "Yes" : "No");
debug("Page cache disabled: %s", CacheDisabled ? "Yes" : "No");
debug("Page accessed: %s", Accessed ? "Yes" : "No");
debug("Page dirty: %s", Dirty ? "Yes" : "No");
debug("Page global: %s", Global ? "Yes" : "No");
}
}
#endif
if (CurCPU)
if (CurCPU->CurrentThread->Stack->Expand(CPU::x64::readcr2().raw))
{
debug("Stack expanded");
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready;
return;
}
break;
}
case CPU::x64::x87FloatingPoint:
{
break;
}
case CPU::x64::AlignmentCheck:
{
break;
}
case CPU::x64::MachineCheck:
{
break;
}
case CPU::x64::SIMDFloatingPoint:
{
break;
}
case CPU::x64::Virtualization:
{
break;
}
case CPU::x64::Security:
{
break;
}
default:
{
break;
}
}
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated;
__sync_synchronize();
error("End of report.");
CPU::Interrupts(CPU::Enable);
debug("Interrupts enabled back.");
return;
}

View File

@ -0,0 +1,296 @@
#ifndef __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__
#define __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__
#include <types.h>
#include <interrupts.hpp>
#include <task.hpp>
#include <cpu.hpp>
#if defined(__amd64__)
typedef struct CPU::x64::TrapFrame CHArchTrapFrame;
struct CRData
{
CHArchTrapFrame *Frame;
CPU::x64::CR0 cr0;
CPU::x64::CR2 cr2;
CPU::x64::CR3 cr3;
CPU::x64::CR4 cr4;
CPU::x64::CR8 cr8;
CPU::x64::EFER efer;
uint64_t dr0, dr1, dr2, dr3, dr6;
CPU::x64::DR7 dr7;
long ID;
void *CPUData;
Tasking::PCB *Process;
Tasking::TCB *Thread;
};
#elif defined(__i386__)
typedef struct CPU::x32::TrapFrame CHArchTrapFrame;
struct CRData
{
CHArchTrapFrame *Frame;
CPU::x32::CR0 cr0;
CPU::x32::CR2 cr2;
CPU::x32::CR3 cr3;
CPU::x32::CR4 cr4;
CPU::x32::CR8 cr8;
CPU::x32::EFER efer;
uint64_t dr0, dr1, dr2, dr3, dr6;
CPU::x32::DR7 dr7;
long ID;
Tasking::PCB *Process;
Tasking::TCB *Thread;
};
#elif defined(__aarch64__)
typedef struct CPU::aarch64::TrapFrame CHArchTrapFrame;
#endif
enum Keys
{
KEY_INVALID = 0x0,
KEY_D_ESCAPE = 0x1,
KEY_D_1 = 0x2,
KEY_D_2 = 0x3,
KEY_D_3 = 0x4,
KEY_D_4 = 0x5,
KEY_D_5 = 0x6,
KEY_D_6 = 0x7,
KEY_D_7 = 0x8,
KEY_D_8 = 0x9,
KEY_D_9 = 0xa,
KEY_D_0 = 0xb,
KEY_D_MINUS = 0xc,
KEY_D_EQUALS = 0xd,
KEY_D_BACKSPACE = 0xe,
KEY_D_TAB = 0xf,
KEY_D_Q = 0x10,
KEY_D_W = 0x11,
KEY_D_E = 0x12,
KEY_D_R = 0x13,
KEY_D_T = 0x14,
KEY_D_Y = 0x15,
KEY_D_U = 0x16,
KEY_D_I = 0x17,
KEY_D_O = 0x18,
KEY_D_P = 0x19,
KEY_D_LBRACKET = 0x1a,
KEY_D_RBRACKET = 0x1b,
KEY_D_RETURN = 0x1c,
KEY_D_LCTRL = 0x1d,
KEY_D_A = 0x1e,
KEY_D_S = 0x1f,
KEY_D_D = 0x20,
KEY_D_F = 0x21,
KEY_D_G = 0x22,
KEY_D_H = 0x23,
KEY_D_J = 0x24,
KEY_D_K = 0x25,
KEY_D_L = 0x26,
KEY_D_SEMICOLON = 0x27,
KEY_D_APOSTROPHE = 0x28,
KEY_D_GRAVE = 0x29,
KEY_D_LSHIFT = 0x2a,
KEY_D_BACKSLASH = 0x2b,
KEY_D_Z = 0x2c,
KEY_D_X = 0x2d,
KEY_D_C = 0x2e,
KEY_D_V = 0x2f,
KEY_D_B = 0x30,
KEY_D_N = 0x31,
KEY_D_M = 0x32,
KEY_D_COMMA = 0x33,
KEY_D_PERIOD = 0x34,
KEY_D_SLASH = 0x35,
KEY_D_RSHIFT = 0x36,
KEY_D_PRTSC = 0x37,
KEY_D_LALT = 0x38,
KEY_D_SPACE = 0x39,
KEY_D_CAPSLOCK = 0x3a,
KEY_D_NUMLOCK = 0x45,
KEY_D_SCROLLLOCK = 0x46,
KEY_D_KP_MULTIPLY = 0x37,
KEY_D_KP_7 = 0x47,
KEY_D_KP_8 = 0x48,
KEY_D_KP_9 = 0x49,
KEY_D_KP_MINUS = 0x4a,
KEY_D_KP_4 = 0x4b,
KEY_D_KP_5 = 0x4c,
KEY_D_KP_6 = 0x4d,
KEY_D_KP_PLUS = 0x4e,
KEY_D_KP_1 = 0x4f,
KEY_D_KP_2 = 0x50,
KEY_D_KP_3 = 0x51,
KEY_D_KP_0 = 0x52,
KEY_D_KP_PERIOD = 0x53,
KEY_D_F1 = 0x3b,
KEY_D_F2 = 0x3c,
KEY_D_F3 = 0x3d,
KEY_D_F4 = 0x3e,
KEY_D_F5 = 0x3f,
KEY_D_F6 = 0x40,
KEY_D_F7 = 0x41,
KEY_D_F8 = 0x42,
KEY_D_F9 = 0x43,
KEY_D_F10 = 0x44,
KEY_D_F11 = 0x57,
KEY_D_F12 = 0x58,
KEY_D_UP = 0x48,
KEY_D_LEFT = 0x4b,
KEY_D_RIGHT = 0x4d,
KEY_D_DOWN = 0x50,
KEY_U_ESCAPE = 0x81,
KEY_U_1 = 0x82,
KEY_U_2 = 0x83,
KEY_U_3 = 0x84,
KEY_U_4 = 0x85,
KEY_U_5 = 0x86,
KEY_U_6 = 0x87,
KEY_U_7 = 0x88,
KEY_U_8 = 0x89,
KEY_U_9 = 0x8a,
KEY_U_0 = 0x8b,
KEY_U_MINUS = 0x8c,
KEY_U_EQUALS = 0x8d,
KEY_U_BACKSPACE = 0x8e,
KEY_U_TAB = 0x8f,
KEY_U_Q = 0x90,
KEY_U_W = 0x91,
KEY_U_E = 0x92,
KEY_U_R = 0x93,
KEY_U_T = 0x94,
KEY_U_Y = 0x95,
KEY_U_U = 0x96,
KEY_U_I = 0x97,
KEY_U_O = 0x98,
KEY_U_P = 0x99,
KEY_U_LBRACKET = 0x9a,
KEY_U_RBRACKET = 0x9b,
KEY_U_RETURN = 0x9c,
KEY_U_LCTRL = 0x9d,
KEY_U_A = 0x9e,
KEY_U_S = 0x9f,
KEY_U_D = 0xa0,
KEY_U_F = 0xa1,
KEY_U_G = 0xa2,
KEY_U_H = 0xa3,
KEY_U_J = 0xa4,
KEY_U_K = 0xa5,
KEY_U_L = 0xa6,
KEY_U_SEMICOLON = 0xa7,
KEY_U_APOSTROPHE = 0xa8,
KEY_U_GRAVE = 0xa9,
KEY_U_LSHIFT = 0xaa,
KEY_U_BACKSLASH = 0xab,
KEY_U_Z = 0xac,
KEY_U_X = 0xad,
KEY_U_C = 0xae,
KEY_U_V = 0xaf,
KEY_U_B = 0xb0,
KEY_U_N = 0xb1,
KEY_U_M = 0xb2,
KEY_U_COMMA = 0xb3,
KEY_U_PERIOD = 0xb4,
KEY_U_SLASH = 0xb5,
KEY_U_RSHIFT = 0xb6,
KEY_U_KP_MULTIPLY = 0xb7,
KEY_U_LALT = 0xb8,
KEY_U_SPACE = 0xb9,
KEY_U_CAPSLOCK = 0xba,
KEY_U_F1 = 0xbb,
KEY_U_F2 = 0xbc,
KEY_U_F3 = 0xbd,
KEY_U_F4 = 0xbe,
KEY_U_F5 = 0xbf,
KEY_U_F6 = 0xc0,
KEY_U_F7 = 0xc1,
KEY_U_F8 = 0xc2,
KEY_U_F9 = 0xc3,
KEY_U_F10 = 0xc4,
KEY_U_NUMLOCK = 0xc5,
KEY_U_SCROLLLOCK = 0xc6,
KEY_U_KP_7 = 0xc7,
KEY_U_KP_8 = 0xc8,
KEY_U_KP_9 = 0xc9,
KEY_U_KP_MINUS = 0xca,
KEY_U_KP_4 = 0xcb,
KEY_U_KP_5 = 0xcc,
KEY_U_KP_6 = 0xcd,
KEY_U_KP_PLUS = 0xce,
KEY_U_KP_1 = 0xcf,
KEY_U_KP_2 = 0xd0,
KEY_U_KP_3 = 0xd1,
KEY_U_KP_0 = 0xd2,
KEY_U_KP_PERIOD = 0xd3,
KEY_U_F11 = 0xd7,
KEY_U_F12 = 0xd8,
};
namespace CrashHandler
{
extern int SBIdx;
class CrashKeyboardDriver : public Interrupts::Handler
{
private:
#if defined(__amd64__)
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
#elif defined(__i386__)
void OnInterruptReceived(void *Frame);
#elif defined(__aarch64__)
void OnInterruptReceived(void *Frame);
#endif
public:
CrashKeyboardDriver();
~CrashKeyboardDriver();
};
void TraceFrames(CHArchTrapFrame *Frame, int Count);
void ArrowInput(uint8_t key);
void UserInput(char *Input);
void HookKeyboard();
void DisplayMainScreen(CRData data);
void DisplayDetailsScreen(CRData data);
void DisplayStackFrameScreen(CRData data);
void DisplayTasksScreen(CRData data);
void DisplayConsoleScreen(CRData data);
}
void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame);
void DebugExceptionHandler(CHArchTrapFrame *Frame);
void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame);
void BreakpointExceptionHandler(CHArchTrapFrame *Frame);
void OverflowExceptionHandler(CHArchTrapFrame *Frame);
void BoundRangeExceptionHandler(CHArchTrapFrame *Frame);
void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame);
void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame);
void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame);
void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame);
void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame);
void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame);
void StackFaultExceptionHandler(CHArchTrapFrame *Frame);
void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame);
void PageFaultExceptionHandler(CHArchTrapFrame *Frame);
void x87FloatingPointExceptionHandler(CHArchTrapFrame *Frame);
void AlignmentCheckExceptionHandler(CHArchTrapFrame *Frame);
void MachineCheckExceptionHandler(CHArchTrapFrame *Frame);
void SIMDFloatingPointExceptionHandler(CHArchTrapFrame *Frame);
void VirtualizationExceptionHandler(CHArchTrapFrame *Frame);
void SecurityExceptionHandler(CHArchTrapFrame *Frame);
void UnknownExceptionHandler(CHArchTrapFrame *Frame);
void UserModeExceptionHandler(CHArchTrapFrame *Frame);
#endif // !__FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__

95
Kernel/Core/Debugger.cpp Normal file
View File

@ -0,0 +1,95 @@
#include <debug.h>
#include <uart.hpp>
#include <printf.h>
#include <lock.hpp>
NewLock(DebuggerLock);
using namespace UniversalAsynchronousReceiverTransmitter;
static inline __no_instrument_function void uart_wrapper(char c, void *unused)
{
UART(COM1).Write(c);
(void)unused;
}
static inline __no_instrument_function void WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function)
{
const char *DbgLvlString;
switch (Level)
{
case DebugLevelError:
DbgLvlString = "ERROR";
break;
case DebugLevelWarning:
DbgLvlString = "WARN ";
break;
case DebugLevelInfo:
DbgLvlString = "INFO ";
break;
case DebugLevelDebug:
DbgLvlString = "DEBUG";
break;
case DebugLevelTrace:
DbgLvlString = "TRACE";
break;
case DebugLevelFixme:
DbgLvlString = "FIXME";
break;
case DebugLevelUbsan:
{
DbgLvlString = "UBSAN";
fctprintf(uart_wrapper, nullptr, "%s|%s: ", DbgLvlString, Function);
return;
}
default:
DbgLvlString = "UNKNW";
break;
}
fctprintf(uart_wrapper, nullptr, "%s|%s->%s:%d: ", DbgLvlString, File, Function, Line);
}
namespace SysDbg
{
__no_instrument_function void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
WritePrefix(Level, File, Line, Function);
va_list args;
va_start(args, Format);
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
}
__no_instrument_function void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
// SmartLock(DebuggerLock);
WritePrefix(Level, File, Line, Function);
va_list args;
va_start(args, Format);
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
}
}
// C compatibility
extern "C" __no_instrument_function void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
WritePrefix(Level, File, Line, Function);
va_list args;
va_start(args, Format);
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
}
// C compatibility
extern "C" __no_instrument_function void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
WritePrefix(Level, File, Line, Function);
va_list args;
va_start(args, Format);
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
}

157
Kernel/Core/Disk.cpp Normal file
View File

@ -0,0 +1,157 @@
#include <disk.hpp>
#include <memory.hpp>
#include <printf.h>
#include "../kernel.h"
#include "../DAPI.hpp"
#include "../Fex.hpp"
namespace Disk
{
void Manager::FetchDisks(unsigned long DriverUID)
{
KernelCallback *callback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
memset(callback, 0, sizeof(KernelCallback));
callback->Reason = FetchReason;
DriverManager->IOCB(DriverUID, (void *)callback);
this->AvailablePorts = callback->DiskCallback.Fetch.Ports;
this->BytesPerSector = callback->DiskCallback.Fetch.BytesPerSector;
debug("AvailablePorts:%ld BytesPerSector:%ld", this->AvailablePorts, this->BytesPerSector);
if (this->AvailablePorts <= 0)
{
KernelAllocator.FreePages((void *)callback, TO_PAGES(sizeof(KernelCallback)));
return;
}
uint8_t *RWBuffer = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(this->BytesPerSector));
for (unsigned char ItrPort = 0; ItrPort < this->AvailablePorts; ItrPort++)
{
Drive *drive = new Drive;
sprintf_(drive->Name, "sd%ld-%d", DriverUID, this->AvailablePorts);
debug("Drive Name: %s", drive->Name);
// TODO: Implement disk type detection. Very useful in the future.
drive->MechanicalDisk = true;
memset(RWBuffer, 0, this->BytesPerSector);
memset(callback, 0, sizeof(KernelCallback));
callback->Reason = ReceiveReason;
callback->DiskCallback.RW = {
.Sector = 0,
.SectorCount = 2,
.Port = ItrPort,
.Buffer = RWBuffer,
.Write = false,
};
DriverManager->IOCB(DriverUID, (void *)callback);
memcpy(&drive->Table, RWBuffer, sizeof(PartitionTable));
/*
----> Add to devfs the disk
*/
if (drive->Table.GPT.Signature == GPT_MAGIC)
{
drive->Style = GPT;
uint32_t Entries = 512 / drive->Table.GPT.EntrySize;
uint32_t Sectors = drive->Table.GPT.PartCount / Entries;
for (uint32_t Block = 0; Block < Sectors; Block++)
{
memset(RWBuffer, 0, this->BytesPerSector);
memset(callback, 0, sizeof(KernelCallback));
callback->Reason = ReceiveReason;
callback->DiskCallback.RW = {
.Sector = 2 + Block,
.SectorCount = 1,
.Port = ItrPort,
.Buffer = RWBuffer,
.Write = false,
};
DriverManager->IOCB(DriverUID, (void *)callback);
for (uint32_t e = 0; e < Entries; e++)
{
GUIDPartitionTablePartition GPTPartition = reinterpret_cast<GUIDPartitionTablePartition *>(RWBuffer)[e];
if (GPTPartition.TypeLow || GPTPartition.TypeHigh)
{
Partition *partition = new Partition;
memcpy(partition->Label, GPTPartition.Label, sizeof(partition->Label));
partition->StartLBA = GPTPartition.StartLBA;
partition->EndLBA = GPTPartition.EndLBA;
partition->Sectors = partition->EndLBA - partition->StartLBA;
partition->Port = ItrPort;
partition->Flags = Present;
partition->Style = GPT;
if (GPTPartition.Attributes & 1)
partition->Flags |= EFISystemPartition;
partition->Index = drive->Partitions.size();
// why there is NUL (\0) between every char?????
char PartName[72];
memcpy(PartName, GPTPartition.Label, 72);
for (int i = 0; i < 72; i++)
if (PartName[i] == '\0')
PartName[i] = ' ';
PartName[71] = '\0';
trace("GPT partition \"%s\" found with %lld sectors", PartName, partition->Sectors);
drive->Partitions.push_back(partition);
char *PartitionName = new char[64];
sprintf_(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
/*
----> Add to devfs the disk
*/
delete[] PartitionName;
}
}
}
trace("%d GPT partitions found.", drive->Partitions.size());
}
else if (drive->Table.MBR.Signature[0] == MBR_MAGIC0 && drive->Table.MBR.Signature[1] == MBR_MAGIC1)
{
drive->Style = MBR;
for (size_t p = 0; p < 4; p++)
if (drive->Table.MBR.Partitions[p].LBAFirst != 0)
{
Partition *partition = new Partition;
partition->StartLBA = drive->Table.MBR.Partitions[p].LBAFirst;
partition->EndLBA = drive->Table.MBR.Partitions[p].LBAFirst + drive->Table.MBR.Partitions[p].Sectors;
partition->Sectors = drive->Table.MBR.Partitions[p].Sectors;
partition->Port = ItrPort;
partition->Flags = Present;
partition->Style = MBR;
partition->Index = drive->Partitions.size();
trace("Partition \"%#llx\" found with %lld sectors.", drive->Table.MBR.UniqueID, partition->Sectors);
drive->Partitions.push_back(partition);
char *PartitionName = new char[64];
sprintf_(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
/*
----> Add to devfs the disk
*/
delete[] PartitionName;
}
trace("%d MBR partitions found.", drive->Partitions.size());
}
else
warn("No partition table found on port %d!", ItrPort);
drives.push_back(drive);
}
KernelAllocator.FreePages((void *)callback, TO_PAGES(sizeof(KernelCallback)));
}
Manager::Manager()
{
}
Manager::~Manager()
{
}
}

View File

@ -0,0 +1,472 @@
#include <driver.hpp>
#include <interrupts.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../kernel.h"
#include "../../DAPI.hpp"
#include "../../Fex.hpp"
#include "api.hpp"
NewLock(DriverInitLock);
NewLock(DriverInterruptLock);
namespace Driver
{
const char *DriverTypesName[] = {
"Unknown",
"Generic",
"Display",
"Network",
"Storage",
"FileSystem",
"Input",
"Audio"};
int Driver::IOCB(unsigned long DUID, void *KCB)
{
foreach (auto var in Drivers)
if (var->DriverUID == DUID)
{
FexExtended *DrvExtHdr = (FexExtended *)((uint64_t)var->Address + EXTENDED_SECTION_ADDRESS);
return ((int (*)(void *))((uint64_t)DrvExtHdr->Driver.Callback + (uint64_t)var->Address))(KCB);
}
return -1;
}
DriverCode Driver::CallDriverEntryPoint(void *fex)
{
KernelAPI *API = (KernelAPI *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelAPI)));
memcpy(API, &KAPI, sizeof(KernelAPI));
API->Info.Offset = (unsigned long)fex;
API->Info.DriverUID = DriverUIDs++;
int ret = ((int (*)(KernelAPI *))((uint64_t)((Fex *)fex)->Pointer + (uint64_t)fex))(API);
if (DriverReturnCode::OK != ret)
return DriverCode::DRIVER_RETURNED_ERROR;
return DriverCode::OK;
}
DriverCode Driver::LoadDriver(uint64_t DriverAddress, uint64_t Size)
{
Fex *DrvHdr = (Fex *)DriverAddress;
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
return DriverCode::INVALID_FEX_HEADER;
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; Pointer: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->Pointer);
if (DrvHdr->Type == FexFormatType::FexFormatType_Driver)
{
FexExtended *DrvExtHdr = (FexExtended *)((uint64_t)DrvHdr + EXTENDED_SECTION_ADDRESS);
debug("Name: \"%s\"; Type: %d; Callback: %#lx", DrvExtHdr->Driver.Name, DrvExtHdr->Driver.Type, DrvExtHdr->Driver.Callback);
if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
{
for (unsigned long Vidx = 0; Vidx < sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) / sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID[0]); Vidx++)
for (unsigned long Didx = 0; Didx < sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID) / sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID[0]); Didx++)
{
if (Vidx >= sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) && Didx >= sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID))
break;
if (DrvExtHdr->Driver.Bind.PCI.VendorID[Vidx] == 0 || DrvExtHdr->Driver.Bind.PCI.DeviceID[Didx] == 0)
continue;
Vector<PCI::PCIDeviceHeader *> devices = PCIManager->FindPCIDevice(DrvExtHdr->Driver.Bind.PCI.VendorID[Vidx], DrvExtHdr->Driver.Bind.PCI.DeviceID[Didx]);
if (devices.size() == 0)
continue;
foreach (auto PCIDevice in devices)
{
debug("[%ld] VendorID: %#x; DeviceID: %#x", devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
Fex *fex = (Fex *)KernelAllocator.RequestPages(TO_PAGES(Size));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uint64_t)fex + EXTENDED_SECTION_ADDRESS);
#ifdef DEBUG
uint8_t *result = md5File((uint8_t *)fex, Size);
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
kfree(result);
#endif
if (CallDriverEntryPoint(fex) != DriverCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s", fexExtended->Driver.Name);
KernelCallback *KCallback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Generic:
{
fixme("Generic driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Display:
{
fixme("Display driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Network:
{
DriverInterruptHook *InterruptHook = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)devices[0])->InterruptLine) + 32, // x86
(void *)((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex),
KCallback);
KCallback->RawPtr = PCIDevice;
KCallback->Reason = CallbackReason::ConfigurationReason;
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
delete InterruptHook;
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
continue;
}
else if (callbackret == DriverReturnCode::OK)
trace("Device found for driver: %s", fexExtended->Driver.Name);
else
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
delete InterruptHook;
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
continue;
}
memset(KCallback, 0, sizeof(KernelCallback));
KCallback->Reason = CallbackReason::InterruptReason;
DriverFile *drvfile = new DriverFile;
drvfile->DriverUID = KAPI.Info.DriverUID;
drvfile->Address = (void *)fex;
drvfile->InterruptHook[0] = InterruptHook;
Drivers.push_back(drvfile);
break;
}
case FexDriverType::FexDriverType_Storage:
{
KCallback->RawPtr = PCIDevice;
KCallback->Reason = CallbackReason::ConfigurationReason;
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
continue;
}
else if (callbackret == DriverReturnCode::OK)
trace("Device found for driver: %s", fexExtended->Driver.Name);
else
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
continue;
}
DriverFile *drvfile = new DriverFile;
drvfile->DriverUID = KAPI.Info.DriverUID;
drvfile->Address = (void *)fex;
drvfile->InterruptHook[0] = nullptr;
Drivers.push_back(drvfile);
break;
}
case FexDriverType::FexDriverType_FileSystem:
{
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Input:
{
fixme("Input driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Audio:
{
fixme("Audio driver: %s", fexExtended->Driver.Name);
break;
}
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
break;
}
}
}
}
}
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
{
Fex *fex = (Fex *)KernelAllocator.RequestPages(TO_PAGES(Size));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uint64_t)fex + EXTENDED_SECTION_ADDRESS);
#ifdef DEBUG
uint8_t *result = md5File((uint8_t *)fex, Size);
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
kfree(result);
#endif
if (CallDriverEntryPoint(fex) != DriverCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
KernelCallback *KCallback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Generic:
{
fixme("Generic driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Display:
{
fixme("Display driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Network:
{
fixme("Network driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Storage:
{
for (unsigned long i = 0; i < sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector) / sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector[0]); i++)
{
if (DrvExtHdr->Driver.Bind.Interrupt.Vector[i] == 0)
break;
fixme("TODO: MULTIPLE BIND INTERRUPT VECTORS %d", DrvExtHdr->Driver.Bind.Interrupt.Vector[i]);
}
fixme("Not implemented");
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
break;
KCallback->RawPtr = nullptr;
KCallback->Reason = CallbackReason::ConfigurationReason;
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
break;
}
else if (callbackret != DriverReturnCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
break;
}
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
// DriverFile *drvfile = new DriverFile;
// Drivers.push_back(drvfile);
break;
}
case FexDriverType::FexDriverType_FileSystem:
{
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Input:
{
DriverInterruptHook *InterruptHook = nullptr;
if (DrvExtHdr->Driver.Bind.Interrupt.Vector[0] != 0)
InterruptHook = new DriverInterruptHook(DrvExtHdr->Driver.Bind.Interrupt.Vector[0] + 32, // x86
(void *)((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex),
KCallback);
for (unsigned long i = 0; i < sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector) / sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector[0]); i++)
{
if (DrvExtHdr->Driver.Bind.Interrupt.Vector[i] == 0)
break;
// InterruptHook = new DriverInterruptHook(DrvExtHdr->Driver.Bind.Interrupt.Vector[i] + 32, // x86
// (void *)((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex),
// KCallback);
fixme("TODO: MULTIPLE BIND INTERRUPT VECTORS %d", DrvExtHdr->Driver.Bind.Interrupt.Vector[i]);
}
KCallback->RawPtr = nullptr;
KCallback->Reason = CallbackReason::ConfigurationReason;
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
break;
}
else if (callbackret != DriverReturnCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
break;
}
memset(KCallback, 0, sizeof(KernelCallback));
KCallback->Reason = CallbackReason::InterruptReason;
DriverFile *drvfile = new DriverFile;
drvfile->DriverUID = KAPI.Info.DriverUID;
drvfile->Address = (void *)fex;
drvfile->InterruptHook[0] = InterruptHook;
Drivers.push_back(drvfile);
break;
}
case FexDriverType::FexDriverType_Audio:
{
fixme("Audio driver: %s", fexExtended->Driver.Name);
break;
}
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
break;
}
}
}
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
{
fixme("Process driver: %s", DrvExtHdr->Driver.Name);
}
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
{
Fex *fex = (Fex *)KernelAllocator.RequestPages(TO_PAGES(Size));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uint64_t)fex + EXTENDED_SECTION_ADDRESS);
#ifdef DEBUG
uint8_t *result = md5File((uint8_t *)fex, Size);
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
kfree(result);
#endif
if (CallDriverEntryPoint(fex) != DriverCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
KernelCallback *KCallback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Input:
{
fixme("Input driver: %s", fexExtended->Driver.Name);
KCallback->RawPtr = nullptr;
break;
KCallback->Reason = CallbackReason::ConfigurationReason;
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
break;
}
else if (callbackret != DriverReturnCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
break;
}
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
DriverFile *drvfile = new DriverFile;
drvfile->DriverUID = KAPI.Info.DriverUID;
drvfile->Address = (void *)fex;
drvfile->InterruptHook[0] = nullptr;
Drivers.push_back(drvfile);
break;
}
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
break;
}
}
}
else
{
error("Unknown driver bind type: %d", DrvExtHdr->Driver.Bind.Type);
}
}
else
return DriverCode::NOT_DRIVER;
return DriverCode::OK;
}
Driver::Driver()
{
SmartCriticalSection(DriverInitLock);
FileSystem::FILE *DriverDirectory = vfs->Open(Config.DriverDirectory);
if (DriverDirectory->Status == FileSystem::FileStatus::OK)
foreach (auto driver in DriverDirectory->Node->Children)
if (driver->Flags == FileSystem::NodeFlags::FS_FILE)
if (cwk_path_has_extension(driver->Name))
{
const char *extension;
cwk_path_get_extension(driver->Name, &extension, nullptr);
if (!strcmp(extension, ".fex"))
{
uint64_t ret = this->LoadDriver(driver->Address, driver->Length);
char retstring[128];
if (ret == DriverCode::OK)
strncpy(retstring, "\e058C19OK", 64);
else
sprintf_(retstring, "\eE85230FAILED (%#lx)", ret);
KPrint("%s %s", driver->Name, retstring);
}
}
vfs->Close(DriverDirectory);
}
Driver::~Driver()
{
}
#if defined(__amd64__)
void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
#elif defined(__i386__)
void DriverInterruptHook::OnInterruptReceived(void *Frame)
#elif defined(__aarch64__)
void DriverInterruptHook::OnInterruptReceived(void *Frame)
#endif
{
SmartCriticalSection(DriverInterruptLock);
((int (*)(void *))(Handle))(Data);
}
DriverInterruptHook::DriverInterruptHook(int Interrupt, void *Address, void *ParamData) : Interrupts::Handler(Interrupt)
{
trace("Interrupt %d Hooked", Interrupt - 32); // x86
Handle = Address;
Data = ParamData;
}
}

View File

@ -0,0 +1,131 @@
#include <driver.hpp>
#include <dumper.hpp>
#include <lock.hpp>
#include "../../kernel.h"
#include "../../Fex.hpp"
#include "api.hpp"
NewLock(DriverDisplayPrintLock);
void DriverDebugPrint(char *String, unsigned long DriverUID)
{
SmartLock(DriverDisplayPrintLock);
trace("[%ld] %s", DriverUID, String);
}
void DriverDisplayPrint(char *String)
{
SmartLock(DriverDisplayPrintLock);
for (unsigned long i = 0; i < strlen(String); i++)
Display->Print(String[i], 0, true);
}
void *RequestPage(unsigned long Size)
{
SmartLock(DriverDisplayPrintLock);
// debug("Requesting %ld pages from the kernel...", Size);
void *ret = KernelAllocator.RequestPages(Size);
// debug("Got %#lx", ret);
return ret;
}
void FreePage(void *Page, unsigned long Size)
{
SmartLock(DriverDisplayPrintLock);
debug("Freeing %ld pages from the address %#lx...", Size, (unsigned long)Page);
KernelAllocator.FreePages(Page, Size);
}
void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags)
{
SmartLock(DriverDisplayPrintLock);
debug("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags);
Memory::Virtual().Map(VirtualAddress, PhysicalAddress, Flags);
}
void UnmapMemory(void *VirtualAddress)
{
SmartLock(DriverDisplayPrintLock);
debug("Unmapping %#lx...", (unsigned long)VirtualAddress);
Memory::Virtual().Unmap(VirtualAddress);
}
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size)
{
SmartLock(DriverDisplayPrintLock);
// debug("Copying %ld bytes from %#lx to %#lx...", Size, (unsigned long)Source, (unsigned long)Destination);
return memcpy(Destination, Source, Size);
}
void *Drivermemset(void *Destination, int Value, unsigned long Size)
{
SmartLock(DriverDisplayPrintLock);
// debug("Setting %ld bytes from %#lx to %#x...", Size, (unsigned long)Destination, Value);
return memset(Destination, Value, Size);
}
void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{
DumpData("DriverNetSend", Data, Size);
}
void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{
DumpData("DriverNetReceive", Data, Size);
}
void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
{
DumpData("DriverDiskRead", Data, SectorCount * 512);
}
void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
{
DumpData("DriverDiskWrite", Data, SectorCount * 512);
}
char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID)
{
return (char *)"Unknown";
}
KernelAPI KAPI = {
.Version = {
.Major = 0,
.Minor = 0,
.Patch = 1},
.Info = {
.Offset = 0,
.DriverUID = 0,
},
.Memory = {
.PageSize = PAGE_SIZE,
.RequestPage = RequestPage,
.FreePage = FreePage,
.Map = MapMemory,
.Unmap = UnmapMemory,
},
.PCI = {
.GetDeviceName = DriverPCIGetDeviceName,
},
.Util = {
.DebugPrint = DriverDebugPrint,
.DisplayPrint = DriverDisplayPrint,
.memcpy = Drivermemcpy,
.memset = Drivermemset,
},
.Command = {
.Network = {
.SendPacket = DriverNetSend,
.ReceivePacket = DriverNetReceive,
},
.Disk = {
.AHCI = {
.ReadSector = DriverAHCIDiskRead,
.WriteSector = DriverAHCIDiskWrite,
},
},
},
};

View File

@ -0,0 +1,10 @@
#ifndef __FENNIX_KERNEL_DRIVER_API_H__
#define __FENNIX_KERNEL_DRIVER_API_H__
#include <types.h>
#include "../../DAPI.hpp"
extern KernelAPI KAPI;
#endif // !__FENNIX_KERNEL_DRIVER_API_H__

View File

@ -0,0 +1,186 @@
#include <interrupts.hpp>
#include <syscalls.hpp>
#include <hashmap.hpp>
#include <smp.hpp>
#include <io.h>
#if defined(__amd64__)
#include "../Architecture/amd64/cpu/gdt.hpp"
#include "../Architecture/amd64/cpu/idt.hpp"
#include "../Architecture/amd64/acpi.hpp"
#include "../Architecture/amd64/cpu/apic.hpp"
#elif defined(__i386__)
#include "../Architecture/i686/cpu/gdt.hpp"
#include "../Architecture/i686/cpu/idt.hpp"
#elif defined(__aarch64__)
#endif
#include "../crashhandler.hpp"
#include "../kernel.h"
extern "C" SafeFunction void ExceptionHandler(void *Data) { CrashHandler::Handle(Data); }
namespace Interrupts
{
HashMap<int, uint64_t> *RegisteredEvents;
#if defined(__amd64__)
/* APIC::APIC */ void *apic[MAX_CPU];
/* APIC::Timer */ void *apicTimer[MAX_CPU];
#elif defined(__i386__)
/* APIC::APIC */ void *apic[MAX_CPU];
#elif defined(__aarch64__)
#endif
void *InterruptFrames[INT_FRAMES_MAX];
void Initialize(int Core)
{
static int once = 0;
if (!once++)
RegisteredEvents = new HashMap<int, uint64_t>;
#if defined(__amd64__)
GlobalDescriptorTable::Init(Core);
InterruptDescriptorTable::Init(Core);
CPUData *CoreData = GetCPU(Core);
CoreData->Checksum = CPU_DATA_CHECKSUM;
CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, (uint64_t)CoreData);
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core;
CoreData->IsActive = true;
CoreData->SystemCallStack = (uint8_t *)((uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE);
CoreData->Stack = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + 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);
asmv("movq %0, %%rsp" ::"r"(CoreData->Stack));
InitializeSystemCalls();
#elif defined(__i386__)
warn("i386 is not supported yet");
#elif defined(__aarch64__)
warn("aarch64 is not supported yet");
#endif
}
void Enable(int Core)
{
#if defined(__amd64__)
if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr)
{
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
apic[Core] = new APIC::APIC(Core);
((APIC::APIC *)apic[Core])->RedirectIRQs(Core);
}
else
{
error("LAPIC not found");
// TODO: PIC
}
#elif defined(__i386__)
warn("i386 is not supported yet");
#elif defined(__aarch64__)
warn("aarch64 is not supported yet");
#endif
}
void InitializeTimer(int Core)
{
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
#if defined(__amd64__)
if (apic[Core] != nullptr)
apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]);
else
{
fixme("apic not found");
}
#elif defined(__i386__)
warn("i386 is not supported yet");
#elif defined(__aarch64__)
warn("aarch64 is not supported yet");
#endif
}
void RemoveAll()
{
for (int i = 0; i < CPU::x64::IRQ223; i++)
RegisteredEvents->DeleteNode(i);
}
extern "C" SafeFunction void MainInterruptHandler(void *Data)
{
#if defined(__amd64__)
CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data;
memmove(InterruptFrames + 1, InterruptFrames, sizeof(InterruptFrames) - sizeof(InterruptFrames[0]));
InterruptFrames[0] = (void *)Frame->rip;
CPUData *CoreData = GetCurrentCPU();
int Core = 0;
if (likely(CoreData != nullptr))
Core = CoreData->ID;
// If this is false, we have a big problem.
if (likely(Frame->InterruptNumber < CPU::x64::IRQ223 && Frame->InterruptNumber > CPU::x64::ISR0))
{
Handler *handler = (Handler *)RegisteredEvents->Get(Frame->InterruptNumber);
if (likely(handler != (Handler *)0xdeadbeef))
handler->OnInterruptReceived(Frame);
else
error("Unhandled IRQ%ld on CPU %d.", Frame->InterruptNumber - 32, Core);
if (likely(apic[Core]))
{
((APIC::APIC *)Interrupts::apic[Core])->EOI();
// TODO: Handle PIC too
return;
}
// TODO: PIC
}
#elif defined(__i386__)
void *Frame = Data;
#elif defined(__aarch64__)
void *Frame = Data;
#endif
error("HALT HALT HALT HALT HALT HALT HALT HALT HALT");
CPU::Stop();
}
Handler::Handler(int InterruptNumber)
{
if (RegisteredEvents->Get(InterruptNumber) != (uint64_t)0xdeadbeef)
{
warn("IRQ%d is already registered.", InterruptNumber - 32);
return;
}
debug("Registering interrupt handler for IRQ%d.", InterruptNumber - 32);
this->InterruptNumber = InterruptNumber;
RegisteredEvents->AddNode(InterruptNumber, (uint64_t)this);
}
Handler::~Handler()
{
debug("Unregistering interrupt handler for IRQ%d.", InterruptNumber - 32);
if (RegisteredEvents->DeleteNode(InterruptNumber) == 0xdeadbeef)
warn("Node %d not found.", InterruptNumber);
}
#if defined(__amd64__)
void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
{
trace("Unhandled interrupt IRQ%d", Frame->InterruptNumber - 32);
#elif defined(__i386__)
void Handler::OnInterruptReceived(void *Frame)
{
trace("Unhandled interrupt received");
#elif defined(__aarch64__)
void Handler::OnInterruptReceived(void *Frame)
{
trace("Unhandled interrupt received");
#endif
}
}

87
Kernel/Core/Lock.cpp Normal file
View File

@ -0,0 +1,87 @@
#include <lock.hpp>
#include <debug.h>
#include <smp.hpp>
#include "../kernel.h"
void LockClass::DeadLock(SpinLockData Lock)
{
CPUData *CoreData = GetCurrentCPU();
long CCore = 0xdead;
if (CoreData != nullptr)
CCore = CoreData->ID;
warn("Potential deadlock in lock '%s' held by '%s'! %ld locks in queue. Core %ld is being held by %ld. (%ld times happened)",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, CCore, Lock.Core,
this->DeadLocks);
// TODO: Print on screen too.
this->DeadLocks++;
if (Config.UnlockDeadLock && this->DeadLocks > 10)
{
warn("Unlocking lock '%s' held by '%s'! %ld locks in queue. Core %ld is being held by %ld.",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, CCore, Lock.Core);
this->DeadLocks = 0;
this->Unlock();
}
if (TaskManager)
TaskManager->Schedule();
}
int LockClass::Lock(const char *FunctionName)
{
// LockData.AttemptingToGet = FunctionName;
// SpinLock_Lock(&LockData.LockData);
// LockData.Count++;
// LockData.CurrentHolder = FunctionName;
// CPUData *CoreData = GetCurrentCPU();
// if (CoreData != nullptr)
// LockData.Core = CoreData->ID;
// __sync_synchronize();
// while (!__sync_bool_compare_and_swap(&IsLocked, false, true))
// CPU::Pause();
// __sync_synchronize();
LockData.AttemptingToGet = FunctionName;
Retry:
unsigned int i = 0;
while (__atomic_exchange_n(&IsLocked, true, __ATOMIC_ACQUIRE) && ++i < 0x10000000)
CPU::Pause();
if (i >= 0x10000000)
{
DeadLock(LockData);
goto Retry;
}
LockData.Count++;
LockData.CurrentHolder = FunctionName;
CPUData *CoreData = GetCurrentCPU();
if (CoreData != nullptr)
LockData.Core = CoreData->ID;
__sync_synchronize();
return 0;
}
int LockClass::Unlock()
{
// SpinLock_Unlock(&LockData.LockData);
// LockData.Count--;
// __sync_synchronize();
// __sync_synchronize();
// __atomic_store_n(&IsLocked, false, __ATOMIC_SEQ_CST);
// IsLocked = false;
__sync_synchronize();
__atomic_store_n(&IsLocked, false, __ATOMIC_RELEASE);
LockData.Count--;
IsLocked = false;
return 0;
}

View File

@ -0,0 +1,285 @@
#include "Xalloc.hpp"
namespace Xalloc
{
class XLockClass
{
struct SpinLockData
{
uint64_t LockData = 0x0;
const char *CurrentHolder = "(nul)";
const char *AttemptingToGet = "(nul)";
uint64_t Count = 0;
};
void DeadLock(SpinLockData Lock)
{
Xalloc_warn("Potential deadlock in lock '%s' held by '%s'! %ld locks in queue.", Lock.AttemptingToGet, Lock.CurrentHolder, Lock.Count);
}
private:
SpinLockData LockData;
bool IsLocked = false;
public:
int Lock(const char *FunctionName)
{
LockData.AttemptingToGet = FunctionName;
Retry:
unsigned int i = 0;
while (__atomic_exchange_n(&IsLocked, true, __ATOMIC_ACQUIRE) && ++i < 0x10000000)
;
if (i >= 0x10000000)
{
DeadLock(LockData);
goto Retry;
}
LockData.Count++;
LockData.CurrentHolder = FunctionName;
__sync_synchronize();
return 0;
}
int Unlock()
{
__sync_synchronize();
__atomic_store_n(&IsLocked, false, __ATOMIC_RELEASE);
LockData.Count--;
IsLocked = false;
return 0;
}
};
class XSmartLock
{
private:
XLockClass *LockPointer = nullptr;
public:
XSmartLock(XLockClass &Lock, const char *FunctionName)
{
this->LockPointer = &Lock;
this->LockPointer->Lock(FunctionName);
}
~XSmartLock() { this->LockPointer->Unlock(); }
};
XLockClass XLock;
#define XSL XSmartLock CONCAT(lock##_, __COUNTER__)(XLock, __FUNCTION__)
class SmartSMAPClass
{
private:
AllocatorV1 *allocator = nullptr;
public:
SmartSMAPClass(AllocatorV1 *allocator)
{
this->allocator = allocator;
this->allocator->Xstac();
}
~SmartSMAPClass() { this->allocator->Xclac(); }
};
#define SmartSMAP SmartSMAPClass XALLOC_CONCAT(SmartSMAP##_, __COUNTER__)(this)
AllocatorV1::AllocatorV1(void *Address, bool UserMode, bool SMAPEnabled)
{
SmartSMAP;
XSL;
void *Position = Address;
UserMapping = UserMode;
SMAPUsed = SMAPEnabled;
for (Xuint64_t i = 0; i < 0x20; i++)
{
void *Page = Xalloc_REQUEST_PAGE();
if (UserMapping)
Xalloc_MAP_MEMORY(Position, Page, Xalloc_MAP_MEMORY_READ_WRITE | Xalloc_MAP_MEMORY_USER);
else
Xalloc_MAP_MEMORY(Position, Page, Xalloc_MAP_MEMORY_READ_WRITE);
Xalloc_trace("Preallocate Heap Memory (%#llx-%#llx [%#llx])...", Position, (Xuint64_t)Position + Xalloc_PAGE_SIZE, Page);
Position = (void *)((Xuint64_t)Position + Xalloc_PAGE_SIZE);
}
Xuint64_t HeapLength = 16 * Xalloc_PAGE_SIZE;
this->HeapStart = Address;
this->HeapEnd = (void *)((Xuint64_t)this->HeapStart + HeapLength);
HeapSegment *StartSegment = (HeapSegment *)Address;
StartSegment->Length = HeapLength - sizeof(HeapSegment);
StartSegment->Next = nullptr;
StartSegment->Last = nullptr;
StartSegment->IsFree = true;
this->LastSegment = StartSegment;
}
AllocatorV1::~AllocatorV1()
{
SmartSMAP;
XSL;
Xalloc_trace("Destructor not implemented yet.");
}
void AllocatorV1::ExpandHeap(Xuint64_t Length)
{
if (Length % Xalloc_PAGE_SIZE)
{
Length -= Length % Xalloc_PAGE_SIZE;
Length += Xalloc_PAGE_SIZE;
}
Xuint64_t PageCount = Length / Xalloc_PAGE_SIZE;
HeapSegment *NewSegment = (HeapSegment *)this->HeapEnd;
for (Xuint64_t i = 0; i < PageCount; i++)
{
void *Page = Xalloc_REQUEST_PAGE();
if (UserMapping)
Xalloc_MAP_MEMORY(this->HeapEnd, Page, Xalloc_MAP_MEMORY_READ_WRITE | Xalloc_MAP_MEMORY_USER);
else
Xalloc_MAP_MEMORY(this->HeapEnd, Page, Xalloc_MAP_MEMORY_READ_WRITE);
// Xalloc_trace("Expanding Heap Memory (%#llx-%#llx [%#llx])...", this->HeapEnd, (Xuint64_t)this->HeapEnd + Xalloc_PAGE_SIZE, Page);
this->HeapEnd = (void *)((Xuint64_t)this->HeapEnd + Xalloc_PAGE_SIZE);
}
NewSegment->IsFree = true;
NewSegment->Last = this->LastSegment;
this->LastSegment->Next = NewSegment;
this->LastSegment = NewSegment;
NewSegment->Next = nullptr;
NewSegment->Length = Length - sizeof(HeapSegment);
NewSegment->CombineBackward(this->LastSegment);
}
void *AllocatorV1::Malloc(Xuint64_t Size)
{
SmartSMAP;
XSL;
if (this->HeapStart == nullptr)
{
Xalloc_err("Memory allocation not initialized yet!");
return 0;
}
if (Size < 0x10)
{
// Xalloc_warn("Allocation size is too small, using 0x10 instead!");
Size = 0x10;
}
// #ifdef DEBUG
// if (Size < 1024)
// debug("Allocating %dB", Size);
// else if (TO_KB(Size) < 1024)
// debug("Allocating %dKB", TO_KB(Size));
// else if (TO_MB(Size) < 1024)
// debug("Allocating %dMB", TO_MB(Size));
// else if (TO_GB(Size) < 1024)
// debug("Allocating %dGB", TO_GB(Size));
// #endif
if (Size % 0x10 > 0) // it is not a multiple of 0x10
{
Size -= (Size % 0x10);
Size += 0x10;
}
if (Size == 0)
{
return nullptr;
}
HeapSegment *CurrentSegment = (HeapSegment *)this->HeapStart;
while (true)
{
if (CurrentSegment->IsFree)
{
if (CurrentSegment->Length > Size)
{
CurrentSegment->Split(Size, this->LastSegment);
CurrentSegment->IsFree = false;
return (void *)((Xuint64_t)CurrentSegment + sizeof(HeapSegment));
}
if (CurrentSegment->Length == Size)
{
CurrentSegment->IsFree = false;
return (void *)((Xuint64_t)CurrentSegment + sizeof(HeapSegment));
}
}
if (CurrentSegment->Next == nullptr)
break;
CurrentSegment = CurrentSegment->Next;
}
ExpandHeap(Size);
XLock.Unlock();
return this->Malloc(Size);
}
void AllocatorV1::Free(void *Address)
{
SmartSMAP;
XSL;
if (this->HeapStart == nullptr)
{
Xalloc_err("Memory allocation not initialized yet!");
return;
}
HeapSegment *Segment = (HeapSegment *)Address - 1;
Segment->IsFree = true;
Segment->CombineForward(this->LastSegment);
Segment->CombineBackward(this->LastSegment);
}
void *AllocatorV1::Calloc(Xuint64_t NumberOfBlocks, Xuint64_t Size)
{
SmartSMAP;
XSL;
if (this->HeapStart == nullptr)
{
Xalloc_err("Memory allocation not initialized yet!");
return 0;
}
if (Size < 0x10)
{
// Xalloc_warn("Allocation size is too small, using 0x10 instead!");
Size = 0x10;
}
XLock.Unlock();
void *Block = this->Malloc(NumberOfBlocks * Size);
XLock.Lock(__FUNCTION__);
if (Block)
Xmemset(Block, 0, NumberOfBlocks * Size);
return Block;
}
void *AllocatorV1::Realloc(void *Address, Xuint64_t Size)
{
SmartSMAP;
XSL;
if (this->HeapStart == nullptr)
{
Xalloc_err("Memory allocation not initialized yet!");
return 0;
}
if (!Address && Size == 0)
{
XLock.Unlock();
this->Free(Address);
return nullptr;
}
else if (!Address)
{
XLock.Unlock();
return this->Calloc(Size, sizeof(char));
}
if (Size < 0x10)
{
// Xalloc_warn("Allocation size is too small, using 0x10 instead!");
Size = 0x10;
}
XLock.Unlock();
void *newAddress = this->Calloc(Size, sizeof(char));
XLock.Lock(__FUNCTION__);
Xmemcpy(newAddress, Address, Size);
return newAddress;
}
}

View File

@ -0,0 +1,180 @@
#pragma once
#include <memory.hpp>
#include <debug.h>
// Functions defines
// Page allocation functions
#define Xalloc_REQUEST_PAGE() KernelAllocator.RequestPage()
#define Xalloc_REQUEST_PAGES(Pages) KernelAllocator.RequestPages(Pages)
#define Xalloc_FREE_PAGE(Address) KernelAllocator.FreePage(Address)
#define Xalloc_FREE_PAGES(Address, Pages) KernelAllocator.FreePages(Address, Pages)
#define Xalloc_MAP_MEMORY(VirtualAddress, PhysicalAddress, Flags) Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags)
#define Xalloc_UNMAP_MEMORY(VirtualAddress) Memory::Virtual(KernelPageTable).Unmap(VirtualAddress)
#define Xalloc_MAP_MEMORY_READ_WRITE Memory::PTFlag::RW
#define Xalloc_MAP_MEMORY_USER Memory::PTFlag::US
#define Xalloc_PAGE_SIZE PAGE_SIZE
#define Xalloc_trace(m, ...) trace(m, ##__VA_ARGS__)
#define Xalloc_warn(m, ...) warn(m, ##__VA_ARGS__)
#define Xalloc_err(m, ...) error(m, ##__VA_ARGS__)
#define XALLOC_CONCAT(x, y) x##y
typedef long unsigned Xuint64_t;
namespace Xalloc
{
class AllocatorV1
{
private:
struct HeapSegment
{
Xuint64_t Length;
HeapSegment *Next;
HeapSegment *Last;
bool IsFree;
HeapSegment *Split(Xuint64_t SplitLength, HeapSegment *LastSegment)
{
if (SplitLength < 0x10)
return nullptr;
int64_t SplitSegmentLength = Length - SplitLength - (sizeof(HeapSegment));
if (SplitSegmentLength < 0x10)
return nullptr;
HeapSegment *NewSplitHdr = (HeapSegment *)((Xuint64_t)this + SplitLength + sizeof(HeapSegment));
Next->Last = NewSplitHdr;
NewSplitHdr->Next = Next;
Next = NewSplitHdr;
NewSplitHdr->Last = this;
NewSplitHdr->Length = SplitSegmentLength;
NewSplitHdr->IsFree = IsFree;
Length = SplitLength;
if (LastSegment == this)
LastSegment = NewSplitHdr;
return NewSplitHdr;
}
void CombineForward(HeapSegment *LastSegment)
{
if (Next == nullptr)
return;
if (Next->IsFree == false)
return;
if (Next == LastSegment)
LastSegment = this;
if (Next->Next != nullptr)
Next->Next->Last = this;
Length = Length + Next->Length + sizeof(HeapSegment);
Next = Next->Next;
}
void CombineBackward(HeapSegment *LastSegment)
{
if (Last != nullptr && Last->IsFree)
Last->CombineForward(LastSegment);
}
} __attribute__((aligned(16)));
void *HeapStart = nullptr;
void *HeapEnd = nullptr;
HeapSegment *LastSegment = nullptr;
bool UserMapping = false;
bool SMAPUsed = false;
void ExpandHeap(Xuint64_t Length);
// TODO: Change memcpy with an optimized version
static inline void *Xmemcpy(void *__restrict__ Destination, const void *__restrict__ Source, Xuint64_t Length)
{
unsigned char *dst = (unsigned char *)Destination;
const unsigned char *src = (const unsigned char *)Source;
for (Xuint64_t i = 0; i < Length; i++)
dst[i] = src[i];
return Destination;
}
// TODO: Change memset with an optimized version
static inline void *Xmemset(void *__restrict__ Destination, int Data, Xuint64_t Length)
{
unsigned char *Buffer = (unsigned char *)Destination;
for (Xuint64_t i = 0; i < Length; i++)
Buffer[i] = (unsigned char)Data;
return Destination;
}
public:
inline void Xstac()
{
if (this->SMAPUsed)
{
#if defined(__amd64__) || defined(__i386__)
asm volatile("stac" ::
: "cc");
#endif
}
}
inline void Xclac()
{
if (this->SMAPUsed)
{
#if defined(__amd64__) || defined(__i386__)
asm volatile("clac" ::
: "cc");
#endif
}
}
/**
* @brief Construct a new Allocator V1 object
*
* @param Address Virtual address to allocate.
* @param UserMode Map the new pages with USER flag?
* @param SMAPEnabled Does the kernel has Supervisor Mode Access Prevention enabled?
*/
AllocatorV1(void *Address, bool UserMode, bool SMAPEnabled);
/**
* @brief Destroy the Allocator V 1 object
*
*/
~AllocatorV1();
/**
* @brief Allocate a new memory block
*
* @param Size Size of the block to allocate.
* @return void* Pointer to the allocated block.
*/
void *Malloc(Xuint64_t Size);
/**
* @brief Free a previously allocated block
*
* @param Address Address of the block to free.
*/
void Free(void *Address);
/**
* @brief Allocate a new memory block
*
* @param NumberOfBlocks Number of blocks to allocate.
* @param Size Size of the block to allocate.
* @return void* Pointer to the allocated block.
*/
void *Calloc(Xuint64_t NumberOfBlocks, Xuint64_t Size);
/**
* @brief Reallocate a previously allocated block
*
* @param Address Address of the block to reallocate.
* @param Size New size of the block.
* @return void* Pointer to the reallocated block.
*/
void *Realloc(void *Address, Xuint64_t Size);
};
}

View File

@ -0,0 +1,342 @@
#include <memory.hpp>
#include <convert.h>
#include <debug.h>
#include "HeapAllocators/Xalloc.hpp"
#include "../Library/liballoc_1_1.h"
using namespace Memory;
Physical KernelAllocator;
PageTable *KernelPageTable = nullptr;
PageTable *UserspaceKernelOnlyPageTable = nullptr;
static MemoryAllocatorType AllocatorType = MemoryAllocatorType::None;
Xalloc::AllocatorV1 *XallocV1Allocator = nullptr;
#ifdef DEBUG
__no_instrument_function void tracepagetable(PageTable *pt)
{
for (int i = 0; i < 512; i++)
{
#if defined(__amd64__)
if (pt->Entries[i].Value.Present)
debug("Entry %03d: %x %x %x %x %x %x %x %x %x %x %x %p-%#llx", i,
pt->Entries[i].Value.Present, pt->Entries[i].Value.ReadWrite,
pt->Entries[i].Value.UserSupervisor, pt->Entries[i].Value.WriteThrough,
pt->Entries[i].Value.CacheDisable, pt->Entries[i].Value.Accessed,
pt->Entries[i].Value.Dirty, pt->Entries[i].Value.PageSize,
pt->Entries[i].Value.Global, pt->Entries[i].Value.PageAttributeTable,
pt->Entries[i].Value.ExecuteDisable, pt->Entries[i].GetAddress(),
pt->Entries[i].Value);
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
}
}
#endif
__no_instrument_function void MapFromZero(PageTable *PT, BootInfo *Info)
{
Virtual va = Virtual(PT);
uint64_t VirtualOffsetNormalVMA = NORMAL_VMA_OFFSET;
uint64_t MemSize = Info->Memory.Size;
for (uint64_t t = 0; t < MemSize; t += PAGE_SIZE)
{
va.Map((void *)t, (void *)t, PTFlag::RW /* | PTFlag::US */);
va.Map((void *)VirtualOffsetNormalVMA, (void *)t, PTFlag::RW /* | PTFlag::US */);
VirtualOffsetNormalVMA += PAGE_SIZE;
}
}
__no_instrument_function void MapFramebuffer(PageTable *PT, BootInfo *Info)
{
Virtual va = Virtual(PT);
int itrfb = 0;
while (1)
{
if (!Info->Framebuffer[itrfb].BaseAddress)
break;
for (uint64_t fb_base = (uint64_t)Info->Framebuffer[itrfb].BaseAddress;
fb_base < ((uint64_t)Info->Framebuffer[itrfb].BaseAddress + ((Info->Framebuffer[itrfb].Pitch * Info->Framebuffer[itrfb].Height) + PAGE_SIZE));
fb_base += PAGE_SIZE)
va.Map((void *)(fb_base + NORMAL_VMA_OFFSET), (void *)fb_base, PTFlag::RW | PTFlag::US | PTFlag::G);
itrfb++;
}
}
__no_instrument_function void MapKernel(PageTable *PT, BootInfo *Info)
{
/* KernelStart KernelTextEnd KernelRoDataEnd KernelEnd
Kernel Start & Text Start ------ Text End ------ Kernel Rodata End ------ Kernel Data End & Kernel End
*/
Virtual va = Virtual(PT);
uint64_t KernelStart = (uint64_t)&_kernel_start;
uint64_t KernelTextEnd = (uint64_t)&_kernel_text_end;
uint64_t KernelDataEnd = (uint64_t)&_kernel_data_end;
uint64_t KernelRoDataEnd = (uint64_t)&_kernel_rodata_end;
uint64_t KernelEnd = (uint64_t)&_kernel_end;
uint64_t BaseKernelMapAddress = (uint64_t)Info->Kernel.PhysicalBase;
uint64_t k;
for (k = KernelStart; k < KernelTextEnd; k += PAGE_SIZE)
{
va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW);
KernelAllocator.LockPage((void *)BaseKernelMapAddress);
BaseKernelMapAddress += PAGE_SIZE;
}
for (k = KernelTextEnd; k < KernelDataEnd; k += PAGE_SIZE)
{
va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G);
KernelAllocator.LockPage((void *)BaseKernelMapAddress);
BaseKernelMapAddress += PAGE_SIZE;
}
for (k = KernelDataEnd; k < KernelRoDataEnd; k += PAGE_SIZE)
{
va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::P | PTFlag::G);
KernelAllocator.LockPage((void *)BaseKernelMapAddress);
BaseKernelMapAddress += PAGE_SIZE;
}
for (k = KernelRoDataEnd; k < KernelEnd; k += PAGE_SIZE)
{
va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G);
KernelAllocator.LockPage((void *)BaseKernelMapAddress);
BaseKernelMapAddress += PAGE_SIZE;
}
debug("\nStart: %#llx - Text End: %#llx - RoEnd: %#llx - End: %#llx\nStart Physical: %#llx - End Physical: %#llx",
KernelStart, KernelTextEnd, KernelRoDataEnd, KernelEnd, Info->Kernel.PhysicalBase, BaseKernelMapAddress - PAGE_SIZE);
}
__no_instrument_function void InitializeMemoryManagement(BootInfo *Info)
{
#ifdef DEBUG
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
{
uint64_t Base = reinterpret_cast<uint64_t>(Info->Memory.Entry[i].BaseAddress);
uint64_t Length = Info->Memory.Entry[i].Length;
uint64_t End = Base + Length;
const char *Type = "Unknown";
switch (Info->Memory.Entry[i].Type)
{
case likely(Usable):
Type = "Usable";
break;
case Reserved:
Type = "Reserved";
break;
case ACPIReclaimable:
Type = "ACPI Reclaimable";
break;
case ACPINVS:
Type = "ACPI NVS";
break;
case BadMemory:
Type = "Bad Memory";
break;
case BootloaderReclaimable:
Type = "Bootloader Reclaimable";
break;
case KernelAndModules:
Type = "Kernel and Modules";
break;
case Framebuffer:
Type = "Framebuffer";
break;
default:
break;
}
debug("%lld: %#016llx-%#016llx %s",
i,
Base,
End,
Type);
}
#endif
trace("Initializing Physical Memory Manager");
KernelAllocator = Physical();
KernelAllocator.Init(Info);
debug("Memory Info: %lldMB / %lldMB (%lldMB reserved)",
TO_MB(KernelAllocator.GetUsedMemory()),
TO_MB(KernelAllocator.GetTotalMemory()),
TO_MB(KernelAllocator.GetReservedMemory()));
AllocatorType = MemoryAllocatorType::Pages;
trace("Initializing Virtual Memory Manager");
KernelPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
memset(KernelPageTable, 0, PAGE_SIZE);
UserspaceKernelOnlyPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
memset(UserspaceKernelOnlyPageTable, 0, PAGE_SIZE);
debug("Mapping from 0x0 to %#llx", Info->Memory.Size);
MapFromZero(KernelPageTable, Info);
debug("Mapping from 0x0 %#llx for Userspace Page Table", Info->Memory.Size);
UserspaceKernelOnlyPageTable[0] = KernelPageTable[0]; // TODO: This is a hack to speed up the boot process
// MapFromZero(UserspaceKernelOnlyPageTable, Info);
/* Mapping Framebuffer address */
debug("Mapping Framebuffer");
MapFramebuffer(KernelPageTable, Info);
debug("Mapping Framebuffer for Userspace Page Table");
MapFramebuffer(UserspaceKernelOnlyPageTable, Info);
/* Kernel mapping */
debug("Mapping Kernel");
MapKernel(KernelPageTable, Info);
debug("Mapping Kernel for Userspace Page Table");
MapKernel(UserspaceKernelOnlyPageTable, Info);
trace("Applying new page table from address %p", KernelPageTable);
#ifdef DEBUG
debug("Kernel:");
tracepagetable(KernelPageTable);
debug("Userspace:");
tracepagetable(UserspaceKernelOnlyPageTable);
#endif
#if defined(__amd64__) || defined(__i386__)
asmv("mov %0, %%cr3" ::"r"(KernelPageTable));
#elif defined(__aarch64__)
asmv("msr ttbr0_el1, %0" ::"r"(KernelPageTable));
#endif
debug("Page table updated.");
if (strstr(Info->Kernel.CommandLine, "xallocv1"))
{
XallocV1Allocator = new Xalloc::AllocatorV1((void *)KERNEL_HEAP_BASE, false, false);
AllocatorType = MemoryAllocatorType::XallocV1;
trace("XallocV1 Allocator initialized (%p)", XallocV1Allocator);
}
else if (strstr(Info->Kernel.CommandLine, "liballoc11"))
{
AllocatorType = MemoryAllocatorType::liballoc11;
}
}
void *HeapMalloc(uint64_t Size)
{
switch (AllocatorType)
{
case unlikely(MemoryAllocatorType::Pages):
return KernelAllocator.RequestPages(TO_PAGES(Size));
case MemoryAllocatorType::XallocV1:
{
void *ret = XallocV1Allocator->Malloc(Size);
memset(ret, 0, Size);
return ret;
}
case MemoryAllocatorType::liballoc11:
{
void *ret = PREFIX(malloc)(Size);
memset(ret, 0, Size);
return ret;
}
default:
throw;
}
}
void *HeapCalloc(uint64_t n, uint64_t Size)
{
switch (AllocatorType)
{
case unlikely(MemoryAllocatorType::Pages):
return KernelAllocator.RequestPages(TO_PAGES(n * Size));
case MemoryAllocatorType::XallocV1:
{
void *ret = XallocV1Allocator->Calloc(n, Size);
memset(ret, 0, n * Size);
return ret;
}
case MemoryAllocatorType::liballoc11:
{
void *ret = PREFIX(calloc)(n, Size);
memset(ret, 0, Size);
return ret;
}
default:
throw;
}
}
void *HeapRealloc(void *Address, uint64_t Size)
{
switch (AllocatorType)
{
case unlikely(MemoryAllocatorType::Pages):
return KernelAllocator.RequestPages(TO_PAGES(Size)); // WARNING: Potential memory leak
case MemoryAllocatorType::XallocV1:
{
void *ret = XallocV1Allocator->Realloc(Address, Size);
memset(ret, 0, Size);
return ret;
}
case MemoryAllocatorType::liballoc11:
{
void *ret = PREFIX(realloc)(Address, Size);
memset(ret, 0, Size);
return ret;
}
default:
throw;
}
}
void HeapFree(void *Address)
{
switch (AllocatorType)
{
case unlikely(MemoryAllocatorType::Pages):
KernelAllocator.FreePage(Address); // WARNING: Potential memory leak
break;
case MemoryAllocatorType::XallocV1:
if (XallocV1Allocator)
XallocV1Allocator->Free(Address);
break;
case MemoryAllocatorType::liballoc11:
PREFIX(free)
(Address);
break;
default:
throw;
}
}
void *operator new(size_t Size)
{
return HeapMalloc(Size);
}
void *operator new[](size_t Size)
{
return HeapMalloc(Size);
}
void *operator new(unsigned long Size, std::align_val_t Alignment)
{
fixme("operator new with alignment(%#lx) is not implemented", Alignment);
return HeapMalloc(Size);
}
void operator delete(void *Pointer)
{
HeapFree(Pointer);
}
void operator delete[](void *Pointer)
{
HeapFree(Pointer);
}
void operator delete(void *Pointer, long unsigned int Size)
{
HeapFree(Pointer);
}
void operator delete[](void *Pointer, long unsigned int Size)
{
HeapFree(Pointer);
}

View File

@ -0,0 +1,42 @@
#include <memory.hpp>
namespace Memory
{
void PageDirectoryEntry::AddFlag(uint64_t Flag) { this->Value.raw |= Flag; }
void PageDirectoryEntry::RemoveFlags(uint64_t Flag) { this->Value.raw &= ~Flag; }
void PageDirectoryEntry::ClearFlags() { this->Value.raw = 0; }
void PageDirectoryEntry::SetFlag(uint64_t Flag, bool Enabled)
{
this->Value.raw = 0;
if (Enabled)
this->Value.raw |= Flag;
}
bool PageDirectoryEntry::GetFlag(uint64_t Flag) { return (this->Value.raw & Flag) > 0 ? true : false; }
uint64_t PageDirectoryEntry::GetFlag() { return this->Value.raw; }
void PageDirectoryEntry::SetAddress(uint64_t Address)
{
#if defined(__amd64__)
Address &= 0x000000FFFFFFFFFF;
this->Value.raw &= 0xFFF0000000000FFF;
this->Value.raw |= (Address << 12);
#elif defined(__i386__)
Address &= 0x000FFFFF;
this->Value.raw &= 0xFFC00003;
this->Value.raw |= (Address << 12);
#elif defined(__aarch64__)
Address &= 0x000000FFFFFFFFFF;
this->Value.raw &= 0xFFF0000000000FFF;
this->Value.raw |= (Address << 12);
#endif
}
uint64_t PageDirectoryEntry::GetAddress()
{
#if defined(__amd64__)
return (this->Value.raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(__i386__)
return (this->Value.raw & 0x003FFFFF000) >> 12;
#elif defined(__aarch64__)
return (this->Value.raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
}

View File

@ -0,0 +1,28 @@
#include <memory.hpp>
namespace Memory
{
Virtual::PageMapIndexer::PageMapIndexer(uint64_t VirtualAddress)
{
#if defined(__amd64__)
uint64_t Address = VirtualAddress;
Address >>= 12;
this->PIndex = Address & 0x1FF;
Address >>= 9;
this->PTIndex = Address & 0x1FF;
Address >>= 9;
this->PDIndex = Address & 0x1FF;
Address >>= 9;
this->PDPIndex = Address & 0x1FF;
#elif defined(__i386__)
uint64_t Address = VirtualAddress;
Address >>= 12;
this->PIndex = Address & 0x3FF;
Address >>= 10;
this->PTIndex = Address & 0x3FF;
Address >>= 10;
this->PDIndex = Address & 0x3FF;
#elif defined(__aarch64__)
#endif
}
}

View File

@ -0,0 +1,277 @@
#include <memory.hpp>
#include <debug.h>
namespace Memory
{
uint64_t Physical::GetTotalMemory()
{
SmartLock(this->MemoryLock);
return this->TotalMemory;
}
uint64_t Physical::GetFreeMemory()
{
SmartLock(this->MemoryLock);
return this->FreeMemory;
}
uint64_t Physical::GetReservedMemory()
{
SmartLock(this->MemoryLock);
return this->ReservedMemory;
}
uint64_t Physical::GetUsedMemory()
{
SmartLock(this->MemoryLock);
return this->UsedMemory;
}
bool Physical::SwapPage(void *Address)
{
fixme("%p", Address);
return false;
}
bool Physical::SwapPages(void *Address, uint64_t PageCount)
{
for (uint64_t i = 0; i < PageCount; i++)
if (!this->SwapPage((void *)((uint64_t)Address + (i * PAGE_SIZE))))
return false;
return false;
}
bool Physical::UnswapPage(void *Address)
{
fixme("%p", Address);
return false;
}
bool Physical::UnswapPages(void *Address, uint64_t PageCount)
{
for (uint64_t i = 0; i < PageCount; i++)
if (!this->UnswapPage((void *)((uint64_t)Address + (i * PAGE_SIZE))))
return false;
return false;
}
void *Physical::RequestPage()
{
SmartLock(this->MemoryLock);
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
{
if (PageBitmap[PageBitmapIndex] == true)
continue;
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
if (this->SwapPage((void *)(PageBitmapIndex * PAGE_SIZE)))
{
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
CPU::Halt(true);
return nullptr;
}
void *Physical::RequestPages(uint64_t Count)
{
SmartLock(this->MemoryLock);
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
{
if (PageBitmap[PageBitmapIndex] == true)
continue;
for (uint64_t Index = PageBitmapIndex; Index < PageBitmap.Size * 8; Index++)
{
if (PageBitmap[Index] == true)
continue;
for (uint64_t i = 0; i < Count; i++)
if (PageBitmap[Index + i] == true)
goto NextPage;
this->LockPages((void *)(Index * PAGE_SIZE), Count);
return (void *)(Index * PAGE_SIZE);
NextPage:
Index += Count;
continue;
}
}
if (this->SwapPages((void *)(PageBitmapIndex * PAGE_SIZE), Count))
{
this->LockPages((void *)(PageBitmapIndex * PAGE_SIZE), Count);
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
CPU::Halt(true);
return nullptr;
}
void Physical::FreePage(void *Address)
{
SmartLock(this->MemoryLock);
if (unlikely(Address == nullptr))
{
warn("Null pointer passed to FreePage.");
return;
}
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == false))
return;
if (PageBitmap.Set(Index, false))
{
FreeMemory += PAGE_SIZE;
UsedMemory -= PAGE_SIZE;
if (PageBitmapIndex > Index)
PageBitmapIndex = Index;
}
}
void Physical::FreePages(void *Address, uint64_t Count)
{
if (unlikely(Address == nullptr || Count == 0))
{
warn("%s%s passed to FreePages.", Address == nullptr ? "Null pointer" : "", Count == 0 ? "Zero count" : "");
return;
}
for (uint64_t t = 0; t < Count; t++)
this->FreePage((void *)((uint64_t)Address + (t * PAGE_SIZE)));
}
void Physical::LockPage(void *Address)
{
if (unlikely(Address == nullptr))
warn("Trying to lock null address.");
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == true))
return;
if (PageBitmap.Set(Index, true))
{
FreeMemory -= PAGE_SIZE;
UsedMemory += PAGE_SIZE;
}
}
void Physical::LockPages(void *Address, uint64_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to lock %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
for (uint64_t i = 0; i < PageCount; i++)
this->LockPage((void *)((uint64_t)Address + (i * PAGE_SIZE)));
}
void Physical::ReservePage(void *Address)
{
if (unlikely(Address == nullptr))
warn("Trying to reserve null address.");
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == true))
return;
if (PageBitmap.Set(Index, true))
{
FreeMemory -= PAGE_SIZE;
ReservedMemory += PAGE_SIZE;
}
}
void Physical::ReservePages(void *Address, uint64_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to reserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
for (uint64_t t = 0; t < PageCount; t++)
this->ReservePage((void *)((uint64_t)Address + (t * PAGE_SIZE)));
}
void Physical::UnreservePage(void *Address)
{
if (unlikely(Address == nullptr))
warn("Trying to unreserve null address.");
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == false))
return;
if (PageBitmap.Set(Index, false))
{
FreeMemory += PAGE_SIZE;
ReservedMemory -= PAGE_SIZE;
if (PageBitmapIndex > Index)
PageBitmapIndex = Index;
}
}
void Physical::UnreservePages(void *Address, uint64_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to unreserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
for (uint64_t t = 0; t < PageCount; t++)
this->UnreservePage((void *)((uint64_t)Address + (t * PAGE_SIZE)));
}
void Physical::Init(BootInfo *Info)
{
SmartLock(this->MemoryLock);
void *LargestFreeMemorySegment = nullptr;
uint64_t LargestFreeMemorySegmentSize = 0;
uint64_t MemorySize = Info->Memory.Size;
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
if (Info->Memory.Entry[i].Type == Usable)
if (Info->Memory.Entry[i].Length > LargestFreeMemorySegmentSize)
{
// We don't want to use 0 as a memory address.
if (Info->Memory.Entry[i].BaseAddress == nullptr)
continue;
LargestFreeMemorySegment = (void *)Info->Memory.Entry[i].BaseAddress;
LargestFreeMemorySegmentSize = Info->Memory.Entry[i].Length;
debug("Largest free memory segment: %llp (%lldMB)",
(void *)Info->Memory.Entry[i].BaseAddress,
TO_MB(Info->Memory.Entry[i].Length));
}
TotalMemory = MemorySize;
FreeMemory = MemorySize;
if (LargestFreeMemorySegment == nullptr)
{
error("No free memory found!");
CPU::Stop();
}
uint64_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1;
trace("Initializing Bitmap at %llp-%llp (%lld Bytes)",
LargestFreeMemorySegment,
(void *)((uint64_t)LargestFreeMemorySegment + BitmapSize),
BitmapSize);
PageBitmap.Size = BitmapSize;
PageBitmap.Buffer = (uint8_t *)LargestFreeMemorySegment;
for (uint64_t i = 0; i < BitmapSize; i++)
*(uint8_t *)(PageBitmap.Buffer + i) = 0;
trace("Reserving pages...");
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
if (Info->Memory.Entry[i].Type != Usable)
this->ReservePages((void *)Info->Memory.Entry[i].BaseAddress, Info->Memory.Entry[i].Length / PAGE_SIZE + 1);
trace("Locking bitmap pages...");
this->ReservePages(0, 0x100);
this->LockPages(PageBitmap.Buffer, PageBitmap.Size / PAGE_SIZE + 1);
}
Physical::Physical() {}
Physical::~Physical() {}
}

View File

@ -0,0 +1,74 @@
#include <memory.hpp>
#include <debug.h>
namespace Memory
{
StackGuard::StackGuard(bool User, PageTable *Table)
{
this->UserMode = User;
this->Table = Table;
if (this->UserMode)
{
void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE));
debug("AllocatedStack: %p", AllocatedStack);
memset(AllocatedStack, 0, USER_STACK_SIZE);
for (uint64_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
{
Virtual(Table).Map((void *)((uint64_t)AllocatedStack + (i * PAGE_SIZE)),
(void *)(USER_STACK_BASE + (i * PAGE_SIZE)),
PTFlag::RW | PTFlag::US);
}
this->StackBottom = (void *)USER_STACK_BASE;
this->StackTop = (void *)(USER_STACK_BASE + USER_STACK_SIZE);
this->Size = USER_STACK_SIZE;
}
else
{
this->StackBottom = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
debug("StackBottom: %p", this->StackBottom);
memset(this->StackBottom, 0, STACK_SIZE);
this->StackTop = (void *)((uint64_t)this->StackBottom + STACK_SIZE);
this->Size = STACK_SIZE;
}
trace("Allocated stack at %p", this->StackBottom);
}
StackGuard::~StackGuard()
{
fixme("Temporarily disabled stack guard deallocation");
// KernelAllocator.FreePages(this->StackBottom, TO_PAGES(this->Size));
// debug("Freed stack at %p", this->StackBottom);
}
bool StackGuard::Expand(uint64_t FaultAddress)
{
if (this->UserMode)
{
if (FaultAddress < (uint64_t)this->StackBottom - USER_STACK_SIZE ||
FaultAddress > (uint64_t)this->StackTop)
{
return false; // It's not about the stack.
}
else
{
void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE));
debug("AllocatedStack: %p", AllocatedStack);
memset(AllocatedStack, 0, USER_STACK_SIZE);
for (uint64_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
Virtual(this->Table).Map((void *)((uint64_t)AllocatedStack + (i * PAGE_SIZE)), (void *)((uint64_t)this->StackBottom - (i * PAGE_SIZE)), PTFlag::RW | PTFlag::US);
this->StackBottom = (void *)((uint64_t)this->StackBottom - USER_STACK_SIZE);
this->Size += USER_STACK_SIZE;
info("Stack expanded to %p", this->StackBottom);
return true;
}
}
else
{
fixme("Not implemented and probably not needed");
return false;
}
error("Reached end of function! How?");
return false;
}
}

View File

@ -0,0 +1,212 @@
#include <memory.hpp>
#include <convert.h>
#include <debug.h>
namespace Memory
{
bool Virtual::Check(void *VirtualAddress, PTFlag Flag)
{
// 0x1000 aligned
uint64_t Address = (uint64_t)VirtualAddress;
Address &= 0xFFFFFFFFFFFFF000;
PageMapIndexer Index = PageMapIndexer((uint64_t)Address);
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex];
PageTable *PDP = nullptr;
PageTable *PD = nullptr;
PageTable *PT = nullptr;
if (PDE.GetFlag(Flag))
PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
else
return false;
PDE = PDP->Entries[Index.PDIndex];
if (PDE.GetFlag(Flag))
PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
else
return false;
PDE = PD->Entries[Index.PTIndex];
if (PDE.GetFlag(Flag))
PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
else
return false;
PDE = PT->Entries[Index.PIndex];
if (PDE.GetFlag(Flag))
return true;
else
return false;
return false;
}
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
{
SmartLock(this->MemoryLock);
if (unlikely(!this->Table))
{
error("No page table");
return;
}
PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress);
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex];
PageTable *PDP = nullptr;
if (!PDE.GetFlag(PTFlag::P))
{
PDP = (PageTable *)KernelAllocator.RequestPage();
memset(PDP, 0, PAGE_SIZE);
PDE.SetFlag(PTFlag::P, true);
PDE.AddFlag(Flags);
PDE.SetAddress((uint64_t)PDP >> 12);
this->Table->Entries[Index.PDPIndex] = PDE;
}
else
PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PDP->Entries[Index.PDIndex];
PageTable *PD = nullptr;
if (!PDE.GetFlag(PTFlag::P))
{
PD = (PageTable *)KernelAllocator.RequestPage();
memset(PD, 0, PAGE_SIZE);
PDE.SetFlag(PTFlag::P, true);
PDE.AddFlag(Flags);
PDE.SetAddress((uint64_t)PD >> 12);
PDP->Entries[Index.PDIndex] = PDE;
}
else
PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PD->Entries[Index.PTIndex];
PageTable *PT = nullptr;
if (!PDE.GetFlag(PTFlag::P))
{
PT = (PageTable *)KernelAllocator.RequestPage();
memset(PT, 0, PAGE_SIZE);
PDE.SetFlag(PTFlag::P, true);
PDE.AddFlag(Flags);
PDE.SetAddress((uint64_t)PT >> 12);
PD->Entries[Index.PTIndex] = PDE;
}
else
PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PT->Entries[Index.PIndex];
PDE.SetFlag(PTFlag::P, true);
PDE.AddFlag(Flags);
PDE.SetAddress((uint64_t)PhysicalAddress >> 12);
PT->Entries[Index.PIndex] = PDE;
#if defined(__amd64__)
CPU::x64::invlpg(VirtualAddress);
#elif defined(__i386__)
CPU::x32::invlpg(VirtualAddress);
#elif defined(__aarch64__)
asmv("dsb sy");
asmv("tlbi vae1is, %0"
:
: "r"(VirtualAddress)
: "memory");
asmv("dsb sy");
asmv("isb");
#endif
#ifdef DEBUG
/* https://stackoverflow.com/a/3208376/9352057 */
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte) \
(byte & 0x80 ? '1' : '0'), \
(byte & 0x40 ? '1' : '0'), \
(byte & 0x20 ? '1' : '0'), \
(byte & 0x10 ? '1' : '0'), \
(byte & 0x08 ? '1' : '0'), \
(byte & 0x04 ? '1' : '0'), \
(byte & 0x02 ? '1' : '0'), \
(byte & 0x01 ? '1' : '0')
if (!this->Check(VirtualAddress, (PTFlag)Flags)) // quick workaround just to see where it fails
warn("Failed to map %#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, BYTE_TO_BINARY(Flags));
#endif
}
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t PageCount, uint64_t Flags)
{
for (uint64_t i = 0; i < PageCount; i++)
this->Map((void *)((uint64_t)VirtualAddress + (i * PAGE_SIZE)), (void *)((uint64_t)PhysicalAddress + (i * PAGE_SIZE)), Flags);
}
void Virtual::Unmap(void *VirtualAddress)
{
SmartLock(this->MemoryLock);
if (!this->Table)
{
error("No page table");
return;
}
PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress);
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex];
if (PDE.GetFlag(PTFlag::P))
{
PageTable *PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PDP->Entries[Index.PDIndex];
if (PDE.GetFlag(PTFlag::P))
{
PageTable *PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PD->Entries[Index.PTIndex];
if (PDE.GetFlag(PTFlag::P))
{
PageTable *PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PT->Entries[Index.PIndex];
if (PDE.GetFlag(PTFlag::P))
{
PDE.ClearFlags();
// debug("Unmapped %#lx", VirtualAddress);
}
}
}
}
#if defined(__amd64__)
CPU::x64::invlpg(VirtualAddress);
#elif defined(__i386__)
CPU::x32::invlpg(VirtualAddress);
#elif defined(__aarch64__)
asmv("dsb sy");
asmv("tlbi vae1is, %0"
:
: "r"(VirtualAddress)
: "memory");
asmv("dsb sy");
asmv("isb");
#endif
}
void Virtual::Unmap(void *VirtualAddress, uint64_t PageCount)
{
for (uint64_t i = 0; i < PageCount; i++)
this->Unmap((void *)((uint64_t)VirtualAddress + (i * PAGE_SIZE)));
}
void Virtual::Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
{
this->Unmap(VirtualAddress);
this->Map(VirtualAddress, PhysicalAddress, Flags);
}
Virtual::Virtual(PageTable *Table)
{
if (Table)
this->Table = Table;
else
this->Table = (PageTable *)CPU::PageTable();
}
Virtual::~Virtual() {}
}

View File

@ -0,0 +1,868 @@
#include <pci.hpp>
#include <memory.hpp>
#include <power.hpp>
#if defined(__amd64__)
#include "../Architecture/amd64/acpi.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../kernel.h"
namespace PCI
{
namespace Descriptors
{
char HexToStringOutput8[128];
const char *u8ToHexString(uint8_t Value)
{
uint8_t *ValuePtr = &Value;
uint8_t *Ptr;
uint8_t Temp;
uint8_t Size = 1 * 2 - 1;
for (uint8_t i = 0; i < Size; i++)
{
Ptr = ((uint8_t *)ValuePtr + i);
Temp = ((*Ptr & 0xF0) >> 4);
HexToStringOutput8[Size - (i * 2 + 1)] = Temp + (Temp > 9 ? 55 : '0');
Temp = ((*Ptr & 0x0F));
HexToStringOutput8[Size - (i * 2)] = Temp + (Temp > 9 ? 55 : '0');
}
HexToStringOutput8[Size + 1] = 0;
return HexToStringOutput8;
}
char HexToStringOutput32[128];
const char *u32ToHexString(uint32_t Value)
{
uint32_t *ValuePtr = &Value;
uint8_t *Ptr;
uint8_t Temp;
uint8_t Size = 4 * 2 - 1;
for (uint8_t i = 0; i < Size; i++)
{
Ptr = ((uint8_t *)ValuePtr + i);
Temp = ((*Ptr & 0xF0) >> 4);
HexToStringOutput32[Size - (i * 2 + 1)] = Temp + (Temp > 9 ? 55 : '0');
Temp = ((*Ptr & 0x0F));
HexToStringOutput32[Size - (i * 2)] = Temp + (Temp > 9 ? 55 : '0');
}
HexToStringOutput32[Size + 1] = 0;
return HexToStringOutput32;
}
const char *MassStorageControllerSubclassName(uint8_t SubclassCode)
{
switch (SubclassCode)
{
case 0x00:
return "SCSI Bus Controller";
case 0x01:
return "IDE Controller";
case 0x02:
return "Floppy Disk Controller";
case 0x03:
return "IPI Bus Controller";
case 0x04:
return "RAID Controller";
case 0x05:
return "ATA Controller";
case 0x06:
return "Serial ATA";
case 0x07:
return "Serial Attached SCSI Controller";
case 0x08:
return "Non-Volatile Memory Controller";
case 0x80:
return "Mass Storage Controller";
default:
break;
}
fixme("Unknown mass storage controller %02x", SubclassCode);
return u8ToHexString(SubclassCode);
}
const char *NetworkControllerSubclassName(uint8_t SubclassCode)
{
switch (SubclassCode)
{
case 0x00:
return "Ethernet Controller";
case 0x01:
return "Token Ring Controller";
case 0x02:
return "FDDI Controller";
case 0x03:
return "ATM Controller";
case 0x04:
return "ISDN Controller";
case 0x05:
return "WorldFip Controller";
case 0x06:
return "PICMG HyperCard Controller";
case 0x07:
return "Infiniband Controller";
case 0x08:
return "Fabric Controller";
case 0x80:
return "Network Controller";
default:
break;
}
fixme("Unknown network controller %02x", SubclassCode);
return u8ToHexString(SubclassCode);
}
const char *DisplayControllerSubclassName(uint8_t SubclassCode)
{
switch (SubclassCode)
{
case 0x00:
return "VGA Compatible Controller";
case 0x01:
return "XGA Controller";
case 0x02:
return "3D Controller";
case 0x80:
return "Display Controller";
default:
break;
}
fixme("Unknown display controller %02x", SubclassCode);
return u8ToHexString(SubclassCode);
}
const char *CommunicationControllerSubclassName(uint8_t SubclassCode)
{
switch (SubclassCode)
{
case 0x00:
return "Serial Controller";
case 0x01:
return "Parallel Controller";
case 0x02:
return "Multi-Serial Controller";
case 0x03:
return "IEEE-1284 Controller";
case 0x04:
return "ATM Controller";
case 0x05:
return "Object Storage Controller";
case 0x80:
return "Communication controller";
default:
break;
}
fixme("Unknown communication controller %02x", SubclassCode);
return u8ToHexString(SubclassCode);
}
const char *BaseSystemPeripheralSubclassName(uint8_t SubclassCode)
{
// not sure if it's right
switch (SubclassCode)
{
case 0x00:
return "Unclassified";
case 0x01:
return "Keyboard";
case 0x02:
return "Pointing Device";
case 0x03:
return "Mouse";
case 0x04:
return "Scanner";
case 0x05:
return "Gameport";
case 0x80:
return "Unclassified";
default:
break;
}
fixme("Unknown base system peripheral %02x", SubclassCode);
return u8ToHexString(SubclassCode);
}
const char *SerialBusControllerSubclassName(uint8_t SubclassCode)
{
switch (SubclassCode)
{
case 0x00:
return "FireWire (IEEE 1394) Controller";
case 0x01:
return "ACCESS Bus Controller";
case 0x02:
return "SSA Controller";
case 0x03:
return "USB Controller";
case 0x04:
return "Fibre Channel Controller";
case 0x05:
return "SMBus Controller";
case 0x06:
return "Infiniband Controller";
case 0x07:
return "IPMI Interface Controller";
case 0x08:
return "SERCOS Interface (IEC 61491) Controller";
case 0x09:
return "CANbus Controller";
case 0x80:
return "Serial Bus Controller";
default:
break;
}
fixme("Unknown serial bus controller %02x", SubclassCode);
return u8ToHexString(SubclassCode);
}
const char *BridgeDeviceSubclassName(uint8_t SubclassCode)
{
switch (SubclassCode)
{
case 0x00:
return "Host Bridge";
case 0x01:
return "ISA Bridge";
case 0x02:
return "EISA Bridge";
case 0x03:
return "MCA Bridge";
case 0x04:
return "PCI-to-PCI Bridge";
case 0x05:
return "PCMCIA Bridge";
case 0x06:
return "NuBus Bridge";
case 0x07:
return "CardBus Bridge";
case 0x08:
return "RACEway Bridge";
case 0x09:
return "PCI-to-PCI Bridge";
case 0x0A:
return "InfiniBand-to-PCI Host Bridge";
case 0x80:
return "Bridge Device";
default:
break;
}
fixme("Unknown bridge device %02x", SubclassCode);
return u8ToHexString(SubclassCode);
}
const char *WirelessControllerSubclassName(uint8_t SubclassCode)
{
switch (SubclassCode)
{
case 0x11:
return "Bluetooth";
case 0x20:
return "802.1a controller";
case 0x21:
return "802.1b controller";
case 0x80:
return "Wireless controller";
default:
break;
}
fixme("Unknown wireless controller %02x", SubclassCode);
return u8ToHexString(SubclassCode);
}
const char *GetVendorName(uint32_t VendorID)
{
switch (VendorID)
{
case 0x1000:
return "Symbios Logic";
case 0x1B36:
case 0x1AF4:
return "Red Hat, Inc.";
case 0x10EC:
return "Realtek Semiconductor Co., Ltd.";
case 0x80EE:
return "VirtualBox";
case 0x1274:
return "Ensoniq";
case 0x1234:
return "QEMU";
case 0x15AD:
return "VMware";
case 0x8086:
return "Intel Corporation";
case 0x1022:
return "Advanced Micro Devices, Inc.";
case 0x10DE:
return "NVIDIA Corporation";
case 0x1AE0:
return "Google, Inc.";
case 0x1a58:
return "Razer USA Ltd.";
case 0x1414:
return "Microsoft Corporation";
default:
break;
}
fixme("Unknown vendor %04x", VendorID);
return u32ToHexString(VendorID);
}
const char *GetDeviceName(uint32_t VendorID, uint32_t DeviceID)
{
switch (VendorID)
{
case SymbiosLogic:
{
switch (DeviceID)
{
case 0x30:
return "53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI";
case 0x1000:
return "63C815";
default:
break;
}
break;
}
case RedHat:
{
switch (DeviceID)
{
case 0x1000:
case 0x1041:
return "Virtio network device";
case 0x1001:
case 0x1042:
return "Virtio block device";
case 0x1002:
case 0x1045:
return "Virtio memory balloon";
case 0x1003:
case 0x1043:
return "Virtio console";
case 0x1004:
case 0x1048:
return "Virtio SCSI";
case 0x1005:
case 0x1044:
return "Virtio RNG";
case 0x1009:
case 0x1049:
case 0x105a:
return "Virtio filesystem";
case 0x1050:
return "Virtio GPU";
case 0x1052:
return "Virtio input";
case 0x1053:
return "Virtio socket";
case 1110:
return "Inter-VM shared memory";
case 0x1af41100:
return "QEMU Virtual Machine";
default:
break;
}
break;
}
case REDHat2:
{
switch (DeviceID)
{
case 0x0001:
return "QEMU PCI-PCI bridge";
case 0x0002:
return "QEMU PCI 16550A Adapter";
case 0x0003:
return "QEMU PCI Dual-port 16550A Adapter";
case 0x0004:
return "QEMU PCI Quad-port 16550A Adapter";
case 0x0005:
return "QEMU PCI Test Device";
case 0x0006:
return "PCI Rocker Ethernet switch device";
case 0x0007:
return "PCI SD Card Host Controller Interface";
case 0x0008:
return "QEMU PCIe Host bridge";
case 0x0009:
return "QEMU PCI Expander bridge";
case 0x000A:
return "PCI-PCI bridge (multiseat)";
case 0x000B:
return "QEMU PCIe Expander bridge";
case 0x000C:
return "QEMU PCIe Root port";
case 0x000D:
return "QEMU XHCI Host Controller";
case 0x0010:
return "QEMU NVM Express Controller";
case 0x0100:
return "QXL paravirtual graphic card";
case 0x1AF41100:
return "QEMU Virtual Machine";
default:
break;
}
break;
}
case Realtek:
{
switch (DeviceID)
{
case 0x8029:
return "RTL-8029(AS)";
case 0x8139:
return "RTL-8139/8139C/8139C+ Ethernet Controller";
default:
break;
}
break;
}
case VirtualBox:
{
switch (DeviceID)
{
case 0xCAFE:
return "VirtualBox Guest Service";
case 0xBEEF:
return "VirtualBox Graphics Adapter";
case 0x0021:
return "USB Tablet";
case 0x0022:
return "Multitouch tablet";
case 0x4E56:
return "NVM Express";
default:
break;
}
break;
}
case Ensoniq:
{
switch (DeviceID)
{
case 0x1371:
return "ES1371/ES1373 / Creative Labs CT2518";
case 0x5000:
return "ES1370 [AudioPCI]";
default:
break;
}
break;
}
case QEMU:
{
switch (DeviceID)
{
case 0x1111:
return "QEMU Display";
default:
break;
}
break;
}
case VMware:
{
switch (DeviceID)
{
case 0x0740:
return "Virtual Machine Communication Interface";
case 0x0405:
return "SVGA II Adapter";
case 0x0790:
return "PCI bridge";
case 0x07A0:
return "PCI Express Root Port";
case 0x0774:
return "USB1.1 UHCI Controller";
case 0x0770:
return "USB2 EHCI Controller";
case 0x0779:
return "USB3 xHCI 1.0 Controller";
case 0x07E0:
return "SATA AHCI controller";
case 0x07F0:
return "NVM Express";
default:
break;
}
break;
}
case IntelCorporation:
{
switch (DeviceID)
{
case 0x1229:
return "82557/8/9/0/1 Ethernet Pro 100";
case 0x1209:
return "8255xER/82551IT Fast Ethernet Controller";
case 0x100E:
return "82540EM Gigabit Ethernet Controller";
case 0x7190:
return "440BX/ZX/DX - 82443BX/ZX/DX Host bridge";
case 0x7191:
return "440BX/ZX/DX - 82443BX/ZX/DX AGP bridge";
case 0x7110:
return "82371AB/EB/MB PIIX4 ISA";
case 0x7111:
return "82371AB/EB/MB PIIX4 IDE";
case 0x7113:
return "82371AB/EB/MB PIIX4 ACPI";
case 0x1e31:
return "7 Series/C210 Series Chipset Family USB xHCI Host Controller";
case 0x100F:
return "82545EM Gigabit Ethernet Controller (Copper)";
case 0x1371:
return "ES1371/ES1373 / Creative Labs CT2518";
case 0x27b9:
return "82801GBM (ICH7-M) LPC Interface Bridge";
case 0x07E0:
return "SATA AHCI controller";
case 0x293E:
return "82801I (ICH9 Family) HD Audio Controller";
case 0x2935:
return "82801I (ICH9 Family) USB UHCI Controller #2";
case 0x2936:
return "82801I (ICH9 Family) USB UHCI Controller #3";
case 0x293A:
return "82801I (ICH9 Family) USB2 EHCI Controller #1";
case 0x2934:
return "82801I (ICH9 Family) USB UHCI Controller #1";
case 0x2668:
return "82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller";
case 0x2415:
return "82801AA AC'97 Audio Controller";
case 0x10D3:
return "82574L Gigabit Network Connection";
case 0x29C0:
return "82G33/G31/P35/P31 Express DRAM Controller";
case 0x2918:
return "82801IB (ICH9) LPC Interface Controller";
case 0x2829:
return "82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode]";
case 0x2922:
return "82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode]";
case 0x2930:
return "82801I (ICH9 Family) SMBus Controller";
default:
break;
}
break;
}
case AdvancedMicroDevices:
{
switch (DeviceID)
{
case 0x2000:
return "79C970 [PCnet32 LANCE]";
default:
break;
}
break;
}
}
fixme("Unknown device %04x:%04x", VendorID, DeviceID);
return u32ToHexString(DeviceID);
}
const char *GetSubclassName(uint8_t ClassCode, uint8_t SubclassCode)
{
switch (ClassCode)
{
case 0x00:
return "Unclassified";
case 0x01:
return MassStorageControllerSubclassName(SubclassCode);
case 0x02:
return NetworkControllerSubclassName(SubclassCode);
case 0x03:
return DisplayControllerSubclassName(SubclassCode);
case 0x04:
return "Multimedia controller";
case 0x05:
return "Memory Controller";
case 0x06:
return BridgeDeviceSubclassName(SubclassCode);
case 0x07:
return CommunicationControllerSubclassName(SubclassCode);
case 0x08:
return BaseSystemPeripheralSubclassName(SubclassCode);
case 0x09:
return "Input device controller";
case 0x0A:
return "Docking station";
case 0x0B:
return "Processor";
case 0x0C:
return SerialBusControllerSubclassName(SubclassCode);
case 0x0D:
return WirelessControllerSubclassName(SubclassCode);
case 0x0E:
return "Intelligent controller";
case 0x0F:
return "Satellite communication controller";
case 0x10:
return "Encryption controller";
case 0x11:
return "Signal processing accelerators";
case 0x12:
return "Processing accelerators";
case 0x13:
return "Non-Essential Instrumentation";
case 0x40:
return "Coprocessor";
default:
break;
}
fixme("Unknown subclass name %02x:%02x", ClassCode, SubclassCode);
return u8ToHexString(SubclassCode);
}
const char *GetProgIFName(uint8_t ClassCode, uint8_t SubclassCode, uint8_t ProgIF)
{
switch (ClassCode)
{
case 0x01:
{
switch (SubclassCode)
{
case 0x06:
{
switch (ProgIF)
{
case 0:
return "Vendor Specific SATA Controller";
case 1:
return "AHCI SATA Controller";
case 2:
return "Serial Storage Bus SATA Controller";
default:
return "SATA controller";
}
break;
}
case 0x08:
{
switch (ProgIF)
{
case 0x01:
return "NVMHCI Controller";
case 0x02:
return "NVM Express Controller";
default:
return "Non-Volatile Memory Controller";
}
break;
}
}
break;
}
case 0x03:
{
switch (SubclassCode)
{
case 0x00:
switch (ProgIF)
{
case 0x00:
return "VGA Controller";
case 0x01:
return "8514-Compatible Controller";
default:
return "VGA Compatible Controller";
}
break;
}
break;
}
case 0x07:
{
switch (SubclassCode)
{
case 0x00:
{
switch (ProgIF)
{
case 0x00:
return "Serial controller <8250>";
case 0x01:
return "Serial controller <16450>";
case 0x02:
return "Serial controller <16550>";
case 0x03:
return "Serial controller <16650>";
case 0x04:
return "Serial controller <16750>";
case 0x05:
return "Serial controller <16850>";
case 0x06:
return "Serial controller <16950";
default:
return "Serial controller";
}
break;
}
default:
break;
}
break;
}
case 0x0C:
{
switch (SubclassCode)
{
case 0x00:
{
switch (ProgIF)
{
case 0x00:
return "Generic FireWire (IEEE 1394) Controller";
case 0x10:
return "OHCI FireWire (IEEE 1394) Controller";
default:
break;
}
break;
}
case 0x03:
{
switch (ProgIF)
{
case 0x00:
return "UHCI (USB1) Controller";
case 0x10:
return "OHCI (USB1) Controller";
case 0x20:
return "EHCI (USB2) Controller";
case 0x30:
return "XHCI (USB3) Controller";
case 0x80:
return "Unspecified";
case 0xFE:
return "USB Device";
default:
break;
}
break;
}
default:
break;
}
break;
}
}
// not really a fixme
// fixme("Unknown prog IF name %02x:%02x:%02x", ClassCode, SubclassCode, ProgIF);
return u8ToHexString(ProgIF);
}
}
#ifdef DEBUG
void e(PCIDeviceHeader *hdr)
{
debug("%s / %s / %s / %s / %s",
Descriptors::GetVendorName(hdr->VendorID),
Descriptors::GetDeviceName(hdr->VendorID, hdr->DeviceID),
Descriptors::DeviceClasses[hdr->Class],
Descriptors::GetSubclassName(hdr->Class, hdr->Subclass),
Descriptors::GetProgIFName(hdr->Class, hdr->Subclass, hdr->ProgIF));
}
#endif
void PCI::EnumerateFunction(uint64_t DeviceAddress, uint64_t Function)
{
uint64_t Offset = Function << 12;
uint64_t FunctionAddress = DeviceAddress + Offset;
Memory::Virtual().Map((void *)FunctionAddress, (void *)FunctionAddress, Memory::PTFlag::RW);
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)FunctionAddress;
if (PCIDeviceHdr->DeviceID == 0)
return;
if (PCIDeviceHdr->DeviceID == 0xFFFF)
return;
Devices.push_back(PCIDeviceHdr);
#ifdef DEBUG
e(PCIDeviceHdr);
#endif
}
void PCI::EnumerateDevice(uint64_t BusAddress, uint64_t Device)
{
uint64_t Offset = Device << 15;
uint64_t DeviceAddress = BusAddress + Offset;
Memory::Virtual().Map((void *)DeviceAddress, (void *)DeviceAddress, Memory::PTFlag::RW);
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)DeviceAddress;
if (PCIDeviceHdr->DeviceID == 0)
return;
if (PCIDeviceHdr->DeviceID == 0xFFFF)
return;
for (uint64_t Function = 0; Function < 8; Function++)
EnumerateFunction(DeviceAddress, Function);
}
void PCI::EnumerateBus(uint64_t BaseAddress, uint64_t Bus)
{
uint64_t Offset = Bus << 20;
uint64_t BusAddress = BaseAddress + Offset;
Memory::Virtual().Map((void *)BusAddress, (void *)BusAddress, Memory::PTFlag::RW);
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)BusAddress;
if (Bus != 0) // TODO: VirtualBox workaround (UNTESTED ON REAL HARDWARE!)
{
if (PCIDeviceHdr->DeviceID == 0)
return;
if (PCIDeviceHdr->DeviceID == 0xFFFF)
return;
}
trace("PCI Bus DeviceID:%#llx VendorID:%#llx BIST:%#llx Cache:%#llx Class:%#llx Cmd:%#llx HdrType:%#llx LatencyTimer:%#llx ProgIF:%#llx RevID:%#llx Status:%#llx SubClass:%#llx ",
PCIDeviceHdr->DeviceID, PCIDeviceHdr->VendorID, PCIDeviceHdr->BIST,
PCIDeviceHdr->CacheLineSize, PCIDeviceHdr->Class, PCIDeviceHdr->Command,
PCIDeviceHdr->HeaderType, PCIDeviceHdr->LatencyTimer, PCIDeviceHdr->ProgIF,
PCIDeviceHdr->RevisionID, PCIDeviceHdr->Status, PCIDeviceHdr->Subclass);
for (uint64_t Device = 0; Device < 32; Device++)
EnumerateDevice(BusAddress, Device);
}
Vector<PCIDeviceHeader *> PCI::FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF)
{
Vector<PCIDeviceHeader *> DeviceFound;
for (auto var : Devices)
if (var->Class == Class && var->Subclass == Subclass && var->ProgIF == ProgIF)
DeviceFound.push_back(var);
return DeviceFound;
}
Vector<PCIDeviceHeader *> PCI::FindPCIDevice(int VendorID, int DeviceID)
{
Vector<PCIDeviceHeader *> DeviceFound;
for (auto var : Devices)
if (var->VendorID == VendorID && var->DeviceID == DeviceID)
DeviceFound.push_back(var);
return DeviceFound;
}
PCI::PCI()
{
#if defined(__amd64__)
int Entries = ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig);
for (int t = 0; t < Entries; t++)
{
DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uint64_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
Memory::Virtual().Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW);
trace("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress,
NewDeviceConfig->StartBus, NewDeviceConfig->EndBus);
for (uint64_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++)
EnumerateBus(NewDeviceConfig->BaseAddress, Bus);
}
#elif defined(__i386__)
error("PCI not implemented on i386");
#elif defined(__aarch64__)
error("PCI not implemented on aarch64");
#endif
}
PCI::~PCI()
{
}
}

125
Kernel/Core/Power.cpp Normal file
View File

@ -0,0 +1,125 @@
#include <power.hpp>
#include <memory.hpp>
#include <debug.h>
#include "../kernel.h"
#if defined(__amd64__)
#include <io.h>
#include "../Architecture/amd64/acpi.hpp"
namespace Power
{
void Power::Reboot()
{
BeforeShutdown();
if (((ACPI::ACPI *)this->acpi)->FADT)
if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported)
((ACPI::DSDT *)this->dsdt)->Reboot();
uint8_t val = 0x02;
while (val & 0x02)
val = inb(0x64);
outb(0x64, 0xFE);
warn("Executing the second attempt to reboot...");
// second attempt to reboot
// https://wiki.osdev.org/Reboot
uint8_t temp;
asmv("cli");
do
{
temp = inb(0x64);
if (((temp) & (1 << (0))) != 0)
inb(0x60);
} while (((temp) & (1 << (1))) != 0);
outb(0x64, 0xFE);
CPU::Stop();
}
void Power::Shutdown()
{
BeforeShutdown();
if (((ACPI::ACPI *)this->acpi)->FADT)
if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported)
((ACPI::DSDT *)this->dsdt)->Shutdown();
outl(0xB004, 0x2000); // for qemu
outl(0x604, 0x2000); // if qemu not working, bochs and older versions of qemu
outl(0x4004, 0x3400); // virtual box
CPU::Stop();
}
void Power::InitDSDT()
{
if (((ACPI::ACPI *)this->acpi)->FADT)
this->dsdt = new ACPI::DSDT((ACPI::ACPI *)acpi);
}
Power::Power()
{
this->acpi = new ACPI::ACPI(bInfo);
this->madt = new ACPI::MADT(((ACPI::ACPI *)acpi)->MADT);
trace("Power manager initialized");
}
Power::~Power()
{
}
}
#elif defined(__i386__)
namespace Power
{
void Power::Reboot()
{
warn("Reboot not implemented for i386");
}
void Power::Shutdown()
{
warn("Shutdown not implemented for i386");
}
Power::Power()
{
error("Power not implemented for i386");
}
Power::~Power()
{
}
}
#elif defined(__aarch64__)
namespace Power
{
void Power::Reboot()
{
warn("Reboot not implemented for aarch64");
}
void Power::Shutdown()
{
warn("Shutdown not implemented for aarch64");
}
Power::Power()
{
error("Power not implemented for aarch64");
}
Power::~Power()
{
}
}
#endif

22
Kernel/Core/README.md Normal file
View File

@ -0,0 +1,22 @@
# Core components
This directory contains the core components of the project. These components are used by the kernel to provide the basic functionality of the operating system.
---
## 💾 Memory
Contains the memory management code.
It is responsible for allocating and freeing memory.
It also provides the `kmalloc`, `kcalloc`, `krealloc` and `kfree` functions that are used by the rest of the kernel.
## 📺 Video
Contains the video management code.
It is responsible for printing text to the screen.
## 🖥 CPU
Contains the CPU management code.
It is responsible for initializing the GDT and IDT.
More code related is in the `Architecture` directory.

27
Kernel/Core/Random.cpp Normal file
View File

@ -0,0 +1,27 @@
#include <rand.hpp>
namespace Random
{
static uint64_t Seed = 0xdeadbeef;
uint16_t rand16()
{
Seed = Seed * 1103515245 + 12345;
return (uint16_t)(Seed / 65536) % __UINT16_MAX__;
}
uint32_t rand32()
{
Seed = Seed * 1103515245 + 12345;
return (uint32_t)(Seed / 65536) % __UINT32_MAX__;
}
uint64_t rand64()
{
Seed = Seed * 1103515245 + 12345;
return (uint64_t)(Seed / 65536) % __UINT64_MAX__;
}
void changeseed(uint64_t CustomSeed) { Seed = CustomSeed; }
}

56
Kernel/Core/StackGuard.c Normal file
View File

@ -0,0 +1,56 @@
#include <types.h>
#include <debug.h>
#include "../kernel.h"
#ifndef STACK_CHK_GUARD_VALUE
#if UINTPTR_MAX == UINT32_MAX
#define STACK_CHK_GUARD_VALUE 0xDEAD57AC
#else
#define STACK_CHK_GUARD_VALUE 0xDEAD57AC00000000
#endif
#endif
__attribute__((weak)) uintptr_t __stack_chk_guard = 0;
__attribute__((weak, no_stack_protector)) uintptr_t __stack_chk_guard_init(void)
{
return STACK_CHK_GUARD_VALUE;
}
extern __attribute__((constructor, no_stack_protector)) void __guard_setup(void)
{
debug("StackGuard: __guard_setup");
if (__stack_chk_guard == 0)
__stack_chk_guard = __stack_chk_guard_init();
}
__attribute__((weak, noreturn, no_stack_protector)) void __stack_chk_fail(void)
{
TaskingPanic();
for (short i = 0; i < 10; i++)
error("Stack smashing detected!");
debug("%#lx", __stack_chk_guard);
KPrint("\eFF0000Stack smashing detected!");
#if defined(__amd64__) || defined(__i386__)
while (1)
asmv("cli; hlt");
#elif defined(__aarch64__)
asmv("wfe");
#endif
}
// https://github.com/gcc-mirror/gcc/blob/master/libssp/ssp.c
__attribute__((weak, noreturn, no_stack_protector)) void __chk_fail(void)
{
TaskingPanic();
for (short i = 0; i < 10; i++)
error("Buffer overflow detected!");
KPrint("\eFF0000Buffer overflow detected!");
#if defined(__amd64__) || defined(__i386__)
while (1)
asmv("cli; hlt");
#elif defined(__aarch64__)
asmv("wfe");
#endif
}

134
Kernel/Core/Symbols.cpp Normal file
View File

@ -0,0 +1,134 @@
#include <symbols.hpp>
#include <memory.hpp>
#include <convert.h>
#include <debug.h>
// #pragma GCC diagnostic ignored "-Wignored-qualifiers"
typedef struct
{
unsigned char e_ident[16];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff;
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Elf64_Ehdr;
typedef struct
{
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
} Elf64_Shdr;
typedef struct
{
uint32_t st_name;
unsigned char st_info;
unsigned char st_other;
uint16_t st_shndx;
uint64_t st_value;
uint64_t st_size;
} Elf64_Sym;
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
namespace SymbolResolver
{
Symbols::SymbolTable SymTable[0x10000];
uint64_t TotalEntries = 0;
Symbols::Symbols(uint64_t Address)
{
debug("Solving symbols for address: %#llx", Address);
Elf64_Ehdr *Header = (Elf64_Ehdr *)Address;
if (Header->e_ident[0] != 0x7F &&
Header->e_ident[1] != 'E' &&
Header->e_ident[2] != 'L' &&
Header->e_ident[3] != 'F')
{
error("Invalid ELF header");
return;
}
Elf64_Shdr *ElfSections = (Elf64_Shdr *)(Address + Header->e_shoff);
Elf64_Sym *ElfSymbols = nullptr;
char *strtab = nullptr;
for (uint64_t i = 0; i < Header->e_shnum; i++)
switch (ElfSections[i].sh_type)
{
case SHT_SYMTAB:
ElfSymbols = (Elf64_Sym *)(Address + ElfSections[i].sh_offset);
TotalEntries = ElfSections[i].sh_size / sizeof(Elf64_Sym);
debug("Symbol table found, %d entries", TotalEntries);
break;
case SHT_STRTAB:
if (Header->e_shstrndx == i)
{
debug("String table found, %d entries", ElfSections[i].sh_size);
}
else
{
strtab = (char *)Address + ElfSections[i].sh_offset;
debug("String table found, %d entries", ElfSections[i].sh_size);
}
break;
}
if (ElfSymbols != nullptr && strtab != nullptr)
{
size_t Index, MinimumIndex;
for (size_t i = 0; i < TotalEntries - 1; i++)
{
MinimumIndex = i;
for (Index = i + 1; Index < TotalEntries; Index++)
if (ElfSymbols[Index].st_value < ElfSymbols[MinimumIndex].st_value)
MinimumIndex = Index;
Elf64_Sym tmp = ElfSymbols[MinimumIndex];
ElfSymbols[MinimumIndex] = ElfSymbols[i];
ElfSymbols[i] = tmp;
}
while (ElfSymbols[0].st_value == 0)
{
ElfSymbols++;
TotalEntries--;
}
trace("Symbol table loaded, %d entries (%ldKB)", TotalEntries, TO_KB(TotalEntries * sizeof(SymbolTable)));
for (size_t i = 0, g = TotalEntries; i < g; i++)
{
SymTable[i].Address = ElfSymbols[i].st_value;
SymTable[i].FunctionName = &strtab[ElfSymbols[i].st_name];
}
}
}
Symbols::~Symbols() {}
const __no_instrument_function char *Symbols::GetSymbolFromAddress(uint64_t Address)
{
Symbols::SymbolTable Result{0, (char *)"<unknown>"};
for (size_t i = 0; i < TotalEntries; i++)
if (SymTable[i].Address <= Address && SymTable[i].Address > Result.Address)
Result = SymTable[i];
return Result.FunctionName;
}
}

View File

@ -0,0 +1,70 @@
#include "smbios.hpp"
#include <debug.h>
#include "../kernel.h"
/* https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.2.0.pdf */
namespace SMBIOS
{
bool CheckSMBIOS()
{
if (bInfo->SMBIOSPtr != nullptr && bInfo->SMBIOSPtr < (void *)0xffffffffffff0000)
{
debug("SMBIOS is available (%#lx).", bInfo->SMBIOSPtr);
return true;
}
debug("SMBIOS is not available. (%#lx)", bInfo->SMBIOSPtr);
return false;
}
SMBIOSEntryPoint *GetSMBIOSEntryPoint() { return (SMBIOSEntryPoint *)bInfo->SMBIOSPtr; }
static inline int SMBIOSTableLength(SMBIOSHeader *Hdr)
{
int i;
const char *strtab = (char *)Hdr + Hdr->Length;
for (i = 1; strtab[i - 1] != '\0' || strtab[i] != '\0'; i++)
;
return Hdr->Length + i + 1;
}
void *GetSMBIOSHeader(SMBIOSType Type)
{
if (!CheckSMBIOS())
return nullptr;
SMBIOSEntryPoint *Header = (SMBIOSEntryPoint *)bInfo->SMBIOSPtr;
debug("Getting SMBIOS header for type %d", Type);
struct SMBIOSHeader *hdr = (SMBIOSHeader *)(uint64_t)Header->TableAddress;
for (int i = 0; i <= 11; i++)
{
if (hdr < (void *)(uint64_t)(Header->TableAddress + Header->TableLength))
if (hdr->Type == Type)
{
debug("Found SMBIOS header for type %d at %#lx", Type, hdr);
return hdr;
}
hdr = (struct SMBIOSHeader *)((uint64_t)hdr + SMBIOSTableLength(hdr));
}
return nullptr;
}
SMBIOSBIOSInformation *GetBIOSInformation() { return (SMBIOSBIOSInformation *)GetSMBIOSHeader(SMBIOSTypeBIOSInformation); }
SMBIOSSystemInformation *GetSystemInformation() { return (SMBIOSSystemInformation *)GetSMBIOSHeader(SMBIOSTypeSystemInformation); }
SMBIOSBaseBoardInformation *GetBaseBoardInformation() { return (SMBIOSBaseBoardInformation *)GetSMBIOSHeader(SMBIOSTypeBaseBoardInformation); }
SMBIOSProcessorInformation *GetProcessorInformation() { return (SMBIOSProcessorInformation *)GetSMBIOSHeader(SMBIOSTypeProcessorInformation); }
SMBIOSMemoryArray *GetMemoryArray() { return (SMBIOSMemoryArray *)GetSMBIOSHeader(SMBIOSTypePhysicalMemoryArray); }
SMBIOSMemoryDevice *GetMemoryDevice() { return (SMBIOSMemoryDevice *)GetSMBIOSHeader(SMBIOSTypeMemoryDevice); }
SMBIOSMemoryArrayMappedAddress *GetMemoryArrayMappedAddress() { return (SMBIOSMemoryArrayMappedAddress *)GetSMBIOSHeader(SMBIOSTypeMemoryArrayMappedAddress); }
SMBIOSMemoryDeviceMappedAddress *GetMemoryDeviceMappedAddress() { return (SMBIOSMemoryDeviceMappedAddress *)GetSMBIOSHeader(SMBIOSTypeMemoryDeviceMappedAddress); }
}

41
Kernel/Core/Time.cpp Normal file
View File

@ -0,0 +1,41 @@
#include <time.hpp>
#include <io.h>
namespace Time
{
Clock ReadClock()
{
Clock tm;
#if defined(__amd64__) || defined(__i386__)
uint32_t t = 0;
outb(0x70, 0x00);
t = inb(0x71);
tm.Second = ((t & 0x0F) + ((t >> 4) * 10));
outb(0x70, 0x02);
t = inb(0x71);
tm.Minute = ((t & 0x0F) + ((t >> 4) * 10));
outb(0x70, 0x04);
t = inb(0x71);
tm.Hour = ((t & 0x0F) + ((t >> 4) * 10));
outb(0x70, 0x07);
t = inb(0x71);
tm.Day = ((t & 0x0F) + ((t >> 4) * 10));
outb(0x70, 0x08);
t = inb(0x71);
tm.Month = ((t & 0x0F) + ((t >> 4) * 10));
outb(0x70, 0x09);
t = inb(0x71);
tm.Year = ((t & 0x0F) + ((t >> 4) * 10));
tm.Counter = 0;
#elif defined(__aarch64__)
tm.Year = 0;
tm.Month = 0;
tm.Day = 0;
tm.Hour = 0;
tm.Minute = 0;
tm.Second = 0;
tm.Counter = 0;
#endif
return tm;
}
}

58
Kernel/Core/Timer.cpp Normal file
View File

@ -0,0 +1,58 @@
#include <time.hpp>
#include <memory.hpp>
#include <debug.h>
#include <io.h>
#if defined(__amd64__)
#include "../Architecture/amd64/acpi.hpp"
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
namespace Time
{
void time::Sleep(uint64_t Milliseconds)
{
#if defined(__amd64__) || defined(__i386__)
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000) / clk;
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
CPU::Pause();
#elif defined(__aarch64__)
#endif
}
time::time(void *_acpi)
{
if (_acpi)
{
#if defined(__amd64__)
this->acpi = _acpi;
ACPI::ACPI *acpi = (ACPI::ACPI *)this->acpi;
if (acpi->HPET)
{
Memory::Virtual().Map((void *)acpi->HPET->Address.Address,
(void *)acpi->HPET->Address.Address,
Memory::PTFlag::RW | Memory::PTFlag::PCD);
this->hpet = (void *)acpi->HPET->Address.Address;
HPET *hpet = (HPET *)this->hpet;
trace("%s timer is at address %016p", acpi->HPET->Header.OEMID, (void *)acpi->HPET->Address.Address);
clk = hpet->GeneralCapabilities >> 32;
mmoutq(&hpet->GeneralConfiguration, 0);
mmoutq(&hpet->MainCounterValue, 0);
mmoutq(&hpet->GeneralConfiguration, 1);
}
else
{
trace("HPET not found");
}
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
}
}
time::~time()
{
}
}

View File

@ -0,0 +1,283 @@
#include "ubsan.h"
#include <convert.h>
#include <debug.h>
// TODO: implement:
/*
__ubsan_handle_type_mismatch_v1_abort
__ubsan_handle_add_overflow_abort
__ubsan_handle_sub_overflow_abort
__ubsan_handle_mul_overflow_abort
__ubsan_handle_negate_overflow_abort
__ubsan_handle_divrem_overflow_abort
__ubsan_handle_shift_out_of_bounds_abort
__ubsan_handle_out_of_bounds_abort
__ubsan_handle_vla_bound_not_positive_abort
__ubsan_handle_float_cast_overflow
__ubsan_handle_float_cast_overflow_abort
__ubsan_handle_load_invalid_value_abort
__ubsan_handle_invalid_builtin_abort
__ubsan_handle_function_type_mismatch_abort
__ubsan_handle_nonnull_return_v1
__ubsan_handle_nonnull_return_v1_abort
__ubsan_handle_nullability_return_v1
__ubsan_handle_nullability_return_v1_abort
__ubsan_handle_nonnull_arg_abort
__ubsan_handle_nullability_arg
__ubsan_handle_nullability_arg_abort
__ubsan_handle_pointer_overflow_abort
__ubsan_handle_cfi_check_fail
*/
extern void __asan_report_load1(void *unknown) { ubsan("load1"); }
extern void __asan_report_load2(void *unknown) { ubsan("load2"); }
extern void __asan_report_load4(void *unknown) { ubsan("load4"); }
extern void __asan_report_load8(void *unknown) { ubsan("load8"); }
extern void __asan_report_load16(void *unknown) { ubsan("load16"); }
extern void __asan_report_load_n(void *unknown, uintptr_t size) { ubsan("loadn"); }
extern void __asan_report_store1(void *unknown) { ubsan("store1"); }
extern void __asan_report_store2(void *unknown) { ubsan("store2"); }
extern void __asan_report_store4(void *unknown) { ubsan("store4"); }
extern void __asan_report_store8(void *unknown) { ubsan("store8"); }
extern void __asan_report_store16(void *unknown) { ubsan("store16"); }
extern void __asan_report_store_n(void *unknown, uintptr_t size) { ubsan("storen"); }
extern void __asan_report_load1_noabort(void *unknown) { ubsan("load1"); }
extern void __asan_report_load2_noabort(void *unknown) { ubsan("load2"); }
extern void __asan_report_load4_noabort(void *unknown) { ubsan("load4"); }
extern void __asan_report_load8_noabort(void *unknown) { ubsan("load8"); }
extern void __asan_report_load16_noabort(void *unknown) { ubsan("load16"); }
extern void __asan_report_load_n_noabort(void *unknown, uintptr_t size) { ubsan("loadn"); }
extern void __asan_report_store1_noabort(void *unknown) { ubsan("store1"); }
extern void __asan_report_store2_noabort(void *unknown) { ubsan("store2"); }
extern void __asan_report_store4_noabort(void *unknown) { ubsan("store4"); }
extern void __asan_report_store8_noabort(void *unknown) { ubsan("store8"); }
extern void __asan_report_store16_noabort(void *unknown) { ubsan("store16"); }
extern void __asan_report_store_n_noabort(void *unknown, uintptr_t size) { ubsan("storen"); }
extern void __asan_stack_malloc_0(uintptr_t size) { ubsan("stack malloc 0"); }
extern void __asan_stack_malloc_1(uintptr_t size) { ubsan("stack malloc 1"); }
extern void __asan_stack_malloc_2(uintptr_t size) { ubsan("stack malloc 2"); }
extern void __asan_stack_malloc_3(uintptr_t size) { ubsan("stack malloc 3"); }
extern void __asan_stack_malloc_4(uintptr_t size) { ubsan("stack malloc 4"); }
extern void __asan_stack_malloc_5(uintptr_t size) { ubsan("stack malloc 5"); }
extern void __asan_stack_malloc_6(uintptr_t size) { ubsan("stack malloc 6"); }
extern void __asan_stack_malloc_7(uintptr_t size) { ubsan("stack malloc 7"); }
extern void __asan_stack_malloc_8(uintptr_t size) { ubsan("stack malloc 8"); }
extern void __asan_stack_malloc_9(uintptr_t size) { ubsan("stack malloc 9"); }
extern void __asan_stack_free_0(void *ptr, uintptr_t size) { ubsan("stack free 0"); }
extern void __asan_stack_free_1(void *ptr, uintptr_t size) { ubsan("stack free 1"); }
extern void __asan_stack_free_2(void *ptr, uintptr_t size) { ubsan("stack free 2"); }
extern void __asan_stack_free_3(void *ptr, uintptr_t size) { ubsan("stack free 3"); }
extern void __asan_stack_free_4(void *ptr, uintptr_t size) { ubsan("stack free 4"); }
extern void __asan_stack_free_5(void *ptr, uintptr_t size) { ubsan("stack free 5"); }
extern void __asan_stack_free_6(void *ptr, uintptr_t size) { ubsan("stack free 6"); }
extern void __asan_stack_free_7(void *ptr, uintptr_t size) { ubsan("stack free 7"); }
extern void __asan_stack_free_8(void *ptr, uintptr_t size) { ubsan("stack free 8"); }
extern void __asan_stack_free_9(void *ptr, uintptr_t size) { ubsan("stack free 9"); }
extern void __asan_poison_stack_memory(void *addr, uintptr_t size) { ubsan("poison stack memory"); }
extern void __asan_unpoison_stack_memory(void *addr, uintptr_t size) { ubsan("unpoison stack memory"); }
extern void __asan_before_dynamic_init(const char *module_name) { ubsan("before dynamic init"); }
extern void __asan_after_dynamic_init(void) { ubsan("after dynamic init"); }
extern void __asan_register_globals(void *unknown, size_t size) { ubsan("register_globals"); }
extern void __asan_unregister_globals(void) { ubsan("unregister_globals"); }
extern void __asan_init(void) { ubsan("init"); }
extern void __asan_version_mismatch_check_v8(void) { ubsan("version_mismatch_check_v8"); }
extern void __asan_option_detect_stack_use_after_return(void) { ubsan("stack use after return"); }
extern __noreturn void __asan_handle_no_return(void)
{
ubsan("no_return");
while (1)
;
}
#define is_aligned(value, alignment) !(value & (alignment - 1))
const char *Type_Check_Kinds[] = {
"Load of",
"Store to",
"Reference binding to",
"Member access within",
"Member call on",
"Constructor call on",
"Downcast of",
"Downcast of",
"Upcast of",
"Cast to virtual base of",
};
bool UBSANMsg(const char *file, uint32_t line, uint32_t column)
{
// blacklist
// if (strstr(file, "liballoc") ||
// strstr(file, "cwalk") ||
// strstr(file, "AdvancedConfigurationandPowerInterface") ||
// strstr(file, "SystemManagementBIOS"))
// return false;
if (strstr(file, "AdvancedConfigurationandPowerInterface.cpp") &&
(line == 17 && column == 47))
return false;
if (strstr(file, "SystemManagementBIOS.cpp") &&
((line == 30 && column == 21) ||
(line == 27 && column == 49) ||
(line == 45 && column == 26)))
return false;
if (strstr(file, "cwalk.c") &&
((line == 1047 && column == 15)))
return false;
if (strstr(file, "liballoc_1_1.c"))
return false;
if (strstr(file, "display.hpp") &&
((line == 113 && column == 43)))
return false;
if (strstr(file, "Xalloc.hpp") &&
(line == 48 && column == 28))
return false;
ubsan("\t\tIn File: %s:%i:%i", file, line, column);
return true;
}
void __ubsan_handle_type_mismatch_v1(struct type_mismatch_v1_data *type_mismatch, uintptr_t pointer)
{
struct source_location *location = &type_mismatch->location;
if (pointer == 0)
{
if (UBSANMsg(location->file, location->line, location->column))
ubsan("Null pointer access.");
}
else if (type_mismatch->alignment != 0 && is_aligned(pointer, type_mismatch->alignment))
{
if (UBSANMsg(location->file, location->line, location->column))
ubsan("Unaligned memory access %#llx.", pointer);
}
else
{
if (UBSANMsg(location->file, location->line, location->column))
ubsan("%s address %#llx with insufficient space for object of type %s",
Type_Check_Kinds[type_mismatch->type_check_kind], (void *)pointer, type_mismatch->type->name);
}
}
void __ubsan_handle_add_overflow(struct overflow_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Addition overflow.");
}
void __ubsan_handle_sub_overflow(struct overflow_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Subtraction overflow.");
}
void __ubsan_handle_mul_overflow(struct overflow_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Multiplication overflow.");
}
void __ubsan_handle_divrem_overflow(struct overflow_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Division overflow.");
}
void __ubsan_handle_negate_overflow(struct overflow_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Negation overflow.");
}
void __ubsan_handle_pointer_overflow(struct overflow_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Pointer overflow.");
}
void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Shift out of bounds.");
}
void __ubsan_handle_load_invalid_value(struct invalid_value_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Invalid load value.");
}
void __ubsan_handle_out_of_bounds(struct array_out_of_bounds_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Array out of bounds.");
}
void __ubsan_handle_vla_bound_not_positive(struct negative_vla_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Variable-length argument is negative.");
}
void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Non-null return is null.");
}
void __ubsan_handle_nonnull_return_v1(struct nonnull_return_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Non-null return is null.");
}
void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Non-null argument is null.");
}
void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Unreachable code reached.");
}
void __ubsan_handle_invalid_builtin(struct invalid_builtin_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Invalid builtin.");
}
void __ubsan_handle_missing_return(struct unreachable_data *data)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Missing return.");
}
void __ubsan_vptr_type_cache(uintptr_t *cache, uintptr_t ptr)
{
ubsan("Vptr type cache.");
*cache = ptr;
}
void __ubsan_handle_dynamic_type_cache_miss(struct dynamic_type_cache_miss_data *data, uintptr_t ptr)
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Dynamic type cache miss.");
}

View File

@ -0,0 +1,148 @@
#include <uart.hpp>
#include <vector.hpp>
#include <debug.h>
volatile bool serialports[8] = {false, false, false, false, false, false, false, false};
Vector<UniversalAsynchronousReceiverTransmitter::Events *> RegisteredEvents;
#if defined(__amd64__) || defined(__i386__)
__no_instrument_function uint8_t NoProfiler_inportb(uint16_t Port)
{
uint8_t Result;
asm("in %%dx, %%al"
: "=a"(Result)
: "d"(Port));
return Result;
}
__no_instrument_function void NoProfiler_outportb(uint16_t Port, uint8_t Data)
{
asmv("out %%al, %%dx"
:
: "a"(Data), "d"(Port));
}
#endif
namespace UniversalAsynchronousReceiverTransmitter
{
#define SERIAL_ENABLE_DLAB 0x80
#define SERIAL_RATE_38400_LO 0x03
#define SERIAL_RATE_38400_HI 0x00
#define SERIAL_BUFFER_EMPTY 0x20
SafeFunction __no_instrument_function UART::UART(SerialPorts Port)
{
#if defined(__amd64__) || defined(__i386__)
if (Port == COMNULL)
return;
this->Port = Port;
int PortNumber = 0;
switch (Port)
{
case COM1:
PortNumber = 0;
break;
case COM2:
PortNumber = 1;
break;
case COM3:
PortNumber = 2;
break;
case COM4:
PortNumber = 3;
break;
case COM5:
PortNumber = 4;
break;
case COM6:
PortNumber = 5;
break;
case COM7:
PortNumber = 6;
break;
case COM8:
PortNumber = 7;
break;
default:
return;
}
if (serialports[PortNumber])
return;
// Initialize the serial port
NoProfiler_outportb(Port + 1, 0x00); // Disable all interrupts
NoProfiler_outportb(Port + 3, SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor)
NoProfiler_outportb(Port + 0, SERIAL_RATE_38400_LO); // Set divisor to 3 (lo byte) 38400 baud
NoProfiler_outportb(Port + 1, SERIAL_RATE_38400_HI); // (hi byte)
NoProfiler_outportb(Port + 3, 0x03); // 8 bits, no parity, one stop bit
NoProfiler_outportb(Port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
NoProfiler_outportb(Port + 4, 0x0B); // IRQs enabled, RTS/DSR set
// Check if the serial port is faulty.
if (NoProfiler_inportb(Port + 0) != 0xAE)
{
static int once = 0;
if (!once++)
warn("Serial port %#llx is faulty.", Port);
// serialports[Port] = false; // ignore for now
// return;
}
// Set to normal operation mode.
NoProfiler_outportb(Port + 4, 0x0F);
serialports[PortNumber] = true;
#endif
}
SafeFunction __no_instrument_function UART::~UART() {}
SafeFunction __no_instrument_function void UART::Write(uint8_t Char)
{
#if defined(__amd64__) || defined(__i386__)
while ((NoProfiler_inportb(Port + 5) & SERIAL_BUFFER_EMPTY) == 0)
;
NoProfiler_outportb(Port, Char);
#endif
foreach (auto e in RegisteredEvents)
if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL)
e->OnSent(Char);
}
SafeFunction __no_instrument_function uint8_t UART::Read()
{
#if defined(__amd64__) || defined(__i386__)
while ((NoProfiler_inportb(Port + 5) & 1) == 0)
;
return NoProfiler_inportb(Port);
#endif
foreach (auto e in RegisteredEvents)
{
if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL)
{
#if defined(__amd64__) || defined(__i386__)
e->OnReceived(NoProfiler_inportb(Port));
#endif
}
}
}
SafeFunction __no_instrument_function Events::Events(SerialPorts Port)
{
this->Port = Port;
RegisteredEvents.push_back(this);
}
SafeFunction __no_instrument_function Events::~Events()
{
for (uint64_t i = 0; i < RegisteredEvents.size(); i++)
if (RegisteredEvents[i] == this)
{
RegisteredEvents.remove(i);
return;
}
}
}

View File

@ -0,0 +1,181 @@
#include <display.hpp>
#include <lock.hpp>
#include <uart.hpp>
#include <debug.h>
extern uint64_t _binary_Files_ter_powerline_v12n_psf_start;
extern uint64_t _binary_Files_ter_powerline_v12n_psf_end;
extern uint64_t _binary_Files_ter_powerline_v12n_psf_size;
NewLock(PrintLock);
namespace Video
{
char Display::Print(char Char, int Index, bool WriteToUART)
{
// SmartLock(PrintLock);
if (this->ColorIteration)
{
// RRGGBB
if (Char >= '0' && Char <= '9')
this->Buffers[Index]->Color = (this->Buffers[Index]->Color << 4) | (Char - '0');
else if (Char >= 'a' && Char <= 'f')
this->Buffers[Index]->Color = (this->Buffers[Index]->Color << 4) | (Char - 'a' + 10);
else if (Char >= 'A' && Char <= 'F')
this->Buffers[Index]->Color = (this->Buffers[Index]->Color << 4) | (Char - 'A' + 10);
else
this->Buffers[Index]->Color = 0xFFFFFF;
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
this->ColorPickerIteration++;
if (this->ColorPickerIteration == 6)
{
this->ColorPickerIteration = 0;
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(']');
this->ColorIteration = false;
}
return Char;
}
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
switch (Char)
{
case '\e':
{
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('[');
this->ColorIteration = true;
return Char;
}
case '\b':
{
switch (this->CurrentFont->GetInfo().Type)
{
case FontType::PCScreenFont1:
{
fixme("PCScreenFont1");
break;
}
case FontType::PCScreenFont2:
{
uint32_t fonthdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width;
uint32_t fonthdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height;
for (unsigned long Y = this->Buffers[Index]->CursorY; Y < this->Buffers[Index]->CursorY + fonthdrHeight; Y++)
for (unsigned long X = this->Buffers[Index]->CursorX - fonthdrWidth; X < this->Buffers[Index]->CursorX; X++)
*(uint32_t *)((uint64_t)this->Buffers[Index]->Buffer +
(Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8)) = 0;
break;
}
default:
warn("Unsupported font type");
break;
}
if (this->Buffers[Index]->CursorX > 0)
this->Buffers[Index]->CursorX -= this->GetCurrentFont()->GetInfo().Width;
return Char;
}
case '\t':
{
this->Buffers[Index]->CursorX = (this->Buffers[Index]->CursorX + 8) & ~(8 - 1);
return Char;
}
case '\r':
{
this->Buffers[Index]->CursorX = 0;
return Char;
}
case '\n':
{
this->Buffers[Index]->CursorX = 0;
this->Buffers[Index]->CursorY += this->GetCurrentFont()->GetInfo().Height;
return Char;
}
}
if (this->Buffers[Index]->CursorY + this->GetCurrentFont()->GetInfo().Height >= this->Buffers[Index]->Height)
{
this->Buffers[Index]->CursorY -= this->GetCurrentFont()->GetInfo().Height;
this->Scroll(Index, 1);
}
if (this->Buffers[Index]->CursorX + this->GetCurrentFont()->GetInfo().Width >= this->Buffers[Index]->Width)
{
this->Buffers[Index]->CursorX = 0;
this->Buffers[Index]->CursorY += this->GetCurrentFont()->GetInfo().Height;
}
switch (this->CurrentFont->GetInfo().Type)
{
case FontType::PCScreenFont1:
{
uint32_t *PixelPtr = (uint32_t *)this->Buffers[Index]->Buffer;
char *FontPtr = (char *)this->CurrentFont->GetInfo().PSF1Font->GlyphBuffer + (Char * this->CurrentFont->GetInfo().PSF1Font->Header->charsize);
for (uint64_t Y = this->Buffers[Index]->CursorY; Y < this->Buffers[Index]->CursorY + 16; Y++)
{
for (uint64_t X = this->Buffers[Index]->CursorX; X < this->Buffers[Index]->CursorX + 8; X++)
if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index]->CursorX))) > 0)
*(unsigned int *)(PixelPtr + X + (Y * this->Buffers[Index]->Width)) = this->Buffers[Index]->Color;
FontPtr++;
}
this->Buffers[Index]->CursorX += 8;
break;
}
case FontType::PCScreenFont2:
{
// if (this->CurrentFont->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE
// Char = this->CurrentFont->PSF2Font->GlyphBuffer[Char];
int BytesPerLine = (this->CurrentFont->GetInfo().PSF2Font->Header->width + 7) / 8;
char *FontPtr = (char *)this->CurrentFont->GetInfo().StartAddress +
this->CurrentFont->GetInfo().PSF2Font->Header->headersize +
(Char > 0 && (unsigned char)Char < this->CurrentFont->GetInfo().PSF2Font->Header->length ? Char : 0) *
this->CurrentFont->GetInfo().PSF2Font->Header->charsize;
uint32_t fonthdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width;
uint32_t fonthdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height;
for (uint64_t Y = this->Buffers[Index]->CursorY; Y < this->Buffers[Index]->CursorY + fonthdrHeight; Y++)
{
for (uint64_t X = this->Buffers[Index]->CursorX; X < this->Buffers[Index]->CursorX + fonthdrWidth; X++)
if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index]->CursorX))) > 0)
*(uint32_t *)((uint64_t)this->Buffers[Index]->Buffer +
(Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8)) = this->Buffers[Index]->Color;
FontPtr += BytesPerLine;
}
this->Buffers[Index]->CursorX += fonthdrWidth;
break;
}
default:
warn("Unsupported font type");
break;
}
return Char;
}
Display::Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont)
{
this->framebuffer = Info;
if (LoadDefaultFont)
{
this->CurrentFont = new Font(&_binary_Files_ter_powerline_v12n_psf_start, &_binary_Files_ter_powerline_v12n_psf_end, FontType::PCScreenFont2);
FontInfo Info = this->CurrentFont->GetInfo();
debug("Font loaded: %dx%d %s",
Info.Width, Info.Height, Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2");
}
this->CreateBuffer(Info.Width, Info.Height, 0);
}
Display::~Display()
{
for (int i = 0; i < 16; i++)
DeleteBuffer(i);
}
}

View File

@ -0,0 +1,54 @@
#include <display.hpp>
#include <debug.h>
#include <cstring>
namespace Video
{
Font::Font(uint64_t *Start, uint64_t *End, FontType Type)
{
trace("Initializing font with start %#llx and end %#llx Type: %d", Start, End, Type);
this->Info.StartAddress = Start;
this->Info.EndAddress = End;
this->Info.Type = Type;
if (Type == FontType::PCScreenFont2)
{
this->Info.PSF2Font = new PSF2_FONT;
uint64_t FontDataLength = End - Start;
PSF2_HEADER *font2 = (PSF2_HEADER *)KernelAllocator.RequestPages(FontDataLength / PAGE_SIZE + 1);
for (uint64_t i = 0; i < FontDataLength / PAGE_SIZE + 1; i++)
Memory::Virtual().Map((void *)(font2 + (i * PAGE_SIZE)), (void *)(font2 + (i * PAGE_SIZE)), Memory::PTFlag::RW);
memcpy((void *)font2, Start, FontDataLength);
this->Info.Width = font2->width;
this->Info.Height = font2->height;
if (font2->magic[0] != PSF2_MAGIC0 || font2->magic[1] != PSF2_MAGIC1 || font2->magic[2] != PSF2_MAGIC2 || font2->magic[3] != PSF2_MAGIC3)
error("Font2 magic mismatch.");
this->Info.PSF2Font->Header = font2;
this->Info.PSF2Font->GlyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uint64_t>(Start) + sizeof(PSF2_HEADER));
}
else if (Type == FontType::PCScreenFont1)
{
this->Info.PSF1Font = new PSF1_FONT;
PSF1_HEADER *font1 = (PSF1_HEADER *)Start;
if (font1->magic[0] != PSF1_MAGIC0 || font1->magic[1] != PSF1_MAGIC1)
error("Font1 magic mismatch.");
uint32_t glyphBufferSize = font1->charsize * 256;
if (font1->mode == 1) // 512 glyph mode
glyphBufferSize = font1->charsize * 512;
void *glyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uint64_t>(Start) + sizeof(PSF1_HEADER));
this->Info.PSF1Font->Header = font1;
this->Info.PSF1Font->GlyphBuffer = glyphBuffer;
UNUSED(glyphBufferSize); // TODO: Use this in the future?
// TODO: Get font size.
this->Info.Width = 16;
this->Info.Height = 8;
}
}
Font::~Font()
{
}
}

View File

@ -0,0 +1,17 @@
#ifndef __FENNIX_KERNEL_CRASH_HANDELR_H__
#define __FENNIX_KERNEL_CRASH_HANDELR_H__
#include <types.h>
#include <interrupts.hpp>
#include <cpu.hpp>
namespace CrashHandler
{
extern void *EHIntFrames[INT_FRAMES_MAX];
void EHPrint(const char *Format, ...);
void Handle(void *Data);
}
#endif // !__FENNIX_KERNEL_CRASH_HANDELR_H__

340
Kernel/Core/smbios.hpp Normal file
View File

@ -0,0 +1,340 @@
#ifndef __FENNIX_KERNEL_SMBIOS_H__
#define __FENNIX_KERNEL_SMBIOS_H__
#include <types.h>
namespace SMBIOS
{
enum SMBIOSType
{
SMBIOSTypeBIOSInformation = 0,
SMBIOSTypeSystemInformation = 1,
SMBIOSTypeBaseBoardInformation = 2,
SMBIOSTypeSystemEnclosure = 3,
SMBIOSTypeProcessorInformation = 4,
SMBIOSTypeMemoryControllerInformation = 5,
SMBIOSTypeMemoryModuleInformation = 6,
SMBIOSTypeCacheInformation = 7,
SMBIOSTypePortConnectorInformation = 8,
SMBIOSTypeSystemSlots = 9,
SMBIOSTypeOnBoardDevicesInformation = 10,
SMBIOSTypeOEMStrings = 11,
SMBIOSTypeSystemConfigurationOptions = 12,
SMBIOSTypeBIOSLanguageInformation = 13,
SMBIOSTypeGroupAssociations = 14,
SMBIOSTypeSystemEventLog = 15,
SMBIOSTypePhysicalMemoryArray = 16,
SMBIOSTypeMemoryDevice = 17,
SMBIOSType32BitMemoryErrorInformation = 18,
SMBIOSTypeMemoryArrayMappedAddress = 19,
SMBIOSTypeMemoryDeviceMappedAddress = 20,
SMBIOSTypeBuiltInPointingDevice = 21,
SMBIOSTypePortableBattery = 22,
SMBIOSTypeSystemReset = 23,
SMBIOSTypeHardwareSecurity = 24,
SMBIOSTypeSystemPowerControls = 25,
SMBIOSTypeVoltageProbe = 26,
SMBIOSTypeCoolingDevice = 27,
SMBIOSTypeTemperatureProbe = 28,
SMBIOSTypeElectricalCurrentProbe = 29,
SMBIOSTypeOutofBandRemoteAccess = 30,
SMBIOSTypeBootIntegrityServices = 31,
SMBIOSTypeSystemBoot = 32,
SMBIOSType64BitMemoryErrorInformation = 33,
SMBIOSTypeManagementDevice = 34,
SMBIOSTypeManagementDeviceComponent = 35,
SMBIOSTypeManagementDeviceThresholdData = 36,
SMBIOSTypeMemoryChannel = 37,
SMBIOSTypeIPMIDevice = 38,
SMBIOSTypePowerSupply = 39,
SMBIOSTypeAdditionalInformation = 40,
SMBIOSTypeOnboardDevicesExtendedInformation = 41,
SMBIOSTypeManagementControllerHostInterface = 42,
SMBIOSTypeTPMDevice = 43,
SMBIOSTypeProcessorAdditionalInformation = 44,
SMBIOSTypeInactive = 126,
SMBIOSTypeEndOfTable = 127
};
struct SMBIOSHeader
{
unsigned char Type;
unsigned char Length;
unsigned short Handle;
};
struct SMBIOSEntryPoint
{
char EntryPointString[4];
unsigned char Checksum;
unsigned char Length;
unsigned char MajorVersion;
unsigned char MinorVersion;
unsigned short MaxStructureSize;
unsigned char EntryPointRevision;
char FormattedArea[5];
char EntryPointString2[5];
unsigned char Checksum2;
unsigned short TableLength;
unsigned int TableAddress;
unsigned short NumberOfStructures;
unsigned char BCDRevision;
};
static inline char *SMBIOSNextString(char *Str)
{
while (*Str != '\0')
Str++;
return Str + 1;
}
struct SMBIOSBIOSInformation
{
SMBIOSHeader Header;
unsigned char Vendor;
unsigned char Version;
unsigned short StartingAddressSegment;
unsigned char ReleaseDate;
unsigned char ROMSize;
unsigned long Characteristics;
unsigned char CharacteristicsExtensionBytes[2];
unsigned char SystemBIOSMajorRelease;
unsigned char SystemBIOSMinorRelease;
unsigned char EmbeddedControllerFirmwareMajorRelease;
unsigned char EmbeddedControllerFirmwareMinorRelease;
const char *GetString(unsigned char Index)
{
char *Str = (char *)((unsigned long)this + this->Header.Length);
Index--;
if (Index == 0 || Index > 10)
return Str;
for (unsigned char i = 0; i < Index; i++)
Str = SMBIOSNextString(Str);
return Str;
}
};
struct SMBIOSSystemInformation
{
SMBIOSHeader Header;
unsigned char Manufacturer;
unsigned char ProductName;
unsigned char Version;
unsigned char SerialNumber;
unsigned char UUID[16];
unsigned char WakeUpType;
unsigned char SKU;
unsigned char Family;
const char *GetString(unsigned char Index)
{
char *Str = (char *)((unsigned long)this + this->Header.Length);
Index--;
if (Index == 0 || Index > 10)
return Str;
for (unsigned char i = 0; i < Index; i++)
Str = SMBIOSNextString(Str);
return Str;
}
};
struct SMBIOSBaseBoardInformation
{
SMBIOSHeader Header;
unsigned char Manufacturer;
unsigned char Product;
unsigned char Version;
unsigned char SerialNumber;
unsigned char AssetTag;
unsigned char FeatureFlags;
unsigned char LocationInChassis;
unsigned short ChassisHandle;
unsigned char BoardType;
unsigned char NumberOfContainedObjectHandles;
unsigned short ContainedObjectHandles[0];
const char *GetString(unsigned char Index)
{
char *Str = (char *)((unsigned long)this + this->Header.Length);
Index--;
if (Index == 0 || Index > 10)
return Str;
for (unsigned char i = 0; i < Index; i++)
Str = SMBIOSNextString(Str);
return Str;
}
};
struct SMBIOSProcessorInformation
{
SMBIOSHeader Header;
unsigned char SocketDesignation;
unsigned char ProcessorType;
unsigned char ProcessorFamily;
unsigned char ProcessorManufacturer;
unsigned long ProcessorID[2];
unsigned char ProcessorVersion;
unsigned char Voltage;
unsigned short ExternalClock;
unsigned short MaxSpeed;
unsigned short CurrentSpeed;
unsigned char Status;
unsigned char ProcessorUpgrade;
unsigned short L1CacheHandle;
unsigned short L2CacheHandle;
unsigned short L3CacheHandle;
unsigned char SerialNumber;
unsigned char AssetTag;
unsigned char PartNumber;
unsigned char CoreCount;
unsigned char CoreEnabled;
unsigned char ThreadCount;
unsigned short ProcessorCharacteristics;
unsigned short ProcessorFamily2;
unsigned short CoreCount2;
unsigned short CoreEnabled2;
unsigned short ThreadCount2;
const char *GetString(unsigned char Index)
{
char *Str = (char *)((unsigned long)this + this->Header.Length);
Index--;
if (Index == 0 || Index > 10)
return Str;
for (unsigned char i = 0; i < Index; i++)
Str = SMBIOSNextString(Str);
return Str;
}
};
struct SMBIOSMemoryDevice
{
SMBIOSHeader Header;
unsigned char PhysicalMemoryArrayHandle;
unsigned char MemoryErrorInformationHandle;
unsigned short TotalWidth;
unsigned short DataWidth;
unsigned short Size;
unsigned char FormFactor;
unsigned char DeviceSet;
unsigned char DeviceLocator;
unsigned char BankLocator;
unsigned char MemoryType;
unsigned short TypeDetail;
unsigned short Speed;
unsigned char Manufacturer;
unsigned char SerialNumber;
unsigned char AssetTag;
unsigned char PartNumber;
unsigned char Attributes;
unsigned short ExtendedSize;
unsigned short ConfiguredMemoryClockSpeed;
unsigned short MinimumVoltage;
unsigned short MaximumVoltage;
unsigned short ConfiguredVoltage;
unsigned char MemoryTechnology;
unsigned char OperatingModeCapability;
unsigned char FirmwareVersion;
unsigned char ModuleManufacturerID;
unsigned char ModuleProductID;
unsigned char MemorySubsystemControllerManufacturerID;
unsigned char MemorySubsystemControllerProductID;
unsigned short NonVolatileSize;
unsigned short VolatileSize;
unsigned short CacheSize;
unsigned short LogicalSize;
unsigned char ExtendedSpeed;
unsigned char ExtendedConfiguredMemorySpeed;
const char *GetString(unsigned char Index)
{
char *Str = (char *)((unsigned long)this + this->Header.Length);
Index--;
if (Index == 0 || Index > 10)
return Str;
for (unsigned char i = 0; i < Index; i++)
Str = SMBIOSNextString(Str);
return Str;
}
};
struct SMBIOSMemoryArrayMappedAddress
{
SMBIOSHeader Header;
unsigned int StartingAddress;
unsigned int EndingAddress;
unsigned short MemoryArrayHandle;
unsigned char PartitionWidth;
const char *GetString(unsigned char Index)
{
char *Str = (char *)((unsigned long)this + this->Header.Length);
Index--;
if (Index == 0 || Index > 10)
return Str;
for (unsigned char i = 0; i < Index; i++)
Str = SMBIOSNextString(Str);
return Str;
}
};
struct SMBIOSMemoryDeviceMappedAddress
{
SMBIOSHeader Header;
unsigned int StartingAddress;
unsigned int EndingAddress;
unsigned short MemoryDeviceHandle;
unsigned short MemoryArrayMappedAddressHandle;
unsigned char PartitionRowPosition;
unsigned char InterleavePosition;
unsigned char InterleavedDataDepth;
const char *GetString(unsigned char Index)
{
char *Str = (char *)((unsigned long)this + this->Header.Length);
Index--;
if (Index == 0 || Index > 10)
return Str;
for (unsigned char i = 0; i < Index; i++)
Str = SMBIOSNextString(Str);
return Str;
}
};
struct SMBIOSMemoryArray
{
SMBIOSHeader Header;
unsigned char Location;
unsigned char Use;
unsigned char MemoryErrorCorrection;
unsigned int MaximumCapacity;
unsigned short MemoryErrorInformationHandle;
unsigned short NumberOfMemoryDevices;
const char *GetString(unsigned char Index)
{
char *Str = (char *)((unsigned long)this + this->Header.Length);
Index--;
if (Index == 0 || Index > 10)
return Str;
for (unsigned char i = 0; i < Index; i++)
Str = SMBIOSNextString(Str);
return Str;
}
};
bool CheckSMBIOS();
SMBIOSEntryPoint *GetSMBIOSEntryPoint();
void *GetSMBIOSHeader(SMBIOSType Type);
SMBIOSBIOSInformation *GetBIOSInformation();
SMBIOSSystemInformation *GetSystemInformation();
SMBIOSBaseBoardInformation *GetBaseBoardInformation();
SMBIOSProcessorInformation *GetProcessorInformation();
SMBIOSMemoryArray *GetMemoryArray();
SMBIOSMemoryDevice *GetMemoryDevice();
SMBIOSMemoryArrayMappedAddress *GetMemoryArrayMappedAddress();
SMBIOSMemoryDeviceMappedAddress *GetMemoryDeviceMappedAddress();
}
#endif // !__FENNIX_KERNEL_SMBIOS_H__

Some files were not shown because too many files have changed in this diff Show More