5 Commits

Author SHA1 Message Date
b4c0a78c6c Merge remote-tracking branch 'Kernel/memory-test' into Kernel-memory-test 2024-11-20 05:16:21 +02:00
653f5a6042 Kernel/memory-test 2024-11-20 05:15:59 +02:00
9a22cfe02e Now works 2022-12-05 20:46:27 +02:00
7bff9f260e oopsie 2022-12-05 20:43:10 +02:00
a32ca16d2b Attempt to rewrite the VMM - currently not working 2022-12-05 06:00:45 +02:00
359 changed files with 11111 additions and 50896 deletions

1
Kernel/.gitignore vendored
View File

@ -4,4 +4,5 @@
*.map *.map
*.fsys *.fsys
*.log *.log
Files/*.psf
.dccache .dccache

View File

@ -4,23 +4,6 @@
"head", "head",
], ],
"body": [ "body": [
"/*",
" This file is part of Fennix Kernel.",
"",
" Fennix Kernel is free software: you can redistribute it and/or",
" modify it under the terms of the GNU General Public License as",
" published by the Free Software Foundation, either version 3 of",
" the License, or (at your option) any later version.",
"",
" Fennix Kernel is distributed in the hope that it will be useful,",
" but WITHOUT ANY WARRANTY; without even the implied warranty of",
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
" GNU General Public License for more details.",
"",
" You should have received a copy of the GNU General Public License",
" along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
"*/",
"",
"#ifndef __FENNIX_KERNEL_${2:header}_H__", "#ifndef __FENNIX_KERNEL_${2:header}_H__",
"#define __FENNIX_KERNEL_${2:header}_H__", "#define __FENNIX_KERNEL_${2:header}_H__",
"", "",
@ -41,29 +24,5 @@
"/** @brief $0 */" "/** @brief $0 */"
], ],
"description": "Create kernel documentation brief." "description": "Create kernel documentation brief."
},
"License": {
"prefix": [
"license",
],
"body": [
"/*",
" This file is part of Fennix Kernel.",
"",
" Fennix Kernel is free software: you can redistribute it and/or",
" modify it under the terms of the GNU General Public License as",
" published by the Free Software Foundation, either version 3 of",
" the License, or (at your option) any later version.",
"",
" Fennix Kernel is distributed in the hope that it will be useful,",
" but WITHOUT ANY WARRANTY; without even the implied warranty of",
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
" GNU General Public License for more details.",
"",
" You should have received a copy of the GNU General Public License",
" along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
"*/"
],
"description": "Create kernel license."
} }
} }

View File

@ -1,12 +1,9 @@
{ {
"configurations": [ "configurations": [
{ {
"name": "Fennix x64 (Linux, GCC, debug)", "name": "Linux",
"includePath": [ "includePath": [
"${workspaceFolder}/include", "${workspaceFolder}/include/**"
"${workspaceFolder}/include/**",
"${workspaceFolder}/include_std",
"${workspaceFolder}/include_std/**"
], ],
"defines": [ "defines": [
"__debug_vscode__", "__debug_vscode__",
@ -14,204 +11,37 @@
"KERNEL_VERSION=\"1.0\"", "KERNEL_VERSION=\"1.0\"",
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"", "GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"", "GIT_COMMIT_SHORT=\"0000000\"",
"a64",
"a86",
"DEBUG=\"1\"" "DEBUG=\"1\""
], ],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/amd64-elf-gcc", "compilerPath": "/usr/bin/gcc",
"cStandard": "c17", "cStandard": "c17",
"cppStandard": "c++20", "cppStandard": "c++20",
"intelliSenseMode": "gcc-x64", "intelliSenseMode": "gcc-x64",
"configurationProvider": "ms-vscode.makefile-tools", "configurationProvider": "ms-vscode.makefile-tools",
"compilerArgs": [ "compilerArgs": [
// Compiler flags // "-m32",
"-fno-pic", "-mcmodel=kernel", /* 64-bit only */
"-fno-pie",
"-mno-red-zone",
"-march=core2",
"-pipe",
"-mcmodel=kernel",
"-fno-builtin",
// Warnings
"-Wall",
"-Wextra",
"-Wfloat-equal",
"-Wpointer-arith",
"-Wcast-align",
"-Wredundant-decls",
"-Winit-self",
"-Wswitch-default",
"-Wstrict-overflow=5",
"-Wconversion",
// C++ flags
"-fno-rtti", "-fno-rtti",
"-fexceptions", "-fexceptions",
// Linker flags
"-T${workspaceFolder}/Architecture/amd64/linker.ld",
"-Wl,-static,--no-dynamic-linker,-ztext",
"-nostdlib",
"-nodefaultlibs",
"-nolibc",
"-zmax-page-size=0x1000",
"-shared",
// Debug flags
"-ggdb3",
"-O0",
"-fdiagnostics-color=always",
"-fverbose-asm",
"-fstack-usage",
"-fstack-check",
"-fsanitize=undefined",
// VSCode flags
"-ffreestanding",
"-nostdinc",
"-nostdinc++"
]
},
{
"name": "Fennix x32 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/include/**",
"${workspaceFolder}/include_std",
"${workspaceFolder}/include_std/**"
],
"defines": [
"__debug_vscode__",
"KERNEL_NAME=\"Fennix\"",
"KERNEL_VERSION=\"1.0\"",
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"a32",
"a86",
"DEBUG=\"1\""
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-elf-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "gcc-x86",
"configurationProvider": "ms-vscode.makefile-tools",
"compilerArgs": [
// Compiler flags
"-fno-pic", "-fno-pic",
"-fno-pie", "-fno-pie",
"-mno-80387", "-mno-80387",
"-mno-mmx", "-mno-mmx",
"-mno-3dnow", "-mno-3dnow",
"-mno-red-zone", "-mno-red-zone",
"-march=pentium", "-mno-sse",
"-mno-sse2",
"-march=nehalem",
"-pipe", "-pipe",
"-msoft-float", "-msoft-float",
"-fno-builtin", "-fno-builtin",
"-ffreestanding",
// Warnings "-nostdinc",
"-Wall",
"-Wextra",
"-Wfloat-equal",
"-Wpointer-arith",
"-Wcast-align",
"-Wredundant-decls",
"-Winit-self",
"-Wswitch-default",
"-Wstrict-overflow=5",
"-Wconversion",
// C++ flags
"-fno-rtti",
"-fexceptions",
// Linker flags
"-T${workspaceFolder}/Architecture/i386/linker.ld",
"-Wl,-static,--no-dynamic-linker,-ztext", "-Wl,-static,--no-dynamic-linker,-ztext",
"-nostdlib",
"-nodefaultlibs",
"-nolibc",
"-zmax-page-size=0x1000",
"-shared", "-shared",
"-zmax-page-size=0x1000",
// Debug flags "-nostdinc++",
"-ggdb3", "-fsanitize=undefined"
"-O0",
"-fdiagnostics-color=always",
"-fverbose-asm",
"-fstack-usage",
"-fstack-check",
"-fsanitize=undefined",
// VSCode flags
"-ffreestanding",
"-nostdinc",
"-nostdinc++"
]
},
{
"name": "Fennix Aarch64 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/include/**",
"${workspaceFolder}/include_std",
"${workspaceFolder}/include_std/**"
],
"defines": [
"__debug_vscode__",
"KERNEL_NAME=\"Fennix\"",
"KERNEL_VERSION=\"1.0\"",
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"aa64",
"DEBUG=\"1\""
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-elf-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "linux-gcc-arm64",
"configurationProvider": "ms-vscode.makefile-tools",
"compilerArgs": [
// Compiler flags
"-pipe",
"-fno-builtin",
"-msoft-float",
"-fPIC",
"-Wstack-protector",
// Warnings
"-Wall",
"-Wextra",
"-Wfloat-equal",
"-Wpointer-arith",
"-Wcast-align",
"-Wredundant-decls",
"-Winit-self",
"-Wswitch-default",
"-Wstrict-overflow=5",
"-Wconversion",
// C++ flags
"-fno-rtti",
"-fexceptions",
// Linker flags
"-T${workspaceFolder}/Architecture/aarch64/linker.ld",
"-fPIC",
// Debug flags
"-ggdb3",
"-O0",
"-fdiagnostics-color=always",
"-fverbose-asm",
"-fstack-usage",
"-fstack-check",
"-fsanitize=undefined",
// VSCode flags
"-ffreestanding",
"-nostdinc",
"-nostdinc++"
] ]
} }
], ],

View File

@ -1,13 +1,16 @@
{ {
"recommendations": [ "recommendations": [
"pejmannikram.vscode-auto-scroll",
"aaron-bond.better-comments",
"ms-vscode.cpptools", "ms-vscode.cpptools",
"wayou.vscode-todo-highlight", "streetsidesoftware.code-spell-checker",
"gruntfuggly.todo-tree", "naumovs.color-highlight",
"13xforever.language-x86-64-assembly",
"webfreak.debug",
"zixuanwang.linkerscript",
"maziac.hex-hover-converter",
"cschlosser.doxdocgen", "cschlosser.doxdocgen",
"streetsidesoftware.code-spell-checker" "ferrierbenjamin.fold-unfold-all-icone",
"ajshort.include-autocomplete",
"zixuanwang.linkerscript",
"ibm.output-colorizer",
"christian-kohler.path-intellisense",
"Gruntfuggly.todo-tree"
] ]
} }

View File

@ -2,7 +2,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "Attach to a running VM instance", "name": "Attach to a running QEMU instance",
"type": "cppdbg", "type": "cppdbg",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/kernel.fsys", "program": "${workspaceRoot}/kernel.fsys",

View File

@ -8,12 +8,11 @@
"C_Cpp.default.cppStandard": "c++20", "C_Cpp.default.cppStandard": "c++20",
"C_Cpp.intelliSenseMemoryLimit": 16384, "C_Cpp.intelliSenseMemoryLimit": 16384,
"editor.smoothScrolling": true, "editor.smoothScrolling": true,
"editor.cursorSmoothCaretAnimation": "on", "editor.cursorSmoothCaretAnimation": true,
"C_Cpp.codeAnalysis.clangTidy.checks.disabled": [ "C_Cpp.codeAnalysis.clangTidy.checks.disabled": [
"clang-analyzer-security.insecureAPI.strcpy", "clang-analyzer-security.insecureAPI.strcpy",
"clang-diagnostic-unknown-warning-option", "clang-diagnostic-unknown-warning-option",
"clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling", "clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling",
"clang-diagnostic-implicit-exception-spec-mismatch", "clang-diagnostic-implicit-exception-spec-mismatch"
"clang-diagnostic-unknown-attributes"
] ]
} }

View File

@ -1,36 +0,0 @@
/* Based on this tutorial:
https://github.com/s-matyukevich/raspberry-pi-os */
.section ".text.boot"
.extern _bss_start
.extern _bss_end
.extern arm64Entry
memzero:
str xzr, [x0], #8
subs x1, x1, #8
b.gt memzero
ret
.global _start
_start:
mrs x0, mpidr_el1
and x0, x0, #0xFF
cbz x0, _start2
b CPU_Loop
_start2:
adr x0, _bss_start
adr x1, _bss_end
sub x1, x1, x0
bl memzero
mov sp, #0x200000
bl arm64Entry
Halt:
wfe
b Halt
CPU_Loop:
b CPU_Loop

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <types.h> #include <types.h>
#include <debug.h> #include <debug.h>

View File

@ -1,25 +1,8 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp> #include <syscalls.hpp>
#include <cpu.hpp> #include <cpu.hpp>
extern "C" __naked __used __no_stack_protector void SystemCallHandlerStub() extern "C" __attribute__((naked, used, no_stack_protector)) void SystemCallHandlerStub()
{ {
} }

View File

@ -1,23 +1,6 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <smp.hpp> #include <smp.hpp>
#include <ints.hpp> #include <interrupts.hpp>
#include <memory.hpp> #include <memory.hpp>
#include <cpu.hpp> #include <cpu.hpp>
@ -26,7 +9,7 @@
volatile bool CPUEnabled = false; volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers" #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __aligned(0x1000) CPUData CPUs[MAX_CPU] = {0}; static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
CPUData *GetCPU(uint64_t id) { return &CPUs[id]; } CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
@ -50,8 +33,6 @@ CPUData *GetCurrentCPU()
namespace SMP namespace SMP
{ {
int CPUCores = 0;
void Initialize(void *madt) void Initialize(void *madt)
{ {
fixme("SMP::Initialize() is not implemented!"); fixme("SMP::Initialize() is not implemented!");

View File

@ -1,33 +1,8 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
ENTRY(_start) ENTRY(_start)
SECTIONS SECTIONS
{ {
.text.boot : . = 0x80000;
{
*(.text.boot)
. += CONSTANT(MAXPAGESIZE);
_bss_start = .;
*(.text.bss)
_bss_end = .;
}
_kernel_start = .; _kernel_start = .;
.text : .text :
{ {
@ -51,22 +26,6 @@ SECTIONS
. = ALIGN(4096); . = ALIGN(4096);
_kernel_rodata_end = .; _kernel_rodata_end = .;
.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 = .);
}
.bss : .bss :
{ {
*(.bss .bss.*) *(.bss .bss.*)

View File

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

View File

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

View File

@ -1,155 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "acpi.hpp"
#include <debug.h>
#include <io.h>
#include "../../kernel.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++)
{
// TODO: 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 (int i = 0; i < 4; i++)
{
if (SDTHdr->Signature[i] != Signature[i])
break;
if (i == 3)
{
trace("%s found at address %p", Signature, (uintptr_t)SDTHdr);
return SDTHdr;
}
}
}
// warn("%s not found!", Signature);
return nullptr;
}
void ACPI::SearchTables(ACPIHeader *Header)
{
if (!Header)
return;
HPET = (HPETHeader *)FindTable(Header, (char *)"HPET");
FADT = (FADTHeader *)FindTable(Header, (char *)"FACP");
MCFG = (MCFGHeader *)FindTable(Header, (char *)"MCFG");
BGRT = (BGRTHeader *)FindTable(Header, (char *)"BGRT");
SRAT = (SRATHeader *)FindTable(Header, (char *)"SRAT");
TPM2 = (TPM2Header *)FindTable(Header, (char *)"TPM2");
TCPA = (TCPAHeader *)FindTable(Header, (char *)"TCPA");
WAET = (WAETHeader *)FindTable(Header, (char *)"WAET");
MADT = (MADTHeader *)FindTable(Header, (char *)"APIC");
HEST = (HESTHeader *)FindTable(Header, (char *)"HEST");
FindTable(Header, (char *)"BERT");
FindTable(Header, (char *)"CPEP");
FindTable(Header, (char *)"DSDT");
FindTable(Header, (char *)"ECDT");
FindTable(Header, (char *)"EINJ");
FindTable(Header, (char *)"ERST");
FindTable(Header, (char *)"FACS");
FindTable(Header, (char *)"MSCT");
FindTable(Header, (char *)"MPST");
FindTable(Header, (char *)"OEMx");
FindTable(Header, (char *)"PMTT");
FindTable(Header, (char *)"PSDT");
FindTable(Header, (char *)"RASF");
FindTable(Header, (char *)"RSDT");
FindTable(Header, (char *)"SBST");
FindTable(Header, (char *)"SLIT");
FindTable(Header, (char *)"SSDT");
FindTable(Header, (char *)"XSDT");
FindTable(Header, (char *)"DRTM");
FindTable(Header, (char *)"FPDT");
FindTable(Header, (char *)"GTDT");
FindTable(Header, (char *)"PCCT");
FindTable(Header, (char *)"S3PT");
FindTable(Header, (char *)"MATR");
FindTable(Header, (char *)"MSDM");
FindTable(Header, (char *)"WPBT");
FindTable(Header, (char *)"OSDT");
FindTable(Header, (char *)"RSDP");
FindTable(Header, (char *)"NFIT");
FindTable(Header, (char *)"ASF!");
FindTable(Header, (char *)"BOOT");
FindTable(Header, (char *)"CSRT");
FindTable(Header, (char *)"DBG2");
FindTable(Header, (char *)"DBGP");
FindTable(Header, (char *)"DMAR");
FindTable(Header, (char *)"IBFT");
FindTable(Header, (char *)"IORT");
FindTable(Header, (char *)"IVRS");
FindTable(Header, (char *)"LPIT");
FindTable(Header, (char *)"MCHI");
FindTable(Header, (char *)"MTMR");
FindTable(Header, (char *)"SLIC");
FindTable(Header, (char *)"SPCR");
FindTable(Header, (char *)"SPMI");
FindTable(Header, (char *)"UEFI");
FindTable(Header, (char *)"VRTC");
FindTable(Header, (char *)"WDAT");
FindTable(Header, (char *)"WDDT");
FindTable(Header, (char *)"WDRT");
FindTable(Header, (char *)"ATKG");
FindTable(Header, (char *)"GSCI");
FindTable(Header, (char *)"IEIT");
FindTable(Header, (char *)"HMAT");
FindTable(Header, (char *)"CEDT");
FindTable(Header, (char *)"AEST");
}
ACPI::ACPI()
{
trace("Initializing ACPI");
if (bInfo.RSDP->Revision >= 2 && bInfo.RSDP->XSDTAddress)
{
debug("XSDT supported");
XSDTSupported = true;
XSDT = (ACPIHeader *)(bInfo.RSDP->XSDTAddress);
}
else
{
debug("RSDT supported");
XSDT = (ACPIHeader *)(uintptr_t)bInfo.RSDP->RSDTAddress;
}
this->SearchTables(XSDT);
if (FADT)
{
outb(s_cst(uint16_t, FADT->SMI_CommandPort), FADT->AcpiEnable);
while (!(inw(s_cst(uint16_t, FADT->PM1aControlBlock)) & 1))
;
}
}
ACPI::~ACPI()
{
}
}

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

@ -1,47 +0,0 @@
[bits 32]
section .bootstrap.text
align 32
global gdtr
gdtr:
dw GDT32_END - GDT32 - 1
dd GDT32
align 32
GDT32:
dq 0x0
dw 0xffff
dw 0x0000
db 0x00
dw 0xcf9a
db 0x00
dw 0xffff
dw 0x0000
db 0x00
dw 0xcf92
db 0x00
dw 0x0100
dw 0x1000
db 0x00
dw 0x4092
db 0x00
GDT32_END:
global LoadGDT32
LoadGDT32:
lgdt [gdtr]
jmp 0x8:ActivateGDT
ActivateGDT:
mov cx, 0x10
mov ss, cx
mov ds, cx
mov es, cx
mov fs, cx
mov cx, 0x18
mov gs, cx
ret

View File

@ -1,5 +0,0 @@
section .multiboot
align 4
dd 0x1BADB002
dd 1 << 0 | 1 << 1
dd -(0x1BADB002 + (1 << 0 | 1 << 1))

View File

@ -1,64 +0,0 @@
; https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html
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_INFO_REQUEST_TAG_START:
dw 1
dw 0
dd MB2_INFO_REQUEST_TAG_END - MB2_INFO_REQUEST_TAG_START
dd 1 ; Command Line
dd 2 ; Boot Loader Name
dd 3 ; Module
dd 4 ; Basic Memory Information
dd 5 ; BIOS Boot Device
dd 6 ; Memory Map
dd 7 ; VBE
dd 8 ; Framebuffer
dd 9 ; ELF Sections
dd 10 ; APM Table
dd 11 ; EFI 32-bit System Table Pointer
dd 12 ; EFI 64-bit System Table Pointer
; dd 13 ; SMBIOS
dd 14 ; ACPI Old
dd 15 ; ACPI New
dd 16 ; Network
dd 17 ; EFI Memory Map
dd 18 ; EFI Boot Services Notifier
dd 19 ; EFI 32-bit Image Handle Pointer
dd 20 ; EFI 64-bit Image Handle Pointer
dd 21 ; Load Base Address
MB2_INFO_REQUEST_TAG_END:
align 8
MB2_FRAMEBUFFER_TAG_START:
dw 5
dw 1
dd MB2_FRAMEBUFFER_TAG_END - MB2_FRAMEBUFFER_TAG_START
dd 0
dd 0
dd 32
MB2_FRAMEBUFFER_TAG_END:
align 8
MB2_EGA_SUPPORT_TAG_START:
dw 4
dw 0
dd MB2_EGA_SUPPORT_TAG_END - MB2_EGA_SUPPORT_TAG_START
dd 1 ; https://www.gnu.org/software/grub/manual/multiboot2/html_node/Console-header-tags.html
MB2_EGA_SUPPORT_TAG_END:
align 8
MB2_MODULE_ALIGN_TAG_START:
dw 6
dw 0
dd MB2_MODULE_ALIGN_TAG_END - MB2_MODULE_ALIGN_TAG_START
MB2_MODULE_ALIGN_TAG_END:
align 8
MB2_TAG_START:
dw 0
dw 0
dd MB2_TAG_END - MB2_TAG_START
MB2_TAG_END:
HEADER_END:

View File

@ -1,299 +0,0 @@
#include <types.h>
#include <boot/protocols/multiboot2.h>
#include <memory.hpp>
#include <io.h>
#include "../../../kernel.h"
EXTERNC void multiboot_main(uint64_t Magic, uint64_t Info)
{
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);
CPU::Stop();
}
BootInfo mb2binfo{};
// Clear the BSS
// memset_unsafe(&_kernel_rodata_end, 0, &_kernel_end - &_kernel_rodata_end);
{
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);
int pos = 0;
auto InfoAddress = Info;
for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8);
;
Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7)))
{
if (Tag->type == MULTIBOOT_TAG_TYPE_END)
{
debug("End of multiboot2 tags");
break;
}
switch (Tag->type)
{
case MULTIBOOT_TAG_TYPE_CMDLINE:
{
strncpy(mb2binfo.Kernel.CommandLine,
((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string));
debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine);
break;
}
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
{
strncpy(mb2binfo.Bootloader.Name,
((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string));
debug("Bootloader name: %s", mb2binfo.Bootloader.Name);
break;
}
case MULTIBOOT_TAG_TYPE_MODULE:
{
multiboot_tag_module *module = (multiboot_tag_module *)Tag;
static int module_count = 0;
mb2binfo.Modules[module_count].Address = (void *)(uint64_t)module->mod_start;
mb2binfo.Modules[module_count].Size = module->size;
strncpy(mb2binfo.Modules[module_count].Path, "(null)", 6);
strncpy(mb2binfo.Modules[module_count].CommandLine, module->cmdline,
strlen(module->cmdline));
debug("Module: %s", mb2binfo.Modules[module_count].Path);
module_count++;
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;
size_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry);
mb2binfo.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];
mb2binfo.Memory.Size += entry.len;
switch (entry.type)
{
case MULTIBOOT_MEMORY_AVAILABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = Usable;
break;
case MULTIBOOT_MEMORY_RESERVED:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = Reserved;
break;
case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = ACPIReclaimable;
break;
case MULTIBOOT_MEMORY_NVS:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = ACPINVS;
break;
case MULTIBOOT_MEMORY_BADRAM:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = BadMemory;
break;
default:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = Unknown;
break;
}
debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]",
mb2binfo.Memory.Entry[i].BaseAddress,
mb2binfo.Memory.Entry[i].Length,
mb2binfo.Memory.Entry[i].Type);
}
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;
mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width;
mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height;
mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch;
mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp;
switch (fb->common.framebuffer_type)
{
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
{
mb2binfo.Framebuffer[fb_count].Type = Indexed;
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
{
mb2binfo.Framebuffer[fb_count].Type = RGB;
mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size;
mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position;
mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size;
mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position;
mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size;
mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
{
mb2binfo.Framebuffer[fb_count].Type = EGA;
break;
}
default:
{
mb2binfo.Framebuffer[fb_count].Type = Unknown_Framebuffer_Type;
break;
}
}
debug("Framebuffer %d: %dx%d %d bpp", fb_count, 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:
{
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
debug("OLD ACPI RSDP: %p", mb2binfo.RSDP);
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_NEW:
{
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
debug("NEW ACPI RSDP: %p", mb2binfo.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;
mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr;
mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000);
mb2binfo.Kernel.Size = ((uint64_t)&_kernel_end - (uint64_t)&_kernel_start) + ((uint64_t)&_bootstrap_end - (uint64_t)&_bootstrap_start);
debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase);
break;
}
default:
{
error("Unknown multiboot2 tag type: %d", Tag->type);
break;
}
}
}
tmp = inb(0x61) & 0xFC;
outb(0x61, tmp);
}
Entry(&mb2binfo);
}

View File

@ -1,287 +0,0 @@
#include <types.h>
union __attribute__((packed)) PageTableEntry
{
struct
{
bool Present : 1; // 0
bool ReadWrite : 1; // 1
bool UserSupervisor : 1; // 2
bool WriteThrough : 1; // 3
bool CacheDisable : 1; // 4
bool Accessed : 1; // 5
bool Dirty : 1; // 6
bool PageAttributeTable : 1; // 7
bool Global : 1; // 8
uint8_t Available0 : 3; // 9-11
uint64_t Address : 40; // 12-51
uint32_t Available1 : 7; // 52-58
uint8_t ProtectionKey : 4; // 59-62
bool ExecuteDisable : 1; // 63
};
uint64_t raw;
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
{
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
}
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
};
struct __attribute__((packed)) PageTableEntryPtr
{
PageTableEntry Entries[512];
};
union __attribute__((packed)) PageDirectoryEntry
{
struct
{
bool Present : 1; // 0
bool ReadWrite : 1; // 1
bool UserSupervisor : 1; // 2
bool WriteThrough : 1; // 3
bool CacheDisable : 1; // 4
bool Accessed : 1; // 5
bool Available0 : 1; // 6
bool PageSize : 1; // 7
uint8_t Available1 : 4; // 8-11
uint64_t Address : 40; // 12-51
uint32_t Available2 : 11; // 52-62
bool ExecuteDisable : 1; // 63
};
uint64_t raw;
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
{
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
}
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
};
struct __attribute__((packed)) PageDirectoryEntryPtr
{
PageDirectoryEntry Entries[512];
};
union __attribute__((packed)) PageDirectoryPointerTableEntry
{
struct
{
bool Present : 1; // 0
bool ReadWrite : 1; // 1
bool UserSupervisor : 1; // 2
bool WriteThrough : 1; // 3
bool CacheDisable : 1; // 4
bool Accessed : 1; // 5
bool Available0 : 1; // 6
bool PageSize : 1; // 7
uint8_t Available1 : 4; // 8-11
uint64_t Address : 40; // 12-51
uint32_t Available2 : 11; // 52-62
bool ExecuteDisable : 1; // 63
};
uint64_t raw;
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
{
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
}
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
};
struct __attribute__((packed)) PageDirectoryPointerTableEntryPtr
{
PageDirectoryPointerTableEntry Entries[512];
};
union __attribute__((packed)) PageMapLevel4
{
struct
{
bool Present : 1; // 0
bool ReadWrite : 1; // 1
bool UserSupervisor : 1; // 2
bool WriteThrough : 1; // 3
bool CacheDisable : 1; // 4
bool Accessed : 1; // 5
bool Available0 : 1; // 6
bool Reserved0 : 1; // 7
uint8_t Available1 : 4; // 8-11
uint64_t Address : 40; // 12-51
uint32_t Available2 : 11; // 52-62
bool ExecuteDisable : 1; // 63
};
uint64_t raw;
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
{
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
}
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
};
struct PageTable4
{
PageMapLevel4 Entries[512];
} __attribute__((aligned(0x1000)));
extern "C" char BootPageTable[];
extern uintptr_t _kernel_start, _kernel_end;
__attribute__((section(".bootstrap.data"))) static PageTable4 *BPTable = (PageTable4 *)BootPageTable;
__attribute__((section(".bootstrap.data"))) static size_t BPT_Allocated = 0x4000;
__always_inline inline SafeFunction NIF void *RequestPage()
{
void *Page = (void *)(BootPageTable + BPT_Allocated);
BPT_Allocated += 0x1000;
if (BPT_Allocated >= 0x10000) /* The length of BootPageTable */
{
while (true)
;
}
return Page;
}
class PageMapIndexer
{
public:
uintptr_t PMLIndex = 0;
uintptr_t PDPTEIndex = 0;
uintptr_t PDEIndex = 0;
uintptr_t PTEIndex = 0;
__always_inline inline SafeFunction NIF PageMapIndexer(uintptr_t VirtualAddress)
{
uintptr_t Address = VirtualAddress;
Address >>= 12;
this->PTEIndex = Address & 0x1FF;
Address >>= 9;
this->PDEIndex = Address & 0x1FF;
Address >>= 9;
this->PDPTEIndex = Address & 0x1FF;
Address >>= 9;
this->PMLIndex = Address & 0x1FF;
}
};
__attribute__((section(".bootstrap.text"))) SafeFunction NIF void MB2_64_Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
{
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
// Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only
uint64_t DirectoryFlags = Flags & 0x3F;
PageMapLevel4 PML4 = BPTable->Entries[Index.PMLIndex];
PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr;
if (!PML4.Present)
{
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)RequestPage();
if (PDPTEPtr == nullptr)
return;
{
void *ptr = PDPTEPtr;
uint8_t value = 0;
size_t num = 0x1000;
uint8_t *p = (uint8_t *)ptr;
for (size_t i = 0; i < num; i++)
p[i] = value;
}
PML4.Present = true;
PML4.SetAddress((uintptr_t)PDPTEPtr >> 12);
}
else
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
PML4.raw |= DirectoryFlags;
BPTable->Entries[Index.PMLIndex] = PML4;
PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex];
PageDirectoryEntryPtr *PDEPtr = nullptr;
if (!PDPTE.Present)
{
PDEPtr = (PageDirectoryEntryPtr *)RequestPage();
if (PDEPtr == nullptr)
return;
{
void *ptr = PDEPtr;
uint8_t value = 0;
size_t num = 0x1000;
uint8_t *p = (uint8_t *)ptr;
for (size_t i = 0; i < num; i++)
p[i] = value;
}
PDPTE.Present = true;
PDPTE.SetAddress((uintptr_t)PDEPtr >> 12);
}
else
PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.GetAddress() << 12);
PDPTE.raw |= DirectoryFlags;
PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE;
PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex];
PageTableEntryPtr *PTEPtr = nullptr;
if (!PDE.Present)
{
PTEPtr = (PageTableEntryPtr *)RequestPage();
if (PTEPtr == nullptr)
return;
{
void *ptr = PTEPtr;
uint8_t value = 0;
size_t num = 0x1000;
uint8_t *p = (uint8_t *)ptr;
for (size_t i = 0; i < num; i++)
p[i] = value;
}
PDE.Present = true;
PDE.SetAddress((uintptr_t)PTEPtr >> 12);
}
else
PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12);
PDE.raw |= DirectoryFlags;
PDEPtr->Entries[Index.PDEIndex] = PDE;
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
PTE.Present = true;
PTE.raw |= Flags;
PTE.SetAddress((uintptr_t)PhysicalAddress >> 12);
PTEPtr->Entries[Index.PTEIndex] = PTE;
asmv("invlpg (%0)"
:
: "r"(VirtualAddress)
: "memory");
}
EXTERNC __attribute__((section(".bootstrap.text"))) SafeFunction NIF __attribute__((section(".bootstrap.text"))) void UpdatePageTable64()
{
BPTable = (PageTable4 *)BootPageTable;
// for (size_t i = 0; i < 0x10000000; i += 0x1000)
// MB2_64_Map((void *)i, (void *)i, 0x3);
uintptr_t KernelStart = (uintptr_t)&_kernel_start;
uintptr_t KernelEnd = (uintptr_t)&_kernel_end;
uintptr_t PhysicalStart = KernelStart - 0xFFFFFFFF80000000;
for (uintptr_t i = KernelStart; i < KernelEnd; i += 0x1000)
{
MB2_64_Map((void *)i, (void *)PhysicalStart, 0x3);
PhysicalStart += 0x1000;
}
asmv("mov %%cr3, %%rax\n"
"mov %%rax, %%cr3\n"
:
:
: "rax");
}

View File

@ -1,114 +0,0 @@
[bits 32]
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
extern multiboot_main
extern LoadGDT32
extern BootPageTable
extern UpdatePageTable
section .bootstrap.data
MB_HeaderMagic:
dq 0
MB_HeaderInfo:
dq 0
section .bootstrap.text
global _start
_start:
cli
mov [MB_HeaderMagic], eax
mov [MB_HeaderInfo], ebx
mov ecx, cr4
or ecx, 0x00000010 ; Set PSE in CR4
or ecx, 0x00000020 ; Set PAE in CR4
mov cr4, ecx
call LoadGDT32
call UpdatePageTable
mov ecx, BootPageTable
mov cr3, ecx
mov ecx, 0xC0000080 ; EFER
rdmsr
or eax, 0x800 | 0x100 | 0x1 ; Set LME, LMA, SCE
wrmsr
mov ecx, cr0
or ecx, 0x80000000 | 0x1 ; Set PG and PE in CR0
mov cr0, ecx
lgdt [GDT64.Ptr]
jmp GDT64.code:HigherHalfStart
extern UpdatePageTable64
[bits 64]
HigherHalfStart:
mov ax, GDT64.data
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
call UpdatePageTable64
mov rsp, KernelStack + KERNEL_STACK_SIZE
mov rdi, [MB_HeaderMagic]
mov rsi, [MB_HeaderInfo]
push rsi
push rdi
call multiboot_main
.Hang:
hlt
jmp .Hang
; Access bits
PRESENT equ 1 << 7
NOT_SYS equ 1 << 4
EXEC equ 1 << 3
DC equ 1 << 2
RW equ 1 << 1
ACCESSED equ 1 << 0
; Flags bits
GRAN_4K equ 1 << 7
SZ_32 equ 1 << 6
LONG_MODE equ 1 << 5
section .bootstrap.data
GDT64:
.null: equ $ - GDT64
dq 0
.code: equ $ - GDT64
dd 0xFFFF
db 0
db PRESENT | NOT_SYS | EXEC | RW
db GRAN_4K | LONG_MODE | 0xF
db 0
.data: equ $ - GDT64
dd 0xFFFF
db 0
db PRESENT | NOT_SYS | RW
db GRAN_4K | SZ_32 | 0xF
db 0
.tss: equ $ - GDT64
dd 0x00000068
dd 0x00CF8900
.Ptr:
dw $ - GDT64 - 1
dq GDT64
section .bootstrap.bss
align 16
KernelStack:
resb KERNEL_STACK_SIZE

View File

@ -1,45 +0,0 @@
PAGE_TABLE_SIZE equ 0x4 ; 1GB
[bits 32]
section .bootstrap.data
align 0x1000
global BootPageTable
BootPageTable:
times (0x10000) dq 0 ; 0x4000
section .bootstrap.text
global UpdatePageTable
UpdatePageTable:
mov edi, (BootPageTable + 0x0000) ; First PML4E
mov eax, (BootPageTable + 0x1000) ; First PDPTE
or eax, 11b ; Bitwise OR on rax (PDPTE) with 11b (Present, Write)
mov dword [edi], eax ; Write 11b to PML4E
mov edi, (BootPageTable + 0x1000) ; First PDPTE
mov eax, (BootPageTable + 0x2000) ; First PDE
or eax, 11b ; Bitwise OR on rax (PDE) with 11b (Present, Write)
mov ecx, PAGE_TABLE_SIZE ; For loop instruction
mov ebx, 0x0 ; Value to store in the next 4 bytes
.FillPageTableLevel3:
mov dword [edi], eax ; Store modified PDE in PDPTE
mov dword [edi + 4], ebx ; Store the rbx value in the next 4 bytes
add eax, 0x1000 ; Increment (page size)
adc ebx, 0 ; Add 0 to carry flag
add edi, 8 ; Add 8 to rdi (next PDE)
loop .FillPageTableLevel3 ; Loop until rcx is 0
mov edi, (BootPageTable + 0x2000) ; First PDE
mov eax, 10000011b ; Present, Write, Large Page
mov ecx, (512 * PAGE_TABLE_SIZE) ; For loop instruction
mov ebx, 0x0 ; Value to store in the next 4 bytes
.FillPageTableLevel2:
mov dword [edi], eax ; Store modified PDE in PDPTE
mov dword [edi + 4], ebx ; Store the rbx value in the next 4 bytes
add eax, 1 << 21 ; Increment (page size)
adc ebx, 0 ; Add 0 (carry flag) to rbx to increment if there was a carry
add edi, 8 ; Add 8 to rdi (next PDE)
loop .FillPageTableLevel2 ; Loop until rcx is 0
ret

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "acpi.hpp" #include "acpi.hpp"
#include <time.hpp> #include <time.hpp>
@ -23,7 +6,6 @@
#include <io.h> #include <io.h>
#include "cpu/apic.hpp" #include "cpu/apic.hpp"
#include "../../kernel.h"
#define ACPI_TIMER 0x0001 #define ACPI_TIMER 0x0001
#define ACPI_BUSMASTER 0x0010 #define ACPI_BUSMASTER 0x0010
@ -36,7 +18,7 @@
namespace ACPI namespace ACPI
{ {
__always_inline inline bool IsCanonical(uint64_t Address) __attribute__((always_inline)) inline bool IsCanonical(uint64_t Address)
{ {
return ((Address <= 0x00007FFFFFFFFFFF) || ((Address >= 0xFFFF800000000000) && (Address <= 0xFFFFFFFFFFFFFFFF))); return ((Address <= 0x00007FFFFFFFFFFF) || ((Address >= 0xFFFF800000000000) && (Address <= 0xFFFFFFFFFFFFFFFF)));
} }
@ -56,13 +38,13 @@ namespace ACPI
uint16_t a = 0, b = 0; uint16_t a = 0, b = 0;
if (acpi->FADT->PM1aEventBlock) if (acpi->FADT->PM1aEventBlock)
{ {
a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock)); a = inw(acpi->FADT->PM1aEventBlock);
outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a); outw(acpi->FADT->PM1aEventBlock, a);
} }
if (acpi->FADT->PM1bEventBlock) if (acpi->FADT->PM1bEventBlock)
{ {
b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock)); b = inw(acpi->FADT->PM1bEventBlock);
outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b); outw(acpi->FADT->PM1bEventBlock, b);
} }
Event = a | b; Event = a | b;
} }
@ -78,15 +60,14 @@ namespace ACPI
} }
else if (Event & ACPI_POWER_BUTTON) else if (Event & ACPI_POWER_BUTTON)
{ {
if (TaskManager) this->Shutdown();
{ Time::Clock tm = Time::ReadClock();
TaskManager->CreateThread(TaskManager->CreateProcess(nullptr, while (tm.Second == Time::ReadClock().Second)
"Shutdown", ;
Tasking::TaskTrustLevel::Kernel), outw(0xB004, 0x2000);
(Tasking::IP)KST_Shutdown); outw(0x604, 0x2000);
} outw(0x4004, 0x3400);
else CPU::Stop();
KernelShutdownThread(false);
} }
else if (Event & ACPI_SLEEP_BUTTON) else if (Event & ACPI_SLEEP_BUTTON)
{ {
@ -121,24 +102,12 @@ namespace ACPI
trace("Shutting down..."); trace("Shutting down...");
if (SCI_EN == 1) if (SCI_EN == 1)
{ {
outw(s_cst(uint16_t, acpi->FADT->PM1aControlBlock), outw(acpi->FADT->PM1aControlBlock, (inw(acpi->FADT->PM1aControlBlock) & 0xE3FF) | ((SLP_TYPa << 10) | ACPI_SLEEP));
s_cst(uint16_t,
(inw(s_cst(uint16_t,
acpi->FADT->PM1aControlBlock)) &
0xE3FF) |
((SLP_TYPa << 10) | ACPI_SLEEP)));
if (acpi->FADT->PM1bControlBlock) if (acpi->FADT->PM1bControlBlock)
outw(s_cst(uint16_t, acpi->FADT->PM1bControlBlock), outw(acpi->FADT->PM1bControlBlock, (inw(acpi->FADT->PM1bControlBlock) & 0xE3FF) | ((SLP_TYPb << 10) | ACPI_SLEEP));
s_cst(uint16_t, outw(PM1a_CNT, SLP_TYPa | SLP_EN);
(inw(
s_cst(uint16_t, acpi->FADT->PM1bControlBlock)) &
0xE3FF) |
((SLP_TYPb << 10) | ACPI_SLEEP)));
outw(s_cst(uint16_t, PM1a_CNT), SLP_TYPa | SLP_EN);
if (PM1b_CNT) if (PM1b_CNT)
outw(s_cst(uint16_t, PM1b_CNT), SLP_TYPb | SLP_EN); outw(PM1b_CNT, SLP_TYPb | SLP_EN);
} }
} }
@ -148,17 +117,12 @@ namespace ACPI
switch (acpi->FADT->ResetReg.AddressSpace) switch (acpi->FADT->ResetReg.AddressSpace)
{ {
case ACPI_GAS_MMIO: case ACPI_GAS_MMIO:
{
*(uint8_t *)(acpi->FADT->ResetReg.Address) = acpi->FADT->ResetValue; *(uint8_t *)(acpi->FADT->ResetReg.Address) = acpi->FADT->ResetValue;
break; break;
}
case ACPI_GAS_IO: case ACPI_GAS_IO:
{ outb(acpi->FADT->ResetReg.Address, acpi->FADT->ResetValue);
outb(s_cst(uint16_t, acpi->FADT->ResetReg.Address), acpi->FADT->ResetValue);
break; break;
}
case ACPI_GAS_PCI: case ACPI_GAS_PCI:
{
fixme("ACPI_GAS_PCI not supported."); fixme("ACPI_GAS_PCI not supported.");
/* /*
seg - 0 seg - 0
@ -170,15 +134,9 @@ namespace ACPI
*/ */
break; break;
} }
default:
{
error("Unknown reset register address space: %d", acpi->FADT->ResetReg.AddressSpace);
break;
}
}
} }
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt) DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt + CPU::x64::IRQ0)
{ {
this->acpi = acpi; this->acpi = acpi;
uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt); uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt);
@ -202,11 +160,11 @@ namespace ACPI
S5Address += ((*S5Address & 0xC0) >> 6) + 2; S5Address += ((*S5Address & 0xC0) >> 6) + 2;
if (*S5Address == 0x0A) if (*S5Address == 0x0A)
S5Address++; S5Address++;
SLP_TYPa = s_cst(uint16_t, *(S5Address) << 10); SLP_TYPa = *(S5Address) << 10;
S5Address++; S5Address++;
if (*S5Address == 0x0A) if (*S5Address == 0x0A)
S5Address++; S5Address++;
SLP_TYPb = s_cst(uint16_t, *(S5Address) << 10); SLP_TYPb = *(S5Address) << 10;
SMI_CMD = acpi->FADT->SMI_CommandPort; SMI_CMD = acpi->FADT->SMI_CommandPort;
ACPI_ENABLE = acpi->FADT->AcpiEnable; ACPI_ENABLE = acpi->FADT->AcpiEnable;
ACPI_DISABLE = acpi->FADT->AcpiDisable; ACPI_DISABLE = acpi->FADT->AcpiDisable;
@ -220,8 +178,8 @@ namespace ACPI
uint16_t value = ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE; uint16_t value = ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE;
{ {
uint16_t a = s_cst(uint16_t, acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2)); uint16_t a = acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2);
uint16_t b = s_cst(uint16_t, acpi->FADT->PM1bEventBlock + (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); debug("SCI Event: %#llx [a:%#x b:%#x]", value, a, b);
if (acpi->FADT->PM1aEventBlock) if (acpi->FADT->PM1aEventBlock)
outw(a, value); outw(a, value);
@ -233,13 +191,13 @@ namespace ACPI
uint16_t a = 0, b = 0; uint16_t a = 0, b = 0;
if (acpi->FADT->PM1aEventBlock) if (acpi->FADT->PM1aEventBlock)
{ {
a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock)); a = inw(acpi->FADT->PM1aEventBlock);
outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a); outw(acpi->FADT->PM1aEventBlock, a);
} }
if (acpi->FADT->PM1bEventBlock) if (acpi->FADT->PM1bEventBlock)
{ {
b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock)); b = inw(acpi->FADT->PM1bEventBlock);
outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b); outw(acpi->FADT->PM1bEventBlock, b);
} }
} }
((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1); ((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1);

View File

@ -1,35 +1,18 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <boot/binfo.h> #include <boot/binfo.h>
#include <types.h> #include <types.h>
#include <debug.h> #include <debug.h>
#include <convert.h> #include <convert.h>
#include "../../../../tools/limine/limine.h" #include "../../../tools/limine/limine.h"
#include "../../../kernel.h" #include "../../kernel.h"
void InitLimine(); void init_limine();
static volatile struct limine_entry_point_request EntryPointRequest = { static volatile struct limine_entry_point_request EntryPointRequest = {
.id = LIMINE_ENTRY_POINT_REQUEST, .id = LIMINE_ENTRY_POINT_REQUEST,
.revision = 0, .revision = 0,
.response = NULL, .response = NULL,
.entry = InitLimine}; .entry = init_limine};
static volatile struct limine_bootloader_info_request BootloaderInfoRequest = { static volatile struct limine_bootloader_info_request BootloaderInfoRequest = {
.id = LIMINE_BOOTLOADER_INFO_REQUEST, .id = LIMINE_BOOTLOADER_INFO_REQUEST,
.revision = 0}; .revision = 0};
@ -54,42 +37,14 @@ static volatile struct limine_kernel_file_request KernelFileRequest = {
static volatile struct limine_module_request ModuleRequest = { static volatile struct limine_module_request ModuleRequest = {
.id = LIMINE_MODULE_REQUEST, .id = LIMINE_MODULE_REQUEST,
.revision = 0}; .revision = 0};
static volatile struct limine_smbios_request SmbiosRequest = { static volatile struct limine_smbios_request SmbiosRequest = {
.id = LIMINE_SMBIOS_REQUEST, .id = LIMINE_SMBIOS_REQUEST,
.revision = 0}; .revision = 0};
void *TempStackPtr = NULL; SafeFunction __no_instrument_function void init_limine()
__naked __used __no_stack_protector void InitLimine()
{ {
asmv("mov %%rsp, %0" struct BootInfo binfo;
: "=r"(TempStackPtr));
asmv("mov %0, %%rsp"
:
: "r"((uintptr_t)TempStackPtr - 0xFFFF800000000000));
asmv("mov $0, %rax\n"
"mov $0, %rbx\n"
"mov $0, %rcx\n"
"mov $0, %rdx\n"
"mov $0, %rsi\n"
"mov $0, %rdi\n"
"mov $0, %rbp\n"
"mov $0, %r8\n"
"mov $0, %r9\n"
"mov $0, %r10\n"
"mov $0, %r11\n"
"mov $0, %r12\n"
"mov $0, %r13\n"
"mov $0, %r14\n"
"mov $0, %r15");
asmv("jmp InitLimineAfterStack");
}
SafeFunction NIF void InitLimineAfterStack()
{
struct BootInfo binfo = {};
struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response; struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response;
info("Bootloader: %s %s", BootloaderInfoResponse->name, BootloaderInfoResponse->version); info("Bootloader: %s %s", BootloaderInfoResponse->name, BootloaderInfoResponse->version);
@ -98,7 +53,8 @@ SafeFunction NIF void InitLimineAfterStack()
if (TerminalResponse == NULL || TerminalResponse->terminal_count < 1) if (TerminalResponse == NULL || TerminalResponse->terminal_count < 1)
{ {
warn("No terminal available."); warn("No terminal available.");
inf_loop asmv("hlt"); while (1)
asmv("hlt");
} }
TerminalResponse->write(TerminalResponse->terminals[0], "\033[37mPlease wait... ", 20); TerminalResponse->write(TerminalResponse->terminals[0], "\033[37mPlease wait... ", 20);
@ -112,79 +68,66 @@ SafeFunction NIF void InitLimineAfterStack()
if (FrameBufferResponse == NULL || FrameBufferResponse->framebuffer_count < 1) if (FrameBufferResponse == NULL || FrameBufferResponse->framebuffer_count < 1)
{ {
error("No framebuffer available [%#lx;%ld]", FrameBufferResponse, error("No framebuffer available [%p;%ld]", FrameBufferResponse,
(FrameBufferResponse == NULL) ? 0 : FrameBufferResponse->framebuffer_count); (FrameBufferResponse == NULL) ? 0 : FrameBufferResponse->framebuffer_count);
TerminalResponse->write(TerminalResponse->terminals[0], "No framebuffer available", 24); TerminalResponse->write(TerminalResponse->terminals[0], "No framebuffer available", 24);
inf_loop asmv("hlt"); while (1)
asmv("hlt");
} }
if (MemmapResponse == NULL || MemmapResponse->entry_count < 1) if (MemmapResponse == NULL || MemmapResponse->entry_count < 1)
{ {
error("No memory map available [%#lx;%ld]", MemmapResponse, error("No memory map available [%p;%ld]", MemmapResponse,
(MemmapResponse == NULL) ? 0 : MemmapResponse->entry_count); (MemmapResponse == NULL) ? 0 : MemmapResponse->entry_count);
TerminalResponse->write(TerminalResponse->terminals[0], "No memory map available", 23); TerminalResponse->write(TerminalResponse->terminals[0], "No memory map available", 23);
inf_loop asmv("hlt"); while (1)
asmv("hlt");
} }
if (KernelAddressResponse == NULL) if (KernelAddressResponse == NULL)
{ {
error("No kernel address available [%#lx]", KernelAddressResponse); error("No kernel address available [%p]", KernelAddressResponse);
TerminalResponse->write(TerminalResponse->terminals[0], "No kernel address available", 27); TerminalResponse->write(TerminalResponse->terminals[0], "No kernel address available", 27);
inf_loop asmv("hlt"); while (1)
asmv("hlt");
} }
if (RsdpResponse == NULL || RsdpResponse->address == 0) if (RsdpResponse == NULL || RsdpResponse->address == 0)
{ {
error("No RSDP address available [%#lx;%#lx]", RsdpResponse, error("No RSDP address available [%p;%p]", RsdpResponse,
(RsdpResponse == NULL) ? 0 : RsdpResponse->address); (RsdpResponse == NULL) ? 0 : RsdpResponse->address);
TerminalResponse->write(TerminalResponse->terminals[0], "No RSDP address available", 25); TerminalResponse->write(TerminalResponse->terminals[0], "No RSDP address available", 25);
inf_loop asmv("hlt"); while (1)
asmv("hlt");
} }
if (KernelFileResponse == NULL || KernelFileResponse->kernel_file == NULL) if (KernelFileResponse == NULL || KernelFileResponse->kernel_file == NULL)
{ {
error("No kernel file available [%#lx;%#lx]", KernelFileResponse, error("No kernel file available [%p;%p]", KernelFileResponse,
(KernelFileResponse == NULL) ? 0 : KernelFileResponse->kernel_file); (KernelFileResponse == NULL) ? 0 : KernelFileResponse->kernel_file);
TerminalResponse->write(TerminalResponse->terminals[0], "No kernel file available", 24); TerminalResponse->write(TerminalResponse->terminals[0], "No kernel file available", 24);
inf_loop asmv("hlt"); while (1)
asmv("hlt");
} }
if (ModuleResponse == NULL || ModuleResponse->module_count < 1) if (ModuleResponse == NULL || ModuleResponse->module_count < 1)
{ {
error("No module information available [%#lx;%ld]", ModuleResponse, error("No module information available [%p;%ld]", ModuleResponse,
(ModuleResponse == NULL) ? 0 : ModuleResponse->module_count); (ModuleResponse == NULL) ? 0 : ModuleResponse->module_count);
TerminalResponse->write(TerminalResponse->terminals[0], "No module information available", 31); TerminalResponse->write(TerminalResponse->terminals[0], "No module information available", 31);
inf_loop asmv("hlt"); while (1)
asmv("hlt");
} }
/* Actual parsing starts here */
for (uint64_t i = 0; i < FrameBufferResponse->framebuffer_count; i++) for (uint64_t i = 0; i < FrameBufferResponse->framebuffer_count; i++)
{ {
struct limine_framebuffer *framebuffer = FrameBufferResponse->framebuffers[i]; struct limine_framebuffer *framebuffer = FrameBufferResponse->framebuffers[i];
switch (framebuffer->memory_model) binfo.Framebuffer[i].BaseAddress = (void *)((uint64_t)framebuffer->address - 0xffff800000000000);
{ binfo.Framebuffer[i].Width = framebuffer->width;
case LIMINE_FRAMEBUFFER_RGB: binfo.Framebuffer[i].Height = framebuffer->height;
binfo.Framebuffer[i].Type = RGB; binfo.Framebuffer[i].Pitch = framebuffer->pitch;
break;
default:
{
error("Unsupported framebuffer memory model %d", framebuffer->memory_model);
TerminalResponse->write(TerminalResponse->terminals[0], "Unsupported framebuffer memory model", 37);
inf_loop asmv("hlt");
}
}
binfo.Framebuffer[i].BaseAddress = (void *)((uintptr_t)framebuffer->address - 0xFFFF800000000000);
binfo.Framebuffer[i].Width = (uint32_t)framebuffer->width;
binfo.Framebuffer[i].Height = (uint32_t)framebuffer->height;
binfo.Framebuffer[i].Pitch = (uint32_t)framebuffer->pitch;
binfo.Framebuffer[i].BitsPerPixel = framebuffer->bpp; binfo.Framebuffer[i].BitsPerPixel = framebuffer->bpp;
binfo.Framebuffer[i].MemoryModel = framebuffer->memory_model;
binfo.Framebuffer[i].RedMaskSize = framebuffer->red_mask_size; binfo.Framebuffer[i].RedMaskSize = framebuffer->red_mask_size;
binfo.Framebuffer[i].RedMaskShift = framebuffer->red_mask_shift; binfo.Framebuffer[i].RedMaskShift = framebuffer->red_mask_shift;
binfo.Framebuffer[i].GreenMaskSize = framebuffer->green_mask_size; binfo.Framebuffer[i].GreenMaskSize = framebuffer->green_mask_size;
@ -193,24 +136,9 @@ SafeFunction NIF void InitLimineAfterStack()
binfo.Framebuffer[i].BlueMaskShift = framebuffer->blue_mask_shift; binfo.Framebuffer[i].BlueMaskShift = framebuffer->blue_mask_shift;
binfo.Framebuffer[i].ExtendedDisplayIdentificationData = framebuffer->edid; binfo.Framebuffer[i].ExtendedDisplayIdentificationData = framebuffer->edid;
binfo.Framebuffer[i].EDIDSize = framebuffer->edid_size; binfo.Framebuffer[i].EDIDSize = framebuffer->edid_size;
debug("Framebuffer %d: %dx%d %d bpp", i, framebuffer->width, framebuffer->height, framebuffer->bpp);
debug("Framebuffer %d: %dx%d %d bpp", i, 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",
binfo.Framebuffer[i].Width, (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.Framebuffer[i].Height,
binfo.Framebuffer[i].BitsPerPixel);
debug("More info:\nAddress: %#lx\nPitch: %ld\nType: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d\nEDID: %#lx\nEDIDSize: %d",
binfo.Framebuffer[i].BaseAddress,
binfo.Framebuffer[i].Pitch,
binfo.Framebuffer[i].Type,
binfo.Framebuffer[i].RedMaskSize,
binfo.Framebuffer[i].RedMaskShift,
binfo.Framebuffer[i].GreenMaskSize,
binfo.Framebuffer[i].GreenMaskShift,
binfo.Framebuffer[i].BlueMaskSize,
binfo.Framebuffer[i].BlueMaskShift,
binfo.Framebuffer[i].ExtendedDisplayIdentificationData,
binfo.Framebuffer[i].EDIDSize);
} }
binfo.Memory.Entries = MemmapResponse->entry_count; binfo.Memory.Entries = MemmapResponse->entry_count;
@ -223,12 +151,6 @@ SafeFunction NIF void InitLimineAfterStack()
} }
struct limine_memmap_entry *entry = MemmapResponse->entries[i]; struct limine_memmap_entry *entry = MemmapResponse->entries[i];
if (!entry)
{
warn("Null memory entry %ld (%#lx), skipping...", i, entry);
continue;
}
binfo.Memory.Size += entry->length; binfo.Memory.Size += entry->length;
switch (entry->type) switch (entry->type)
{ {
@ -288,59 +210,48 @@ SafeFunction NIF void InitLimineAfterStack()
break; break;
} }
binfo.Modules[i].Address = (void *)((uint64_t)ModuleResponse->modules[i]->address - 0xFFFF800000000000); binfo.Modules[i].Address = (void *)((uint64_t)ModuleResponse->modules[i]->address - 0xffff800000000000);
binfo.Modules[i].Size = ModuleResponse->modules[i]->size;
strncpy(binfo.Modules[i].Path, strncpy(binfo.Modules[i].Path,
ModuleResponse->modules[i]->path, ModuleResponse->modules[i]->path,
strlen(ModuleResponse->modules[i]->path) + 1); strlen(ModuleResponse->modules[i]->path) + 1);
strncpy(binfo.Modules[i].CommandLine, strncpy(binfo.Modules[i].CommandLine,
ModuleResponse->modules[i]->cmdline, ModuleResponse->modules[i]->cmdline,
strlen(ModuleResponse->modules[i]->cmdline) + 1); strlen(ModuleResponse->modules[i]->cmdline) + 1);
binfo.Modules[i].Size = ModuleResponse->modules[i]->size;
debug("Module %d:\nAddress: %#lx\nPath: \"%s\"\nCommand Line: \"%s\"\nSize: %ld", debug("Module %d:\nAddress: %p\nPath: %s\nCommand Line: %s\nSize: %ld", i,
i, (uint64_t)ModuleResponse->modules[i]->address - 0xffff800000000000, ModuleResponse->modules[i]->path,
binfo.Modules[i].Address, ModuleResponse->modules[i]->cmdline, ModuleResponse->modules[i]->size);
binfo.Modules[i].Path,
binfo.Modules[i].CommandLine,
binfo.Modules[i].Size);
} }
binfo.RSDP = (struct RSDPInfo *)((uintptr_t)RsdpResponse->address - 0xFFFF800000000000); binfo.RSDP = (struct RSDPInfo *)((uint64_t)RsdpResponse->address - 0xffff800000000000);
debug("RSDP: %#lx [Signature: \"%.8s\"] [OEM: \"%.6s\"]", trace("RSDP: %p(%p) [Signature: %.8s] [OEM: %.6s]",
binfo.RSDP, binfo.RSDP->Signature, binfo.RSDP->OEMID); RsdpResponse->address, binfo.RSDP, binfo.RSDP->Signature, binfo.RSDP->OEMID);
if (SmbiosResponse->entry_64 != NULL) debug("SMBIOS: %p %p", SmbiosResponse->entry_32, SmbiosResponse->entry_64);
binfo.SMBIOSPtr = (void *)((uintptr_t)SmbiosResponse->entry_64 - 0xFFFF800000000000); if (SmbiosResponse->entry_32 != NULL)
else if (SmbiosResponse->entry_32 != NULL) binfo.SMBIOSPtr = (void *)((uint64_t)SmbiosResponse->entry_32 - 0xffff800000000000);
binfo.SMBIOSPtr = (void *)((uintptr_t)SmbiosResponse->entry_32 - 0xFFFF800000000000); else if (SmbiosResponse->entry_64 != NULL)
binfo.SMBIOSPtr = (void *)((uint64_t)SmbiosResponse->entry_64 - 0xffff800000000000);
else else
binfo.SMBIOSPtr = NULL; binfo.SMBIOSPtr = NULL;
debug("SMBIOS: %#lx %#lx (binfo: %#lx)",
SmbiosResponse->entry_32,
SmbiosResponse->entry_64,
binfo.SMBIOSPtr);
binfo.Kernel.PhysicalBase = (void *)KernelAddressResponse->physical_base; binfo.Kernel.PhysicalBase = (void *)KernelAddressResponse->physical_base;
binfo.Kernel.VirtualBase = (void *)KernelAddressResponse->virtual_base; binfo.Kernel.VirtualBase = (void *)KernelAddressResponse->virtual_base;
binfo.Kernel.FileBase = (void *)((uintptr_t)KernelFileResponse->kernel_file->address - 0xFFFF800000000000); binfo.Kernel.FileBase = KernelFileResponse->kernel_file->address;
binfo.Kernel.Size = KernelFileResponse->kernel_file->size;
strncpy(binfo.Kernel.CommandLine, strncpy(binfo.Kernel.CommandLine,
KernelFileResponse->kernel_file->cmdline, KernelFileResponse->kernel_file->cmdline,
strlen(KernelFileResponse->kernel_file->cmdline) + 1); strlen(KernelFileResponse->kernel_file->cmdline) + 1);
binfo.Kernel.Size = KernelFileResponse->kernel_file->size;
debug("Kernel physical address: %#lx", binfo.Kernel.PhysicalBase); trace("Kernel physical address: %p", KernelAddressResponse->physical_base);
debug("Kernel virtual address: %#lx", binfo.Kernel.VirtualBase); trace("Kernel virtual address: %p", KernelAddressResponse->virtual_base);
strncpy(binfo.Bootloader.Name, strncpy(binfo.Bootloader.Name,
BootloaderInfoResponse->name, BootloaderInfoResponse->name,
strlen(BootloaderInfoResponse->name) + 1); strlen(BootloaderInfoResponse->name) + 1);
strncpy(binfo.Bootloader.Version, strncpy(binfo.Bootloader.Version,
BootloaderInfoResponse->version, BootloaderInfoResponse->version,
strlen(BootloaderInfoResponse->version) + 1); strlen(BootloaderInfoResponse->version) + 1);
// Call kernel entry point
Entry(&binfo); Entry(&binfo);
} }

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "acpi.hpp" #include "acpi.hpp"
#include <memory.hpp> #include <memory.hpp>
@ -49,7 +32,7 @@ namespace ACPI
{ {
ioapic.push_back((MADTIOApic *)ptr); ioapic.push_back((MADTIOApic *)ptr);
KPrint("I/O APIC \e8888FF%d\eCCCCCC (Address \e8888FF%#lx\eCCCCCC) found.", ioapic.back()->APICID, ioapic.back()->Address); KPrint("I/O APIC \e8888FF%d\eCCCCCC (Address \e8888FF%#lx\eCCCCCC) found.", ioapic.back()->APICID, ioapic.back()->Address);
Memory::Virtual(KernelPageTable).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. 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; break;
} }
case 2: case 2:
@ -73,13 +56,8 @@ namespace ACPI
KPrint("APIC found at \e8888FF%#lx\eCCCCCC", LAPICAddress); KPrint("APIC found at \e8888FF%#lx\eCCCCCC", LAPICAddress);
break; break;
} }
default:
{
KPrint("Unknown MADT entry \e8888FF%#lx\eCCCCCC", *(ptr));
break;
} }
} Memory::Virtual().Map((void *)LAPICAddress, (void *)LAPICAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page?
Memory::Virtual(KernelPageTable).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. CPUCores--; // We start at 0 (BSP) and end at 11 (APs), so we have 12 cores.
KPrint("Total CPU cores: %d", CPUCores + 1); KPrint("Total CPU cores: %d", CPUCores + 1);

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp> #include <syscalls.hpp>
#include <cpu.hpp> #include <cpu.hpp>
@ -29,58 +12,68 @@ extern "C" uint64_t SystemCallsHandler(SyscallsFrame *regs);
extern "C" void SystemCallHandlerStub(); extern "C" void SystemCallHandlerStub();
extern "C" __naked __used __no_stack_protector __aligned(16) void SystemCallHandlerStub() extern "C" __attribute__((naked, used, no_stack_protector)) void SystemCallHandlerStub_broken()
{ {
asmv("swapgs\n" // asmv(
// // "cmp $0x08, 0x8(%rsp)\n"
// // "je 1f\n"
// "swapgs\n"
// // "1:\n"
"mov %rsp, %gs:0x8\n" // CPUData->TempStack // "mov %rsp, 0x8(%gs)\n" // CPUData->TempStack
"mov %gs:0x0, %rsp\n" // CPUData->SystemCallStack // "mov 0x0(%gs), %rsp\n" // CPUData->SystemCallStack
"push $0x1b\n" // user data segment // "push $0x1b\n" // user data segment
"push %gs:0x8\n" // saved stack // "push 0x8(%gs)\n" // saved stack
"push %r11\n" // saved rflags // "push %r11\n" // saved rflags
"push $0x23\n" // user code segment // "push $0x23\n" // user code segment
"push %rcx\n" // Current RIP // "push %rcx\n" // Current RIP
"push %rax\n" // "push %rax\n"
"push %rbx\n" // "push %rbx\n"
"push %rcx\n" // "push %rcx\n"
"push %rdx\n" // "push %rdx\n"
"push %rsi\n" // "push %rsi\n"
"push %rdi\n" // "push %rdi\n"
"push %rbp\n" // "push %rbp\n"
"push %r8\n" // "push %r8\n"
"push %r9\n" // "push %r9\n"
"push %r10\n" // "push %r10\n"
"push %r11\n" // "push %r11\n"
"push %r12\n" // "push %r12\n"
"push %r13\n" // "push %r13\n"
"push %r14\n" // "push %r14\n"
"push %r15\n" // "push %r15\n"
"mov %rsp, %rdi\n" // "mov %rsp, %rdi\n"
"mov $0, %rbp\n" // "mov $0, %rbp\n"
"call SystemCallsHandler\n" // "call SystemCallsHandler\n"
"pop %r15\n" // "pop %r15\n"
"pop %r14\n" // "pop %r14\n"
"pop %r13\n" // "pop %r13\n"
"pop %r12\n" // "pop %r12\n"
"pop %r11\n" // "pop %r11\n"
"pop %r10\n" // "pop %r10\n"
"pop %r9\n" // "pop %r9\n"
"pop %r8\n" // "pop %r8\n"
"pop %rbp\n" // "pop %rbp\n"
"pop %rdi\n" // "pop %rdi\n"
"pop %rsi\n" // "pop %rsi\n"
"pop %rdx\n" // "pop %rdx\n"
"pop %rcx\n" // "pop %rcx\n"
"pop %rbx\n" // "pop %rbx\n"
// /* "pop %rax\n" */
"mov %gs:0x8, %rsp\n" // CPUData->TempStack // "mov 0x8(%gs), %rsp\n" // CPUData->TempStack
"swapgs\n" // // "cmp $0x08, 0x8(%rsp)\n"
"sti\n" // // "je 1f\n"
"sysretq\n"); // "swapgs\n"
// // "1:\n"
// "sti\n"
// "sysretq\n");
} }
void InitializeSystemCalls() void InitializeSystemCalls()

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

@ -1,29 +1,12 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_ACPI_H__ #ifndef __FENNIX_KERNEL_ACPI_H__
#define __FENNIX_KERNEL_ACPI_H__ #define __FENNIX_KERNEL_ACPI_H__
#include <types.h> #include <types.h>
#include <boot/binfo.h> #include <boot/binfo.h>
#include <ints.hpp> #include <interrupts.hpp>
#include <vector.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#include <vector>
namespace ACPI namespace ACPI
{ {
@ -41,7 +24,7 @@ namespace ACPI
uint32_t OEMRevision; uint32_t OEMRevision;
uint32_t CreatorID; uint32_t CreatorID;
uint32_t CreatorRevision; uint32_t CreatorRevision;
} __packed; } __attribute__((packed));
struct GenericAddressStructure struct GenericAddressStructure
{ {
@ -50,13 +33,13 @@ namespace ACPI
uint8_t BitOffset; uint8_t BitOffset;
uint8_t AccessSize; uint8_t AccessSize;
uint64_t Address; uint64_t Address;
} __packed; } __attribute__((packed));
struct MCFGHeader struct MCFGHeader
{ {
struct ACPIHeader Header; struct ACPIHeader Header;
uint64_t Reserved; uint64_t Reserved;
} __packed; } __attribute__((packed));
struct HPETHeader struct HPETHeader
{ {
@ -71,7 +54,7 @@ namespace ACPI
uint8_t HPETNumber; uint8_t HPETNumber;
uint16_t MinimumTick; uint16_t MinimumTick;
uint8_t PageProtection; uint8_t PageProtection;
} __packed; } __attribute__((packed));
struct FADTHeader struct FADTHeader
{ {
@ -127,7 +110,7 @@ namespace ACPI
struct GenericAddressStructure X_PMTimerBlock; struct GenericAddressStructure X_PMTimerBlock;
struct GenericAddressStructure X_GPE0Block; struct GenericAddressStructure X_GPE0Block;
struct GenericAddressStructure X_GPE1Block; struct GenericAddressStructure X_GPE1Block;
} __packed; } __attribute__((packed));
struct BGRTHeader struct BGRTHeader
{ {
@ -181,7 +164,7 @@ namespace ACPI
uint32_t LocalControllerAddress; uint32_t LocalControllerAddress;
uint32_t Flags; uint32_t Flags;
char Entries[]; char Entries[];
} __packed; } __attribute__((packed));
ACPIHeader *XSDT = nullptr; ACPIHeader *XSDT = nullptr;
MCFGHeader *MCFG = nullptr; MCFGHeader *MCFG = nullptr;
@ -198,7 +181,7 @@ namespace ACPI
void *FindTable(ACPIHeader *ACPIHeader, char *Signature); void *FindTable(ACPIHeader *ACPIHeader, char *Signature);
void SearchTables(ACPIHeader *Header); void SearchTables(ACPIHeader *Header);
ACPI(); ACPI(BootInfo *Info);
~ACPI(); ~ACPI();
}; };
@ -209,7 +192,7 @@ namespace ACPI
{ {
uint8_t Type; uint8_t Type;
uint8_t Length; uint8_t Length;
} __packed; } __attribute__((packed));
struct MADTIOApic struct MADTIOApic
{ {
@ -218,7 +201,7 @@ namespace ACPI
uint8_t reserved; uint8_t reserved;
uint32_t Address; uint32_t Address;
uint32_t GSIBase; uint32_t GSIBase;
} __packed; } __attribute__((packed));
struct MADTIso struct MADTIso
{ {
@ -227,7 +210,7 @@ namespace ACPI
uint8_t IRQSource; uint8_t IRQSource;
uint32_t GSI; uint32_t GSI;
uint16_t Flags; uint16_t Flags;
} __packed; } __attribute__((packed));
struct MADTNmi struct MADTNmi
{ {
@ -235,7 +218,7 @@ namespace ACPI
uint8_t processor; uint8_t processor;
uint16_t flags; uint16_t flags;
uint8_t lint; uint8_t lint;
} __packed; } __attribute__((packed));
struct LocalAPIC struct LocalAPIC
{ {
@ -243,7 +226,7 @@ namespace ACPI
uint8_t ACPIProcessorId; uint8_t ACPIProcessorId;
uint8_t APICId; uint8_t APICId;
uint32_t Flags; uint32_t Flags;
} __packed; } __attribute__((packed));
struct LAPIC struct LAPIC
{ {
@ -252,10 +235,10 @@ namespace ACPI
void *VirtualAddress; void *VirtualAddress;
}; };
std::vector<MADTIOApic *> ioapic; Vector<MADTIOApic *> ioapic;
std::vector<MADTIso *> iso; Vector<MADTIso *> iso;
std::vector<MADTNmi *> nmi; Vector<MADTNmi *> nmi;
std::vector<LocalAPIC *> lapic; Vector<LocalAPIC *> lapic;
struct LAPIC *LAPICAddress; struct LAPIC *LAPICAddress;
uint16_t CPUCores; uint16_t CPUCores;

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "apic.hpp" #include "apic.hpp"
#include <memory.hpp> #include <memory.hpp>
@ -30,7 +13,6 @@
NewLock(APICLock); NewLock(APICLock);
using namespace CPU::x64; using namespace CPU::x64;
using namespace CPU::x86;
/* /*
In constructor APIC::APIC::APIC(int): In constructor APIC::APIC::APIC(int):
@ -48,18 +30,16 @@ namespace APIC
uint32_t APIC::Read(uint32_t Register) uint32_t APIC::Read(uint32_t Register)
{ {
#ifdef DEBUG
if (Register != APIC_ICRLO && if (Register != APIC_ICRLO &&
Register != APIC_ICRHI && Register != APIC_ICRHI &&
Register != APIC_ID) Register != APIC_ID)
debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0); debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0);
#endif
if (x2APICSupported) if (x2APICSupported)
{ {
if (Register != APIC_ICRHI) if (Register != APIC_ICRHI)
return s_cst(uint32_t, rdmsr((Register >> 4) + 0x800)); return rdmsr((Register >> 4) + 0x800);
else else
return s_cst(uint32_t, rdmsr(0x30 + 0x800)); return rdmsr(0x30 + 0x800);
} }
else else
{ {
@ -72,7 +52,6 @@ namespace APIC
void APIC::Write(uint32_t Register, uint32_t Value) void APIC::Write(uint32_t Register, uint32_t Value)
{ {
#ifdef DEBUG
if (Register != APIC_EOI && if (Register != APIC_EOI &&
Register != APIC_TDCR && Register != APIC_TDCR &&
Register != APIC_TIMER && Register != APIC_TIMER &&
@ -80,7 +59,6 @@ namespace APIC
Register != APIC_ICRLO && Register != APIC_ICRLO &&
Register != APIC_ICRHI) Register != APIC_ICRHI)
debug("APIC::Write(%#lx, %#lx) [x2=%d]", Register, Value, x2APICSupported ? 1 : 0); debug("APIC::Write(%#lx, %#lx) [x2=%d]", Register, Value, x2APICSupported ? 1 : 0);
#endif
if (x2APICSupported) if (x2APICSupported)
{ {
if (Register != APIC_ICRHI) if (Register != APIC_ICRHI)
@ -128,32 +106,29 @@ namespace APIC
} while (icr.DeliveryStatus != Idle); } while (icr.DeliveryStatus != Idle);
} }
void APIC::IPI(int CPU, InterruptCommandRegisterLow icr) void APIC::IPI(uint8_t CPU, InterruptCommandRegisterLow icr)
{ {
SmartCriticalSection(APICLock); SmartCriticalSection(APICLock);
if (x2APICSupported) if (x2APICSupported)
{ {
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw)); fixme("Not implemented for x2APIC");
this->WaitForIPI(); // wrmsr(MSR_X2APIC_ICR, ((uint64_t)CPU) << 32);
} }
else else
{ {
this->Write(APIC_ICRHI, (CPU << 24)); this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw)); this->Write(APIC_ICRLO, icr.raw);
this->WaitForIPI(); this->WaitForIPI();
} }
} }
void APIC::SendInitIPI(int CPU) void APIC::SendInitIPI(uint8_t CPU)
{ {
SmartCriticalSection(APICLock); SmartCriticalSection(APICLock);
if (x2APICSupported) if (x2APICSupported)
{ {
InterruptCommandRegisterLow icr = {.raw = 0}; fixme("Not implemented for x2APIC");
icr.DeliveryMode = INIT; // wrmsr(MSR_X2APIC_ICR, ((uint64_t)CPU) << 32);
icr.Level = Assert;
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
} }
else else
{ {
@ -161,31 +136,27 @@ namespace APIC
icr.DeliveryMode = INIT; icr.DeliveryMode = INIT;
icr.Level = Assert; icr.Level = Assert;
this->Write(APIC_ICRHI, (CPU << 24)); this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw)); this->Write(APIC_ICRLO, icr.raw);
this->WaitForIPI(); this->WaitForIPI();
} }
} }
void APIC::SendStartupIPI(int CPU, uint64_t StartupAddress) void APIC::SendStartupIPI(uint8_t CPU, uint64_t StartupAddress)
{ {
SmartCriticalSection(APICLock); SmartCriticalSection(APICLock);
if (x2APICSupported) if (x2APICSupported)
{ {
InterruptCommandRegisterLow icr = {.raw = 0}; warn("Not tested for x2APIC");
icr.Vector = s_cst(uint8_t, StartupAddress >> 12); wrmsr(MSR_X2APIC_ICR, ((uint64_t)CPU) << 32 | StartupAddress);
icr.DeliveryMode = Startup;
icr.Level = Assert;
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
} }
else else
{ {
InterruptCommandRegisterLow icr = {.raw = 0}; InterruptCommandRegisterLow icr = {.raw = 0};
icr.Vector = s_cst(uint8_t, StartupAddress >> 12); icr.Vector = StartupAddress >> 12;
icr.DeliveryMode = Startup; icr.DeliveryMode = Startup;
icr.Level = Assert; icr.Level = Assert;
this->Write(APIC_ICRHI, (CPU << 24)); this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw)); this->Write(APIC_ICRLO, icr.raw);
this->WaitForIPI(); this->WaitForIPI();
} }
} }
@ -196,14 +167,14 @@ namespace APIC
return ((IOAPICVersion *)&TableAddress)->MaximumRedirectionEntry; return ((IOAPICVersion *)&TableAddress)->MaximumRedirectionEntry;
} }
void APIC::RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status) void APIC::RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status)
{ {
uint64_t Value = Vector; uint64_t Value = Vector;
int64_t IOAPICTarget = -1; int64_t IOAPICTarget = -1;
for (uint64_t i = 0; ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i] != 0; i++) 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 <= GSI)
if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase + IOGetMaxRedirect(s_cst(uint32_t, i)) > GSI) if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase + IOGetMaxRedirect(i) > GSI)
{ {
IOAPICTarget = i; IOAPICTarget = i;
break; break;
@ -233,7 +204,7 @@ namespace APIC
this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister + 1, (uint32_t)(Value >> 32)); this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister + 1, (uint32_t)(Value >> 32));
} }
void APIC::RedirectIRQ(int CPU, uint16_t IRQ, int Status) void APIC::RedirectIRQ(int CPU, uint8_t IRQ, int Status)
{ {
for (uint64_t i = 0; i < ((ACPI::MADT *)PowerManager->GetMADT())->iso.size(); i++) for (uint64_t i = 0; i < ((ACPI::MADT *)PowerManager->GetMADT())->iso.size(); i++)
if (((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource == IRQ) if (((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource == IRQ)
@ -252,7 +223,7 @@ namespace APIC
{ {
SmartCriticalSection(APICLock); SmartCriticalSection(APICLock);
debug("Redirecting IRQs..."); debug("Redirecting IRQs...");
for (uint8_t i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
this->RedirectIRQ(CPU, i, 1); this->RedirectIRQ(CPU, i, 1);
debug("Redirecting IRQs completed."); debug("Redirecting IRQs completed.");
} }
@ -265,34 +236,14 @@ namespace APIC
uint64_t BaseHigh = BaseStruct.ApicBaseHi; uint64_t BaseHigh = BaseStruct.ApicBaseHi;
this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u; this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u;
trace("APIC Address: %#lx", this->APICBaseAddress); trace("APIC Address: %#lx", this->APICBaseAddress);
Memory::Virtual().Map((void *)this->APICBaseAddress, (void *)this->APICBaseAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD);
bool x2APICSupported = false; uint32_t rcx;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) cpuid(1, 0, 0, &rcx, 0);
if (rcx & CPUID_FEAT_RCX_x2APIC)
{ {
CPU::x86::AMD::CPUID0x00000001 cpuid; // this->x2APICSupported = true;
cpuid.Get(); warn("x2APIC not supported yet.");
if (cpuid.ECX.x2APIC) // wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
{
// x2APICSupported = cpuid.ECX.x2APIC;
fixme("x2APIC is supported");
}
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
CPU::x86::Intel::CPUID0x00000001 cpuid;
cpuid.Get();
if (cpuid.ECX.x2APIC)
{
// x2APICSupported = cpuid.ECX.x2APIC;
fixme("x2APIC is supported");
}
}
if (x2APICSupported)
{
this->x2APICSupported = true;
wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
BaseStruct.EN = 1; BaseStruct.EN = 1;
wrmsr(MSR_APIC_BASE, BaseStruct.raw); wrmsr(MSR_APIC_BASE, BaseStruct.raw);
} }
@ -333,7 +284,7 @@ namespace APIC
Spurious Spurious = {.raw = this->Read(APIC_SVR)}; Spurious Spurious = {.raw = this->Read(APIC_SVR)};
Spurious.Vector = IRQ223; // TODO: Should I map the IRQ to something? Spurious.Vector = IRQ223; // TODO: Should I map the IRQ to something?
Spurious.Software = 1; Spurious.Software = 1;
this->Write(APIC_SVR, s_cst(uint32_t, Spurious.raw)); this->Write(APIC_SVR, Spurious.raw);
static int once = 0; static int once = 0;
if (!once++) if (!once++)
@ -350,23 +301,23 @@ namespace APIC
APIC::~APIC() {} APIC::~APIC() {}
void Timer::OnInterruptReceived(TrapFrame *Frame) { UNUSED(Frame); } void Timer::OnInterruptReceived(TrapFrame *Frame) {}
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds) void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
{ {
SmartCriticalSection(APICLock); SmartCriticalSection(APICLock);
LVTTimer timer = {.raw = 0}; LVTTimer timer = {.raw = 0};
timer.Vector = s_cst(uint8_t, Vector); timer.Vector = Vector;
timer.TimerMode = 0; timer.TimerMode = 0;
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0) if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
this->lapic->Write(APIC_TDCR, DivideBy128); this->lapic->Write(APIC_TDCR, DivideBy128);
else else
this->lapic->Write(APIC_TDCR, DivideBy16); this->lapic->Write(APIC_TDCR, DivideBy16);
this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks * Miliseconds)); this->lapic->Write(APIC_TICR, Ticks * Miliseconds);
this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw)); this->lapic->Write(APIC_TIMER, timer.raw);
} }
Timer::Timer(APIC *apic) : Interrupts::Handler(0) /* IRQ0 */ Timer::Timer(APIC *apic) : Interrupts::Handler(IRQ0)
{ {
SmartCriticalSection(APICLock); SmartCriticalSection(APICLock);
this->lapic = apic; this->lapic = apic;
@ -377,7 +328,7 @@ namespace APIC
this->lapic->Write(APIC_TDCR, Divider); this->lapic->Write(APIC_TDCR, Divider);
this->lapic->Write(APIC_TICR, 0xFFFFFFFF); this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
TimeManager->Sleep(1, Time::Units::Milliseconds); TimeManager->Sleep(10);
// Mask the timer // Mask the timer
this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */); this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);
@ -391,8 +342,8 @@ namespace APIC
// Initialize APIC timer // Initialize APIC timer
this->lapic->Write(APIC_TDCR, Divider); this->lapic->Write(APIC_TDCR, Divider);
this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks)); this->lapic->Write(APIC_TICR, Ticks);
this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw)); this->lapic->Write(APIC_TIMER, timer.raw);
trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks); trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks);
KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks); KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks);
} }

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "gdt.hpp" #include "gdt.hpp"
#include <memory.hpp> #include <memory.hpp>
@ -25,98 +8,75 @@
namespace GlobalDescriptorTable namespace GlobalDescriptorTable
{ {
static GlobalDescriptorTableEntries GDTEntriesTemplate = { static GlobalDescriptorTableEntries GDTEntriesTemplate = {
.Null = // null
{ {.Length = 0x0,
.Length = 0x0,
.BaseLow = 0x0, .BaseLow = 0x0,
.BaseMiddle = 0x0, .BaseMiddle = 0x0,
.Access = {.Raw = 0x0}, .Access = {.Raw = 0x0},
.Flags = {.Raw = 0x0}, .Flags = {.Raw = 0x0},
.BaseHigh = 0x0, .BaseHigh = 0x0},
},
.Code = // kernel code
{ {.Length = 0x0,
.Length = 0x0,
.BaseLow = 0x0, .BaseLow = 0x0,
.BaseMiddle = 0x0, .BaseMiddle = 0x0,
.Access = { .Access = {.A = 0,
.A = 0,
.RW = 1, .RW = 1,
.DC = 0, .DC = 0,
.E = 1, .E = 1,
.S = 1, .S = 1,
.DPL = 0, .DPL = 0,
.P = 1, .P = 1},
}, .Flags = {.Unknown = 0x0, .L = 1},
.Flags = { .BaseHigh = 0x0},
.Unknown = 0x0,
.L = 1,
},
.BaseHigh = 0x0,
},
.Data = { // kernel data
.Length = 0x0, {.Length = 0x0,
.BaseLow = 0x0, .BaseLow = 0x0,
.BaseMiddle = 0x0, .BaseMiddle = 0x0,
.Access = { .Access = {.A = 0,
.A = 0,
.RW = 1, .RW = 1,
.DC = 0, .DC = 0,
.E = 0, .E = 0,
.S = 1, .S = 1,
.DPL = 0, .DPL = 0,
.P = 1, .P = 1},
},
.Flags = {.Raw = 0x0}, .Flags = {.Raw = 0x0},
.BaseHigh = 0x0, .BaseHigh = 0x0},
},
.UserData = { // user data
.Length = 0x0, {.Length = 0x0,
.BaseLow = 0x0, .BaseLow = 0x0,
.BaseMiddle = 0x0, .BaseMiddle = 0x0,
.Access = { .Access = {.A = 0,
.A = 0,
.RW = 1, .RW = 1,
.DC = 0, .DC = 0,
.E = 0, .E = 0,
.S = 1, .S = 1,
.DPL = 3, .DPL = 3,
.P = 1, .P = 1},
}, .Flags = {.Raw = 0x0},
.Flags = { .BaseHigh = 0x0},
.Raw = 0x0,
},
.BaseHigh = 0x0,
},
.UserCode = { // user code
.Length = 0x0, {.Length = 0x0,
.BaseLow = 0x0, .BaseLow = 0x0,
.BaseMiddle = 0x0, .BaseMiddle = 0x0,
.Access = { .Access = {.A = 0,
.A = 0,
.RW = 1, .RW = 1,
.DC = 0, .DC = 0,
.E = 1, .E = 1,
.S = 1, .S = 1,
.DPL = 3, .DPL = 3,
.P = 1, .P = 1},
}, .Flags = {.Unknown = 0x0, .L = 1},
.Flags = { .BaseHigh = 0x0},
.Unknown = 0x0,
.L = 1,
},
.BaseHigh = 0x0,
},
.TaskStateSegment = {}, // tss
}; {}};
GlobalDescriptorTableEntries GDTEntries[MAX_CPU] __aligned(16); static GlobalDescriptorTableEntries GDTEntries[MAX_CPU];
GlobalDescriptorTableDescriptor gdt[MAX_CPU] __aligned(16); GlobalDescriptorTableDescriptor gdt[MAX_CPU];
TaskStateSegment tss[MAX_CPU] = { TaskStateSegment tss[MAX_CPU] = {
0, 0,
@ -125,7 +85,6 @@ namespace GlobalDescriptorTable
{0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0},
0, 0,
0, 0,
0,
}; };
void *CPUStackPointer[MAX_CPU]; void *CPUStackPointer[MAX_CPU];
@ -154,61 +113,41 @@ namespace GlobalDescriptorTable
"movw %%ax, %%es\n" :: "movw %%ax, %%es\n" ::
: "memory", "rax"); : "memory", "rax");
CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)); CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
memset(CPUStackPointer[Core], 0, STACK_SIZE);
debug("CPU %d Stack Pointer: %#lx-%#lx (%d pages)", Core,
CPUStackPointer[Core], (uintptr_t)CPUStackPointer[Core] + STACK_SIZE,
TO_PAGES(STACK_SIZE + 1));
uintptr_t Base = (uintptr_t)&tss[Core]; uint64_t Base = (uint64_t)&tss[Core];
size_t Limit = Base + sizeof(TaskStateSegment); uint64_t Limit = Base + sizeof(TaskStateSegment);
gdt[Core].Entries->TaskStateSegment.Length = Limit & 0xFFFF; gdt[Core].Entries->TaskStateSegment.Length = Limit & 0xFFFF;
gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF; gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF;
gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF; gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF;
gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 0xFF; gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 0xFF;
gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); gdt[Core].Entries->TaskStateSegment.BaseUpper = (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.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); gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF);
tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment); tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment);
tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE; tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE;
tss[Core].InterruptStackTable[0] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
for (size_t i = 0; i < sizeof(tss[Core].InterruptStackTable) / sizeof(tss[Core].InterruptStackTable[7]); i++) 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;
void *NewStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1));
tss[Core].InterruptStackTable[i] = (uint64_t)NewStack + STACK_SIZE;
memset((void *)(tss[Core].InterruptStackTable[i] - STACK_SIZE), 0, STACK_SIZE);
debug("IST-%d: %#lx-%#lx", i, NewStack, (uintptr_t)NewStack + STACK_SIZE);
}
CPU::x64::ltr(GDT_TSS); CPU::x64::ltr(GDT_TSS);
asmv("mov %%rsp, %0"
: "=r"(tss[Core].StackPointer[0]));
debug("GDT_KERNEL_CODE: %#lx", GDT_KERNEL_CODE); trace("GDT_KERNEL_CODE: %#lx", GDT_KERNEL_CODE);
debug("GDT_KERNEL_DATA: %#lx", GDT_KERNEL_DATA); trace("GDT_KERNEL_DATA: %#lx", GDT_KERNEL_DATA);
debug("GDT_USER_CODE: %#lx", GDT_USER_CODE); trace("GDT_USER_CODE: %#lx", GDT_USER_CODE);
debug("GDT_USER_DATA: %#lx", GDT_USER_DATA); trace("GDT_USER_DATA: %#lx", GDT_USER_DATA);
debug("GDT_TSS: %#lx", GDT_TSS); trace("GDT_TSS: %#lx", GDT_TSS);
debug("Global Descriptor Table initialized"); trace("Global Descriptor Table initialized");
} }
SafeFunction void SetKernelStack(void *Stack) SafeFunction void SetKernelStack(void *Stack)
{ {
long CPUID = GetCurrentCPU()->ID; if (Stack)
if (Stack != nullptr) tss[GetCurrentCPU()->ID].StackPointer[0] = (uint64_t)Stack;
tss[CPUID].StackPointer[0] = (uint64_t)Stack;
else else
tss[CPUID].StackPointer[0] = (uint64_t)CPUStackPointer[CPUID] + STACK_SIZE; tss[GetCurrentCPU()->ID].StackPointer[0] = (uint64_t)CPUStackPointer[GetCurrentCPU()->ID] + STACK_SIZE;
/*
FIXME: There's a bug in kernel which if
we won't update "tss[CPUID].StackPointer[0]"
with the current stack pointer, the kernel
will crash.
*/
asmv("mov %%rsp, %0"
: "=r"(tss[CPUID].StackPointer[0]));
} }
void *GetKernelStack() { return (void *)tss[GetCurrentCPU()->ID].StackPointer[0]; }
} }

View File

@ -1,32 +1,10 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "idt.hpp" #include "idt.hpp"
#include <memory.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#include <debug.h> #include <debug.h>
#include <io.h> #include <io.h>
#include "gdt.hpp" #include "gdt.hpp"
#include "../../../kernel.h"
/* conversion from uint64_t {aka long unsigned int} to unsigned char:2 may change value */
#pragma GCC diagnostic ignored "-Wconversion"
extern "C" void MainInterruptHandler(void *Data); extern "C" void MainInterruptHandler(void *Data);
extern "C" void ExceptionHandler(void *Data); extern "C" void ExceptionHandler(void *Data);
@ -35,36 +13,41 @@ namespace InterruptDescriptorTable
{ {
static InterruptDescriptorTableEntry Entries[0x100]; static InterruptDescriptorTableEntry Entries[0x100];
InterruptDescriptorTableDescriptor idtd = { InterruptDescriptorTableDescriptor idtd = {.Length = sizeof(Entries) - 1,
.Length = sizeof(Entries) - 1, .Entries = Entries};
.Entries = Entries,
};
void SetEntry(uint8_t Index, void SetEntry(uint8_t Index,
void (*Base)(), void (*Base)(),
InterruptStackTableType InterruptStackTable, InterruptDescriptorTableFlags Attribute,
InterruptGateType Gate, uint8_t InterruptStackTable,
InterruptRingType Ring, InterruptDescriptorTableFlags Ring,
bool Present,
uint16_t SegmentSelector) uint16_t SegmentSelector)
{ {
Entries[Index].BaseLow = s_cst(uint16_t, ((uint64_t)Base & 0xFFFF)); Entries[Index].BaseLow = (uint16_t)((uint64_t)Base & 0xFFFF);
Entries[Index].BaseHigh = s_cst(uint64_t, ((uint64_t)Base >> 16 /* & 0xFFFF */)); Entries[Index].BaseHigh = (uint64_t)((uint64_t)Base >> 16 /* & 0xFFFF */);
Entries[Index].SegmentSelector = SegmentSelector; Entries[Index].SegmentSelector = SegmentSelector;
Entries[Index].Flags = Gate; Entries[Index].Flags = Attribute;
Entries[Index].Reserved1 = 0; Entries[Index].Reserved1 = 0;
Entries[Index].Reserved2 = 0; Entries[Index].Reserved2 = 0;
Entries[Index].Reserved3 = 0; Entries[Index].Reserved3 = 0;
Entries[Index].InterruptStackTable = InterruptStackTable; Entries[Index].InterruptStackTable = InterruptStackTable;
Entries[Index].Ring = Ring; Entries[Index].Ring = Ring;
Entries[Index].Present = Present; Entries[Index].Present = 1;
} }
extern "C" __naked __used __no_stack_protector __aligned(16) void ExceptionHandlerStub() extern "C" __attribute__((naked, used, no_stack_protector)) void ExceptionHandlerStub()
{ {
asm("cld\n" asm(
"cli\n" // "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 %rax\n"
"pushq %rbx\n" "pushq %rbx\n"
"pushq %rcx\n" "pushq %rcx\n"
@ -84,6 +67,7 @@ namespace InterruptDescriptorTable
"movq %rsp, %rdi\n" "movq %rsp, %rdi\n"
"call ExceptionHandler\n" "call ExceptionHandler\n"
// pop all registers
"popq %r15\n" "popq %r15\n"
"popq %r14\n" "popq %r14\n"
"popq %r13\n" "popq %r13\n"
@ -102,14 +86,30 @@ namespace InterruptDescriptorTable
"addq $16, %rsp\n" "addq $16, %rsp\n"
"iretq"); // pop CS RIP RFLAGS SS RSP // "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" __naked __used __no_stack_protector __aligned(16) void InterruptHandlerStub() extern "C" void WarnSwapgs() { warn("swapgs"); }
{
asm("cld\n"
"cli\n"
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 %rax\n"
"pushq %rbx\n" "pushq %rbx\n"
"pushq %rcx\n" "pushq %rcx\n"
@ -147,28 +147,35 @@ namespace InterruptDescriptorTable
"addq $16, %rsp\n" "addq $16, %rsp\n"
"sti\n" // "cmp $0x1000, %rsp\n"
"iretq"); // pop CS RIP RFLAGS SS RSP // "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 #pragma region Exceptions
#define EXCEPTION_HANDLER(num) \ #define EXCEPTION_HANDLER(num) \
__naked __used __no_stack_protector __aligned(16) static void InterruptHandler_##num() \ __attribute__((naked, no_stack_protector)) static void InterruptHandler_##num() \
{ \ { \
asm("pushq $0\npushq $" #num "\n" \ asm("pushq $0\npushq $" #num "\n" \
"jmp ExceptionHandlerStub"); \ "jmp ExceptionHandlerStub"); \
} }
#define EXCEPTION_ERROR_HANDLER(num) \ #define EXCEPTION_ERROR_HANDLER(num) \
__naked __used __no_stack_protector __aligned(16) static void InterruptHandler_##num() \ __attribute__((naked, no_stack_protector)) static void InterruptHandler_##num() \
{ \ { \
asm("pushq $" #num "\n" \ asm("pushq $" #num "\n" \
"jmp ExceptionHandlerStub"); \ "jmp ExceptionHandlerStub"); \
} }
#define INTERRUPT_HANDLER(num) \ #define INTERRUPT_HANDLER(num) \
__naked __used __no_stack_protector __aligned(16) void InterruptHandler_##num() \ __attribute__((naked, used, no_stack_protector)) void InterruptHandler_##num() \
{ \ { \
asm("pushq $0\npushq $" #num "\n" \ asm("pushq $0\npushq $" #num "\n" \
"jmp InterruptHandlerStub\n"); \ "jmp InterruptHandlerStub\n"); \
@ -446,7 +453,8 @@ namespace InterruptDescriptorTable
void Init(int Core) void Init(int Core)
{ {
if (Core == 0) /* Disable PIC using BSP */ static int once = 0;
if (!once++)
{ {
// PIC // PIC
outb(0x20, 0x10 | 0x1); outb(0x20, 0x10 | 0x1);
@ -477,281 +485,271 @@ namespace InterruptDescriptorTable
/* ISR */ /* ISR */
#ifdef DEBUG SetEntry(0x0, InterruptHandler_0x0, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
// if (!DebuggerIsAttached) SetEntry(0x1, InterruptHandler_0x1, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
if (true) 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);
#endif SetEntry(0x4, InterruptHandler_0x4, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x0, InterruptHandler_0x0, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x5, InterruptHandler_0x5, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1, InterruptHandler_0x1, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x6, InterruptHandler_0x6, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2, InterruptHandler_0x2, IST2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x7, InterruptHandler_0x7, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3, InterruptHandler_0x3, IST1, TRAP_32BIT, RING3, (!DebuggerIsAttached), GDT_KERNEL_CODE); /* Do not handle breakpoints if we are debugging the kernel. */ SetEntry(0x8, InterruptHandler_0x8, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4, InterruptHandler_0x4, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x9, InterruptHandler_0x9, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5, InterruptHandler_0x5, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa, InterruptHandler_0xa, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6, InterruptHandler_0x6, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb, InterruptHandler_0xb, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7, InterruptHandler_0x7, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc, InterruptHandler_0xc, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8, InterruptHandler_0x8, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd, InterruptHandler_0xd, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9, InterruptHandler_0x9, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe, InterruptHandler_0xe, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa, InterruptHandler_0xa, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf, InterruptHandler_0xf, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb, InterruptHandler_0xb, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x10, InterruptHandler_0x10, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc, InterruptHandler_0xc, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x11, InterruptHandler_0x11, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd, InterruptHandler_0xd, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x12, InterruptHandler_0x12, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe, InterruptHandler_0xe, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x13, InterruptHandler_0x13, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf, InterruptHandler_0xf, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x14, InterruptHandler_0x14, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x10, InterruptHandler_0x10, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x15, InterruptHandler_0x15, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x11, InterruptHandler_0x11, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x16, InterruptHandler_0x16, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x12, InterruptHandler_0x12, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x17, InterruptHandler_0x17, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x13, InterruptHandler_0x13, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x18, InterruptHandler_0x18, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x14, InterruptHandler_0x14, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x19, InterruptHandler_0x19, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x15, InterruptHandler_0x15, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x1a, InterruptHandler_0x1a, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x16, InterruptHandler_0x16, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x1b, InterruptHandler_0x1b, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x17, InterruptHandler_0x17, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x1c, InterruptHandler_0x1c, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x18, InterruptHandler_0x18, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x1d, InterruptHandler_0x1d, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x19, InterruptHandler_0x19, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x1e, InterruptHandler_0x1e, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1a, InterruptHandler_0x1a, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x1f, InterruptHandler_0x1f, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1b, InterruptHandler_0x1b, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1c, InterruptHandler_0x1c, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1d, InterruptHandler_0x1d, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1e, InterruptHandler_0x1e, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1f, InterruptHandler_0x1f, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
#ifdef DEBUG
}
else
KPrint("\eFFA500The debugger is attached, not setting up the ISR.");
#endif
/* IRQ */ /* IRQ */
SetEntry(0x20, InterruptHandler_0x20, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x20, InterruptHandler_0x20, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x21, InterruptHandler_0x21, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x21, InterruptHandler_0x21, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x22, InterruptHandler_0x22, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x22, InterruptHandler_0x22, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x23, InterruptHandler_0x23, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x23, InterruptHandler_0x23, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x24, InterruptHandler_0x24, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x24, InterruptHandler_0x24, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x25, InterruptHandler_0x25, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x25, InterruptHandler_0x25, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x26, InterruptHandler_0x26, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x26, InterruptHandler_0x26, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x27, InterruptHandler_0x27, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x27, InterruptHandler_0x27, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x28, InterruptHandler_0x28, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x28, InterruptHandler_0x28, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x29, InterruptHandler_0x29, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x29, InterruptHandler_0x29, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2a, InterruptHandler_0x2a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x2a, InterruptHandler_0x2a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2b, InterruptHandler_0x2b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x2b, InterruptHandler_0x2b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2c, InterruptHandler_0x2c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x2c, InterruptHandler_0x2c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2d, InterruptHandler_0x2d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x2d, InterruptHandler_0x2d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2e, InterruptHandler_0x2e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x2e, InterruptHandler_0x2e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2f, InterruptHandler_0x2f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x2f, InterruptHandler_0x2f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
/* Reserved by OS */ /* Reserved by OS */
SetEntry(0x30, InterruptHandler_0x30, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x30, InterruptHandler_0x30, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x31, InterruptHandler_0x31, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x31, InterruptHandler_0x31, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x32, InterruptHandler_0x32, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x32, InterruptHandler_0x32, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x33, InterruptHandler_0x33, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x33, InterruptHandler_0x33, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x34, InterruptHandler_0x34, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x34, InterruptHandler_0x34, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x35, InterruptHandler_0x35, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x35, InterruptHandler_0x35, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x36, InterruptHandler_0x36, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x36, InterruptHandler_0x36, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x37, InterruptHandler_0x37, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x37, InterruptHandler_0x37, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x38, InterruptHandler_0x38, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x38, InterruptHandler_0x38, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x39, InterruptHandler_0x39, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x39, InterruptHandler_0x39, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3a, InterruptHandler_0x3a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x3a, InterruptHandler_0x3a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3b, InterruptHandler_0x3b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x3b, InterruptHandler_0x3b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3c, InterruptHandler_0x3c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x3c, InterruptHandler_0x3c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3d, InterruptHandler_0x3d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x3d, InterruptHandler_0x3d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
/* Free */ /* Free */
SetEntry(0x3e, InterruptHandler_0x3e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x3e, InterruptHandler_0x3e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3f, InterruptHandler_0x3f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x3f, InterruptHandler_0x3f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x40, InterruptHandler_0x40, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x40, InterruptHandler_0x40, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x41, InterruptHandler_0x41, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x41, InterruptHandler_0x41, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x42, InterruptHandler_0x42, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x42, InterruptHandler_0x42, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x43, InterruptHandler_0x43, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x43, InterruptHandler_0x43, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x44, InterruptHandler_0x44, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x44, InterruptHandler_0x44, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x45, InterruptHandler_0x45, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x45, InterruptHandler_0x45, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x46, InterruptHandler_0x46, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x46, InterruptHandler_0x46, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x47, InterruptHandler_0x47, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x47, InterruptHandler_0x47, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x48, InterruptHandler_0x48, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x48, InterruptHandler_0x48, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x49, InterruptHandler_0x49, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x49, InterruptHandler_0x49, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4a, InterruptHandler_0x4a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x4a, InterruptHandler_0x4a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4b, InterruptHandler_0x4b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x4b, InterruptHandler_0x4b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4c, InterruptHandler_0x4c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x4c, InterruptHandler_0x4c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4d, InterruptHandler_0x4d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x4d, InterruptHandler_0x4d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4e, InterruptHandler_0x4e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x4e, InterruptHandler_0x4e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4f, InterruptHandler_0x4f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x4f, InterruptHandler_0x4f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x50, InterruptHandler_0x50, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x50, InterruptHandler_0x50, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x51, InterruptHandler_0x51, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x51, InterruptHandler_0x51, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x52, InterruptHandler_0x52, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x52, InterruptHandler_0x52, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x53, InterruptHandler_0x53, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x53, InterruptHandler_0x53, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x54, InterruptHandler_0x54, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x54, InterruptHandler_0x54, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x55, InterruptHandler_0x55, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x55, InterruptHandler_0x55, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x56, InterruptHandler_0x56, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x56, InterruptHandler_0x56, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x57, InterruptHandler_0x57, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x57, InterruptHandler_0x57, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x58, InterruptHandler_0x58, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x58, InterruptHandler_0x58, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x59, InterruptHandler_0x59, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x59, InterruptHandler_0x59, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5a, InterruptHandler_0x5a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x5a, InterruptHandler_0x5a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5b, InterruptHandler_0x5b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x5b, InterruptHandler_0x5b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5c, InterruptHandler_0x5c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x5c, InterruptHandler_0x5c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5d, InterruptHandler_0x5d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x5d, InterruptHandler_0x5d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5e, InterruptHandler_0x5e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x5e, InterruptHandler_0x5e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5f, InterruptHandler_0x5f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x5f, InterruptHandler_0x5f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x60, InterruptHandler_0x60, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x60, InterruptHandler_0x60, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x61, InterruptHandler_0x61, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x61, InterruptHandler_0x61, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x62, InterruptHandler_0x62, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x62, InterruptHandler_0x62, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x63, InterruptHandler_0x63, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x63, InterruptHandler_0x63, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x64, InterruptHandler_0x64, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x64, InterruptHandler_0x64, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x65, InterruptHandler_0x65, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x65, InterruptHandler_0x65, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x66, InterruptHandler_0x66, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x66, InterruptHandler_0x66, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x67, InterruptHandler_0x67, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x67, InterruptHandler_0x67, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x68, InterruptHandler_0x68, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x68, InterruptHandler_0x68, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x69, InterruptHandler_0x69, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x69, InterruptHandler_0x69, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6a, InterruptHandler_0x6a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x6a, InterruptHandler_0x6a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6b, InterruptHandler_0x6b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x6b, InterruptHandler_0x6b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6c, InterruptHandler_0x6c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x6c, InterruptHandler_0x6c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6d, InterruptHandler_0x6d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x6d, InterruptHandler_0x6d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6e, InterruptHandler_0x6e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x6e, InterruptHandler_0x6e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6f, InterruptHandler_0x6f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x6f, InterruptHandler_0x6f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x70, InterruptHandler_0x70, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x70, InterruptHandler_0x70, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x71, InterruptHandler_0x71, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x71, InterruptHandler_0x71, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x72, InterruptHandler_0x72, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x72, InterruptHandler_0x72, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x73, InterruptHandler_0x73, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x73, InterruptHandler_0x73, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x74, InterruptHandler_0x74, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x74, InterruptHandler_0x74, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x75, InterruptHandler_0x75, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x75, InterruptHandler_0x75, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x76, InterruptHandler_0x76, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x76, InterruptHandler_0x76, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x77, InterruptHandler_0x77, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x77, InterruptHandler_0x77, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x78, InterruptHandler_0x78, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x78, InterruptHandler_0x78, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x79, InterruptHandler_0x79, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x79, InterruptHandler_0x79, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7a, InterruptHandler_0x7a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x7a, InterruptHandler_0x7a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7b, InterruptHandler_0x7b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x7b, InterruptHandler_0x7b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7c, InterruptHandler_0x7c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x7c, InterruptHandler_0x7c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7d, InterruptHandler_0x7d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x7d, InterruptHandler_0x7d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7e, InterruptHandler_0x7e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x7e, InterruptHandler_0x7e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7f, InterruptHandler_0x7f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x7f, InterruptHandler_0x7f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x80, InterruptHandler_0x80, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x80, InterruptHandler_0x80, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x81, InterruptHandler_0x81, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x81, InterruptHandler_0x81, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x82, InterruptHandler_0x82, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x82, InterruptHandler_0x82, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x83, InterruptHandler_0x83, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x83, InterruptHandler_0x83, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x84, InterruptHandler_0x84, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x84, InterruptHandler_0x84, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x85, InterruptHandler_0x85, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x85, InterruptHandler_0x85, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x86, InterruptHandler_0x86, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x86, InterruptHandler_0x86, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x87, InterruptHandler_0x87, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x87, InterruptHandler_0x87, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x88, InterruptHandler_0x88, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x88, InterruptHandler_0x88, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x89, InterruptHandler_0x89, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x89, InterruptHandler_0x89, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8a, InterruptHandler_0x8a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x8a, InterruptHandler_0x8a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8b, InterruptHandler_0x8b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x8b, InterruptHandler_0x8b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8c, InterruptHandler_0x8c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x8c, InterruptHandler_0x8c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8d, InterruptHandler_0x8d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x8d, InterruptHandler_0x8d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8e, InterruptHandler_0x8e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x8e, InterruptHandler_0x8e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8f, InterruptHandler_0x8f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x8f, InterruptHandler_0x8f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x90, InterruptHandler_0x90, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x90, InterruptHandler_0x90, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x91, InterruptHandler_0x91, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x91, InterruptHandler_0x91, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x92, InterruptHandler_0x92, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x92, InterruptHandler_0x92, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x93, InterruptHandler_0x93, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x93, InterruptHandler_0x93, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x94, InterruptHandler_0x94, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x94, InterruptHandler_0x94, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x95, InterruptHandler_0x95, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x95, InterruptHandler_0x95, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x96, InterruptHandler_0x96, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x96, InterruptHandler_0x96, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x97, InterruptHandler_0x97, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x97, InterruptHandler_0x97, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x98, InterruptHandler_0x98, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x98, InterruptHandler_0x98, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x99, InterruptHandler_0x99, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x99, InterruptHandler_0x99, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9a, InterruptHandler_0x9a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x9a, InterruptHandler_0x9a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9b, InterruptHandler_0x9b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x9b, InterruptHandler_0x9b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9c, InterruptHandler_0x9c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x9c, InterruptHandler_0x9c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9d, InterruptHandler_0x9d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x9d, InterruptHandler_0x9d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9e, InterruptHandler_0x9e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x9e, InterruptHandler_0x9e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9f, InterruptHandler_0x9f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0x9f, InterruptHandler_0x9f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa0, InterruptHandler_0xa0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa0, InterruptHandler_0xa0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa1, InterruptHandler_0xa1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa1, InterruptHandler_0xa1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa2, InterruptHandler_0xa2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa2, InterruptHandler_0xa2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa3, InterruptHandler_0xa3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa3, InterruptHandler_0xa3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa4, InterruptHandler_0xa4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa4, InterruptHandler_0xa4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa5, InterruptHandler_0xa5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa5, InterruptHandler_0xa5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa6, InterruptHandler_0xa6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa6, InterruptHandler_0xa6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa7, InterruptHandler_0xa7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa7, InterruptHandler_0xa7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa8, InterruptHandler_0xa8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa8, InterruptHandler_0xa8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa9, InterruptHandler_0xa9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xa9, InterruptHandler_0xa9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xaa, InterruptHandler_0xaa, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xaa, InterruptHandler_0xaa, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xab, InterruptHandler_0xab, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xab, InterruptHandler_0xab, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xac, InterruptHandler_0xac, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xac, InterruptHandler_0xac, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xad, InterruptHandler_0xad, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xad, InterruptHandler_0xad, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xae, InterruptHandler_0xae, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xae, InterruptHandler_0xae, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xaf, InterruptHandler_0xaf, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xaf, InterruptHandler_0xaf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb0, InterruptHandler_0xb0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb0, InterruptHandler_0xb0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb1, InterruptHandler_0xb1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb1, InterruptHandler_0xb1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb2, InterruptHandler_0xb2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb2, InterruptHandler_0xb2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb3, InterruptHandler_0xb3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb3, InterruptHandler_0xb3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb4, InterruptHandler_0xb4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb4, InterruptHandler_0xb4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb5, InterruptHandler_0xb5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb5, InterruptHandler_0xb5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb6, InterruptHandler_0xb6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb6, InterruptHandler_0xb6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb7, InterruptHandler_0xb7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb7, InterruptHandler_0xb7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb8, InterruptHandler_0xb8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb8, InterruptHandler_0xb8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb9, InterruptHandler_0xb9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xb9, InterruptHandler_0xb9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xba, InterruptHandler_0xba, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xba, InterruptHandler_0xba, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbb, InterruptHandler_0xbb, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xbb, InterruptHandler_0xbb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbc, InterruptHandler_0xbc, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xbc, InterruptHandler_0xbc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbd, InterruptHandler_0xbd, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xbd, InterruptHandler_0xbd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbe, InterruptHandler_0xbe, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xbe, InterruptHandler_0xbe, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbf, InterruptHandler_0xbf, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xbf, InterruptHandler_0xbf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc0, InterruptHandler_0xc0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc0, InterruptHandler_0xc0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc1, InterruptHandler_0xc1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc1, InterruptHandler_0xc1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc2, InterruptHandler_0xc2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc2, InterruptHandler_0xc2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc3, InterruptHandler_0xc3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc3, InterruptHandler_0xc3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc4, InterruptHandler_0xc4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc4, InterruptHandler_0xc4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc5, InterruptHandler_0xc5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc5, InterruptHandler_0xc5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc6, InterruptHandler_0xc6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc6, InterruptHandler_0xc6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc7, InterruptHandler_0xc7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc7, InterruptHandler_0xc7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc8, InterruptHandler_0xc8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc8, InterruptHandler_0xc8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc9, InterruptHandler_0xc9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xc9, InterruptHandler_0xc9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xca, InterruptHandler_0xca, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xca, InterruptHandler_0xca, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcb, InterruptHandler_0xcb, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xcb, InterruptHandler_0xcb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcc, InterruptHandler_0xcc, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xcc, InterruptHandler_0xcc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcd, InterruptHandler_0xcd, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xcd, InterruptHandler_0xcd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xce, InterruptHandler_0xce, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xce, InterruptHandler_0xce, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcf, InterruptHandler_0xcf, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xcf, InterruptHandler_0xcf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd0, InterruptHandler_0xd0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd0, InterruptHandler_0xd0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd1, InterruptHandler_0xd1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd1, InterruptHandler_0xd1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd2, InterruptHandler_0xd2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd2, InterruptHandler_0xd2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd3, InterruptHandler_0xd3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd3, InterruptHandler_0xd3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd4, InterruptHandler_0xd4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd4, InterruptHandler_0xd4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd5, InterruptHandler_0xd5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd5, InterruptHandler_0xd5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd6, InterruptHandler_0xd6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd6, InterruptHandler_0xd6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd7, InterruptHandler_0xd7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd7, InterruptHandler_0xd7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd8, InterruptHandler_0xd8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd8, InterruptHandler_0xd8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd9, InterruptHandler_0xd9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xd9, InterruptHandler_0xd9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xda, InterruptHandler_0xda, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xda, InterruptHandler_0xda, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdb, InterruptHandler_0xdb, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xdb, InterruptHandler_0xdb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdc, InterruptHandler_0xdc, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xdc, InterruptHandler_0xdc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdd, InterruptHandler_0xdd, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xdd, InterruptHandler_0xdd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xde, InterruptHandler_0xde, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xde, InterruptHandler_0xde, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdf, InterruptHandler_0xdf, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xdf, InterruptHandler_0xdf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe0, InterruptHandler_0xe0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe0, InterruptHandler_0xe0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe1, InterruptHandler_0xe1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe1, InterruptHandler_0xe1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe2, InterruptHandler_0xe2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe2, InterruptHandler_0xe2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe3, InterruptHandler_0xe3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe3, InterruptHandler_0xe3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe4, InterruptHandler_0xe4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe4, InterruptHandler_0xe4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe5, InterruptHandler_0xe5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe5, InterruptHandler_0xe5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe6, InterruptHandler_0xe6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe6, InterruptHandler_0xe6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe7, InterruptHandler_0xe7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe7, InterruptHandler_0xe7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe8, InterruptHandler_0xe8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe8, InterruptHandler_0xe8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe9, InterruptHandler_0xe9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xe9, InterruptHandler_0xe9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xea, InterruptHandler_0xea, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xea, InterruptHandler_0xea, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xeb, InterruptHandler_0xeb, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xeb, InterruptHandler_0xeb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xec, InterruptHandler_0xec, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xec, InterruptHandler_0xec, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xed, InterruptHandler_0xed, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xed, InterruptHandler_0xed, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xee, InterruptHandler_0xee, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xee, InterruptHandler_0xee, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xef, InterruptHandler_0xef, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xef, InterruptHandler_0xef, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf0, InterruptHandler_0xf0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf0, InterruptHandler_0xf0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf1, InterruptHandler_0xf1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf1, InterruptHandler_0xf1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf2, InterruptHandler_0xf2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf2, InterruptHandler_0xf2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf3, InterruptHandler_0xf3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf3, InterruptHandler_0xf3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf4, InterruptHandler_0xf4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf4, InterruptHandler_0xf4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf5, InterruptHandler_0xf5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf5, InterruptHandler_0xf5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf6, InterruptHandler_0xf6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf6, InterruptHandler_0xf6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf7, InterruptHandler_0xf7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf7, InterruptHandler_0xf7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf8, InterruptHandler_0xf8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf8, InterruptHandler_0xf8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf9, InterruptHandler_0xf9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xf9, InterruptHandler_0xf9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfa, InterruptHandler_0xfa, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xfa, InterruptHandler_0xfa, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfb, InterruptHandler_0xfb, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xfb, InterruptHandler_0xfb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfc, InterruptHandler_0xfc, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xfc, InterruptHandler_0xfc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfd, InterruptHandler_0xfd, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xfd, InterruptHandler_0xfd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfe, InterruptHandler_0xfe, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xfe, InterruptHandler_0xfe, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xff, InterruptHandler_0xff, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE); SetEntry(0xff, InterruptHandler_0xff, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
CPU::x64::lidt(&idtd); CPU::x64::lidt(&idtd);
} }
} }

View File

@ -1,28 +1,5 @@
; This file is part of Fennix Kernel.
;
; Fennix Kernel is free software: you can redistribute it and/or
; modify it under the terms of the GNU General Public License as
; published by the Free Software Foundation, either version 3 of
; the License, or (at your option) any later version.
;
; Fennix Kernel is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
; This has to be the same as enum SMPTrampolineAddress.
TRAMPOLINE_PAGE_TABLE equ 0x500
TRAMPOLINE_START_ADDR equ 0x520
TRAMPOLINE_STACK equ 0x570
TRAMPOLINE_GDT equ 0x580
TRAMPOLINE_IDT equ 0x590
TRAMPOLINE_CORE equ 0x600
TRAMPOLINE_START equ 0x2000
[bits 16] [bits 16]
TRAMPOLINE_BASE equ 0x2000
extern StartCPU extern StartCPU
global _trampoline_start global _trampoline_start
@ -34,11 +11,11 @@ _trampoline_start:
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
o32 lgdt [ProtectedMode_gdtr - _trampoline_start + TRAMPOLINE_START] o32 lgdt [ProtectedMode_gdtr - _trampoline_start + TRAMPOLINE_BASE]
mov eax, cr0 mov eax, cr0
or al, 0x1 or al, 0x1
mov cr0, eax mov cr0, eax
jmp 0x8:(Trampoline32 - _trampoline_start + TRAMPOLINE_START) jmp 0x8:(Trampoline32 - _trampoline_start + TRAMPOLINE_BASE)
[bits 32] [bits 32]
section .text section .text
@ -47,7 +24,7 @@ Trampoline32:
mov ds, bx mov ds, bx
mov es, bx mov es, bx
mov ss, bx mov ss, bx
mov eax, dword [TRAMPOLINE_PAGE_TABLE] mov eax, dword [0x500]
mov cr3, eax mov cr3, eax
mov eax, cr4 mov eax, cr4
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5). or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
@ -60,8 +37,8 @@ Trampoline32:
mov eax, cr0 mov eax, cr0
or eax, 1 << 31 or eax, 1 << 31
mov cr0, eax mov cr0, eax
lgdt [LongMode_gdtr - _trampoline_start + TRAMPOLINE_START] lgdt [LongMode_gdtr - _trampoline_start + TRAMPOLINE_BASE]
jmp 0x8:(Trampoline64 - _trampoline_start + TRAMPOLINE_START) jmp 0x8:(Trampoline64 - _trampoline_start + TRAMPOLINE_BASE)
[bits 64] [bits 64]
Trampoline64: Trampoline64:
@ -72,9 +49,9 @@ Trampoline64:
mov ax, 0x0 mov ax, 0x0
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
lgdt [TRAMPOLINE_GDT] lgdt [0x580]
lidt [TRAMPOLINE_IDT] lidt [0x590]
mov rsp, [TRAMPOLINE_STACK] mov rsp, [0x570]
mov rbp, 0x0 ; Terminate stack traces here. mov rbp, 0x0 ; Terminate stack traces here.
; Reset RFLAGS. ; Reset RFLAGS.
push 0x0 push 0x0
@ -99,7 +76,7 @@ vcode64:
align 16 align 16
LongMode_gdtr: LongMode_gdtr:
dw LongModeGDTEnd - LongModeGDTStart - 1 dw LongModeGDTEnd - LongModeGDTStart - 1
dq LongModeGDTStart - _trampoline_start + TRAMPOLINE_START dq LongModeGDTStart - _trampoline_start + TRAMPOLINE_BASE
align 16 align 16
LongModeGDTStart: LongModeGDTStart:
@ -111,7 +88,7 @@ LongModeGDTEnd:
align 16 align 16
ProtectedMode_gdtr: ProtectedMode_gdtr:
dw ProtectedModeGDTEnd - ProtectedModeGDTStart - 1 dw ProtectedModeGDTEnd - ProtectedModeGDTStart - 1
dd ProtectedModeGDTStart - _trampoline_start + TRAMPOLINE_START dd ProtectedModeGDTStart - _trampoline_start + TRAMPOLINE_BASE
align 16 align 16
ProtectedModeGDTStart: ProtectedModeGDTStart:

View File

@ -1,27 +1,9 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <smp.hpp> #include <smp.hpp>
#include <interrupts.hpp>
#include <memory.hpp> #include <memory.hpp>
#include <ints.hpp>
#include <assert.h> #include <assert.h>
#include <cpu.hpp> #include <cpu.hpp>
#include <atomic>
#include "../../../kernel.h" #include "../../../kernel.h"
#include "../acpi.hpp" #include "../acpi.hpp"
@ -29,7 +11,6 @@
extern "C" uint64_t _trampoline_start, _trampoline_end; extern "C" uint64_t _trampoline_start, _trampoline_end;
/* https://wiki.osdev.org/Memory_Map_(x86) */
enum SMPTrampolineAddress enum SMPTrampolineAddress
{ {
PAGE_TABLE = 0x500, PAGE_TABLE = 0x500,
@ -41,45 +22,47 @@ enum SMPTrampolineAddress
TRAMPOLINE_START = 0x2000 TRAMPOLINE_START = 0x2000
}; };
std::atomic_bool CPUEnabled = false; volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers" #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __aligned(PAGE_SIZE) CPUData CPUs[MAX_CPU] = {0}; static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
SafeFunction CPUData *GetCPU(long id) { return &CPUs[id]; } CPUData *GetCPU(long id) { return &CPUs[id]; }
CPUData *GetCurrentCPU()
SafeFunction CPUData *GetCurrentCPU()
{ {
if (unlikely(!Interrupts::apic[0])) CPUData *data = (CPUData *)CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE);
return &CPUs[0]; /* No APIC means we are on the BSP. */
int CoreID = ((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24; if (data == nullptr && Interrupts::apic[0])
data = &CPUs[((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24];
if (unlikely((&CPUs[CoreID])->IsActive != true)) if (data == nullptr)
return nullptr; // The caller should handle this.
if (!data->IsActive)
{ {
error("CPU %d is not active!", CoreID); error("CPU %d is not active!", data->ID);
assert((&CPUs[0])->IsActive == true); /* We can't continue without the BSP. */ if ((&CPUs[0])->IsActive)
return &CPUs[0]; return &CPUs[0];
else
return nullptr; // We are in trouble.
} }
assert(data->Checksum == CPU_DATA_CHECKSUM); // This should never happen.
assert((&CPUs[CoreID])->Checksum == CPU_DATA_CHECKSUM); /* This should never happen. */ return data;
return &CPUs[CoreID];
} }
extern "C" void StartCPU() extern "C" void StartCPU()
{ {
CPU::Interrupts(CPU::Disable); CPU::Interrupts(CPU::Disable);
int CoreID = (int)*reinterpret_cast<int *>(CORE); CPU::InitializeFeatures();
CPU::InitializeFeatures(CoreID); uint64_t CoreID = (int)*reinterpret_cast<int *>(CORE);
// Initialize GDT and IDT // Initialize GDT and IDT
Interrupts::Initialize(CoreID); Interrupts::Initialize(CoreID);
Interrupts::Enable(CoreID); Interrupts::Enable(CoreID);
Interrupts::InitializeTimer(CoreID); Interrupts::InitializeTimer(CoreID);
asmv("mov %0, %%rsp" ::"r"((&CPUs[CoreID])->Stack));
CPU::Interrupts(CPU::Enable); CPU::Interrupts(CPU::Enable);
KPrint("\e058C19CPU \e8888FF%d \e058C19is online", CoreID); KPrint("\e058C19CPU \e8888FF%d \e058C19is online", CoreID);
CPUEnabled.store(true, std::memory_order_release); CPUEnabled = true;
CPU::Halt(true); CPU::Halt(true);
} }
@ -89,6 +72,12 @@ namespace SMP
void Initialize(void *madt) 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; int Cores = ((ACPI::MADT *)madt)->CPUCores + 1;
if (Config.Cores > ((ACPI::MADT *)madt)->CPUCores + 1) if (Config.Cores > ((ACPI::MADT *)madt)->CPUCores + 1)
@ -98,44 +87,43 @@ namespace SMP
CPUCores = Cores; CPUCores = Cores;
uint64_t TrampolineLength = (uintptr_t)&_trampoline_end - (uintptr_t)&_trampoline_start;
Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW);
/* We reserved the TRAMPOLINE_START address inside Physical class. */
Memory::Virtual().Map((void *)TRAMPOLINE_START, (void *)TRAMPOLINE_START, TrampolineLength, Memory::PTFlag::RW);
memcpy((void *)TRAMPOLINE_START, &_trampoline_start, TrampolineLength);
debug("Trampoline address: %#lx-%#lx", TRAMPOLINE_START, TRAMPOLINE_START + TrampolineLength);
void *CPUTmpStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1));
asmv("sgdt [0x580]\n"
"sidt [0x590]\n");
VPOKE(uintptr_t, STACK) = (uintptr_t)CPUTmpStack + STACK_SIZE;
VPOKE(uintptr_t, PAGE_TABLE) = (uintptr_t)KernelPageTable;
VPOKE(uint64_t, START_ADDR) = (uintptr_t)&StartCPU;
for (int i = 0; i < Cores; i++) for (int i = 0; i < Cores; i++)
{ {
debug("Initializing CPU %d", i); debug("Initializing CPU %d", i);
if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24) != ((ACPI::MADT *)madt)->lapic[i]->ACPIProcessorId) if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24) != ((ACPI::MADT *)madt)->lapic[i]->ACPIProcessorId)
{ {
VPOKE(int, CORE) = i;
((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24)); ((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); ((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])->SendInitIPI(((ACPI::MADT *)madt)->lapic[i]->APICId);
((APIC::APIC *)Interrupts::apic[0])->SendStartupIPI(((ACPI::MADT *)madt)->lapic[i]->APICId, TRAMPOLINE_START); ((APIC::APIC *)Interrupts::apic[0])->SendStartupIPI(((ACPI::MADT *)madt)->lapic[i]->APICId, TRAMPOLINE_START);
while (!CPUEnabled.load(std::memory_order_acquire)) while (!CPUEnabled)
CPU::Pause(); CPU::Pause();
CPUEnabled.store(false, std::memory_order_release);
trace("CPU %d loaded.", ((ACPI::MADT *)madt)->lapic[i]->APICId); trace("CPU %d loaded.", ((ACPI::MADT *)madt)->lapic[i]->APICId);
KernelAllocator.FreePages((void *)*reinterpret_cast<long *>(STACK), TO_PAGES(STACK_SIZE));
CPUEnabled = false;
} }
else else
KPrint("\e058C19CPU \e8888FF%d \e058C19is the BSP", ((ACPI::MADT *)madt)->lapic[i]->APICId); KPrint("\e058C19CPU \e8888FF%d \e058C19is the BSP", ((ACPI::MADT *)madt)->lapic[i]->APICId);
} }
KernelAllocator.FreePages(CPUTmpStack, TO_PAGES(STACK_SIZE + 1));
/* We are going to unmap the page after we are done with it. */
Memory::Virtual().Unmap(0x0);
} }
} }

View File

@ -1,26 +1,9 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_APIC_H__ #ifndef __FENNIX_KERNEL_APIC_H__
#define __FENNIX_KERNEL_APIC_H__ #define __FENNIX_KERNEL_APIC_H__
#include <types.h> #include <types.h>
#include <ints.hpp> #include <interrupts.hpp>
#include <cpu.hpp> #include <cpu.hpp>
namespace APIC namespace APIC
@ -170,7 +153,7 @@ namespace APIC
uint64_t Reserved2 : 14; uint64_t Reserved2 : 14;
}; };
uint64_t raw; uint64_t raw;
} __packed LVTTimer; } __attribute__((packed)) LVTTimer;
typedef union typedef union
{ {
@ -190,7 +173,7 @@ namespace APIC
uint64_t Reserved1 : 19; uint64_t Reserved1 : 19;
}; };
uint64_t raw; uint64_t raw;
} __packed Spurious; } __attribute__((packed)) Spurious;
typedef union typedef union
{ {
@ -239,7 +222,7 @@ namespace APIC
uint64_t Reserved2 : 12; uint64_t Reserved2 : 12;
}; };
uint64_t raw; uint64_t raw;
} __packed InterruptCommandRegisterLow; } __attribute__((packed)) InterruptCommandRegisterLow;
typedef union typedef union
{ {
@ -251,7 +234,7 @@ namespace APIC
uint64_t Destination : 8; uint64_t Destination : 8;
}; };
uint64_t raw; uint64_t raw;
} __packed InterruptCommandRegisterHigh; } __attribute__((packed)) InterruptCommandRegisterHigh;
typedef union typedef union
{ {
@ -298,7 +281,7 @@ namespace APIC
uint64_t High; uint64_t High;
} split; } split;
uint64_t raw; uint64_t raw;
} __packed IOAPICRedirectEntry; } __attribute__((packed)) IOAPICRedirectEntry;
typedef union typedef union
{ {
@ -310,7 +293,7 @@ namespace APIC
uint64_t Reserved2 : 8; uint64_t Reserved2 : 8;
}; };
uint64_t raw; uint64_t raw;
} __packed IOAPICVersion; } __attribute__((packed)) IOAPICVersion;
class APIC class APIC
{ {
@ -326,12 +309,12 @@ namespace APIC
void EOI(); void EOI();
void RedirectIRQs(int CPU = 0); void RedirectIRQs(int CPU = 0);
void WaitForIPI(); void WaitForIPI();
void IPI(int CPU, InterruptCommandRegisterLow icr); void IPI(uint8_t CPU, InterruptCommandRegisterLow icr);
void SendInitIPI(int CPU); void SendInitIPI(uint8_t CPU);
void SendStartupIPI(int CPU, uint64_t StartupAddress); void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress);
uint32_t IOGetMaxRedirect(uint32_t APICID); uint32_t IOGetMaxRedirect(uint32_t APICID);
void RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status); void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
void RedirectIRQ(int CPU, uint16_t IRQ, int Status); void RedirectIRQ(int CPU, uint8_t IRQ, int Status);
APIC(int Core); APIC(int Core);
~APIC(); ~APIC();
}; };

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

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_GDT_H__ #ifndef __FENNIX_KERNEL_GDT_H__
#define __FENNIX_KERNEL_GDT_H__ #define __FENNIX_KERNEL_GDT_H__
@ -32,43 +15,43 @@ namespace GlobalDescriptorTable
/** @brief Access bit. /** @brief Access bit.
* @note The CPU sets this bit to 1 when the segment is accessed. * @note The CPU sets this bit to 1 when the segment is accessed.
*/ */
uint64_t A : 1; uint8_t A : 1;
/** @brief Readable bit for code segments, writable bit for data segments. /** @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 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. * @details For data segments, this bit must be 1 for the segment to be writable.
*/ */
uint64_t RW : 1; uint8_t RW : 1;
/** @brief Direction bit for data segments, conforming bit for code segments. /** @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 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. * @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level.
*/ */
uint64_t DC : 1; uint8_t DC : 1;
/** @brief Executable bit. /** @brief Executable bit.
* @details This bit must be 1 for code-segment descriptors. * @details This bit must be 1 for code-segment descriptors.
* @details This bit must be 0 for data-segment and system descriptors. * @details This bit must be 0 for data-segment and system descriptors.
*/ */
uint64_t E : 1; uint8_t E : 1;
/** @brief Descriptor type. /** @brief Descriptor type.
* @details This bit must be 0 for system descriptors. * @details This bit must be 0 for system descriptors.
* @details This bit must be 1 for code or data segment descriptor. * @details This bit must be 1 for code or data segment descriptor.
*/ */
uint64_t S : 1; uint8_t S : 1;
/** @brief Descriptor privilege level. /** @brief Descriptor privilege level.
* @details This field determines the privilege level of the segment. * @details This field determines the privilege level of the segment.
* @details 0 = kernel mode, 3 = user mode. * @details 0 = kernel mode, 3 = user mode.
*/ */
uint64_t DPL : 2; uint8_t DPL : 2;
/** @brief Present bit. /** @brief Present bit.
* @details This bit must be 1 for all valid descriptors. * @details This bit must be 1 for all valid descriptors.
*/ */
uint64_t P : 1; uint8_t P : 1;
} __packed; } __attribute__((packed));
uint8_t Raw; uint8_t Raw;
}; };
@ -78,14 +61,14 @@ namespace GlobalDescriptorTable
struct struct
{ {
/** @brief Unknown. */ /** @brief Unknown. */
uint64_t Unknown : 5; uint8_t Unknown : 5;
/** @brief Long mode. /** @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 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. * @details If the long mode bit is set, the segment is in 64-bit long mode.
*/ */
uint64_t L : 1; uint8_t L : 1;
} __packed; } __attribute__((packed));
uint8_t Raw; uint8_t Raw;
}; };
@ -101,18 +84,17 @@ namespace GlobalDescriptorTable
/* HIGH */ /* HIGH */
uint32_t BaseUpper; uint32_t BaseUpper;
uint32_t Reserved; uint32_t Reserved;
} __packed TaskStateSegmentEntry; } __attribute__((packed)) TaskStateSegmentEntry;
typedef struct _TaskStateSegment typedef struct _TaskStateSegment
{ {
uint32_t Reserved0 __aligned(16); uint32_t Reserved0 __attribute__((aligned(16)));
uint64_t StackPointer[3]; uint64_t StackPointer[3];
uint64_t Reserved1; uint64_t Reserved1;
uint64_t InterruptStackTable[7]; uint64_t InterruptStackTable[7];
uint64_t Reserved2; uint16_t Reserved2;
uint16_t Reserved3;
uint16_t IOMapBaseAddressOffset; uint16_t IOMapBaseAddressOffset;
} __packed TaskStateSegment; } __attribute__((packed)) TaskStateSegment;
typedef struct _GlobalDescriptorTableEntry typedef struct _GlobalDescriptorTableEntry
{ {
@ -128,7 +110,7 @@ namespace GlobalDescriptorTable
GlobalDescriptorTableFlags Flags; GlobalDescriptorTableFlags Flags;
/** @brief High Base */ /** @brief High Base */
uint8_t BaseHigh; uint8_t BaseHigh;
} __packed GlobalDescriptorTableEntry; } __attribute__((packed)) GlobalDescriptorTableEntry;
typedef struct _GlobalDescriptorTableEntries typedef struct _GlobalDescriptorTableEntries
{ {
@ -138,7 +120,7 @@ namespace GlobalDescriptorTable
GlobalDescriptorTableEntry UserData; GlobalDescriptorTableEntry UserData;
GlobalDescriptorTableEntry UserCode; GlobalDescriptorTableEntry UserCode;
TaskStateSegmentEntry TaskStateSegment; TaskStateSegmentEntry TaskStateSegment;
} __packed GlobalDescriptorTableEntries; } __attribute__((packed)) GlobalDescriptorTableEntries;
typedef struct _GlobalDescriptorTableDescriptor typedef struct _GlobalDescriptorTableDescriptor
{ {
@ -146,13 +128,11 @@ namespace GlobalDescriptorTable
uint16_t Length; uint16_t Length;
/** @brief GDT entries address */ /** @brief GDT entries address */
GlobalDescriptorTableEntries *Entries; GlobalDescriptorTableEntries *Entries;
} __packed GlobalDescriptorTableDescriptor; } __attribute__((packed)) GlobalDescriptorTableDescriptor;
extern void *CPUStackPointer[]; extern void *CPUStackPointer[];
extern TaskStateSegment tss[];
void Init(int Core); void Init(int Core);
void SetKernelStack(void *Stack); void SetKernelStack(void *Stack);
void *GetKernelStack();
} }
#define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code) #define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code)

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_IDT_H__ #ifndef __FENNIX_KERNEL_IDT_H__
#define __FENNIX_KERNEL_IDT_H__ #define __FENNIX_KERNEL_IDT_H__
@ -22,33 +5,19 @@
namespace InterruptDescriptorTable namespace InterruptDescriptorTable
{ {
typedef enum _InterruptGateType typedef enum _InterruptDescriptorTableFlags
{ {
TASK = 0b101, FlagGate_TASK = 0b101,
INT_16BIT = 0b110, FlagGate_16BIT_INT = 0b110,
TRAP_16BIT = 0b111, FlagGate_16BIT_TRAP = 0b111,
INT_32BIT = 0b1110, FlagGate_32BIT_INT = 0b1110,
TRAP_32BIT = 0b1111, FlagGate_32BIT_TRAP = 0b1111,
} InterruptGateType; FlagGate_RING0 = 0b0,
FlagGate_RING1 = 0b1,
typedef enum _InterruptRingType FlagGate_RING2 = 0b10,
{ FlagGate_RING3 = 0b11,
RING0 = 0b0, FlagGate_PRESENT = 0b1, // Not sure if this is correct.
RING1 = 0b1, } InterruptDescriptorTableFlags;
RING2 = 0b10,
RING3 = 0b11,
} InterruptRingType;
typedef enum _InterruptStackTableType
{
IST0 = 0b0,
IST1 = 0b1,
IST2 = 0b10,
IST3 = 0b11,
IST4 = 0b100,
IST5 = 0b101,
IST6 = 0b110,
} InterruptStackTableType;
typedef struct _InterruptDescriptorTableEntry typedef struct _InterruptDescriptorTableEntry
{ {
@ -56,28 +25,21 @@ namespace InterruptDescriptorTable
uint64_t SegmentSelector : 16; uint64_t SegmentSelector : 16;
uint64_t InterruptStackTable : 3; uint64_t InterruptStackTable : 3;
uint64_t Reserved1 : 5; uint64_t Reserved1 : 5;
uint64_t Flags : 4; InterruptDescriptorTableFlags Flags : 4;
uint64_t Reserved2 : 1; uint64_t Reserved2 : 1;
uint64_t Ring : 2; uint64_t Ring : 2;
uint64_t Present : 1; uint64_t Present : 1;
uint64_t BaseHigh : 48; uint64_t BaseHigh : 48;
uint64_t Reserved3 : 32; uint64_t Reserved3 : 32;
} __packed InterruptDescriptorTableEntry; } __attribute__((packed)) InterruptDescriptorTableEntry;
typedef struct _InterruptDescriptorTableDescriptor typedef struct _InterruptDescriptorTableDescriptor
{ {
uint16_t Length; uint16_t Length;
InterruptDescriptorTableEntry *Entries; InterruptDescriptorTableEntry *Entries;
} __packed InterruptDescriptorTableDescriptor; } __attribute__((packed)) InterruptDescriptorTableDescriptor;
void SetEntry(uint8_t Index,
void (*Base)(),
InterruptStackTableType InterruptStackTable,
InterruptGateType Gate,
InterruptRingType Ring,
bool Present,
uint16_t SegmentSelector);
void SetEntry(uint8_t Index, void (*Base)(), InterruptDescriptorTableFlags Attribute, uint8_t InterruptStackTable, InterruptDescriptorTableFlags Ring, uint16_t SegmentSelector);
void Init(int Core); void Init(int Core);
} }

View File

@ -1,64 +1,35 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
OUTPUT_FORMAT(elf64-x86-64) OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64) OUTPUT_ARCH(i386:x86-64)
KERNEL_VMA = 0xFFFFFFFF80000000;
ENTRY(_start) ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0x100000; . = 0xffffffff80000000;
_bootstrap_start = .; _kernel_start = .;
.bootstrap : .text :
{
*(.multiboot)
*(.multiboot2)
*(.bootstrap .bootstrap.*)
}
. += CONSTANT(MAXPAGESIZE);
_bootstrap_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += KERNEL_VMA;
. += CONSTANT(MAXPAGESIZE);
_kernel_start = ALIGN(CONSTANT(MAXPAGESIZE));
.text : AT(ADDR(.text) - KERNEL_VMA)
{ {
*(.text .text.*) *(.text .text.*)
} }
_kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE)); _kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE); . += CONSTANT(MAXPAGESIZE);
.data : AT(ADDR(.data) - KERNEL_VMA) .data :
{ {
*(.data .data.*) *(.data .data.*)
} }
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE)); _kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE); . += CONSTANT(MAXPAGESIZE);
.rodata : AT(ADDR(.rodata) - KERNEL_VMA) .rodata :
{ {
*(.rodata .rodata.*) *(.rodata .rodata.*)
} }
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.init_array : AT(ADDR(.init_array) - KERNEL_VMA) .init_array :
{ {
PROVIDE_HIDDEN(__init_array_start = .); PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(.init_array .ctors)) KEEP(*(.init_array .ctors))
@ -66,17 +37,17 @@ SECTIONS
PROVIDE_HIDDEN (__init_array_end = .); PROVIDE_HIDDEN (__init_array_end = .);
} }
.fini_array : AT(ADDR(.fini_array) - KERNEL_VMA) .fini_array :
{ {
PROVIDE_HIDDEN(__fini_array_start = .); PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP(*(.fini_array .dtors)) KEEP(*(.fini_array .dtors))
PROVIDE_HIDDEN (__fini_array_end = .); PROVIDE_HIDDEN (__fini_array_end = .);
} }
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE); . += CONSTANT(MAXPAGESIZE);
.bss : AT(ADDR(.bss) - KERNEL_VMA)
.bss :
{ {
*(COMMON) *(COMMON)
*(.bss .bss.*) *(.bss .bss.*)

View File

@ -4,12 +4,12 @@
int Entry(void *Info); int Entry(void *Info);
// void _start(void *Raw) void _start(void *Raw)
// { {
// UNUSED(Raw); error("ERROR! INVALID BOOT PROTOCOL!");
// error("ERROR! INVALID BOOT PROTOCOL!"); while (1)
// while (1) asmv("hlt");
// asmv("hlt"); Entry(NULL);
// Entry(NULL); return;
// return; }
// } // C stuff

View File

@ -1,5 +0,0 @@
section .multiboot
align 4
dd 0x1BADB002
dd 1 << 0 | 1 << 1
dd -(0x1BADB002 + (1 << 0 | 1 << 1))

View File

@ -1,41 +0,0 @@
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_INFO_REQUEST_TAG_START:
dw 1
dw 0
dd MB2_INFO_REQUEST_TAG_END - MB2_INFO_REQUEST_TAG_START
dd 1 ; Command Line
dd 2 ; Boot Loader Name
dd 3 ; Module
dd 4 ; Basic Memory Information
dd 5 ; BIOS Boot Device
dd 6 ; Memory Map
dd 7 ; VBE
dd 8 ; Framebuffer
dd 9 ; ELF Sections
dd 10 ; APM Table
dd 11 ; EFI 32-bit System Table Pointer
dd 12 ; EFI 64-bit System Table Pointer
; dd 13 ; SMBIOS
dd 14 ; ACPI Old
dd 15 ; ACPI New
dd 16 ; Network
dd 17 ; EFI Memory Map
dd 18 ; EFI Boot Services Notifier
dd 19 ; EFI 32-bit Image Handle Pointer
dd 20 ; EFI 64-bit Image Handle Pointer
dd 21 ; Load Base Address
MB2_INFO_REQUEST_TAG_END:
align 8
MB2_TAG_START:
dw 0
dw 0
dd MB2_TAG_END - MB2_TAG_START
MB2_TAG_END:
HEADER_END:

View File

@ -1,50 +0,0 @@
[bits 32]
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
extern multiboot_main
extern BootPageTable
global _start
section .text
MB_HeaderMagic:
dq 0
MB_HeaderInfo:
dq 0
_start:
cli
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 [MB_HeaderMagic], eax
mov [MB_HeaderInfo], ebx
mov esp, KernelStack + KERNEL_STACK_SIZE
mov eax, [MB_HeaderMagic]
mov ebx, [MB_HeaderInfo]
push ebx ; Multiboot2 Header
add ebx, KERNEL_VIRTUAL_BASE
push eax ; Multiboot2 Magic
call multiboot_main
.Hang:
hlt
jmp .Hang
section .bss
align 16
KernelStack:
resb KERNEL_STACK_SIZE

View File

@ -1,10 +0,0 @@
KERNEL_PAGE_NUMBER equ 768 ; 0xC0000000
section .data
global BootPageTable
align 0x1000
BootPageTable:
dd 0x00000083
times (KERNEL_PAGE_NUMBER - 1) dd 0
dd 0x00000083
times (1024 - KERNEL_PAGE_NUMBER - 1) dd 0

View File

@ -1,30 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <cpu.hpp>
#include "cpu/gdt.hpp"
using namespace CPU::x32;
extern "C" uint32_t SystemCallsHandler(SyscallsFrame *regs);
void InitializeSystemCalls()
{
}

View File

@ -1,294 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_ACPI_H__
#define __FENNIX_KERNEL_ACPI_H__
#include <types.h>
#include <boot/binfo.h>
#include <ints.hpp>
#include <cpu.hpp>
#include <vector>
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;
} __packed;
struct GenericAddressStructure
{
uint8_t AddressSpace;
uint8_t BitWidth;
uint8_t BitOffset;
uint8_t AccessSize;
uint64_t Address;
} __packed;
struct MCFGHeader
{
struct ACPIHeader Header;
uint64_t Reserved;
} __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;
} __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;
} __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[];
} __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();
~ACPI();
};
class MADT
{
public:
struct APICHeader
{
uint8_t Type;
uint8_t Length;
} __packed;
struct MADTIOApic
{
struct APICHeader Header;
uint8_t APICID;
uint8_t reserved;
uint32_t Address;
uint32_t GSIBase;
} __packed;
struct MADTIso
{
struct APICHeader Header;
uint8_t BuSSource;
uint8_t IRQSource;
uint32_t GSI;
uint16_t Flags;
} __packed;
struct MADTNmi
{
struct APICHeader Header;
uint8_t processor;
uint16_t flags;
uint8_t lint;
} __packed;
struct LocalAPIC
{
struct APICHeader Header;
uint8_t ACPIProcessorId;
uint8_t APICId;
uint32_t Flags;
} __packed;
struct LAPIC
{
uint8_t id;
uintptr_t PhysicalAddress;
void *VirtualAddress;
};
std::vector<MADTIOApic *> ioapic;
std::vector<MADTIso *> iso;
std::vector<MADTNmi *> nmi;
std::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

@ -1,116 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "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
{}};
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)
{
}
SafeFunction void SetKernelStack(void *Stack)
{
}
}

View File

@ -1,54 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <smp.hpp>
#include <ints.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 __aligned(0x1000) 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

@ -1,162 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#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;
} __packed;
uint8_t Raw;
};
union GlobalDescriptorTableFlags
{
// TODO: Add more flags.
struct
{
/** @brief Unknown. */
uint8_t Unknown : 5;
/** @brief Long mode.
* @details If the long mode bit is clear, the segment is in 32-bit protected mode.
* @details If the long mode bit is set, the segment is in 64-bit long mode.
*/
uint8_t L : 1;
} __packed;
uint8_t Raw;
};
typedef struct _TaskStateSegmentEntry
{
/* LOW */
uint16_t Length;
uint16_t BaseLow;
uint8_t BaseMiddle;
GlobalDescriptorTableAccess Flags;
uint8_t Granularity;
uint8_t BaseHigh;
/* HIGH */
uint32_t BaseUpper;
uint32_t Reserved;
} __packed TaskStateSegmentEntry;
typedef struct _TaskStateSegment
{
uint32_t Reserved0 __aligned(16);
uint64_t StackPointer[3];
uint64_t Reserved1;
uint64_t InterruptStackTable[7];
uint16_t Reserved2;
uint16_t IOMapBaseAddressOffset;
} __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;
} __packed GlobalDescriptorTableEntry;
typedef struct _GlobalDescriptorTableEntries
{
GlobalDescriptorTableEntry Null;
GlobalDescriptorTableEntry Code;
GlobalDescriptorTableEntry Data;
GlobalDescriptorTableEntry UserData;
GlobalDescriptorTableEntry UserCode;
TaskStateSegmentEntry TaskStateSegment;
} __packed GlobalDescriptorTableEntries;
typedef struct _GlobalDescriptorTableDescriptor
{
/** @brief GDT entries length */
uint16_t Length;
/** @brief GDT entries address */
GlobalDescriptorTableEntries *Entries;
} __packed GlobalDescriptorTableDescriptor;
extern void *CPUStackPointer[];
extern TaskStateSegment tss[];
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

@ -1,28 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#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

@ -1,93 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386)
KERNEL_VMA = 0xC0000000;
ENTRY(_start)
SECTIONS
{
. = 0x100000;
_bootstrap_start = .;
.bootstrap :
{
*(.multiboot)
*(.multiboot2)
*(.bootstrap .bootstrap.*)
}
. += CONSTANT(MAXPAGESIZE);
_bootstrap_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += KERNEL_VMA;
. += CONSTANT(MAXPAGESIZE);
_kernel_start = ALIGN(CONSTANT(MAXPAGESIZE));
.text : AT(ADDR(.text) - KERNEL_VMA)
{
*(.text .text.*)
}
_kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.data : AT(ADDR(.data) - KERNEL_VMA)
{
*(.data .data.*)
}
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.rodata : AT(ADDR(.rodata) - KERNEL_VMA)
{
*(.rodata .rodata.*)
}
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.init_array : AT(ADDR(.init_array) - KERNEL_VMA)
{
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 : AT(ADDR(.fini_array) - KERNEL_VMA)
{
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 : AT(ADDR(.bss) - KERNEL_VMA)
{
*(COMMON)
*(.bss .bss.*)
}
. += CONSTANT(MAXPAGESIZE);
_kernel_end = ALIGN(CONSTANT(MAXPAGESIZE));
/DISCARD/ :
{
*(.comment*)
*(.note*)
}
}

View File

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

View File

@ -158,7 +158,7 @@ int __ctzdi2(arith64_u64 a)
arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c) arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c)
{ {
if (b > a) if (b > a) //
{ {
if (c) if (c)
*c = a; *c = a;
@ -283,45 +283,3 @@ int __gedf2(double a, double b) { return a >= b; }
int __fixdfsi(double a) { return (int)a; } int __fixdfsi(double a) { return (int)a; }
long __fixdfdi(double a) { return (long)a; } long __fixdfdi(double a) { return (long)a; }
int __ledf2(double a, double b) { return a <= b; } int __ledf2(double a, double b) { return a <= b; }
/* FIXME: Check if these functions are implemented correctly */
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
typedef struct
{
uint64_t value;
} atomic_uint64_t;
uint64_t __atomic_load_8(const atomic_uint64_t *p)
{
uint64_t value;
__asm__ volatile("lock cmpxchg8b %1"
: "=A"(value)
: "m"(*p)
: "memory");
return value;
}
void __atomic_store_8(atomic_uint64_t *p, uint64_t value)
{
__asm__ volatile("lock cmpxchg8b %0"
: "=m"(p->value)
: "a"((uint32_t)value), "d"((uint32_t)(value >> 32)), "m"(*p)
: "memory");
}
/* FIXME: __fixsfsi is not implemented correctly(?) */
int __fixsfsi(float a) { return (int)a; }
int __ltsf2(float a, float b) { return a < b; }
int __eqsf2(float a, float b) { return a == b; }
float __divsf3(float a, float b) { return a / b; }
double __extendsfdf2(float a) { return (double)a; }
float __truncdfsf2(double a) { return (float)a; }
float __subsf3(float a, float b) { return a - b; }
float __floatsisf(int a) { return (float)a; }
int __fixunssfsi(float a) { return (int)a; }
float __mulsf3(float a, float b) { return a * b; }
float __addsf3(float a, float b) { return a + b; }

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pic.hpp" #include "pic.hpp"
#include <io.h> #include <io.h>

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_8259PIC_H__ #ifndef __FENNIX_KERNEL_8259PIC_H__
#define __FENNIX_KERNEL_8259PIC_H__ #define __FENNIX_KERNEL_8259PIC_H__

View File

@ -1,12 +1,60 @@
#include <types.h> #include <types.h>
#include <boot/protocols/multiboot2.h> #include <boot/protocols/multiboot2.h>
#include <memory.hpp>
#include <io.h> #include <io.h>
#include "../../../kernel.h" #include "../../kernel.h"
EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info) 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 (Info == NULL || Magic == NULL)
{ {
@ -19,6 +67,7 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC) else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC)
{ {
error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC); error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC);
trace("Hello, World!");
CPU::Stop(); CPU::Stop();
} }
@ -30,47 +79,40 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
if (tmp != (tmp | 3)) if (tmp != (tmp | 3))
outb(0x61, tmp | 3); outb(0x61, tmp | 3);
BootInfo mb2binfo; BootInfo binfo;
int pos = 0; uint32_t Itr = 0;
auto InfoAddress = Info;
for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8); for (uint32_t i = 8; i < Info->Size; i += Itr)
;
Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7)))
{ {
multiboot_tag *Tag = (multiboot_tag *)((uint8_t *)Info + i);
if (Tag->type == MULTIBOOT_TAG_TYPE_END) if (Tag->type == MULTIBOOT_TAG_TYPE_END)
{
debug("End of multiboot2 tags");
break; break;
}
switch (Tag->type) switch (Tag->type)
{ {
case MULTIBOOT_TAG_TYPE_CMDLINE: case MULTIBOOT_TAG_TYPE_CMDLINE:
{ {
strncpy(mb2binfo.Kernel.CommandLine, strncpy(binfo.Kernel.CommandLine,
((multiboot_tag_string *)Tag)->string, ((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string)); strlen(((multiboot_tag_string *)Tag)->string));
debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine);
break; break;
} }
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
{ {
strncpy(mb2binfo.Bootloader.Name, strncpy(binfo.Bootloader.Name,
((multiboot_tag_string *)Tag)->string, ((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string)); strlen(((multiboot_tag_string *)Tag)->string));
debug("Bootloader name: %s", mb2binfo.Bootloader.Name);
break; break;
} }
case MULTIBOOT_TAG_TYPE_MODULE: case MULTIBOOT_TAG_TYPE_MODULE:
{ {
multiboot_tag_module *module = (multiboot_tag_module *)Tag; multiboot_tag_module *module = (multiboot_tag_module *)Tag;
static int module_count = 0; static int module_count = 0;
mb2binfo.Modules[module_count++].Address = (void *)(uint64_t)module->mod_start; binfo.Modules[module_count++].Address = (void *)module->mod_start;
mb2binfo.Modules[module_count++].Size = module->size; binfo.Modules[module_count++].Size = module->size;
strncpy(mb2binfo.Modules[module_count++].Path, "(null)", 6); strncpy(binfo.Modules[module_count++].Path, "(null)", 6);
strncpy(mb2binfo.Modules[module_count++].CommandLine, module->cmdline, strncpy(binfo.Modules[module_count++].CommandLine, module->cmdline,
strlen(module->cmdline)); strlen(module->cmdline));
debug("Module: %s", mb2binfo.Modules[module_count++].Path);
break; break;
} }
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
@ -91,7 +133,8 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
{ {
multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag; multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag;
uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry); uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry);
mb2binfo.Memory.Entries = EntryCount;
binfo.Memory.Entries = EntryCount;
for (uint32_t i = 0; i < EntryCount; i++) for (uint32_t i = 0; i < EntryCount; i++)
{ {
if (EntryCount > MAX_MEMORY_ENTRIES) if (EntryCount > MAX_MEMORY_ENTRIES)
@ -99,45 +142,42 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
warn("Too many memory entries, skipping the rest..."); warn("Too many memory entries, skipping the rest...");
break; break;
} }
multiboot_mmap_entry entry = mmap->entries[i]; multiboot_mmap_entry entry = mmap->entries[i];
mb2binfo.Memory.Size += entry.len; binfo.Memory.Size += entry.len;
switch (entry.type) switch (entry.type)
{ {
case MULTIBOOT_MEMORY_AVAILABLE: case MULTIBOOT_MEMORY_AVAILABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len; binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = Usable; binfo.Memory.Entry[i].Type = Usable;
break; break;
case MULTIBOOT_MEMORY_RESERVED: case MULTIBOOT_MEMORY_RESERVED:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len; binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = Reserved; binfo.Memory.Entry[i].Type = Reserved;
break; break;
case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len; binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = ACPIReclaimable; binfo.Memory.Entry[i].Type = ACPIReclaimable;
break; break;
case MULTIBOOT_MEMORY_NVS: case MULTIBOOT_MEMORY_NVS:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len; binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = ACPINVS; binfo.Memory.Entry[i].Type = ACPINVS;
break; break;
case MULTIBOOT_MEMORY_BADRAM: case MULTIBOOT_MEMORY_BADRAM:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len; binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = BadMemory; binfo.Memory.Entry[i].Type = BadMemory;
break; break;
default: default:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len; binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = Unknown; binfo.Memory.Entry[i].Type = Unknown;
break; break;
} }
debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]",
mb2binfo.Memory.Entry[i].BaseAddress,
mb2binfo.Memory.Entry[i].Length,
mb2binfo.Memory.Entry[i].Type);
} }
break; break;
} }
@ -152,40 +192,43 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
{ {
multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag; multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag;
static int fb_count = 0; static int fb_count = 0;
mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width; binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height; binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width;
mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch; binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height;
mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp; 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) switch (fb->common.framebuffer_type)
{ {
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
{ {
mb2binfo.Framebuffer[fb_count].Type = Indexed; fixme("indexed");
break; break;
} }
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
{ {
mb2binfo.Framebuffer[fb_count].Type = RGB; binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size;
mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size; binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position;
mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position; binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size;
mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size; binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position;
mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position; binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size;
mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size; binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
break; break;
} }
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
{ {
mb2binfo.Framebuffer[fb_count].Type = EGA; fixme("ega_text");
break; break;
} }
} }
debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); 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", 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->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_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->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position);
fb_count++; fb_count++;
break; break;
} }
@ -223,14 +266,12 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
} }
case MULTIBOOT_TAG_TYPE_ACPI_OLD: case MULTIBOOT_TAG_TYPE_ACPI_OLD:
{ {
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp; binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
debug("OLD ACPI RSDP: %p", mb2binfo.RSDP);
break; break;
} }
case MULTIBOOT_TAG_TYPE_ACPI_NEW: case MULTIBOOT_TAG_TYPE_ACPI_NEW:
{ {
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp; binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
debug("NEW ACPI RSDP: %p", mb2binfo.RSDP);
break; break;
} }
case MULTIBOOT_TAG_TYPE_NETWORK: case MULTIBOOT_TAG_TYPE_NETWORK:
@ -266,21 +307,37 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
{ {
multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag; multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag;
mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr; binfo.Kernel.PhysicalBase = (void *)load_base_addr->load_base_addr;
mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000); binfo.Kernel.VirtualBase = (void *)(load_base_addr->load_base_addr + 0xC0000000);
debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase);
break;
}
default:
{
error("Unknown multiboot2 tag type: %d", Tag->type);
break; break;
} }
} }
Itr = Tag->size;
if ((Itr % 8) != 0)
Itr += (8 - Itr % 8);
} }
tmp = inb(0x61) & 0xFC; tmp = inb(0x61) & 0xFC;
outb(0x61, tmp); outb(0x61, tmp);
Entry(&mb2binfo); 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

@ -1,26 +1,9 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_APIC_H__ #ifndef __FENNIX_KERNEL_APIC_H__
#define __FENNIX_KERNEL_APIC_H__ #define __FENNIX_KERNEL_APIC_H__
#include <types.h> #include <types.h>
#include <ints.hpp> #include <interrupts.hpp>
#include <cpu.hpp> #include <cpu.hpp>
namespace APIC namespace APIC
@ -170,7 +153,7 @@ namespace APIC
uint64_t Reserved2 : 14; uint64_t Reserved2 : 14;
}; };
uint64_t raw; uint64_t raw;
} __packed LVTTimer; } __attribute__((packed)) LVTTimer;
typedef union typedef union
{ {
@ -190,7 +173,7 @@ namespace APIC
uint64_t Reserved1 : 19; uint64_t Reserved1 : 19;
}; };
uint64_t raw; uint64_t raw;
} __packed Spurious; } __attribute__((packed)) Spurious;
typedef union typedef union
{ {
@ -239,7 +222,7 @@ namespace APIC
uint64_t Reserved2 : 12; uint64_t Reserved2 : 12;
}; };
uint64_t raw; uint64_t raw;
} __packed InterruptCommandRegisterLow; } __attribute__((packed)) InterruptCommandRegisterLow;
typedef union typedef union
{ {
@ -251,7 +234,7 @@ namespace APIC
uint64_t Destination : 8; uint64_t Destination : 8;
}; };
uint64_t raw; uint64_t raw;
} __packed InterruptCommandRegisterHigh; } __attribute__((packed)) InterruptCommandRegisterHigh;
typedef union typedef union
{ {
@ -298,7 +281,7 @@ namespace APIC
uint64_t High; uint64_t High;
} split; } split;
uint64_t raw; uint64_t raw;
} __packed IOAPICRedirectEntry; } __attribute__((packed)) IOAPICRedirectEntry;
typedef union typedef union
{ {
@ -310,7 +293,7 @@ namespace APIC
uint64_t Reserved2 : 8; uint64_t Reserved2 : 8;
}; };
uint64_t raw; uint64_t raw;
} __packed IOAPICVersion; } __attribute__((packed)) IOAPICVersion;
class APIC class APIC
{ {
@ -331,7 +314,7 @@ namespace APIC
void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress); void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress);
uint32_t IOGetMaxRedirect(uint32_t APICID); uint32_t IOGetMaxRedirect(uint32_t APICID);
void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status); void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
void RedirectIRQ(int CPU, uint16_t IRQ, int Status); void RedirectIRQ(int CPU, uint8_t IRQ, int Status);
APIC(int Core); APIC(int Core);
~APIC(); ~APIC();
}; };
@ -341,7 +324,7 @@ namespace APIC
private: private:
APIC *lapic; APIC *lapic;
uint64_t Ticks = 0; uint64_t Ticks = 0;
void OnInterruptReceived(CPU::x32::TrapFrame *Frame); void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
public: public:
uint64_t GetTicks() { return Ticks; } uint64_t GetTicks() { return Ticks; }

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,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

@ -1,51 +1,29 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cpu.hpp> #include <cpu.hpp>
#include <memory.hpp> #include <memory.hpp>
#include <convert.h> #include <convert.h>
#include <debug.h> #include <debug.h>
#include <smp.hpp>
#include "../kernel.h" #include "../kernel.h"
namespace CPU namespace CPU
{ {
static bool SSEEnabled = false;
char *Vendor() char *Vendor()
{ {
static char Vendor[13] = {0}; static char Vendor[13];
if (Vendor[0] != 0) #if defined(__amd64__)
return Vendor; uint32_t rax, rbx, rcx, rdx;
#if defined(a64) x64::cpuid(0x0, &rax, &rbx, &rcx, &rdx);
uint32_t eax, ebx, ecx, edx; memcpy(Vendor + 0, &rbx, 4);
x64::cpuid(0x0, &eax, &ebx, &ecx, &edx); memcpy(Vendor + 4, &rdx, 4);
memcpy(Vendor + 0, &ebx, 4); memcpy(Vendor + 8, &rcx, 4);
memcpy(Vendor + 4, &edx, 4); #elif defined(__i386__)
memcpy(Vendor + 8, &ecx, 4); uint32_t rax, rbx, rcx, rdx;
#elif defined(a32) x32::cpuid(0x0, &rax, &rbx, &rcx, &rdx);
uint32_t eax, ebx, ecx, edx; memcpy(Vendor + 0, &rbx, 4);
x32::cpuid(0x0, &eax, &ebx, &ecx, &edx); memcpy(Vendor + 4, &rdx, 4);
memcpy(Vendor + 0, &ebx, 4); memcpy(Vendor + 8, &rcx, 4);
memcpy(Vendor + 4, &edx, 4); #elif defined(__aarch64__)
memcpy(Vendor + 8, &ecx, 4);
#elif defined(aa64)
asmv("mrs %0, MIDR_EL1" asmv("mrs %0, MIDR_EL1"
: "=r"(Vendor[0])); : "=r"(Vendor[0]));
#endif #endif
@ -54,44 +32,42 @@ namespace CPU
char *Name() char *Name()
{ {
static char Name[49] = {0}; static char Name[49];
if (Name[0] != 0) #if defined(__amd64__)
return Name; uint32_t rax, rbx, rcx, rdx;
#if defined(a64) x64::cpuid(0x80000002, &rax, &rbx, &rcx, &rdx);
uint32_t eax, ebx, ecx, edx; memcpy(Name + 0, &rax, 4);
x64::cpuid(0x80000002, &eax, &ebx, &ecx, &edx); memcpy(Name + 4, &rbx, 4);
memcpy(Name + 0, &eax, 4); memcpy(Name + 8, &rcx, 4);
memcpy(Name + 4, &ebx, 4); memcpy(Name + 12, &rdx, 4);
memcpy(Name + 8, &ecx, 4); x64::cpuid(0x80000003, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 12, &edx, 4); memcpy(Name + 16, &rax, 4);
x64::cpuid(0x80000003, &eax, &ebx, &ecx, &edx); memcpy(Name + 20, &rbx, 4);
memcpy(Name + 16, &eax, 4); memcpy(Name + 24, &rcx, 4);
memcpy(Name + 20, &ebx, 4); memcpy(Name + 28, &rdx, 4);
memcpy(Name + 24, &ecx, 4); x64::cpuid(0x80000004, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 28, &edx, 4); memcpy(Name + 32, &rax, 4);
x64::cpuid(0x80000004, &eax, &ebx, &ecx, &edx); memcpy(Name + 36, &rbx, 4);
memcpy(Name + 32, &eax, 4); memcpy(Name + 40, &rcx, 4);
memcpy(Name + 36, &ebx, 4); memcpy(Name + 44, &rdx, 4);
memcpy(Name + 40, &ecx, 4); #elif defined(__i386__)
memcpy(Name + 44, &edx, 4); uint32_t rax, rbx, rcx, rdx;
#elif defined(a32) x32::cpuid(0x80000002, &rax, &rbx, &rcx, &rdx);
uint32_t eax, ebx, ecx, edx; memcpy(Name + 0, &rax, 4);
x32::cpuid(0x80000002, &eax, &ebx, &ecx, &edx); memcpy(Name + 4, &rbx, 4);
memcpy(Name + 0, &eax, 4); memcpy(Name + 8, &rcx, 4);
memcpy(Name + 4, &ebx, 4); memcpy(Name + 12, &rdx, 4);
memcpy(Name + 8, &ecx, 4); x32::cpuid(0x80000003, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 12, &edx, 4); memcpy(Name + 16, &rax, 4);
x32::cpuid(0x80000003, &eax, &ebx, &ecx, &edx); memcpy(Name + 20, &rbx, 4);
memcpy(Name + 16, &eax, 4); memcpy(Name + 24, &rcx, 4);
memcpy(Name + 20, &ebx, 4); memcpy(Name + 28, &rdx, 4);
memcpy(Name + 24, &ecx, 4); x32::cpuid(0x80000004, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 28, &edx, 4); memcpy(Name + 32, &rax, 4);
x32::cpuid(0x80000004, &eax, &ebx, &ecx, &edx); memcpy(Name + 36, &rbx, 4);
memcpy(Name + 32, &eax, 4); memcpy(Name + 40, &rcx, 4);
memcpy(Name + 36, &ebx, 4); memcpy(Name + 44, &rdx, 4);
memcpy(Name + 40, &ecx, 4); #elif defined(__aarch64__)
memcpy(Name + 44, &edx, 4);
#elif defined(aa64)
asmv("mrs %0, MIDR_EL1" asmv("mrs %0, MIDR_EL1"
: "=r"(Name[0])); : "=r"(Name[0]));
#endif #endif
@ -100,22 +76,20 @@ namespace CPU
char *Hypervisor() char *Hypervisor()
{ {
static char Hypervisor[13] = {0}; static char Hypervisor[13];
if (Hypervisor[0] != 0) #if defined(__amd64__)
return Hypervisor; uint32_t rax, rbx, rcx, rdx;
#if defined(a64) x64::cpuid(0x40000000, &rax, &rbx, &rcx, &rdx);
uint32_t eax, ebx, ecx, edx; memcpy(Hypervisor + 0, &rbx, 4);
x64::cpuid(0x40000000, &eax, &ebx, &ecx, &edx); memcpy(Hypervisor + 4, &rcx, 4);
memcpy(Hypervisor + 0, &ebx, 4); memcpy(Hypervisor + 8, &rdx, 4);
memcpy(Hypervisor + 4, &ecx, 4); #elif defined(__i386__)
memcpy(Hypervisor + 8, &edx, 4); uint32_t rax, rbx, rcx, rdx;
#elif defined(a32) x64::cpuid(0x40000000, &rax, &rbx, &rcx, &rdx);
uint32_t eax, ebx, ecx, edx; memcpy(Hypervisor + 0, &rbx, 4);
x64::cpuid(0x40000000, &eax, &ebx, &ecx, &edx); memcpy(Hypervisor + 4, &rcx, 4);
memcpy(Hypervisor + 0, &ebx, 4); memcpy(Hypervisor + 8, &rdx, 4);
memcpy(Hypervisor + 4, &ecx, 4); #elif defined(__aarch64__)
memcpy(Hypervisor + 8, &edx, 4);
#elif defined(aa64)
asmv("mrs %0, MIDR_EL1" asmv("mrs %0, MIDR_EL1"
: "=r"(Hypervisor[0])); : "=r"(Hypervisor[0]));
#endif #endif
@ -128,50 +102,50 @@ namespace CPU
{ {
case Check: case Check:
{ {
uintptr_t Flags; #if defined(__amd64__)
#if defined(a64) uint64_t rflags;
asmv("pushfq"); asmv("pushfq");
asmv("popq %0" asmv("popq %0"
: "=r"(Flags)); : "=r"(rflags));
return Flags & (1 << 9); return rflags & (1 << 9);
#elif defined(a32) #elif defined(__i386__)
uint32_t rflags;
asmv("pushfl"); asmv("pushfl");
asmv("popl %0" asmv("popl %0"
: "=r"(Flags)); : "=r"(rflags));
return Flags & (1 << 9); return rflags & (1 << 9);
#elif defined(aa64) #elif defined(__aarch64__)
uint64_t daif;
asmv("mrs %0, daif" asmv("mrs %0, daif"
: "=r"(Flags)); : "=r"(daif));
return !(Flags & (1 << 2)); return !(daif & (1 << 2));
#endif #endif
} }
case Enable: case Enable:
{ {
#if defined(a86) #if defined(__amd64__) || defined(__i386__)
asmv("sti"); asmv("sti");
#elif defined(aa64) #elif defined(__aarch64__)
asmv("msr daifclr, #2"); asmv("msr daifclr, #2");
#endif #endif
return true; return true;
} }
case Disable: case Disable:
{ {
#if defined(a86) #if defined(__amd64__) || defined(__i386__)
asmv("cli"); asmv("cli");
#elif defined(aa64) #elif defined(__aarch64__)
asmv("msr daifset, #2"); asmv("msr daifset, #2");
#endif #endif
return true; return true;
} }
default:
break;
} }
return false; return false;
} }
void *PageTable(void *PT) void *PageTable(void *PT)
{ {
#if defined(a64) #if defined(__amd64__)
if (PT) if (PT)
asmv("movq %0, %%cr3" asmv("movq %0, %%cr3"
: :
@ -179,7 +153,7 @@ namespace CPU
else else
asmv("movq %%cr3, %0" asmv("movq %%cr3, %0"
: "=r"(PT)); : "=r"(PT));
#elif defined(a32) #elif defined(__i386__)
if (PT) if (PT)
asmv("movl %0, %%cr3" asmv("movl %0, %%cr3"
: :
@ -187,7 +161,7 @@ namespace CPU
else else
asmv("movl %%cr3, %0" asmv("movl %%cr3, %0"
: "=r"(PT)); : "=r"(PT));
#elif defined(aa64) #elif defined(__aarch64__)
if (PT) if (PT)
asmv("msr ttbr0_el1, %0" asmv("msr ttbr0_el1, %0"
: :
@ -199,52 +173,15 @@ namespace CPU
return PT; return PT;
} }
void InitializeFeatures(long Core) void InitializeFeatures()
{ {
#if defined(a64) #if defined(__amd64__)
bool PGESupport = false;
bool SSESupport = false;
bool UMIPSupport = false;
bool SMEPSupport = false;
bool SMAPSupport = false;
static int BSP = 0; static int BSP = 0;
x64::CR0 cr0 = x64::readcr0(); x64::CR0 cr0 = x64::readcr0();
x64::CR4 cr4 = x64::readcr4(); x64::CR4 cr4 = x64::readcr4();
uint32_t rax, rbx, rcx, rdx;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx);
{ if (rdx & x64::CPUID_FEAT_RDX_PGE)
CPU::x86::AMD::CPUID0x00000001 cpuid1;
CPU::x86::AMD::CPUID0x00000007 cpuid7;
cpuid1.Get();
cpuid7.Get();
PGESupport = cpuid1.EDX.PGE;
SSESupport = cpuid1.EDX.SSE;
SMEPSupport = cpuid7.EBX.SMEP;
SMAPSupport = cpuid7.EBX.SMAP;
UMIPSupport = cpuid7.ECX.UMIP;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
CPU::x86::Intel::CPUID0x00000001 cpuid1;
CPU::x86::Intel::CPUID0x00000007_0 cpuid7_0;
cpuid1.Get();
cpuid7_0.Get();
PGESupport = cpuid1.EDX.PGE;
SSESupport = cpuid1.EDX.SSE;
SMEPSupport = cpuid7_0.EBX.SMEP;
SMAPSupport = cpuid7_0.EBX.SMAP;
UMIPSupport = cpuid7_0.ECX.UMIP;
}
if (Config.SIMD == false)
{
debug("Disabling SSE support...");
SSESupport = false;
}
if (PGESupport)
{ {
debug("Enabling global pages support..."); debug("Enabling global pages support...");
if (!BSP) if (!BSP)
@ -252,12 +189,7 @@ namespace CPU
cr4.PGE = 1; cr4.PGE = 1;
} }
bool SSEEnableAfter = false; if (rdx & x64::CPUID_FEAT_RDX_SSE)
/* Not sure if my code is not working properly or something else is the issue. */
if ((strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0 &&
strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0) &&
SSESupport)
{ {
debug("Enabling SSE support..."); debug("Enabling SSE support...");
if (!BSP) if (!BSP)
@ -266,227 +198,77 @@ namespace CPU
cr0.MP = 1; cr0.MP = 1;
cr4.OSFXSR = 1; cr4.OSFXSR = 1;
cr4.OSXMMEXCPT = 1; cr4.OSXMMEXCPT = 1;
CPUData *CoreData = GetCPU(Core);
CoreData->Data.FPU = (CPU::x64::FXState *)KernelAllocator.RequestPages(TO_PAGES(sizeof(CPU::x64::FXState) + 1));
memset(CoreData->Data.FPU, 0, FROM_PAGES(TO_PAGES(sizeof(CPU::x64::FXState))));
CoreData->Data.FPU->mxcsr = 0b0001111110000000;
CoreData->Data.FPU->mxcsrmask = 0b1111111110111111;
CoreData->Data.FPU->fcw = 0b0000001100111111;
CPU::x64::fxrstor(CoreData->Data.FPU);
SSEEnableAfter = true;
} }
if (!BSP)
KPrint("Enabling CPU cache.");
cr0.NW = 0; cr0.NW = 0;
cr0.CD = 0; cr0.CD = 0;
cr0.WP = 1; cr0.WP = 1;
x64::writecr0(cr0); x64::writecr0(cr0);
if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0 &&
strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
{
// FIXME: I don't think this is reporting correctly. This has to be fixed asap.
debug("Enabling UMIP, SMEP & SMAP support..."); debug("Enabling UMIP, SMEP & SMAP support...");
if (UMIPSupport) x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx);
if (rdx & x64::CPUID_FEAT_RDX_UMIP)
{ {
if (!BSP) if (!BSP)
KPrint("UMIP is supported."); KPrint("UMIP is supported.");
debug("UMIP is supported."); fixme("Not going to enable UMIP.");
// cr4.UMIP = 1; // cr4.UMIP = 1;
} }
if (rdx & x64::CPUID_FEAT_RDX_SMEP)
if (SMEPSupport)
{ {
if (!BSP) if (!BSP)
KPrint("SMEP is supported."); KPrint("SMEP is supported.");
debug("SMEP is supported."); fixme("Not going to enable SMEP.");
// cr4.SMEP = 1; // cr4.SMEP = 1;
} }
if (rdx & x64::CPUID_FEAT_RDX_SMAP)
if (SMAPSupport)
{ {
if (!BSP) if (!BSP)
KPrint("SMAP is supported."); KPrint("SMAP is supported.");
debug("SMAP is supported."); fixme("Not going to enable SMAP.");
// cr4.SMAP = 1; // cr4.SMAP = 1;
} }
} if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0 &&
strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
x64::writecr4(cr4);
else else
{ {
if (!BSP) if (!BSP)
{ {
if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) == 0) if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0)
KPrint("VirtualBox detected. Not using UMIP, SMEP & SMAP"); KPrint("VirtualBox detected. Not using UMIP, SMEP & SMAP");
else if (strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) == 0) else if (strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
KPrint("QEMU (TCG) detected. Not using UMIP, SMEP & SMAP"); KPrint("QEMU (TCG) detected. Not using UMIP, SMEP & SMAP");
} }
} }
debug("Writing CR4...");
x64::writecr4(cr4);
debug("Wrote CR4.");
debug("Enabling PAT support..."); debug("Enabling PAT support...");
x64::wrmsr(x64::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16)); x64::wrmsr(x64::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16));
if (!BSP++) if (!BSP++)
trace("Features for BSP initialized."); trace("Features for BSP initialized.");
if (SSEEnableAfter) #elif defined(__i386__)
SSEEnabled = true; #elif defined(__aarch64__)
#elif defined(a32)
#elif defined(aa64)
#endif #endif
} }
uintptr_t Counter() uint64_t Counter()
{ {
// TODO: Get the counter from the x2APIC or any other timer that is available. (TSC is not available on all CPUs) // TODO: Get the counter from the x2APIC or any other timer that is available. (TSC is not available on all CPUs)
uintptr_t Counter; #if defined(__amd64__)
#if defined(a64) uint64_t counter;
asmv("rdtsc" asmv("rdtsc"
: "=A"(Counter)); : "=A"(counter));
#elif defined(a32) return counter;
asmv("rdtsc" #elif defined(__i386__)
: "=A"(Counter)); return 0;
#elif defined(aa64) #elif defined(__aarch64__)
uint64_t counter;
asmv("mrs %0, cntvct_el0" asmv("mrs %0, cntvct_el0"
: "=r"(Counter)); : "=r"(counter));
return counter;
#endif #endif
return Counter;
}
uint64_t CheckSIMD()
{
#if defined(a32)
return SIMD_NONE; /* TODO: Support x86 SIMD on x32 */
#endif
if (unlikely(!SSEEnabled))
return SIMD_NONE;
// return SIMD_SSE;
#if defined(a86)
static uint64_t SIMDType = SIMD_NONE;
if (likely(SIMDType != SIMD_NONE))
return SIMDType;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
CPU::x86::AMD::CPUID0x00000001 cpuid;
asmv("cpuid"
: "=a"(cpuid.EAX.raw), "=b"(cpuid.EBX.raw), "=c"(cpuid.ECX.raw), "=d"(cpuid.EDX.raw)
: "a"(0x1));
if (cpuid.ECX.SSE42)
SIMDType |= SIMD_SSE42;
else if (cpuid.ECX.SSE41)
SIMDType |= SIMD_SSE41;
else if (cpuid.ECX.SSE3)
SIMDType |= SIMD_SSE3;
else if (cpuid.EDX.SSE2)
SIMDType |= SIMD_SSE2;
else if (cpuid.EDX.SSE)
SIMDType |= SIMD_SSE;
#ifdef DEBUG
if (cpuid.ECX.SSE42)
debug("SSE4.2 is supported.");
if (cpuid.ECX.SSE41)
debug("SSE4.1 is supported.");
if (cpuid.ECX.SSE3)
debug("SSE3 is supported.");
if (cpuid.EDX.SSE2)
debug("SSE2 is supported.");
if (cpuid.EDX.SSE)
debug("SSE is supported.");
#endif
return SIMDType;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
CPU::x86::Intel::CPUID0x00000001 cpuid;
asmv("cpuid"
: "=a"(cpuid.EAX.raw), "=b"(cpuid.EBX.raw), "=c"(cpuid.ECX.raw), "=d"(cpuid.EDX.raw)
: "a"(0x1));
if (cpuid.ECX.SSE4_2)
SIMDType |= SIMD_SSE42;
else if (cpuid.ECX.SSE4_1)
SIMDType |= SIMD_SSE41;
else if (cpuid.ECX.SSE3)
SIMDType |= SIMD_SSE3;
else if (cpuid.EDX.SSE2)
SIMDType |= SIMD_SSE2;
else if (cpuid.EDX.SSE)
SIMDType |= SIMD_SSE;
#ifdef DEBUG
if (cpuid.ECX.SSE4_2)
debug("SSE4.2 is supported.");
if (cpuid.ECX.SSE4_1)
debug("SSE4.1 is supported.");
if (cpuid.ECX.SSE3)
debug("SSE3 is supported.");
if (cpuid.EDX.SSE2)
debug("SSE2 is supported.");
if (cpuid.EDX.SSE)
debug("SSE is supported.");
#endif
return SIMDType;
}
debug("No SIMD support.");
#endif // a64 || a32
return SIMD_NONE;
}
bool CheckSIMD(x86SIMDType Type)
{
if (unlikely(!SSEEnabled))
return false;
#if defined(a86)
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
CPU::x86::AMD::CPUID0x00000001 cpuid;
asmv("cpuid"
: "=a"(cpuid.EAX.raw), "=b"(cpuid.EBX.raw), "=c"(cpuid.ECX.raw), "=d"(cpuid.EDX.raw)
: "a"(0x1));
if (Type == SIMD_SSE42)
return cpuid.ECX.SSE42;
else if (Type == SIMD_SSE41)
return cpuid.ECX.SSE41;
else if (Type == SIMD_SSE3)
return cpuid.ECX.SSE3;
else if (Type == SIMD_SSE2)
return cpuid.EDX.SSE2;
else if (Type == SIMD_SSE)
return cpuid.EDX.SSE;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
CPU::x86::Intel::CPUID0x00000001 cpuid;
asmv("cpuid"
: "=a"(cpuid.EAX.raw), "=b"(cpuid.EBX.raw), "=c"(cpuid.ECX.raw), "=d"(cpuid.EDX.raw)
: "a"(0x1));
if (Type == SIMD_SSE42)
return cpuid.ECX.SSE4_2;
else if (Type == SIMD_SSE41)
return cpuid.ECX.SSE4_1;
else if (Type == SIMD_SSE3)
return cpuid.ECX.SSE3;
else if (Type == SIMD_SSE2)
return cpuid.EDX.SSE2;
else if (Type == SIMD_SSE)
return cpuid.EDX.SSE;
}
#endif // a64 || a32
return false;
} }
} }

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../crashhandler.hpp" #include "../crashhandler.hpp"
#include "chfcts.hpp" #include "chfcts.hpp"
@ -24,15 +7,15 @@
#include <smp.hpp> #include <smp.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#if defined(a64) #if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp" #include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32) #elif defined(__i386__)
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#include "../../kernel.h" #include "../../kernel.h"
static const char *PageFaultDescriptions[8] = { static const char *PagefaultDescriptions[8] = {
"Supervisory process tried to read a non-present page entry\n", "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 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 to a non-present page entry\n",
@ -45,92 +28,49 @@ static const char *PageFaultDescriptions[8] = {
SafeFunction void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame) SafeFunction void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame)
{ {
fixme("Divide by zero exception\n"); fixme("Divide by zero exception\n");
UNUSED(Frame);
} }
SafeFunction void DebugExceptionHandler(CHArchTrapFrame *Frame) SafeFunction void DebugExceptionHandler(CHArchTrapFrame *Frame)
{ {
CrashHandler::EHPrint("\eDD2920System crashed!\n");
CrashHandler::EHPrint("Kernel triggered debug exception.\n"); CrashHandler::EHPrint("Kernel triggered debug exception.\n");
UNUSED(Frame);
} }
SafeFunction void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame) { fixme("NMI exception"); }
SafeFunction void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame) SafeFunction void BreakpointExceptionHandler(CHArchTrapFrame *Frame) { fixme("Breakpoint exception"); }
{ SafeFunction void OverflowExceptionHandler(CHArchTrapFrame *Frame) { fixme("Overflow exception"); }
fixme("NMI exception"); SafeFunction void BoundRangeExceptionHandler(CHArchTrapFrame *Frame) { fixme("Bound range exception"); }
UNUSED(Frame);
}
SafeFunction void BreakpointExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Breakpoint exception");
UNUSED(Frame);
}
SafeFunction void OverflowExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Overflow exception");
UNUSED(Frame);
}
SafeFunction void BoundRangeExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Bound range exception");
UNUSED(Frame);
}
SafeFunction void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame) SafeFunction void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame)
{ {
CrashHandler::EHPrint("\eDD2920System crashed!\n");
CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n"); CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n");
UNUSED(Frame);
} }
SafeFunction void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame) { fixme("Device not available exception"); }
SafeFunction void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame) SafeFunction void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame) { fixme("Double fault exception"); }
{ SafeFunction void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame) { fixme("Coprocessor segment overrun exception"); }
fixme("Device not available exception"); SafeFunction void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame) { fixme("Invalid TSS exception"); }
UNUSED(Frame); SafeFunction void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame) { fixme("Segment not present exception"); }
}
SafeFunction void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Double fault exception");
UNUSED(Frame);
}
SafeFunction void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Coprocessor segment overrun exception");
UNUSED(Frame);
}
SafeFunction void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Invalid TSS exception");
UNUSED(Frame);
}
SafeFunction void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Segment not present exception");
UNUSED(Frame);
}
SafeFunction void StackFaultExceptionHandler(CHArchTrapFrame *Frame) SafeFunction void StackFaultExceptionHandler(CHArchTrapFrame *Frame)
{ {
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode}; CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
#if defined(a64) 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); CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->rip);
#elif defined(a32) #elif defined(__i386__)
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->eip); CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->eip);
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
CrashHandler::EHPrint("External: %d\n", SelCode.External); CrashHandler::EHPrint("External: %d\n", SelCode.External);
CrashHandler::EHPrint("Table: %d\n", SelCode.Table); CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx); CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
CrashHandler::EHPrint("Error code: %#lx\n", Frame->ErrorCode); CrashHandler::EHPrint("Error code: %#lx\n", Frame->ErrorCode);
} }
SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame) 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}; CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
// switch (SelCode.Table) // switch (SelCode.Table)
// { // {
@ -150,20 +90,22 @@ SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame)
// memcpy(desc_tmp, "Unknown", 7); // memcpy(desc_tmp, "Unknown", 7);
// break; // break;
// } // }
CrashHandler::EHPrint("\eDD2920System crashed!\n");
CrashHandler::EHPrint("Kernel performed an illegal operation.\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("External: %d\n", SelCode.External);
CrashHandler::EHPrint("Table: %d\n", SelCode.Table); CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx); CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
} }
SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame) SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
{ {
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
#if defined(a64) CrashHandler::EHPrint("\eDD2920System crashed!\n\eFFFFFF");
CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->rip); #if defined(__amd64__)
#elif defined(a32) CrashHandler::EHPrint("An exception occurred at %#lx by %#lx\n", CPU::x64::readcr2().PFLA, Frame->rip);
CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->eip); #elif defined(__i386__)
#elif defined(aa64) CrashHandler::EHPrint("An exception occurred at %#lx by %#lx\n", CPU::x64::readcr2().PFLA, Frame->eip);
#elif defined(__aarch64__)
#endif #endif
CrashHandler::EHPrint("Page: %s\n", params.P ? "Present" : "Not Present"); CrashHandler::EHPrint("Page: %s\n", params.P ? "Present" : "Not Present");
CrashHandler::EHPrint("Write Operation: %s\n", params.W ? "Read-Only" : "Read-Write"); CrashHandler::EHPrint("Write Operation: %s\n", params.W ? "Read-Only" : "Read-Write");
@ -176,171 +118,12 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
if (Frame->ErrorCode & 0x00000008) if (Frame->ErrorCode & 0x00000008)
CrashHandler::EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n"); CrashHandler::EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n");
else else
CrashHandler::EHPrint(PageFaultDescriptions[Frame->ErrorCode & 0b111]); CrashHandler::EHPrint(PagefaultDescriptions[Frame->ErrorCode & 0b111]);
#ifdef DEBUG
uintptr_t CheckPageFaultAddress = 0;
CheckPageFaultAddress = CrashHandler::PageFaultAddress;
if (CheckPageFaultAddress == 0)
#ifdef a64
CheckPageFaultAddress = Frame->rip;
#elif defined(a32)
CheckPageFaultAddress = Frame->eip;
#elif defined(aa64)
CheckPageFaultAddress = 0;
#endif
#if defined(a64)
Memory::Virtual vma = Memory::Virtual(((Memory::PageTable4 *)CPU::x64::readcr3().raw));
#elif defined(a32)
Memory::Virtual vma = Memory::Virtual(((Memory::PageTable4 *)CPU::x32::readcr3().raw));
#elif defined(aa64)
Memory::Virtual vma = Memory::Virtual();
#warning "TODO: aa64"
#endif
bool PageAvailable = vma.Check((void *)CheckPageFaultAddress);
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 *)CheckPageFaultAddress);
bool ReadWrite = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW);
bool User = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US);
bool WriteThrough = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT);
bool CacheDisabled = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD);
bool Accessed = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A);
bool Dirty = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D);
bool Global = vma.Check((void *)CheckPageFaultAddress, 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");
if (Present)
{
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
Memory::Virtual::PageMapIndexer Index = Memory::Virtual::PageMapIndexer((uintptr_t)CheckPageFaultLinearAddress);
debug("Index for %#lx is PML:%d PDPTE:%d PDE:%d PTE:%d",
CheckPageFaultLinearAddress,
Index.PMLIndex,
Index.PDPTEIndex,
Index.PDEIndex,
Index.PTEIndex);
#if defined(a64)
Memory::PageMapLevel4 PML4 = ((Memory::PageTable4 *)CPU::x64::readcr3().raw)->Entries[Index.PMLIndex];
#elif defined(a32)
Memory::PageMapLevel4 PML4 = ((Memory::PageTable4 *)CPU::x32::readcr3().raw)->Entries[Index.PMLIndex];
#elif defined(aa64)
Memory::PageMapLevel4 PML4 = {.raw = 0};
#warning "TODO: aa64"
#endif
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
Index.PMLIndex, 0, 0, 0,
PML4.Present ? "1" : "0",
PML4.ReadWrite ? "1" : "0",
PML4.UserSupervisor ? "1" : "0",
PML4.WriteThrough ? "1" : "0",
PML4.CacheDisable ? "1" : "0",
PML4.Accessed ? "1" : "0",
PML4.ExecuteDisable ? "1" : "0",
PML4.GetAddress() << 12);
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
Index.PMLIndex, Index.PDPTEIndex, 0, 0,
PDPTE->Entries[Index.PDPTEIndex].Present ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].ReadWrite ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].UserSupervisor ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].WriteThrough ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].CacheDisable ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].Accessed ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].ExecuteDisable ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, 0,
PDE->Entries[Index.PDEIndex].Present ? "1" : "0",
PDE->Entries[Index.PDEIndex].ReadWrite ? "1" : "0",
PDE->Entries[Index.PDEIndex].UserSupervisor ? "1" : "0",
PDE->Entries[Index.PDEIndex].WriteThrough ? "1" : "0",
PDE->Entries[Index.PDEIndex].CacheDisable ? "1" : "0",
PDE->Entries[Index.PDEIndex].Accessed ? "1" : "0",
PDE->Entries[Index.PDEIndex].ExecuteDisable ? "1" : "0",
PDE->Entries[Index.PDEIndex].GetAddress() << 12);
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:%#lx",
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, Index.PTEIndex,
PTE->Entries[Index.PTEIndex].Present ? "1" : "0",
PTE->Entries[Index.PTEIndex].ReadWrite ? "1" : "0",
PTE->Entries[Index.PTEIndex].UserSupervisor ? "1" : "0",
PTE->Entries[Index.PTEIndex].WriteThrough ? "1" : "0",
PTE->Entries[Index.PTEIndex].CacheDisable ? "1" : "0",
PTE->Entries[Index.PTEIndex].Accessed ? "1" : "0",
PTE->Entries[Index.PTEIndex].Dirty ? "1" : "0",
PTE->Entries[Index.PTEIndex].PageAttributeTable ? "1" : "0",
PTE->Entries[Index.PTEIndex].Global ? "1" : "0",
PTE->Entries[Index.PTEIndex].ProtectionKey,
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
}
}
#endif
}
SafeFunction void x87FloatingPointExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("x87 floating point exception");
UNUSED(Frame);
}
SafeFunction void AlignmentCheckExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Alignment check exception");
UNUSED(Frame);
}
SafeFunction void MachineCheckExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Machine check exception");
UNUSED(Frame);
}
SafeFunction void SIMDFloatingPointExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("SIMD floating point exception");
UNUSED(Frame);
}
SafeFunction void VirtualizationExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Virtualization exception");
UNUSED(Frame);
}
SafeFunction void SecurityExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Security exception");
UNUSED(Frame);
}
SafeFunction void UnknownExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Unknown exception");
UNUSED(Frame);
} }
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

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../crashhandler.hpp" #include "../crashhandler.hpp"
#include "chfcts.hpp" #include "chfcts.hpp"
@ -23,34 +6,42 @@
#include <convert.h> #include <convert.h>
#include <printf.h> #include <printf.h>
#include <lock.hpp> #include <lock.hpp>
#include <rand.hpp>
#include <uart.hpp>
#include <debug.h> #include <debug.h>
#include <smp.hpp> #include <smp.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#include <io.h> #include <io.h>
#if defined(a64) #if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp" #include "../../Architecture/amd64/cpu/gdt.hpp"
#include "../Architecture/amd64/cpu/apic.hpp" #elif defined(__i386__)
#elif defined(a32) #elif defined(__aarch64__)
#include "../../Architecture/i386/cpu/gdt.hpp"
#include "../Architecture/i386/cpu/apic.hpp"
#elif defined(aa64)
#endif #endif
#include "../../kernel.h" #include "../../kernel.h"
#include "../../DAPI.hpp"
NewLock(UserInputLock); 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.Present ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.ReadWrite ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.UserSupervisor ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.WriteThrough ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.CacheDisable ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Accessed ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Dirty ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.PageSize ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Global ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.GetAddress() << 12); \
Display->SetBuffer(SBIdx);
namespace CrashHandler namespace CrashHandler
{ {
uintptr_t PageFaultAddress = 0;
void *EHIntFrames[INT_FRAMES_MAX]; void *EHIntFrames[INT_FRAMES_MAX];
static bool ExceptionOccurred = false; static bool ExceptionOccurred = false;
int SBIdx = 255; int SBIdx = 255;
SafeFunction void printfWrapper(char c, void *unused) SafeFunction void printfWrapper(char c, void *unused)
{ {
Display->Print(c, SBIdx, true); Display->Print(c, SBIdx, true);
@ -65,42 +56,6 @@ namespace CrashHandler
va_end(args); va_end(args);
} }
SafeFunction void EHDumpData(void *Address, unsigned long Length)
{
EHPrint("-------------------------------------------------------------------------\n");
Display->SetBuffer(SBIdx);
unsigned char *AddressChar = (unsigned char *)Address;
unsigned char Buffer[17];
unsigned long Iterate;
for (Iterate = 0; Iterate < Length; Iterate++)
{
if ((Iterate % 16) == 0)
{
if (Iterate != 0)
EHPrint(" \e8A78FF%s\eAABBCC\n", Buffer);
EHPrint(" \e9E9E9E%04x\eAABBCC ", Iterate);
Display->SetBuffer(SBIdx);
}
EHPrint(" \e4287f5%02x\eAABBCC", AddressChar[Iterate]);
if ((AddressChar[Iterate] < 0x20) || (AddressChar[Iterate] > 0x7e))
Buffer[Iterate % 16] = '.';
else
Buffer[Iterate % 16] = AddressChar[Iterate];
Buffer[(Iterate % 16) + 1] = '\0';
}
while ((Iterate % 16) != 0)
{
EHPrint(" ");
Display->SetBuffer(SBIdx);
Iterate++;
}
EHPrint(" \e8A78FF%s\eAABBCC\n", Buffer);
EHPrint("-------------------------------------------------------------------------\n\n.");
Display->SetBuffer(SBIdx);
}
SafeFunction char *TrimWhiteSpace(char *str) SafeFunction char *TrimWhiteSpace(char *str)
{ {
char *end; char *end;
@ -169,70 +124,6 @@ namespace CrashHandler
EHPrint(" \eAAF00F%s", CPU::Vendor()); EHPrint(" \eAAF00F%s", CPU::Vendor());
EHPrint(" \eAA00FF%s", CPU::Name()); EHPrint(" \eAA00FF%s", CPU::Name());
Display->SetBufferCursor(SBIdx, 0, fi.Height + 10); Display->SetBufferCursor(SBIdx, 0, fi.Height + 10);
/* https://imgflip.com/i/77slbl */
if ((Random::rand32() % 100) >= 98)
{
debug("Easter egg activated!");
int BaseXOffset = sb->Width - 14;
int BaseYOffset = 8;
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 0, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 0, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 0, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 7, BaseYOffset + 0, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 1, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 1, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 1, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 1, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 1, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 7, BaseYOffset + 1, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 8, BaseYOffset + 1, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 1, BaseYOffset + 2, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 2, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 2, 0xFFFFFF, SBIdx);
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 2, 0x000000, SBIdx);
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 2, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 2, 0xFFFFFF, SBIdx);
Display->SetPixel(BaseXOffset + 7, BaseYOffset + 2, 0x000000, SBIdx);
Display->SetPixel(BaseXOffset + 8, BaseYOffset + 2, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 1, BaseYOffset + 3, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 3, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 3, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 3, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 3, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 3, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 7, BaseYOffset + 3, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 0, BaseYOffset + 4, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 1, BaseYOffset + 4, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 4, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 4, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 4, 0xA84832, SBIdx);
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 4, 0xA84832, SBIdx);
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 4, 0xA84832, SBIdx);
Display->SetPixel(BaseXOffset + 7, BaseYOffset + 4, 0xA84832, SBIdx);
Display->SetPixel(BaseXOffset + 0, BaseYOffset + 5, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 1, BaseYOffset + 5, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 5, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 5, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 5, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 5, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 5, 0x21852E, SBIdx);
Display->SetPixel(BaseXOffset + 0, BaseYOffset + 6, 0x1216FF, SBIdx);
Display->SetPixel(BaseXOffset + 1, BaseYOffset + 6, 0x1216FF, SBIdx);
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 6, 0x1216FF, SBIdx);
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 6, 0x1216FF, SBIdx);
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 6, 0x1216FF, SBIdx);
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 6, 0x1216FF, SBIdx);
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 6, 0x1216FF, SBIdx);
Display->SetBuffer(SBIdx);
}
} }
SafeFunction void DisplayBottomOverlay() SafeFunction void DisplayBottomOverlay()
@ -333,24 +224,18 @@ namespace CrashHandler
EHPrint("exit - Shutdown the OS.\n"); EHPrint("exit - Shutdown the OS.\n");
EHPrint("reboot - Reboot the OS.\n"); EHPrint("reboot - Reboot the OS.\n");
EHPrint("help - Display this help message.\n"); EHPrint("help - Display this help message.\n");
EHPrint("showbuf,sb <INDEX> - Display the contents of a screen buffer.\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(" - 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(" - \eFF4400WARNING: This can crash the system if a wrong buffer is selected.\eFAFAFA\n");
EHPrint("ifr <COUNT> - Show interrupt frames.\n"); EHPrint("ifr <COUNT> - Show interrupt frames.\n");
EHPrint("tlb <ADDRESS> - Print the page table entries\n"); EHPrint("tlb <ADDRESS> - Print the page table entries\n");
EHPrint("bitmap - Print the memory bitmap\n"); EHPrint("bitmap - Print the memory bitmap\n");
EHPrint("mem - Print the memory allocation\n");
EHPrint("cr<INDEX> - Print the CPU control register\n");
EHPrint("tss <CORE> - Print the CPU task state segment\n");
EHPrint("dump <ADDRESS HEX> <LENGTH DEC> - Dump memory\n");
EHPrint(" - \eFF4400WARNING: This can crash the system if you try to read from an unmapped page.\eFAFAFA\n");
EHPrint("uartmemdmp <INDEX> <SKIP INACCESSIBLE (bool 0,1)> - Dump the memory of a UART.\n");
EHPrint("main - Show the main screen.\n"); EHPrint("main - Show the main screen.\n");
EHPrint("details - Show the details screen.\n"); EHPrint("details - Show the details screen.\n");
EHPrint("frames - Show the stack frame screen.\n"); EHPrint("frames - Show the stack frame screen.\n");
EHPrint("tasks - Show the tasks screen.\n"); EHPrint("tasks - Show the tasks screen.\n");
EHPrint("console - Show the console screen.\n"); EHPrint("console - Show the console screen.\n");
EHPrint("Also, you can use the arrow keys to navigate between the screens.\n"); EHPrint("Also, you can use the arrow keys to navigate the menu.\n");
EHPrint("=========================================================================\n"); EHPrint("=========================================================================\n");
EHPrint("Kernel Compiled at: %s %s with C++ Standard: %d\n", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD); EHPrint("Kernel Compiled at: %s %s with C++ Standard: %d\n", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
EHPrint("C++ Language Version (__cplusplus): %ld\n", __cplusplus); EHPrint("C++ Language Version (__cplusplus): %ld\n", __cplusplus);
@ -369,35 +254,33 @@ namespace CrashHandler
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
CPU::Stop(); CPU::Stop();
} }
else if (strncmp(Input, "showbuf", 7) == 0 || strncmp(Input, "sb", 2) == 0) else if (strncmp(Input, "showbuf", 7) == 0)
{ {
char *arg = TrimWhiteSpace(Input + 7); char *arg = TrimWhiteSpace(Input + 7);
int tmpidx = SBIdx; int tmpidx = SBIdx;
SBIdx = atoi(arg); SBIdx = atoi(arg);
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
#if defined(a86)
for (int i = 0; i < 5000000; i++) for (int i = 0; i < 5000000; i++)
inb(0x80); inb(0x80);
#endif // a64 || a32
SBIdx = tmpidx; SBIdx = tmpidx;
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
} }
else if (strncmp(Input, "ifr", 3) == 0) else if (strncmp(Input, "ifr", 3) == 0)
{ {
char *arg = TrimWhiteSpace(Input + 3); char *arg = TrimWhiteSpace(Input + 3);
int CountI = atoi(arg); uint64_t CountI = atoi(arg);
int TotalCount = sizeof(EHIntFrames) / sizeof(EHIntFrames[0]); uint64_t TotalCount = sizeof(EHIntFrames) / sizeof(EHIntFrames[0]);
debug("Printing %ld interrupt frames.", CountI); debug("Printing %ld interrupt frames.", CountI);
if (CountI > TotalCount) if (CountI > TotalCount)
{ {
EHPrint("\eFF4400Count too big! Maximum allowed is %ld\eFAFAFA\n", TotalCount); EHPrint("eFF4400Count too big! Maximum allowed is %ld\eFAFAFA\n", TotalCount);
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
} }
else else
{ {
for (int i = 0; i < CountI; i++) for (uint64_t i = 0; i < CountI; i++)
{ {
if (EHIntFrames[i]) if (EHIntFrames[i])
{ {
@ -405,20 +288,17 @@ namespace CrashHandler
continue; continue;
EHPrint("\n\e2565CC%p", EHIntFrames[i]); EHPrint("\n\e2565CC%p", EHIntFrames[i]);
EHPrint("\e7925CC-"); EHPrint("\e7925CC-");
#if defined(a64) #if defined(__amd64__)
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) if ((uint64_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(a32) #elif defined(__i386__)
if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) if ((uint64_t)EHIntFrames[i] >= 0xC0000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(aa64) #elif defined(__aarch64__)
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
#endif #endif
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i])); EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uint64_t)EHIntFrames[i]));
else else
EHPrint("\eFF4CA9Outside Kernel"); EHPrint("\eFF4CA9Outside Kernel");
#if defined(a86)
for (int i = 0; i < 20000; i++) for (int i = 0; i < 20000; i++)
inb(0x80); inb(0x80);
#endif // a64 || a32
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
} }
} }
@ -427,102 +307,66 @@ namespace CrashHandler
else if (strncmp(Input, "tlb", 3) == 0) else if (strncmp(Input, "tlb", 3) == 0)
{ {
char *arg = TrimWhiteSpace(Input + 3); char *arg = TrimWhiteSpace(Input + 3);
uintptr_t Address = NULL; uint64_t Address = NULL;
Address = strtol(arg, NULL, 16); Address = strtol(arg, NULL, 16);
debug("Converted %s to %#lx", arg, Address); debug("Converted %s to %#lx", arg, Address);
Memory::PageTable4 *BasePageTable = (Memory::PageTable4 *)Address; Memory::PageTable4 *BasePageTable = (Memory::PageTable4 *)Address;
if (Memory::Virtual().Check(BasePageTable)) if (Memory::Virtual().Check(BasePageTable))
for (int Index = 0; Index < 512; Index++)
{ {
for (int PMLIndex = 0; PMLIndex < 512; PMLIndex++) if (BasePageTable->Entries[Index].raw == 0)
{ continue;
Memory::PageMapLevel4 PML4 = BasePageTable->Entries[PMLIndex];
EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", // TRACE_PAGE_TABLE(BasePageTable->Entries[Index], Index, "");
PMLIndex, 0, 0, 0, // for (int i = 0; i < 10000; i++)
PML4.Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // inb(0x80);
PML4.ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PML4.UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // if (BasePageTable->Entries[Index].GetFlag(Memory::PTFlag::P))
PML4.WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // {
PML4.CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // Memory::PageTable4 *PDP = (Memory::PageTable4 *)((uint64_t)BasePageTable->Entries[Index].GetAddress() << 12);
PML4.Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // for (int PMLIndex = 0; PMLIndex < 512; PMLIndex++)
PML4.ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // {
PML4.GetAddress() << 12); // if (PDP->Entries[PMLIndex].raw == 0)
Display->SetBuffer(SBIdx); // continue;
if (PML4.Present) // TRACE_PAGE_TABLE(PDP->Entries[PMLIndex], PMLIndex, " ");
{ // for (int i = 0; i < 10000; i++)
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); // inb(0x80);
if (PDPTE)
{ // if (PDP->Entries[PMLIndex].GetFlag(Memory::PTFlag::P))
for (int PDPTEIndex = 0; PDPTEIndex < 512; PDPTEIndex++) // {
{ // Memory::PageTable4 *PD = (Memory::PageTable4 *)((uint64_t)PDP->Entries[PMLIndex].GetAddress() << 12);
EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", // for (int PDPTEIndex = 0; PDPTEIndex < 512; PDPTEIndex++)
PMLIndex, PDPTEIndex, 0, 0, // {
PDPTE->Entries[PDPTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // if (PD->Entries[PDPTEIndex].raw == 0)
PDPTE->Entries[PDPTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // continue;
PDPTE->Entries[PDPTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // TRACE_PAGE_TABLE(PD->Entries[PDPTEIndex], PDPTEIndex, " ");
PDPTE->Entries[PDPTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // for (int i = 0; i < 10000; i++)
PDPTE->Entries[PDPTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // inb(0x80);
PDPTE->Entries[PDPTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDPTE->Entries[PDPTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // if (PD->Entries[PDPTEIndex].GetFlag(Memory::PTFlag::P))
PDPTE->Entries[PDPTEIndex].GetAddress() << 12); // {
Display->SetBuffer(SBIdx); // Memory::PageTable4 *PT = (Memory::PageTable4 *)((uint64_t)PD->Entries[PDPTEIndex].GetAddress() << 12);
if ((PDPTE->Entries[PDPTEIndex].Present)) // for (int PTEIndex = 0; PTEIndex < 512; PTEIndex++)
{ // {
Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[PDPTEIndex].GetAddress() << 12); // if (PT->Entries[PTEIndex].raw == 0)
if (PDE) // continue;
{ // TRACE_PAGE_TABLE(PT->Entries[PTEIndex], PTEIndex, " ");
for (int PDEIndex = 0; PDEIndex < 512; PDEIndex++) // for (int i = 0; i < 10000; i++)
{ // inb(0x80);
EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n", // }
PMLIndex, PDPTEIndex, PDEIndex, 0, // }
PDE->Entries[PDEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // }
PDE->Entries[PDEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // }
PDE->Entries[PDEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // }
PDE->Entries[PDEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5", // }
PDE->Entries[PDEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDE->Entries[PDEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDE->Entries[PDEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDE->Entries[PDEIndex].GetAddress() << 12);
Display->SetBuffer(SBIdx);
if ((PDE->Entries[PDEIndex].Present))
{
Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[PDEIndex].GetAddress() << 12);
if (PTE)
{
for (int PTEIndex = 0; PTEIndex < 512; PTEIndex++)
{
EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:\e888888%#lx\n",
PMLIndex, PDPTEIndex, PDEIndex, PTEIndex,
PTE->Entries[PTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PTE->Entries[PTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PTE->Entries[PTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PTE->Entries[PTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PTE->Entries[PTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PTE->Entries[PTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PTE->Entries[PTEIndex].Dirty ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PTE->Entries[PTEIndex].PageAttributeTable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PTE->Entries[PTEIndex].Global ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PTE->Entries[PTEIndex].ProtectionKey,
PTE->Entries[PTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PTE->Entries[PTEIndex].GetAddress() << 12);
Display->SetBuffer(SBIdx);
}
}
}
}
}
}
}
}
}
}
} }
} }
else if (strncmp(Input, "bitmap", 6) == 0) else if (strncmp(Input, "bitmap", 6) == 0)
{ {
Bitmap bm = KernelAllocator.GetPageBitmap(); Bitmap bm = KernelAllocator.GetPageBitmap();
EHPrint("\n\eFAFAFA[0%%] %08ld: ", 0); EHPrint("\n\eFAFAFA%08ld: ", 0);
for (size_t i = 0; i < bm.Size; i++) for (uint64_t i = 0; i < bm.Size; i++)
{ {
if (bm.Get(i)) if (bm.Get(i))
EHPrint("\eFF00001"); EHPrint("\eFF00001");
@ -530,211 +374,13 @@ namespace CrashHandler
EHPrint("\e00FF000"); EHPrint("\e00FF000");
if (i % 128 == 127) if (i % 128 == 127)
{ {
short Percentage = s_cst(short, (i * 100) / bm.Size); EHPrint("\n\eFAFAFA%08ld: ", i);
EHPrint("\n\eFAFAFA[%03ld%%] %08ld: ", Percentage, i);
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
} }
} }
EHPrint("\n\e22AA44--- END OF BITMAP ---\nBitmap size: %ld\n\n.", bm.Size); EHPrint("\n\e22AA44--- END OF BITMAP ---\nBitmap size: %ld\n", bm.Size);
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
} }
else if (strcmp(Input, "mem") == 0)
{
uint64_t Total = KernelAllocator.GetTotalMemory();
uint64_t Used = KernelAllocator.GetUsedMemory();
uint64_t Free = KernelAllocator.GetFreeMemory();
uint64_t Reserved = KernelAllocator.GetReservedMemory();
EHPrint("\e22AA44Total: %ld bytes\n\eFF0000Used: %ld bytes\n\e00FF00Free: %ld bytes\n\eFF00FFReserved: %ld bytes\n", Total, Used, Free, Reserved);
int Progress = s_cst(int, (Used * 100) / Total);
int ReservedProgress = s_cst(int, (Reserved * 100) / Total);
EHPrint("\e22AA44%3d%% \eCCCCCC[", Progress);
for (int i = 0; i < Progress; i++)
EHPrint("\eFF0000|");
for (int i = 0; i < 100 - Progress; i++)
EHPrint("\e00FF00|");
for (int i = 0; i < ReservedProgress; i++)
EHPrint("\eFF00FF|");
EHPrint("\eCCCCCC]\n");
Display->SetBuffer(SBIdx);
}
else if (strncmp(Input, "cr", 2) == 0)
{
char *cr = TrimWhiteSpace(Input + 2);
switch (cr[0])
{
case '0':
{
#if defined(a64)
EHPrint("\e44AA000: %#lx\n", CPU::x64::readcr0());
#elif defined(a32)
EHPrint("\e44AA000: %#lx\n", CPU::x32::readcr0());
#endif
break;
}
case '2':
{
#if defined(a64)
EHPrint("\e44AA002: %#lx\n", PageFaultAddress);
#elif defined(a32)
EHPrint("\e44AA002: %#lx\n", CPU::x32::readcr2());
#endif
break;
}
case '3':
{
#if defined(a64)
EHPrint("\e44AA003: %#lx\n", CPU::x64::readcr3());
#elif defined(a32)
EHPrint("\e44AA003: %#lx\n", CPU::x32::readcr3());
#endif
break;
}
case '4':
{
#if defined(a64)
EHPrint("\e44AA004: %#lx\n", CPU::x64::readcr4());
#elif defined(a32)
EHPrint("\e44AA004: %#lx\n", CPU::x32::readcr4());
#endif
break;
}
case '8':
{
#if defined(a64)
EHPrint("\e44AA008: %#lx\n", CPU::x64::readcr8());
#elif defined(a32)
EHPrint("\e44AA008: %#lx\n", CPU::x32::readcr8());
#endif
break;
}
default:
EHPrint("\eFF0000Invalid CR\n");
break;
}
}
else if (strncmp(Input, "tss", 3) == 0)
{
char *arg = TrimWhiteSpace(Input + 3);
int TSSIndex = atoi(arg);
if (TSSIndex > SMP::CPUCores)
{
EHPrint("\eFF0000Invalid TSS index\n");
}
else
{
#if defined(a86)
GlobalDescriptorTable::TaskStateSegment tss = GlobalDescriptorTable::tss[TSSIndex];
EHPrint("\eFAFAFAStack Pointer 0: \eAABB22%#lx\n", tss.StackPointer[0]);
EHPrint("\eFAFAFAStack Pointer 1: \eAABB22%#lx\n", tss.StackPointer[1]);
EHPrint("\eFAFAFAStack Pointer 2: \eAABB22%#lx\n", tss.StackPointer[2]);
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[0]);
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[1]);
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[2]);
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[3]);
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[4]);
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[5]);
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[6]);
EHPrint("\eFAFAFAI/O Map Base Address Offset: \eAABB22%#lx\n", tss.IOMapBaseAddressOffset);
EHPrint("\eFAFAFAReserved 0: \eAABB22%#lx\n", tss.Reserved0);
EHPrint("\eFAFAFAReserved 1: \eAABB22%#lx\n", tss.Reserved1);
EHPrint("\eFAFAFAReserved 2: \eAABB22%#lx\n", tss.Reserved2);
#elif defined(aa64)
EHPrint("\eFF0000AArch64 does not have TSS\n");
#endif
}
}
else if (strncmp(Input, "dump", 4) == 0)
{
char *arg = TrimWhiteSpace(Input + 4);
char *addr = strtok(arg, " ");
char *len = strtok(NULL, " ");
if (addr == NULL || len == NULL)
{
EHPrint("\eFF0000Invalid arguments\n");
}
else
{
uint64_t Address = strtoul(addr, NULL, 16);
uint64_t Length = strtoul(len, NULL, 10);
debug("Dumping %ld bytes from %#lx\n", Length, Address);
EHDumpData((void *)Address, Length);
}
}
else if (strncmp(Input, "uartmemdmp", 10) == 0)
{
char *arg = TrimWhiteSpace(Input + 10);
char *cPort = strtok(arg, " ");
char *cBoolSkip = strtok(NULL, " ");
UniversalAsynchronousReceiverTransmitter::SerialPorts port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM1;
switch (cPort[0])
{
case '1':
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM1;
break;
case '2':
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM2;
break;
case '3':
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM3;
break;
case '4':
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM4;
break;
case '5':
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM5;
break;
case '6':
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM6;
break;
case '7':
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM7;
break;
case '8':
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM8;
break;
default:
EHPrint("\eFF0000Invalid port! Defaulting to 1.\n");
break;
}
EHPrint("\eF8F8F8Dumping memory to UART port %c (%#lx) and %s inaccessible pages.\n", cPort[0], port, cBoolSkip[0] == '1' ? "skipping" : "zeroing");
Display->SetBuffer(SBIdx);
uint64_t Length = KernelAllocator.GetTotalMemory();
uint64_t ProgressLength = Length;
UniversalAsynchronousReceiverTransmitter::UART uart(port);
Memory::Virtual vma;
uint8_t *Address = reinterpret_cast<uint8_t *>(0x0);
int Progress = 0;
for (size_t i = 0; i < Length; i++)
{
if (vma.Check(Address))
uart.Write(*Address);
else if (cBoolSkip[0] == '0')
uart.Write((uint8_t)0);
else
ProgressLength--;
Address++;
if (unlikely(i % 0x1000 == 0))
{
int NewProgress = (int)((i * 100) / ProgressLength);
if (unlikely(NewProgress != Progress))
{
Progress = NewProgress;
EHPrint("\n%d%%\n", Progress);
Display->SetBuffer(SBIdx);
}
Display->Print('.', SBIdx);
if (unlikely(i % 0x500 == 0))
Display->SetBuffer(SBIdx);
}
}
EHPrint("\nDone.\n");
}
else if (strcmp(Input, "main") == 0) else if (strcmp(Input, "main") == 0)
{ {
SBIdx = 255; SBIdx = 255;
@ -770,109 +416,44 @@ namespace CrashHandler
DisplayConsoleScreen(crashdata); DisplayConsoleScreen(crashdata);
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
} }
else if (strlen(Input) > 0) else
{
if (strlen(Input) > 0)
EHPrint("Unknown command: %s", Input); EHPrint("Unknown command: %s", Input);
}
DisplayBottomOverlay(); DisplayBottomOverlay();
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
} }
SafeFunction void StopAllCores()
{
#if defined(a86)
/* FIXME: Can't send IPIs to other cores
* because it causes another exception on
* the other cores.
*
* Also it makes every core to stay at 100% usage for some reason.
*/
// if (SMP::CPUCores > 1)
// {
// for (int i = 1; i < SMP::CPUCores; i++)
// {
// APIC::InterruptCommandRegisterLow icr;
// icr.Vector = CPU::x86::IRQ29;
// icr.Level = APIC::APICLevel::Assert;
// ((APIC::APIC *)Interrupts::apic[i])->IPI(i, icr);
// __sync;
// }
// }
// APIC::InterruptCommandRegisterLow icr;
// icr.Vector = CPU::x86::IRQ29;
// icr.Level = APIC::APICLevel::Assert;
// icr.DestinationShorthand = APIC::APICDestinationShorthand::AllExcludingSelf;
// ((APIC::APIC *)Interrupts::apic[0])->IPI(0, icr);
// CPU::Interrupts(CPU::Enable);
__sync;
CPU::Interrupts(CPU::Disable);
// }
#elif defined(aa64)
#endif
}
SafeFunction void Handle(void *Data) SafeFunction void Handle(void *Data)
{ {
// TODO: SUPPORT SMP // TODO: SUPPORT SMP
CPU::Interrupts(CPU::Disable); CPU::Interrupts(CPU::Disable);
SBIdx = 255; error("An exception occurred!");
CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data;
#if defined(a64)
debug("-----------------------------------------------------------------------------------");
error("Exception: %#llx", Frame->InterruptNumber);
for (size_t i = 0; i < INT_FRAMES_MAX; i++) for (size_t i = 0; i < INT_FRAMES_MAX; i++)
EHIntFrames[i] = Interrupts::InterruptFrames[i]; EHIntFrames[i] = Interrupts::InterruptFrames[i];
PageFaultAddress = CPU::x64::readcr2().PFLA;
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) if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA)
{ {
if (PageFaultAddress) debug("Exception in kernel mode");
{
debug("Exception in kernel mode (ip: %#lx cr2: %#lx (%s))",
Frame->rip, PageFaultAddress, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol");
}
else
{
debug("Exception in kernel mode (ip: %#lx (%s))",
Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol");
}
CPUData *data = GetCurrentCPU();
if (data)
{
if (data->CurrentThread)
{
if (!data->CurrentThread->Security.IsCritical)
{
fixme("Exception in non-critical thread (kernel mode)");
}
}
}
if (TaskManager) if (TaskManager)
TaskManager->Panic(); TaskManager->Panic();
ForceUnlock = true; debug("ePanicSchedStop");
Display->CreateBuffer(0, 0, SBIdx); Display->CreateBuffer(0, 0, SBIdx);
StopAllCores(); debug("e0");
} }
else else
{ {
if (PageFaultAddress) debug("Exception in user mode");
{
debug("Exception in user mode (ip: %#lx cr2: %#lx (%s))",
Frame->rip, PageFaultAddress, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol");
}
else
{
debug("Exception in user mode (ip: %#lx (%s))",
Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol");
}
CPUData *data = GetCurrentCPU(); CPUData *data = GetCurrentCPU();
if (!data) if (!data)
{ {
ForceUnlock = true;
Display->CreateBuffer(0, 0, SBIdx); Display->CreateBuffer(0, 0, SBIdx);
StopAllCores();
EHPrint("\eFF0000Cannot get CPU data! This results in a kernel crash!"); EHPrint("\eFF0000Cannot get CPU data! This results in a kernel crash!");
error("Cannot 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!"); error("This should never happen!");
@ -880,16 +461,7 @@ namespace CrashHandler
else else
{ {
debug("CPU %ld data is valid", data->ID); debug("CPU %ld data is valid", data->ID);
if (data->CurrentThread->Security.IsCritical) if (data->CurrentThread)
{
debug("Critical thread \"%s\"(%d) died", data->CurrentThread->Name, data->CurrentThread->ID);
if (TaskManager)
TaskManager->Panic();
ForceUnlock = true;
Display->CreateBuffer(0, 0, SBIdx);
StopAllCores();
}
else
{ {
debug("Current thread is valid %#lx", data->CurrentThread); debug("Current thread is valid %#lx", data->CurrentThread);
UserModeExceptionHandler(Frame); UserModeExceptionHandler(Frame);
@ -902,20 +474,22 @@ namespace CrashHandler
{ {
SBIdx = 255; SBIdx = 255;
Display->ClearBuffer(SBIdx); Display->ClearBuffer(SBIdx);
debug("e0-1");
Display->SetBufferCursor(SBIdx, 0, 0); Display->SetBufferCursor(SBIdx, 0, 0);
debug("e0-2");
CPU::x64::CR0 cr0 = CPU::x64::readcr0(); CPU::x64::CR0 cr0 = CPU::x64::readcr0();
CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress}; CPU::x64::CR2 cr2 = CPU::x64::readcr2();
CPU::x64::CR3 cr3 = CPU::x64::readcr3(); CPU::x64::CR3 cr3 = CPU::x64::readcr3();
CPU::x64::CR4 cr4 = CPU::x64::readcr4(); CPU::x64::CR4 cr4 = CPU::x64::readcr4();
CPU::x64::CR8 cr8 = CPU::x64::readcr8(); CPU::x64::CR8 cr8 = CPU::x64::readcr8();
CPU::x64::EFER efer; CPU::x64::EFER efer;
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER); efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
uintptr_t ds; uint64_t ds;
asmv("mov %%ds, %0" asmv("mov %%ds, %0"
: "=r"(ds)); : "=r"(ds));
EHPrint("\eFF2525FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n", 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), CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
Frame->ss, Frame->cs, ds); Frame->ss, Frame->cs, ds);
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11); EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
@ -955,24 +529,21 @@ namespace CrashHandler
EHPrint("\nException occurred while handling exception! HALTED!"); EHPrint("\nException occurred while handling exception! HALTED!");
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
Interrupts::RemoveAll();
CPU::Stop(); CPU::Stop();
} }
ExceptionOccurred = true; ExceptionOccurred = true;
Interrupts::RemoveAll();
if (DriverManager)
DriverManager->Panic();
debug("Reading control registers..."); debug("Reading control registers...");
crashdata.Frame = Frame; crashdata.Frame = Frame;
crashdata.cr0 = CPU::x64::readcr0(); crashdata.cr0 = CPU::x64::readcr0();
crashdata.cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress}; crashdata.cr2 = CPU::x64::readcr2();
crashdata.cr3 = CPU::x64::readcr3(); crashdata.cr3 = CPU::x64::readcr3();
crashdata.cr4 = CPU::x64::readcr4(); crashdata.cr4 = CPU::x64::readcr4();
crashdata.cr8 = CPU::x64::readcr8(); crashdata.cr8 = CPU::x64::readcr8();
crashdata.efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER); crashdata.efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
uintptr_t ds; uint64_t ds;
asmv("mov %%ds, %0" asmv("mov %%ds, %0"
: "=r"(ds)); : "=r"(ds));
@ -1018,8 +589,8 @@ namespace CrashHandler
if (TaskManager && cpudata != nullptr) if (TaskManager && cpudata != nullptr)
{ {
crashdata.Process = cpudata->CurrentProcess.load(); crashdata.Process = cpudata->CurrentProcess;
crashdata.Thread = cpudata->CurrentThread.load(); crashdata.Thread = cpudata->CurrentThread;
error("Current Process: %s(%ld)", error("Current Process: %s(%ld)",
cpudata->CurrentProcess->Name, cpudata->CurrentProcess->Name,
@ -1085,10 +656,8 @@ namespace CrashHandler
} }
goto CrashEnd; goto CrashEnd;
#elif defined(a32) #elif defined(__i386__)
goto CrashEnd; #elif defined(__aarch64__)
#elif defined(aa64)
goto CrashEnd;
#endif #endif
CrashEnd: CrashEnd:

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../crashhandler.hpp" #include "../crashhandler.hpp"
#include "chfcts.hpp" #include "chfcts.hpp"
@ -26,10 +9,10 @@
#include <cpu.hpp> #include <cpu.hpp>
#include <io.h> #include <io.h>
#if defined(a64) #if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp" #include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32) #elif defined(__i386__)
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#include "../../kernel.h" #include "../../kernel.h"
@ -94,9 +77,8 @@ static inline int GetLetterFromScanCode(uint8_t ScanCode)
namespace CrashHandler namespace CrashHandler
{ {
CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */ CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(CPU::x64::IRQ1)
{ {
#if defined(a86)
while (inb(0x64) & 0x1) while (inb(0x64) & 0x1)
inb(0x60); inb(0x60);
@ -109,8 +91,6 @@ namespace CrashHandler
outb(0x21, 0xFD); outb(0x21, 0xFD);
outb(0xA1, 0xFF); outb(0xA1, 0xFF);
#endif // defined(a86)
CPU::Interrupts(CPU::Enable); // Just to be sure. CPU::Interrupts(CPU::Enable); // Just to be sure.
} }
@ -122,16 +102,14 @@ namespace CrashHandler
int BackSpaceLimit = 0; int BackSpaceLimit = 0;
static char UserInputBuffer[1024]; static char UserInputBuffer[1024];
#if defined(a64) #if defined(__amd64__)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x64::TrapFrame *Frame) SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
#elif defined(a32) #elif defined(__i386__)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x32::TrapFrame *Frame) SafeFunction void CrashKeyboardDriver::OnInterruptReceived(void *Frame)
#elif defined(aa64) #elif defined(__aarch64__)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame) SafeFunction void CrashKeyboardDriver::OnInterruptReceived(void *Frame)
#endif #endif
{ {
#if defined(a86)
UNUSED(Frame);
uint8_t scanCode = inb(0x60); uint8_t scanCode = inb(0x60);
if (scanCode == KEY_D_TAB || if (scanCode == KEY_D_TAB ||
scanCode == KEY_D_LCTRL || scanCode == KEY_D_LCTRL ||
@ -147,9 +125,6 @@ namespace CrashHandler
case KEY_D_RIGHT: case KEY_D_RIGHT:
case KEY_D_DOWN: case KEY_D_DOWN:
ArrowInput(scanCode); ArrowInput(scanCode);
break;
default:
break;
} }
int key = GetLetterFromScanCode(scanCode); int key = GetLetterFromScanCode(scanCode);
@ -172,23 +147,18 @@ namespace CrashHandler
} }
else else
{ {
append(UserInputBuffer, s_cst(char, key)); append(UserInputBuffer, key);
Display->Print((char)key, SBIdx); Display->Print(key, SBIdx);
BackSpaceLimit++; BackSpaceLimit++;
} }
Display->SetBuffer(SBIdx); // Update as we type. Display->SetBuffer(SBIdx); // Update as we type.
} }
#endif // a64 || a32
} }
SafeFunction void HookKeyboard() SafeFunction void HookKeyboard()
{ {
CrashKeyboardDriver kbd; // We don't want to allocate memory. CrashKeyboardDriver kbd; // We don't want to allocate memory.
#if defined(a86)
asmv("KeyboardHookLoop: nop; jmp KeyboardHookLoop;"); asmv("KeyboardHookLoop: nop; jmp KeyboardHookLoop;");
#elif defined(aa64)
asmv("KeyboardHookLoop: nop; b KeyboardHookLoop;");
#endif
// CPU::Halt(true); // This is an infinite loop. // CPU::Halt(true); // This is an infinite loop.
} }
} }

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../crashhandler.hpp" #include "../crashhandler.hpp"
#include "chfcts.hpp" #include "chfcts.hpp"
@ -24,10 +7,10 @@
#include <smp.hpp> #include <smp.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#if defined(a64) #if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp" #include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32) #elif defined(__i386__)
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#include "../../kernel.h" #include "../../kernel.h"
@ -37,88 +20,55 @@ namespace CrashHandler
struct StackFrame struct StackFrame
{ {
struct StackFrame *rbp; struct StackFrame *rbp;
uintptr_t rip; uint64_t rip;
}; };
SafeFunction void TraceFrames(CRData data, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel) SafeFunction void TraceFrames(CHArchTrapFrame *Frame, int Count)
{ {
if (!Memory::Virtual().Check(data.Frame))
{
EHPrint("Invalid frame pointer: %p\n", data.Frame);
return;
}
if (!Memory::Virtual().Check(SymHandle)) #if defined(__amd64__)
{ struct StackFrame *frames = (struct StackFrame *)Frame->rbp; // (struct StackFrame *)__builtin_frame_address(0);
EHPrint("Invalid symbol handle: %p\n", SymHandle); #elif defined(__i386__)
return; struct StackFrame *frames = (struct StackFrame *)Frame->ebp; // (struct StackFrame *)__builtin_frame_address(0);
} #elif defined(__aarch64__)
bool TriedRetryBP = false;
struct StackFrame *frames = nullptr;
RetryBP:
#if defined(a64)
if (TriedRetryBP == false)
frames = (struct StackFrame *)data.Frame->rbp;
#elif defined(a32)
if (TriedRetryBP == false)
frames = (struct StackFrame *)data.Frame->ebp;
#elif defined(aa64)
#endif #endif
if (!Memory::Virtual().Check((void *)frames)) debug("Stack tracing...");
{
if (TriedRetryBP == false)
{
frames = (struct StackFrame *)Memory::Virtual(data.Process->PageTable).GetPhysical((void *)frames);
TriedRetryBP = true;
goto RetryBP;
}
#if defined(a64)
EHPrint("Invalid rbp pointer: %p\n", data.Frame->rbp);
#elif defined(a32)
EHPrint("Invalid ebp pointer: %p\n", data.Frame->ebp);
#elif defined(aa64)
#endif
return;
}
debug("\nStack tracing... %p %d %p %d", data.Frame, Count, frames, Kernel);
EHPrint("\e7981FC\nStack Trace:\n"); EHPrint("\e7981FC\nStack Trace:\n");
if (!frames || !frames->rip || !frames->rbp) if (!frames || !frames->rip || !frames->rbp)
{ {
#if defined(a64) #if defined(__amd64__)
EHPrint("\e2565CC%p", (void *)data.Frame->rip); EHPrint("\e2565CC%p", (void *)Frame->rip);
#elif defined(a32) #elif defined(__i386__)
EHPrint("\e2565CC%p", (void *)data.Frame->eip); EHPrint("\e2565CC%p", (void *)Frame->eip);
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
EHPrint("\e7925CC-"); EHPrint("\e7925CC-");
#if defined(a64) #if defined(__amd64__)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->rip)); EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
#elif defined(a32) #elif defined(__i386__)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->eip)); EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->eip));
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
EHPrint("\e7981FC <- Exception"); EHPrint("\e7981FC <- Exception");
EHPrint("\eFF0000\n< No stack trace available. >\n"); EHPrint("\eFF0000\n< No stack trace available. >\n");
} }
else else
{ {
#if defined(a64) #if defined(__amd64__)
EHPrint("\e2565CC%p", (void *)data.Frame->rip); EHPrint("\e2565CC%p", (void *)Frame->rip);
EHPrint("\e7925CC-"); EHPrint("\e7925CC-");
if ((data.Frame->rip >= 0xFFFFFFFF80000000 && data.Frame->rip <= (uintptr_t)&_kernel_end) || !Kernel) if (Frame->rip >= 0xFFFFFFFF80000000 && Frame->rip <= (uint64_t)&_kernel_end)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->rip)); EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
else else
EHPrint("Outside Kernel"); EHPrint("Outside Kernel");
#elif defined(a32) #elif defined(__i386__)
EHPrint("\e2565CC%p", (void *)data.Frame->eip); EHPrint("\e2565CC%p", (void *)Frame->eip);
EHPrint("\e7925CC-"); EHPrint("\e7925CC-");
if ((data.Frame->eip >= 0xC0000000 && data.Frame->eip <= (uintptr_t)&_kernel_end) || !Kernel) if (Frame->eip >= 0xC0000000 && Frame->eip <= (uint64_t)&_kernel_end)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->eip)); EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->eip));
else else
EHPrint("Outside Kernel"); EHPrint("Outside Kernel");
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
EHPrint("\e7981FC <- Exception"); EHPrint("\e7981FC <- Exception");
for (int frame = 0; frame < Count; ++frame) for (int frame = 0; frame < Count; ++frame)
@ -127,14 +77,13 @@ namespace CrashHandler
break; break;
EHPrint("\n\e2565CC%p", (void *)frames->rip); EHPrint("\n\e2565CC%p", (void *)frames->rip);
EHPrint("\e7925CC-"); EHPrint("\e7925CC-");
#if defined(a64) #if defined(__amd64__)
if ((frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel) if (frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uint64_t)&_kernel_end)
#elif defined(a32) #elif defined(__i386__)
if ((frames->rip >= 0xC0000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel) if (frames->rip >= 0xC0000000 && frames->rip <= (uint64_t)&_kernel_end)
#elif defined(aa64) #elif defined(__aarch64__)
if ((frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel)
#endif #endif
EHPrint("\e25CCC9%s", SymHandle->GetSymbolFromAddress(frames->rip)); EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress(frames->rip));
else else
EHPrint("\eFF4CA9Outside Kernel"); EHPrint("\eFF4CA9Outside Kernel");
@ -143,6 +92,5 @@ namespace CrashHandler
frames = frames->rbp; frames = frames->rbp;
} }
} }
EHPrint("\n");
} }
} }

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp" #include "../../crashhandler.hpp"
#include "../chfcts.hpp" #include "../chfcts.hpp"
@ -24,10 +7,10 @@
#include <smp.hpp> #include <smp.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#if defined(a64) #if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp" #include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32) #elif defined(__i386__)
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#include "../../../kernel.h" #include "../../../kernel.h"
@ -37,6 +20,5 @@ namespace CrashHandler
SafeFunction void DisplayConsoleScreen(CRData data) SafeFunction void DisplayConsoleScreen(CRData data)
{ {
EHPrint("TODO"); EHPrint("TODO");
UNUSED(data);
} }
} }

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp" #include "../../crashhandler.hpp"
#include "../chfcts.hpp" #include "../chfcts.hpp"
@ -24,10 +7,10 @@
#include <smp.hpp> #include <smp.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#if defined(a64) #if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp" #include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32) #elif defined(__i386__)
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#include "../../../kernel.h" #include "../../../kernel.h"
@ -45,49 +28,49 @@ namespace CrashHandler
data.Thread->Name, data.Thread->Name,
data.Thread->ID); data.Thread->ID);
EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", data.ID); EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", data.ID);
uintptr_t ds; #if defined(__amd64__)
#if defined(a64)
CPUData *cpu = (CPUData *)data.CPUData; CPUData *cpu = (CPUData *)data.CPUData;
if (cpu) if (cpu)
{ {
EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu); EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu);
EHPrint("Syscalls Stack: %#lx, TempStack: %#lx\n", cpu->SystemCallStack, cpu->TempStack); EHPrint("Syscalls Stack: %#lx\n", cpu->SystemCallStack);
EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", cpu->Stack, cpu->ID, cpu->ErrorCode); 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("Is Active: %s\n", cpu->IsActive ? "true" : "false");
EHPrint("Current Process: %#lx, Current Thread: %#lx\n", cpu->CurrentProcess, cpu->CurrentThread); EHPrint("Current Process: %#lx\n", cpu->CurrentProcess);
EHPrint("Current Thread: %#lx\n", cpu->CurrentThread);
EHPrint("Arch Specific Data: %#lx\n", cpu->Data); EHPrint("Arch Specific Data: %#lx\n", cpu->Data);
EHPrint("Checksum: 0x%X\n", cpu->Checksum); EHPrint("Checksum: 0x%X\n", cpu->Checksum);
} }
uint64_t ds;
asmv("mov %%ds, %0" asmv("mov %%ds, %0"
: "=r"(ds)); : "=r"(ds));
#elif defined(a32) #elif defined(__i386__)
uint32_t ds;
asmv("mov %%ds, %0" asmv("mov %%ds, %0"
: "=r"(ds)); : "=r"(ds));
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#if defined(a64)
EHPrint("\e7981FCFS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n", 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), CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
data.Frame->ss, data.Frame->cs, ds); 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("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("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("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("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); 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(a32) #elif defined(__i386__)
EHPrint("\e7981FCFS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE),
data.Frame->ss, data.Frame->cs, ds);
EHPrint("EAX=%#llx EBX=%#llx ECX=%#llx EDX=%#llx\n", data.Frame->eax, data.Frame->ebx, data.Frame->ecx, data.Frame->edx); 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("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); 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(aa64) #elif defined(__aarch64__)
#endif #endif
#if defined(a86)
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("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("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);
@ -109,15 +92,16 @@ namespace CrashHandler
data.cr4.PCE ? "True " : "False", data.cr4.UMIP ? "True " : "False", data.cr4.OSFXSR ? "True " : "False", data.cr4.OSXMMEXCPT ? "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.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", data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False",
#if defined(a64) #if defined(__amd64__)
data.cr4.Reserved0, data.cr4.Reserved1, data.cr4.Reserved2); data.cr4.Reserved0, data.cr4.Reserved1, data.cr4.Reserved2);
#elif defined(a32) #elif defined(__i386__)
data.cr4.Reserved0, data.cr4.Reserved1, 0); data.cr4.Reserved0, data.cr4.Reserved1, 0);
#elif defined(__aarch64__)
#endif #endif
EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL);
#endif // a64 || a32
#if defined(a64) 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", 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.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.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False",
@ -125,7 +109,7 @@ namespace CrashHandler
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.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.ID ? "True " : "False", data.Frame->rflags.AlwaysOne,
data.Frame->rflags.Reserved0, data.Frame->rflags.Reserved1, data.Frame->rflags.Reserved2, data.Frame->rflags.Reserved3); data.Frame->rflags.Reserved0, data.Frame->rflags.Reserved1, data.Frame->rflags.Reserved2, data.Frame->rflags.Reserved3);
#elif defined(a32) #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", 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.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.SF ? "True " : "False", data.Frame->eflags.TF ? "True " : "False", data.Frame->eflags.IF ? "True " : "False", data.Frame->eflags.DF ? "True " : "False",
@ -133,10 +117,9 @@ namespace CrashHandler
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.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.ID ? "True " : "False", data.Frame->eflags.AlwaysOne,
data.Frame->eflags.Reserved0, data.Frame->eflags.Reserved1, data.Frame->eflags.Reserved2); data.Frame->eflags.Reserved0, data.Frame->eflags.Reserved1, data.Frame->eflags.Reserved2);
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#if defined(a86)
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", 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.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.LocalDR2 ? "True " : "False", data.dr7.GlobalDR2 ? "True " : "False", data.dr7.LocalDR3 ? "True " : "False", data.dr7.GlobalDR3 ? "True " : "False",
@ -148,111 +131,110 @@ namespace CrashHandler
data.efer.SCE ? "True " : "False", data.efer.LME ? "True " : "False", data.efer.LMA ? "True " : "False", data.efer.NXE ? "True " : "False", 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.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); data.efer.Reserved0, data.efer.Reserved1, data.efer.Reserved2);
#endif
switch (data.Frame->InterruptNumber) switch (data.Frame->InterruptNumber)
{ {
case CPU::x86::DivideByZero: case CPU::x64::DivideByZero:
{ {
DivideByZeroExceptionHandler(data.Frame); DivideByZeroExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::Debug: case CPU::x64::Debug:
{ {
DebugExceptionHandler(data.Frame); DebugExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::NonMaskableInterrupt: case CPU::x64::NonMaskableInterrupt:
{ {
NonMaskableInterruptExceptionHandler(data.Frame); NonMaskableInterruptExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::Breakpoint: case CPU::x64::Breakpoint:
{ {
BreakpointExceptionHandler(data.Frame); BreakpointExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::Overflow: case CPU::x64::Overflow:
{ {
OverflowExceptionHandler(data.Frame); OverflowExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::BoundRange: case CPU::x64::BoundRange:
{ {
BoundRangeExceptionHandler(data.Frame); BoundRangeExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::InvalidOpcode: case CPU::x64::InvalidOpcode:
{ {
InvalidOpcodeExceptionHandler(data.Frame); InvalidOpcodeExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::DeviceNotAvailable: case CPU::x64::DeviceNotAvailable:
{ {
DeviceNotAvailableExceptionHandler(data.Frame); DeviceNotAvailableExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::DoubleFault: case CPU::x64::DoubleFault:
{ {
DoubleFaultExceptionHandler(data.Frame); DoubleFaultExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::CoprocessorSegmentOverrun: case CPU::x64::CoprocessorSegmentOverrun:
{ {
CoprocessorSegmentOverrunExceptionHandler(data.Frame); CoprocessorSegmentOverrunExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::InvalidTSS: case CPU::x64::InvalidTSS:
{ {
InvalidTSSExceptionHandler(data.Frame); InvalidTSSExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::SegmentNotPresent: case CPU::x64::SegmentNotPresent:
{ {
SegmentNotPresentExceptionHandler(data.Frame); SegmentNotPresentExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::StackSegmentFault: case CPU::x64::StackSegmentFault:
{ {
StackFaultExceptionHandler(data.Frame); StackFaultExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::GeneralProtectionFault: case CPU::x64::GeneralProtectionFault:
{ {
GeneralProtectionExceptionHandler(data.Frame); GeneralProtectionExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::PageFault: case CPU::x64::PageFault:
{ {
PageFaultExceptionHandler(data.Frame); PageFaultExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::x87FloatingPoint: case CPU::x64::x87FloatingPoint:
{ {
x87FloatingPointExceptionHandler(data.Frame); x87FloatingPointExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::AlignmentCheck: case CPU::x64::AlignmentCheck:
{ {
AlignmentCheckExceptionHandler(data.Frame); AlignmentCheckExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::MachineCheck: case CPU::x64::MachineCheck:
{ {
MachineCheckExceptionHandler(data.Frame); MachineCheckExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::SIMDFloatingPoint: case CPU::x64::SIMDFloatingPoint:
{ {
SIMDFloatingPointExceptionHandler(data.Frame); SIMDFloatingPointExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::Virtualization: case CPU::x64::Virtualization:
{ {
VirtualizationExceptionHandler(data.Frame); VirtualizationExceptionHandler(data.Frame);
break; break;
} }
case CPU::x86::Security: case CPU::x64::Security:
{ {
SecurityExceptionHandler(data.Frame); SecurityExceptionHandler(data.Frame);
break; break;

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp" #include "../../crashhandler.hpp"
#include "../chfcts.hpp" #include "../chfcts.hpp"
@ -24,10 +7,10 @@
#include <smp.hpp> #include <smp.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#if defined(a64) #if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp" #include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32) #elif defined(__i386__)
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#include "../../../kernel.h" #include "../../../kernel.h"
@ -61,67 +44,67 @@ namespace CrashHandler
switch (Frame->InterruptNumber) switch (Frame->InterruptNumber)
{ {
case CPU::x86::DivideByZero: case CPU::x64::DivideByZero:
{ {
EHPrint("Exception: Divide By Zero\n"); EHPrint("Exception: Divide By Zero\n");
EHPrint("The processor attempted to divide a number by zero.\n"); EHPrint("The processor attempted to divide a number by zero.\n");
break; break;
} }
case CPU::x86::Debug: case CPU::x64::Debug:
{ {
EHPrint("Exception: Debug\n"); EHPrint("Exception: Debug\n");
EHPrint("A debug exception has occurred.\n"); EHPrint("A debug exception has occurred.\n");
break; break;
} }
case CPU::x86::NonMaskableInterrupt: case CPU::x64::NonMaskableInterrupt:
{ {
EHPrint("Exception: Non-Maskable Interrupt\n"); EHPrint("Exception: Non-Maskable Interrupt\n");
EHPrint("A non-maskable interrupt was received.\n"); EHPrint("A non-maskable interrupt was received.\n");
break; break;
} }
case CPU::x86::Breakpoint: case CPU::x64::Breakpoint:
{ {
EHPrint("Exception: Breakpoint\n"); EHPrint("Exception: Breakpoint\n");
EHPrint("The processor encountered a breakpoint.\n"); EHPrint("The processor encountered a breakpoint.\n");
break; break;
} }
case CPU::x86::Overflow: case CPU::x64::Overflow:
{ {
EHPrint("Exception: Overflow\n"); EHPrint("Exception: Overflow\n");
EHPrint("The processor attempted to add a number to a number that was too large.\n"); EHPrint("The processor attempted to add a number to a number that was too large.\n");
break; break;
} }
case CPU::x86::BoundRange: case CPU::x64::BoundRange:
{ {
EHPrint("Exception: Bound Range\n"); EHPrint("Exception: Bound Range\n");
EHPrint("The processor attempted to access an array element that is out of bounds.\n"); EHPrint("The processor attempted to access an array element that is out of bounds.\n");
break; break;
} }
case CPU::x86::InvalidOpcode: case CPU::x64::InvalidOpcode:
{ {
EHPrint("Exception: Invalid Opcode\n"); EHPrint("Exception: Invalid Opcode\n");
EHPrint("The processor attempted to execute an invalid opcode.\n"); EHPrint("The processor attempted to execute an invalid opcode.\n");
break; break;
} }
case CPU::x86::DeviceNotAvailable: case CPU::x64::DeviceNotAvailable:
{ {
EHPrint("Exception: Device Not Available\n"); EHPrint("Exception: Device Not Available\n");
EHPrint("The processor attempted to use a device that is not available.\n"); EHPrint("The processor attempted to use a device that is not available.\n");
break; break;
} }
case CPU::x86::DoubleFault: case CPU::x64::DoubleFault:
{ {
EHPrint("Exception: Double Fault\n"); EHPrint("Exception: Double Fault\n");
EHPrint("The processor encountered a double fault.\n"); EHPrint("The processor encountered a double fault.\n");
break; break;
} }
case CPU::x86::CoprocessorSegmentOverrun: case CPU::x64::CoprocessorSegmentOverrun:
{ {
EHPrint("Exception: Coprocessor Segment Overrun\n"); EHPrint("Exception: Coprocessor Segment Overrun\n");
EHPrint("The processor attempted to access a segment that is not available.\n"); EHPrint("The processor attempted to access a segment that is not available.\n");
break; break;
} }
case CPU::x86::InvalidTSS: case CPU::x64::InvalidTSS:
{ {
EHPrint("Exception: Invalid TSS\n"); EHPrint("Exception: Invalid TSS\n");
EHPrint("The processor attempted to access a task state segment that is not available or valid.\n"); EHPrint("The processor attempted to access a task state segment that is not available or valid.\n");
@ -158,17 +141,10 @@ namespace CrashHandler
EHPrint(" %ld\n", SelCode.Idx); EHPrint(" %ld\n", SelCode.Idx);
break; break;
} }
default:
{
EHPrint(" ? \n");
EHPrint(" ? \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
} }
break; break;
} }
case CPU::x86::SegmentNotPresent: case CPU::x64::SegmentNotPresent:
{ {
EHPrint("Exception: Segment Not Present\n"); EHPrint("Exception: Segment Not Present\n");
EHPrint("The processor attempted to access a segment that is not present.\n"); EHPrint("The processor attempted to access a segment that is not present.\n");
@ -205,17 +181,10 @@ namespace CrashHandler
EHPrint(" %ld\n", SelCode.Idx); EHPrint(" %ld\n", SelCode.Idx);
break; break;
} }
default:
{
EHPrint(" ? \n");
EHPrint(" ? \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
} }
break; break;
} }
case CPU::x86::StackSegmentFault: case CPU::x64::StackSegmentFault:
{ {
EHPrint("Exception: Stack Segment Fault\n"); EHPrint("Exception: Stack Segment Fault\n");
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode}; CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
@ -251,17 +220,10 @@ namespace CrashHandler
EHPrint(" %ld\n", SelCode.Idx); EHPrint(" %ld\n", SelCode.Idx);
break; break;
} }
default:
{
EHPrint(" ? \n");
EHPrint(" ? \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
} }
break; break;
} }
case CPU::x86::GeneralProtectionFault: case CPU::x64::GeneralProtectionFault:
{ {
EHPrint("Exception: General Protection Fault\n"); EHPrint("Exception: General Protection Fault\n");
EHPrint("Kernel performed an illegal operation.\n"); EHPrint("Kernel performed an illegal operation.\n");
@ -298,27 +260,20 @@ namespace CrashHandler
EHPrint(" %ld\n", SelCode.Idx); EHPrint(" %ld\n", SelCode.Idx);
break; break;
} }
default:
{
EHPrint(" ? \n");
EHPrint(" ? \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
} }
break; break;
} }
case CPU::x86::PageFault: case CPU::x64::PageFault:
{ {
EHPrint("Exception: Page Fault\n"); EHPrint("Exception: Page Fault\n");
EHPrint("The processor attempted to access a page that is not present.\n"); EHPrint("The processor attempted to access a page that is not present.\n");
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
#if defined(a64) #if defined(__amd64__)
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->rip); EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", CPU::x64::readcr2().PFLA, Frame->rip);
#elif defined(a32) #elif defined(__i386__)
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->eip); EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", CPU::x64::readcr2().PFLA, Frame->eip);
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
EHPrint("Page: %s\eFAFAFA\n", params.P ? "\e058C19Present" : "\eE85230Not Present"); EHPrint("Page: %s\eFAFAFA\n", params.P ? "\e058C19Present" : "\eE85230Not Present");
EHPrint("Write Operation: \e8888FF%s\eFAFAFA\n", params.W ? "Read-Only" : "Read-Write"); EHPrint("Write Operation: \e8888FF%s\eFAFAFA\n", params.W ? "Read-Only" : "Read-Write");
@ -336,37 +291,37 @@ namespace CrashHandler
EHPrint("\eFAFAFA"); EHPrint("\eFAFAFA");
break; break;
} }
case CPU::x86::x87FloatingPoint: case CPU::x64::x87FloatingPoint:
{ {
EHPrint("Exception: x87 Floating Point\n"); EHPrint("Exception: x87 Floating Point\n");
EHPrint("The x87 FPU generated an error.\n"); EHPrint("The x87 FPU generated an error.\n");
break; break;
} }
case CPU::x86::AlignmentCheck: case CPU::x64::AlignmentCheck:
{ {
EHPrint("Exception: Alignment Check\n"); EHPrint("Exception: Alignment Check\n");
EHPrint("The CPU detected an unaligned memory access.\n"); EHPrint("The CPU detected an unaligned memory access.\n");
break; break;
} }
case CPU::x86::MachineCheck: case CPU::x64::MachineCheck:
{ {
EHPrint("Exception: Machine Check\n"); EHPrint("Exception: Machine Check\n");
EHPrint("The CPU detected a hardware error.\n"); EHPrint("The CPU detected a hardware error.\n");
break; break;
} }
case CPU::x86::SIMDFloatingPoint: case CPU::x64::SIMDFloatingPoint:
{ {
EHPrint("Exception: SIMD Floating Point\n"); EHPrint("Exception: SIMD Floating Point\n");
EHPrint("The CPU detected an error in the SIMD unit.\n"); EHPrint("The CPU detected an error in the SIMD unit.\n");
break; break;
} }
case CPU::x86::Virtualization: case CPU::x64::Virtualization:
{ {
EHPrint("Exception: Virtualization\n"); EHPrint("Exception: Virtualization\n");
EHPrint("The CPU detected a virtualization error.\n"); EHPrint("The CPU detected a virtualization error.\n");
break; break;
} }
case CPU::x86::Security: case CPU::x64::Security:
{ {
EHPrint("Exception: Security\n"); EHPrint("Exception: Security\n");
EHPrint("The CPU detected a security violation.\n"); EHPrint("The CPU detected a security violation.\n");
@ -380,11 +335,11 @@ namespace CrashHandler
} }
} }
#if defined(a64) #if defined(__amd64__)
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->rip); EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->rip);
#elif defined(a32) #elif defined(__i386__)
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->eip); EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->eip);
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
} }
} }

View File

@ -1,34 +1,17 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp" #include "../../crashhandler.hpp"
#include "../chfcts.hpp" #include "../chfcts.hpp"
#include <ints.hpp> #include <interrupts.hpp>
#include <display.hpp> #include <display.hpp>
#include <printf.h> #include <printf.h>
#include <debug.h> #include <debug.h>
#include <smp.hpp> #include <smp.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#if defined(a64) #if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp" #include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32) #elif defined(__i386__)
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#include "../../../kernel.h" #include "../../../kernel.h"
@ -37,19 +20,10 @@ namespace CrashHandler
{ {
SafeFunction void DisplayStackFrameScreen(CRData data) SafeFunction void DisplayStackFrameScreen(CRData data)
{ {
EHPrint("\eFAFAFATracing 10 frames..."); EHPrint("\eFAFAFATracing 40 frames...\n");
TraceFrames(data, 10, KernelSymbolTable, true); TraceFrames(data.Frame, 40);
if (data.Process) EHPrint("\n\n\eFAFAFATracing interrupt frames...\n");
{ for (uint64_t i = 0; i < 8; i++)
EHPrint("\n\eFAFAFATracing 10 process frames...");
SymbolResolver::Symbols *sh = data.Process->ELFSymbolTable;
if (!sh)
EHPrint("\n\eFF0000< No symbol table available. >\n");
else
TraceFrames(data, 10, sh, false);
}
EHPrint("\n\eFAFAFATracing interrupt frames...");
for (short i = 0; i < 8; i++)
{ {
if (EHIntFrames[i]) if (EHIntFrames[i])
{ {
@ -57,43 +31,16 @@ namespace CrashHandler
continue; continue;
EHPrint("\n\e2565CC%p", EHIntFrames[i]); EHPrint("\n\e2565CC%p", EHIntFrames[i]);
EHPrint("\e7925CC-"); EHPrint("\e7925CC-");
#if defined(a64) #if defined(__amd64__)
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) if ((uint64_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(a32) #elif defined(__i386__)
if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end) if ((uint64_t)EHIntFrames[i] >= 0xC0000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(aa64) #elif defined(__aarch64__)
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
#endif #endif
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i])); EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uint64_t)EHIntFrames[i]));
else else
EHPrint("\eFF4CA9Outside Kernel"); EHPrint("\eFF4CA9Outside Kernel");
} }
} }
if (data.Process && data.Thread)
{
EHPrint("\n\n\eFAFAFATracing thread instruction pointer history...");
SymbolResolver::Symbols *sh = data.Process->ELFSymbolTable;
if (!sh)
EHPrint("\n\eFFA500Warning: No symbol table available.");
int SameItr = 0;
uintptr_t LastRIP = 0;
for (size_t i = 0; i < sizeof(data.Thread->IPHistory) / sizeof(data.Thread->IPHistory[0]); i++)
{
if (data.Thread->IPHistory[i] == LastRIP)
{
SameItr++;
if (SameItr > 2)
continue;
}
else
SameItr = 0;
LastRIP = data.Thread->IPHistory[i];
if (!sh)
EHPrint("\n\eCCCCCC%d: \e2565CC%p", i, data.Thread->IPHistory[i]);
else
EHPrint("\n\eCCCCCC%d: \e2565CC%p\e7925CC-\e25CCC9%s", i, data.Thread->IPHistory[i], sh->GetSymbolFromAddress(data.Thread->IPHistory[i]));
}
EHPrint("\n\e7925CCNote: \e2565CCSame instruction pointers are not shown more than 3 times.\n");
}
} }
} }

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp" #include "../../crashhandler.hpp"
#include "../chfcts.hpp" #include "../chfcts.hpp"
@ -24,10 +7,10 @@
#include <smp.hpp> #include <smp.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#if defined(a64) #if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp" #include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32) #elif defined(__i386__)
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#include "../../../kernel.h" #include "../../../kernel.h"
@ -56,16 +39,16 @@ namespace CrashHandler
"Terminated", // Terminated "Terminated", // Terminated
}; };
std::vector<Tasking::PCB *> Plist = TaskManager->GetProcessList(); Vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
if (TaskManager) if (TaskManager)
{ {
if (data.Thread) if (data.Thread)
#if defined(a64) #if defined(__amd64__)
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip); EHPrint("\eFAFAFACrash occured in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip);
#elif defined(a32) #elif defined(__i386__)
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->eip); EHPrint("\eFAFAFACrash occured in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->eip);
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
EHPrint("\eFAFAFAProcess list (%ld):\n", Plist.size()); EHPrint("\eFAFAFAProcess list (%ld):\n", Plist.size());

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../crashhandler.hpp" #include "../crashhandler.hpp"
#include "chfcts.hpp" #include "chfcts.hpp"
@ -24,10 +7,10 @@
#include <smp.hpp> #include <smp.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#if defined(a64) #if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp" #include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32) #elif defined(__i386__)
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#include "../../kernel.h" #include "../../kernel.h"
@ -51,9 +34,8 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
CPUData *CurCPU = GetCurrentCPU(); CPUData *CurCPU = GetCurrentCPU();
{ {
#if defined(a64)
CPU::x64::CR0 cr0 = CPU::x64::readcr0(); CPU::x64::CR0 cr0 = CPU::x64::readcr0();
CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = CrashHandler::PageFaultAddress}; CPU::x64::CR2 cr2 = CPU::x64::readcr2();
CPU::x64::CR3 cr3 = CPU::x64::readcr3(); CPU::x64::CR3 cr3 = CPU::x64::readcr3();
CPU::x64::CR4 cr4 = CPU::x64::readcr4(); CPU::x64::CR4 cr4 = CPU::x64::readcr4();
CPU::x64::CR8 cr8 = CPU::x64::readcr8(); CPU::x64::CR8 cr8 = CPU::x64::readcr8();
@ -61,45 +43,31 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER); efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
error("Technical Informations on CPU %lld:", CurCPU->ID); error("Technical Informations on CPU %lld:", CurCPU->ID);
uintptr_t ds; #if defined(__amd64__)
uint64_t ds;
asmv("mov %%ds, %0" asmv("mov %%ds, %0"
: "=r"(ds)); : "=r"(ds));
#elif defined(a32) #elif defined(__i386__)
CPU::x32::CR0 cr0 = CPU::x32::readcr0(); uint32_t ds;
CPU::x32::CR2 cr2 = CPU::x32::CR2{.PFLA = CrashHandler::PageFaultAddress};
CPU::x32::CR3 cr3 = CPU::x32::readcr3();
CPU::x32::CR4 cr4 = CPU::x32::readcr4();
CPU::x32::CR8 cr8 = CPU::x32::readcr8();
CPU::x32::EFER efer;
efer.raw = CPU::x32::rdmsr(CPU::x32::MSR_EFER);
error("Technical Informations on CPU %lld:", CurCPU->ID);
uintptr_t ds;
asmv("mov %%ds, %0" asmv("mov %%ds, %0"
: "=r"(ds)); : "=r"(ds));
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#if defined(a64)
error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx", 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), CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
Frame->ss, Frame->cs, ds); 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("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("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("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("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); error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
#elif defined(a32) #elif defined(__i386__)
error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx",
CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE),
Frame->ss, Frame->cs, ds);
error("EAX=%#llx EBX=%#llx ECX=%#llx EDX=%#llx", Frame->eax, Frame->ebx, Frame->ecx, Frame->edx); 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("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); error("EIP=%#llx EFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#if defined(a86)
error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw); 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", 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",
@ -113,9 +81,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
error("CR3: PWT:%s PCD:%s PDBR:%#llx", error("CR3: PWT:%s PCD:%s PDBR:%#llx",
cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR); cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR);
#endif // defined(a86)
#if defined(a64)
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", 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.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.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False",
@ -123,21 +89,10 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "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.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False",
cr4.Reserved0, cr4.Reserved1, cr4.Reserved2); cr4.Reserved0, cr4.Reserved1, cr4.Reserved2);
#elif defined(a32)
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",
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);
#endif
#if defined(a86)
error("CR8: TPL:%d", cr8.TPL); error("CR8: TPL:%d", cr8.TPL);
#endif // defined(a86)
#if defined(a64) #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", 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.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.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False",
@ -145,7 +100,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "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.ID ? "True " : "False", Frame->rflags.AlwaysOne,
Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3); Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3);
#elif defined(a32) #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", 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.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.SF ? "True " : "False", Frame->eflags.TF ? "True " : "False", Frame->eflags.IF ? "True " : "False", Frame->eflags.DF ? "True " : "False",
@ -153,88 +108,81 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
Frame->eflags.VM ? "True " : "False", Frame->eflags.AC ? "True " : "False", Frame->eflags.VIF ? "True " : "False", Frame->eflags.VIP ? "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.ID ? "True " : "False", Frame->eflags.AlwaysOne,
Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2); Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2);
#elif defined(aa64) #elif defined(__aarch64__)
#endif #endif
#if defined(a86)
error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x", 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.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.SVME ? "True " : "False", efer.LMSLE ? "True " : "False", efer.FFXSR ? "True " : "False", efer.TCE ? "True " : "False",
efer.Reserved0, efer.Reserved1, efer.Reserved2); efer.Reserved0, efer.Reserved1, efer.Reserved2);
#endif // a64 || a32
} }
switch (Frame->InterruptNumber) switch (Frame->InterruptNumber)
{ {
case CPU::x86::DivideByZero: case CPU::x64::DivideByZero:
{ {
break; break;
} }
case CPU::x86::Debug: case CPU::x64::Debug:
{ {
break; break;
} }
case CPU::x86::NonMaskableInterrupt: case CPU::x64::NonMaskableInterrupt:
{ {
break; break;
} }
case CPU::x86::Breakpoint: case CPU::x64::Breakpoint:
{ {
break; break;
} }
case CPU::x86::Overflow: case CPU::x64::Overflow:
{ {
break; break;
} }
case CPU::x86::BoundRange: case CPU::x64::BoundRange:
{ {
break; break;
} }
case CPU::x86::InvalidOpcode: case CPU::x64::InvalidOpcode:
{ {
break; break;
} }
case CPU::x86::DeviceNotAvailable: case CPU::x64::DeviceNotAvailable:
{ {
break; break;
} }
case CPU::x86::DoubleFault: case CPU::x64::DoubleFault:
{ {
break; break;
} }
case CPU::x86::CoprocessorSegmentOverrun: case CPU::x64::CoprocessorSegmentOverrun:
{ {
break; break;
} }
case CPU::x86::InvalidTSS: case CPU::x64::InvalidTSS:
{ {
break; break;
} }
case CPU::x86::SegmentNotPresent: case CPU::x64::SegmentNotPresent:
{ {
break; break;
} }
case CPU::x86::StackSegmentFault: case CPU::x64::StackSegmentFault:
{ {
break; break;
} }
case CPU::x86::GeneralProtectionFault: case CPU::x64::GeneralProtectionFault:
{ {
break; break;
} }
case CPU::x86::PageFault: case CPU::x64::PageFault:
{ {
uintptr_t CheckPageFaultAddress = 0;
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
#if defined(a64) #if defined(__amd64__)
CheckPageFaultAddress = CrashHandler::PageFaultAddress; error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->rip);
if (CheckPageFaultAddress == 0) #elif defined(__i386__)
CheckPageFaultAddress = Frame->rip; error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->eip);
#elif defined(__aarch64__)
error("An exception occurred at %#lx by %#lx", CrashHandler::PageFaultAddress, Frame->rip);
#elif defined(a32)
error("An exception occurred at %#lx by %#lx", CrashHandler::PageFaultAddress, Frame->eip);
#elif defined(aa64)
#endif #endif
error("Page: %s", params.P ? "Present" : "Not Present"); error("Page: %s", params.P ? "Present" : "Not Present");
error("Write Operation: %s", params.W ? "Read-Only" : "Read-Write"); error("Write Operation: %s", params.W ? "Read-Only" : "Read-Write");
@ -253,21 +201,21 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
if (CurCPU) if (CurCPU)
{ {
Memory::Virtual vma = Memory::Virtual(CurCPU->CurrentProcess->PageTable); Memory::Virtual vma = Memory::Virtual(CurCPU->CurrentProcess->PageTable);
bool PageAvailable = vma.Check((void *)CheckPageFaultAddress); bool PageAvailable = vma.Check((void *)CPU::x64::readcr2().PFLA);
debug("Page available (Check(...)): %s. %s", debug("Page available (Check(...)): %s. %s",
PageAvailable ? "Yes" : "No", PageAvailable ? "Yes" : "No",
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result."); (params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
if (PageAvailable) if (PageAvailable)
{ {
bool Present = vma.Check((void *)CheckPageFaultAddress); bool Present = vma.Check((void *)CPU::x64::readcr2().PFLA);
bool ReadWrite = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW); bool ReadWrite = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::RW);
bool User = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US); bool User = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::US);
bool WriteThrough = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT); bool WriteThrough = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PWT);
bool CacheDisabled = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD); bool CacheDisabled = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PCD);
bool Accessed = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A); bool Accessed = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::A);
bool Dirty = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D); bool Dirty = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::D);
bool Global = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G); bool Global = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::G);
/* ... */ /* ... */
debug("Page available: %s", Present ? "Yes" : "No"); debug("Page available: %s", Present ? "Yes" : "No");
@ -278,80 +226,12 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
debug("Page accessed: %s", Accessed ? "Yes" : "No"); debug("Page accessed: %s", Accessed ? "Yes" : "No");
debug("Page dirty: %s", Dirty ? "Yes" : "No"); debug("Page dirty: %s", Dirty ? "Yes" : "No");
debug("Page global: %s", Global ? "Yes" : "No"); debug("Page global: %s", Global ? "Yes" : "No");
if (Present)
{
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
Memory::Virtual::PageMapIndexer Index = Memory::Virtual::PageMapIndexer((uintptr_t)CheckPageFaultLinearAddress);
debug("Index for %#lx is PML:%d PDPTE:%d PDE:%d PTE:%d",
CheckPageFaultLinearAddress,
Index.PMLIndex,
Index.PDPTEIndex,
Index.PDEIndex,
Index.PTEIndex);
Memory::PageMapLevel4 PML4 = CurCPU->CurrentProcess->PageTable->Entries[Index.PMLIndex];
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
Index.PMLIndex, 0, 0, 0,
PML4.Present ? "1" : "0",
PML4.ReadWrite ? "1" : "0",
PML4.UserSupervisor ? "1" : "0",
PML4.WriteThrough ? "1" : "0",
PML4.CacheDisable ? "1" : "0",
PML4.Accessed ? "1" : "0",
PML4.ExecuteDisable ? "1" : "0",
PML4.GetAddress() << 12);
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
Index.PMLIndex, Index.PDPTEIndex, 0, 0,
PDPTE->Entries[Index.PDPTEIndex].Present ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].ReadWrite ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].UserSupervisor ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].WriteThrough ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].CacheDisable ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].Accessed ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].ExecuteDisable ? "1" : "0",
PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, 0,
PDE->Entries[Index.PDEIndex].Present ? "1" : "0",
PDE->Entries[Index.PDEIndex].ReadWrite ? "1" : "0",
PDE->Entries[Index.PDEIndex].UserSupervisor ? "1" : "0",
PDE->Entries[Index.PDEIndex].WriteThrough ? "1" : "0",
PDE->Entries[Index.PDEIndex].CacheDisable ? "1" : "0",
PDE->Entries[Index.PDEIndex].Accessed ? "1" : "0",
PDE->Entries[Index.PDEIndex].ExecuteDisable ? "1" : "0",
PDE->Entries[Index.PDEIndex].GetAddress() << 12);
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:%#lx",
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, Index.PTEIndex,
PTE->Entries[Index.PTEIndex].Present ? "1" : "0",
PTE->Entries[Index.PTEIndex].ReadWrite ? "1" : "0",
PTE->Entries[Index.PTEIndex].UserSupervisor ? "1" : "0",
PTE->Entries[Index.PTEIndex].WriteThrough ? "1" : "0",
PTE->Entries[Index.PTEIndex].CacheDisable ? "1" : "0",
PTE->Entries[Index.PTEIndex].Accessed ? "1" : "0",
PTE->Entries[Index.PTEIndex].Dirty ? "1" : "0",
PTE->Entries[Index.PTEIndex].PageAttributeTable ? "1" : "0",
PTE->Entries[Index.PTEIndex].Global ? "1" : "0",
PTE->Entries[Index.PTEIndex].ProtectionKey,
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
}
} }
} }
#endif #endif
if (CurCPU) if (CurCPU)
if (CurCPU->CurrentThread->Stack->Expand(CrashHandler::PageFaultAddress)) if (CurCPU->CurrentThread->Stack->Expand(CPU::x64::readcr2().raw))
{ {
debug("Stack expanded"); debug("Stack expanded");
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready; TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready;
@ -359,27 +239,27 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
} }
break; break;
} }
case CPU::x86::x87FloatingPoint: case CPU::x64::x87FloatingPoint:
{ {
break; break;
} }
case CPU::x86::AlignmentCheck: case CPU::x64::AlignmentCheck:
{ {
break; break;
} }
case CPU::x86::MachineCheck: case CPU::x64::MachineCheck:
{ {
break; break;
} }
case CPU::x86::SIMDFloatingPoint: case CPU::x64::SIMDFloatingPoint:
{ {
break; break;
} }
case CPU::x86::Virtualization: case CPU::x64::Virtualization:
{ {
break; break;
} }
case CPU::x86::Security: case CPU::x64::Security:
{ {
break; break;
} }
@ -390,7 +270,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
} }
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated; TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated;
__sync; __sync_synchronize();
error("End of report."); error("End of report.");
CPU::Interrupts(CPU::Enable); CPU::Interrupts(CPU::Enable);
debug("Interrupts enabled back."); debug("Interrupts enabled back.");

View File

@ -1,30 +1,13 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__ #ifndef __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__
#define __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__ #define __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__
#include <types.h> #include <types.h>
#include <ints.hpp> #include <interrupts.hpp>
#include <task.hpp> #include <task.hpp>
#include <cpu.hpp> #include <cpu.hpp>
#if defined(a64) #if defined(__amd64__)
typedef struct CPU::x64::TrapFrame CHArchTrapFrame; typedef struct CPU::x64::TrapFrame CHArchTrapFrame;
struct CRData struct CRData
@ -37,7 +20,7 @@ struct CRData
CPU::x64::CR4 cr4; CPU::x64::CR4 cr4;
CPU::x64::CR8 cr8; CPU::x64::CR8 cr8;
CPU::x64::EFER efer; CPU::x64::EFER efer;
uintptr_t dr0, dr1, dr2, dr3, dr6; uint64_t dr0, dr1, dr2, dr3, dr6;
CPU::x64::DR7 dr7; CPU::x64::DR7 dr7;
long ID; long ID;
@ -46,7 +29,7 @@ struct CRData
Tasking::TCB *Thread; Tasking::TCB *Thread;
}; };
#elif defined(a32) #elif defined(__i386__)
typedef struct CPU::x32::TrapFrame CHArchTrapFrame; typedef struct CPU::x32::TrapFrame CHArchTrapFrame;
struct CRData struct CRData
@ -59,24 +42,15 @@ struct CRData
CPU::x32::CR4 cr4; CPU::x32::CR4 cr4;
CPU::x32::CR8 cr8; CPU::x32::CR8 cr8;
CPU::x32::EFER efer; CPU::x32::EFER efer;
uintptr_t dr0, dr1, dr2, dr3, dr6; uint64_t dr0, dr1, dr2, dr3, dr6;
CPU::x32::DR7 dr7; CPU::x32::DR7 dr7;
long ID; long ID;
Tasking::PCB *Process; Tasking::PCB *Process;
Tasking::TCB *Thread; Tasking::TCB *Thread;
}; };
#elif defined(aa64) #elif defined(__aarch64__)
typedef struct CPU::aarch64::TrapFrame CHArchTrapFrame; typedef struct CPU::aarch64::TrapFrame CHArchTrapFrame;
struct CRData
{
CHArchTrapFrame *Frame;
long ID;
Tasking::PCB *Process;
Tasking::TCB *Thread;
};
#endif #endif
enum Keys enum Keys
@ -270,19 +244,19 @@ namespace CrashHandler
class CrashKeyboardDriver : public Interrupts::Handler class CrashKeyboardDriver : public Interrupts::Handler
{ {
private: private:
#if defined(a64) #if defined(__amd64__)
void OnInterruptReceived(CPU::x64::TrapFrame *Frame); void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
#elif defined(a32) #elif defined(__i386__)
void OnInterruptReceived(CPU::x32::TrapFrame *Frame); void OnInterruptReceived(void *Frame);
#elif defined(aa64) #elif defined(__aarch64__)
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame); void OnInterruptReceived(void *Frame);
#endif #endif
public: public:
CrashKeyboardDriver(); CrashKeyboardDriver();
~CrashKeyboardDriver(); ~CrashKeyboardDriver();
}; };
void TraceFrames(CRData data, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel); void TraceFrames(CHArchTrapFrame *Frame, int Count);
void ArrowInput(uint8_t key); void ArrowInput(uint8_t key);
void UserInput(char *Input); void UserInput(char *Input);

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <debug.h> #include <debug.h>
#include <uart.hpp> #include <uart.hpp>
@ -25,13 +8,13 @@ NewLock(DebuggerLock);
using namespace UniversalAsynchronousReceiverTransmitter; using namespace UniversalAsynchronousReceiverTransmitter;
static inline NIF void uart_wrapper(char c, void *unused) static inline __no_instrument_function void uart_wrapper(char c, void *unused)
{ {
UART(COM1).Write(c); UART(COM1).Write(c);
UNUSED(unused); (void)unused;
} }
static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function) static inline __no_instrument_function void WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function)
{ {
const char *DbgLvlString; const char *DbgLvlString;
switch (Level) switch (Level)
@ -69,7 +52,7 @@ static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line,
namespace SysDbg namespace SysDbg
{ {
NIF void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) __no_instrument_function void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{ {
WritePrefix(Level, File, Line, Function); WritePrefix(Level, File, Line, Function);
va_list args; va_list args;
@ -78,29 +61,9 @@ namespace SysDbg
va_end(args); va_end(args);
} }
NIF void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) __no_instrument_function void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{ {
WritePrefix(Level, File, Line, Function); // SmartLock(DebuggerLock);
va_list args;
va_start(args, Format);
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
}
NIF void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
WritePrefix(Level, File, Line, Function);
va_list args;
va_start(args, Format);
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
}
NIF void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
WritePrefix(Level, File, Line, Function); WritePrefix(Level, File, Line, Function);
va_list args; va_list args;
va_start(args, Format); va_start(args, Format);
@ -111,7 +74,7 @@ namespace SysDbg
} }
// C compatibility // C compatibility
extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) 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); WritePrefix(Level, File, Line, Function);
va_list args; va_list args;
@ -121,7 +84,7 @@ extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Lin
} }
// C compatibility // C compatibility
extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...) 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); WritePrefix(Level, File, Line, Function);
va_list args; va_list args;
@ -130,26 +93,3 @@ extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int
va_end(args); va_end(args);
uart_wrapper('\n', nullptr); uart_wrapper('\n', nullptr);
} }
// C compatibility
extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
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" NIF void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
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);
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <disk.hpp> #include <disk.hpp>
#include <memory.hpp> #include <memory.hpp>
@ -28,76 +11,82 @@ namespace Disk
{ {
void Manager::FetchDisks(unsigned long DriverUID) void Manager::FetchDisks(unsigned long DriverUID)
{ {
KernelCallback callback{}; KernelCallback *callback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
callback.Reason = FetchReason; memset(callback, 0, sizeof(KernelCallback));
DriverManager->IOCB(DriverUID, &callback); callback->Reason = FetchReason;
this->AvailablePorts = callback.DiskCallback.Fetch.Ports; DriverManager->IOCB(DriverUID, (void *)callback);
this->BytesPerSector = callback.DiskCallback.Fetch.BytesPerSector; this->AvailablePorts = callback->DiskCallback.Fetch.Ports;
this->BytesPerSector = callback->DiskCallback.Fetch.BytesPerSector;
debug("AvailablePorts:%ld BytesPerSector:%ld", this->AvailablePorts, this->BytesPerSector); debug("AvailablePorts:%ld BytesPerSector:%ld", this->AvailablePorts, this->BytesPerSector);
if (this->AvailablePorts <= 0) if (this->AvailablePorts <= 0)
{
KernelAllocator.FreePages((void *)callback, TO_PAGES(sizeof(KernelCallback)));
return; return;
}
uint8_t *RWBuffer = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(this->BytesPerSector + 1)); uint8_t *RWBuffer = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(this->BytesPerSector));
for (unsigned char ItrPort = 0; ItrPort < this->AvailablePorts; ItrPort++) for (unsigned char ItrPort = 0; ItrPort < this->AvailablePorts; ItrPort++)
{ {
Drive drive{}; Drive *drive = new Drive;
sprintf(drive.Name, "sd%ld-%d", DriverUID, this->AvailablePorts); sprintf_(drive->Name, "sd%ld-%d", DriverUID, this->AvailablePorts);
debug("Drive Name: %s", drive.Name); debug("Drive Name: %s", drive->Name);
// TODO: Implement disk type detection. Very useful in the future. // TODO: Implement disk type detection. Very useful in the future.
drive.MechanicalDisk = true; drive->MechanicalDisk = true;
memset(RWBuffer, 0, this->BytesPerSector); memset(RWBuffer, 0, this->BytesPerSector);
callback.Reason = ReceiveReason; memset(callback, 0, sizeof(KernelCallback));
callback.DiskCallback.RW = { callback->Reason = ReceiveReason;
callback->DiskCallback.RW = {
.Sector = 0, .Sector = 0,
.SectorCount = 2, .SectorCount = 2,
.Port = ItrPort, .Port = ItrPort,
.Buffer = RWBuffer, .Buffer = RWBuffer,
.Write = false, .Write = false,
}; };
DriverManager->IOCB(DriverUID, &callback); DriverManager->IOCB(DriverUID, (void *)callback);
memcpy(&drive.Table, RWBuffer, sizeof(PartitionTable)); memcpy(&drive->Table, RWBuffer, sizeof(PartitionTable));
/* /*
TODO: Add to devfs the disk ----> Add to devfs the disk
*/ */
if (drive.Table.GPT.Signature == GPT_MAGIC) if (drive->Table.GPT.Signature == GPT_MAGIC)
{ {
drive.Style = GPT; drive->Style = GPT;
uint32_t Entries = 512 / drive.Table.GPT.EntrySize; uint32_t Entries = 512 / drive->Table.GPT.EntrySize;
uint32_t Sectors = drive.Table.GPT.PartCount / Entries; uint32_t Sectors = drive->Table.GPT.PartCount / Entries;
for (uint32_t Block = 0; Block < Sectors; Block++) for (uint32_t Block = 0; Block < Sectors; Block++)
{ {
memset(RWBuffer, 0, this->BytesPerSector); memset(RWBuffer, 0, this->BytesPerSector);
callback.Reason = ReceiveReason; memset(callback, 0, sizeof(KernelCallback));
callback.DiskCallback.RW = { callback->Reason = ReceiveReason;
callback->DiskCallback.RW = {
.Sector = 2 + Block, .Sector = 2 + Block,
.SectorCount = 1, .SectorCount = 1,
.Port = ItrPort, .Port = ItrPort,
.Buffer = RWBuffer, .Buffer = RWBuffer,
.Write = false, .Write = false,
}; };
DriverManager->IOCB(DriverUID, &callback); DriverManager->IOCB(DriverUID, (void *)callback);
for (uint32_t e = 0; e < Entries; e++) for (uint32_t e = 0; e < Entries; e++)
{ {
GUIDPartitionTablePartition GPTPartition = reinterpret_cast<GUIDPartitionTablePartition *>(RWBuffer)[e]; GUIDPartitionTablePartition GPTPartition = reinterpret_cast<GUIDPartitionTablePartition *>(RWBuffer)[e];
if (GPTPartition.TypeLow || GPTPartition.TypeHigh) if (GPTPartition.TypeLow || GPTPartition.TypeHigh)
{ {
Partition partition{}; Partition *partition = new Partition;
memcpy(partition.Label, GPTPartition.Label, sizeof(partition.Label)); memcpy(partition->Label, GPTPartition.Label, sizeof(partition->Label));
partition.StartLBA = GPTPartition.StartLBA; partition->StartLBA = GPTPartition.StartLBA;
partition.EndLBA = GPTPartition.EndLBA; partition->EndLBA = GPTPartition.EndLBA;
partition.Sectors = partition.EndLBA - partition.StartLBA; partition->Sectors = partition->EndLBA - partition->StartLBA;
partition.Port = ItrPort; partition->Port = ItrPort;
partition.Flags = Present; partition->Flags = Present;
partition.Style = GPT; partition->Style = GPT;
if (GPTPartition.Attributes & 1) if (GPTPartition.Attributes & 1)
partition.Flags |= EFISystemPartition; partition->Flags |= EFISystemPartition;
partition.Index = drive.Partitions.size(); partition->Index = drive->Partitions.size();
// why there is NUL (\0) between every char????? // why there is NUL (\0) between every char?????
char PartName[72]; char PartName[72];
memcpy(PartName, GPTPartition.Label, 72); memcpy(PartName, GPTPartition.Label, 72);
@ -105,49 +94,49 @@ namespace Disk
if (PartName[i] == '\0') if (PartName[i] == '\0')
PartName[i] = ' '; PartName[i] = ' ';
PartName[71] = '\0'; PartName[71] = '\0';
trace("GPT partition \"%s\" found with %lld sectors", PartName, partition.Sectors); trace("GPT partition \"%s\" found with %lld sectors", PartName, partition->Sectors);
drive.Partitions.push_back(partition); drive->Partitions.push_back(partition);
// char *PartitionName = new char[64]; char *PartitionName = new char[64];
// sprintf(PartitionName, "sd%ldp%ld", drives.size() - 1, partition.Index); sprintf_(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
/* /*
TODO: Add to devfs the disk ----> Add to devfs the disk
*/ */
// delete[] PartitionName; delete[] PartitionName;
} }
} }
} }
trace("%d GPT partitions found.", drive.Partitions.size()); trace("%d GPT partitions found.", drive->Partitions.size());
} }
else if (drive.Table.MBR.Signature[0] == MBR_MAGIC0 && drive.Table.MBR.Signature[1] == MBR_MAGIC1) else if (drive->Table.MBR.Signature[0] == MBR_MAGIC0 && drive->Table.MBR.Signature[1] == MBR_MAGIC1)
{ {
drive.Style = MBR; drive->Style = MBR;
for (size_t p = 0; p < 4; p++) for (size_t p = 0; p < 4; p++)
if (drive.Table.MBR.Partitions[p].LBAFirst != 0) if (drive->Table.MBR.Partitions[p].LBAFirst != 0)
{ {
Partition partition{}; Partition *partition = new Partition;
partition.StartLBA = drive.Table.MBR.Partitions[p].LBAFirst; partition->StartLBA = drive->Table.MBR.Partitions[p].LBAFirst;
partition.EndLBA = drive.Table.MBR.Partitions[p].LBAFirst + drive.Table.MBR.Partitions[p].Sectors; partition->EndLBA = drive->Table.MBR.Partitions[p].LBAFirst + drive->Table.MBR.Partitions[p].Sectors;
partition.Sectors = drive.Table.MBR.Partitions[p].Sectors; partition->Sectors = drive->Table.MBR.Partitions[p].Sectors;
partition.Port = ItrPort; partition->Port = ItrPort;
partition.Flags = Present; partition->Flags = Present;
partition.Style = MBR; partition->Style = MBR;
partition.Index = drive.Partitions.size(); partition->Index = drive->Partitions.size();
trace("Partition \"%#llx\" found with %lld sectors.", drive.Table.MBR.UniqueID, partition.Sectors); trace("Partition \"%#llx\" found with %lld sectors.", drive->Table.MBR.UniqueID, partition->Sectors);
drive.Partitions.push_back(partition); drive->Partitions.push_back(partition);
// char *PartitionName = new char[64]; char *PartitionName = new char[64];
// sprintf(PartitionName, "sd%ldp%ld", drives.size() - 1, partition.Index); sprintf_(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
/* /*
TODO: Add to devfs the disk ----> Add to devfs the disk
*/ */
// delete[] PartitionName; delete[] PartitionName;
} }
trace("%d MBR partitions found.", drive.Partitions.size()); trace("%d MBR partitions found.", drive->Partitions.size());
} }
else else
warn("No partition table found on port %d!", ItrPort); warn("No partition table found on port %d!", ItrPort);
@ -155,7 +144,7 @@ namespace Disk
drives.push_back(drive); drives.push_back(drive);
} }
KernelAllocator.FreePages(RWBuffer, TO_PAGES(this->BytesPerSector + 1)); KernelAllocator.FreePages((void *)callback, TO_PAGES(sizeof(KernelCallback)));
} }
Manager::Manager() Manager::Manager()
@ -164,6 +153,5 @@ namespace Disk
Manager::~Manager() Manager::~Manager()
{ {
debug("Destructor called");
} }
} }

View File

@ -1,24 +1,7 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <driver.hpp> #include <driver.hpp>
#include <interrupts.hpp>
#include <memory.hpp> #include <memory.hpp>
#include <ints.hpp>
#include <task.hpp> #include <task.hpp>
#include <lock.hpp> #include <lock.hpp>
#include <printf.h> #include <printf.h>
@ -35,309 +18,455 @@ NewLock(DriverInterruptLock);
namespace Driver namespace Driver
{ {
void Driver::Panic() const char *DriverTypesName[] = {
{ "Unknown",
#ifdef DEBUG "Generic",
size_t DriversNum = Drivers.size(); "Display",
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs); "Network",
debug("driver size %ld", DriversNum); "Storage",
#endif "FileSystem",
"Input",
foreach (auto drv in Drivers) "Audio"};
{
KernelCallback callback{};
callback.Reason = StopReason;
DriverManager->IOCB(drv.DriverUID, &callback);
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
{
if (!drv.InterruptHook[j])
continue;
drv.InterruptHook[j]->Disable();
debug("Interrupt hook %#lx disabled", drv.InterruptHook[j]);
}
}
}
void Driver::UnloadAllDrivers()
{
#ifdef DEBUG
size_t DriversNum = Drivers.size();
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
debug("driver size %ld", DriversNum);
#endif
foreach (auto drv in Drivers)
{
KernelCallback callback{};
callback.Reason = StopReason;
debug("Stopping & unloading driver %ld [%#lx]", drv.DriverUID, drv.Address);
DriverManager->IOCB(drv.DriverUID, &callback);
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
{
if (!drv.InterruptHook[j])
continue;
debug("Interrupt hook %#lx", drv.InterruptHook[j]);
delete drv.InterruptHook[j], drv.InterruptHook[j] = nullptr;
}
if (drv.MemTrk)
delete drv.MemTrk, drv.MemTrk = nullptr;
}
Drivers.clear();
}
bool Driver::UnloadDriver(unsigned long DUID)
{
debug("Searching for driver %ld", DUID);
foreach (auto drv in Drivers)
{
if (drv.DriverUID == DUID)
{
KernelCallback callback{};
callback.Reason = StopReason;
debug("Stopping and unloading driver %ld [%#lx]", drv.DriverUID, drv.Address);
this->IOCB(drv.DriverUID, &callback);
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
{
if (!drv.InterruptHook[j])
continue;
debug("Interrupt hook %#lx", drv.InterruptHook[j]);
delete drv.InterruptHook[j], drv.InterruptHook[j] = nullptr;
}
delete drv.MemTrk, drv.MemTrk = nullptr;
Drivers.remove(drv);
return true;
}
}
return false;
}
int Driver::IOCB(unsigned long DUID, void *KCB) int Driver::IOCB(unsigned long DUID, void *KCB)
{ {
foreach (auto Drv in Drivers) foreach (auto var in Drivers)
if (var->DriverUID == DUID)
{ {
if (Drv.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);
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS);
int ret = ((int (*)(void *))((uintptr_t)DrvExtHdr->Driver.Callback + (uintptr_t)Drv.Address))(KCB);
__sync;
return ret;
}
} }
return -1; return -1;
} }
DriverCode Driver::CallDriverEntryPoint(void *fex, void *KAPIAddress) DriverCode Driver::CallDriverEntryPoint(void *fex)
{ {
memcpy(KAPIAddress, &KernelAPITemplate, sizeof(KernelAPI)); KernelAPI *API = (KernelAPI *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelAPI)));
memcpy(API, &KAPI, sizeof(KernelAPI));
((KernelAPI *)KAPIAddress)->Info.Offset = (unsigned long)fex; API->Info.Offset = (unsigned long)fex;
((KernelAPI *)KAPIAddress)->Info.DriverUID = DriverUIDs++; API->Info.DriverUID = DriverUIDs++;
((KernelAPI *)KAPIAddress)->Info.KernelDebug = DebuggerIsAttached;
#ifdef DEBUG int ret = ((int (*)(KernelAPI *))((uint64_t)((Fex *)fex)->Pointer + (uint64_t)fex))(API);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("DRIVER: %s HAS DRIVER ID %ld", fexExtended->Driver.Name, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
#endif
debug("Calling driver entry point ( %#lx %ld )", (unsigned long)fex, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
int ret = ((int (*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)KAPIAddress));
if (DriverReturnCode::OK != ret) if (DriverReturnCode::OK != ret)
return DriverCode::DRIVER_RETURNED_ERROR; return DriverCode::DRIVER_RETURNED_ERROR;
return DriverCode::OK; return DriverCode::OK;
} }
DriverCode Driver::LoadDriver(uintptr_t DriverAddress, uintptr_t Size) DriverCode Driver::LoadDriver(uint64_t DriverAddress, uint64_t Size)
{ {
Fex *DrvHdr = (Fex *)DriverAddress; Fex *DrvHdr = (Fex *)DriverAddress;
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0') if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
{
if (Size > 0x1000)
{
Fex *ElfDrvHdr = (Fex *)(DriverAddress + 0x1000);
if (ElfDrvHdr->Magic[0] != 'F' || ElfDrvHdr->Magic[1] != 'E' || ElfDrvHdr->Magic[2] != 'X' || ElfDrvHdr->Magic[3] != '\0')
return DriverCode::INVALID_FEX_HEADER; return DriverCode::INVALID_FEX_HEADER;
else debug("Fex Magic: \"%s\"; Type: %d; OS: %d; Pointer: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->Pointer);
{
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", ElfDrvHdr->Magic, ElfDrvHdr->Type, ElfDrvHdr->OS, ElfDrvHdr->EntryPoint);
if (ElfDrvHdr->Type == FexFormatType::FexFormatType_Driver)
{
FexExtended *ElfDrvExtHdr = (FexExtended *)((uintptr_t)ElfDrvHdr + EXTENDED_SECTION_ADDRESS);
debug("Name: \"%s\"; Type: %d; Callback: %#lx", ElfDrvExtHdr->Driver.Name, ElfDrvExtHdr->Driver.Type, ElfDrvExtHdr->Driver.Callback);
if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
return this->DriverLoadBindPCI(ElfDrvExtHdr, DriverAddress, Size, true);
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
return this->DriverLoadBindInterrupt(ElfDrvExtHdr, DriverAddress, Size, true);
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
return this->DriverLoadBindProcess(ElfDrvExtHdr, DriverAddress, Size, true);
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
return this->DriverLoadBindInput(ElfDrvExtHdr, DriverAddress, Size, true);
else
error("Unknown driver bind type: %d", ElfDrvExtHdr->Driver.Bind.Type);
}
else
return DriverCode::NOT_DRIVER;
}
}
else
return DriverCode::INVALID_FEX_HEADER;
}
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->EntryPoint);
if (DrvHdr->Type == FexFormatType::FexFormatType_Driver) if (DrvHdr->Type == FexFormatType::FexFormatType_Driver)
{ {
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)DrvHdr + EXTENDED_SECTION_ADDRESS); 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); debug("Name: \"%s\"; Type: %d; Callback: %#lx", DrvExtHdr->Driver.Name, DrvExtHdr->Driver.Type, DrvExtHdr->Driver.Callback);
if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI) if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
return this->DriverLoadBindPCI(DrvExtHdr, DriverAddress, Size); {
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT) for (unsigned long Vidx = 0; Vidx < sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) / sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID[0]); Vidx++)
return this->DriverLoadBindInterrupt(DrvExtHdr, DriverAddress, Size); for (unsigned long Didx = 0; Didx < sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID) / sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID[0]); Didx++)
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS) {
return this->DriverLoadBindProcess(DrvExtHdr, DriverAddress, Size); if (Vidx >= sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) && Didx >= sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID))
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT) break;
return this->DriverLoadBindInput(DrvExtHdr, DriverAddress, Size);
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 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); error("Unknown driver bind type: %d", DrvExtHdr->Driver.Bind.Type);
} }
}
else else
return DriverCode::NOT_DRIVER; return DriverCode::NOT_DRIVER;
return DriverCode::ERROR; return DriverCode::OK;
} }
Driver::Driver() Driver::Driver()
{ {
SmartCriticalSection(DriverInitLock); SmartCriticalSection(DriverInitLock);
FileSystem::FILE *DriverDirectory = vfs->Open(Config.DriverDirectory);
std::string DriverConfigFile = Config.DriverDirectory; if (DriverDirectory->Status == FileSystem::FileStatus::OK)
DriverConfigFile << "/config.ini"; foreach (auto driver in DriverDirectory->Node->Children)
fixme("Loading driver config file: %s", DriverConfigFile.c_str()); if (driver->Flags == FileSystem::NodeFlags::FS_FILE)
VirtualFileSystem::File DriverDirectory = vfs->Open(Config.DriverDirectory);
if (DriverDirectory.IsOK())
{
foreach (auto driver in DriverDirectory.node->Children)
if (driver->Flags == VirtualFileSystem::NodeFlags::FILE)
if (cwk_path_has_extension(driver->Name)) if (cwk_path_has_extension(driver->Name))
{ {
const char *extension; const char *extension;
size_t extension_length; cwk_path_get_extension(driver->Name, &extension, nullptr);
cwk_path_get_extension(driver->Name, &extension, &extension_length); if (!strcmp(extension, ".fex"))
debug("Driver: %s; Extension: %s", driver->Name, extension);
if (strcmp(extension, ".fex") == 0 || strcmp(extension, ".elf") == 0)
{ {
uintptr_t ret = this->LoadDriver(driver->Address, driver->Length); uint64_t ret = this->LoadDriver(driver->Address, driver->Length);
char RetString[128]; char retstring[128];
if (ret == DriverCode::OK) if (ret == DriverCode::OK)
strncpy(RetString, "\e058C19OK", 10); strncpy(retstring, "\e058C19OK", 64);
else if (ret == DriverCode::NOT_AVAILABLE)
strncpy(RetString, "\eFF7900NOT AVAILABLE", 21);
else else
sprintf(RetString, "\eE85230FAILED (%#lx)", ret); sprintf_(retstring, "\eE85230FAILED (%#lx)", ret);
KPrint("%s %s", driver->Name, RetString); KPrint("%s %s", driver->Name, retstring);
} }
} }
}
else
{
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status);
CPU::Stop();
}
vfs->Close(DriverDirectory); vfs->Close(DriverDirectory);
} }
Driver::~Driver() Driver::~Driver()
{ {
debug("Destructor called");
this->UnloadAllDrivers();
} }
#if defined(a64) #if defined(__amd64__)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame) void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
#elif defined(a32) #elif defined(__i386__)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame) void DriverInterruptHook::OnInterruptReceived(void *Frame)
#elif defined(aa64) #elif defined(__aarch64__)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame) void DriverInterruptHook::OnInterruptReceived(void *Frame)
#endif #endif
{ {
SmartLock(DriverInterruptLock); /* Lock in case of multiple interrupts firing at the same time */ SmartCriticalSection(DriverInterruptLock);
if (!this->Enabled) ((int (*)(void *))(Handle))(Data);
}
DriverInterruptHook::DriverInterruptHook(int Interrupt, void *Address, void *ParamData) : Interrupts::Handler(Interrupt)
{ {
debug("Interrupt hook is not enabled"); trace("Interrupt %d Hooked", Interrupt - 32); // x86
return; Handle = Address;
} Data = ParamData;
if (!Handle.InterruptCallback)
{
#if defined(a86)
uint64_t IntNum = Frame->InterruptNumber - 32;
#elif defined(aa64)
uint64_t IntNum = Frame->InterruptNumber;
#endif
warn("Interrupt callback for %ld is not set for driver %ld!", IntNum, Handle.DriverUID);
return;
}
CPURegisters regs;
#if defined(a64)
regs.r15 = Frame->r15;
regs.r14 = Frame->r14;
regs.r13 = Frame->r13;
regs.r12 = Frame->r12;
regs.r11 = Frame->r11;
regs.r10 = Frame->r10;
regs.r9 = Frame->r9;
regs.r8 = Frame->r8;
regs.rbp = Frame->rbp;
regs.rdi = Frame->rdi;
regs.rsi = Frame->rsi;
regs.rdx = Frame->rdx;
regs.rcx = Frame->rcx;
regs.rbx = Frame->rbx;
regs.rax = Frame->rax;
regs.InterruptNumber = Frame->InterruptNumber;
regs.ErrorCode = Frame->ErrorCode;
regs.rip = Frame->rip;
regs.cs = Frame->cs;
regs.rflags = Frame->rflags.raw;
regs.rsp = Frame->rsp;
regs.ss = Frame->ss;
#elif defined(a32)
regs.ebp = Frame->ebp;
regs.edi = Frame->edi;
regs.esi = Frame->esi;
regs.edx = Frame->edx;
regs.ecx = Frame->ecx;
regs.ebx = Frame->ebx;
regs.eax = Frame->eax;
regs.InterruptNumber = Frame->InterruptNumber;
regs.ErrorCode = Frame->ErrorCode;
regs.eip = Frame->eip;
regs.cs = Frame->cs;
regs.eflags = Frame->eflags.raw;
regs.esp = Frame->esp;
regs.ss = Frame->ss;
#elif defined(aa64)
#endif
((int (*)(void *))(Handle.InterruptCallback))(&regs);
UNUSED(Frame);
}
DriverInterruptHook::DriverInterruptHook(int Interrupt, DriverFile Handle) : Interrupts::Handler(Interrupt)
{
this->Handle = Handle;
#if defined(a86)
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
#elif defined(aa64)
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
#endif
} }
} }

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <driver.hpp> #include <driver.hpp>
#include <dumper.hpp> #include <dumper.hpp>
@ -24,18 +7,13 @@
#include "../../Fex.hpp" #include "../../Fex.hpp"
#include "api.hpp" #include "api.hpp"
// show debug messages
// #define DEBUG_DRIVER_API 1
#ifdef DEBUG_DRIVER_API
#define drvdbg(m, ...) debug(m, ##__VA_ARGS__)
#else
#define drvdbg(m, ...)
#endif
NewLock(DriverDisplayPrintLock); NewLock(DriverDisplayPrintLock);
void DriverDebugPrint(char *String, unsigned long DriverUID) { trace("[%ld] %s", DriverUID, String); } void DriverDebugPrint(char *String, unsigned long DriverUID)
{
SmartLock(DriverDisplayPrintLock);
trace("[%ld] %s", DriverUID, String);
}
void DriverDisplayPrint(char *String) void DriverDisplayPrint(char *String)
{ {
@ -46,117 +24,74 @@ void DriverDisplayPrint(char *String)
void *RequestPage(unsigned long Size) void *RequestPage(unsigned long Size)
{ {
void *ret = KernelAllocator.RequestPages(Size + 1); SmartLock(DriverDisplayPrintLock);
drvdbg("Allocated %ld pages (%#lx-%#lx)", Size, (unsigned long)ret, (unsigned long)ret + FROM_PAGES(Size)); // debug("Requesting %ld pages from the kernel...", Size);
void *ret = KernelAllocator.RequestPages(Size);
// debug("Got %#lx", ret);
return ret; return ret;
} }
void FreePage(void *Page, unsigned long Size) void FreePage(void *Page, unsigned long Size)
{ {
drvdbg("Freeing %ld pages (%#lx-%#lx)", Size, (unsigned long)Page, (unsigned long)Page + FROM_PAGES(Size)); SmartLock(DriverDisplayPrintLock);
KernelAllocator.FreePages(Page, Size + 1); 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) void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags)
{ {
SmartLock(DriverDisplayPrintLock); SmartLock(DriverDisplayPrintLock);
drvdbg("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags); debug("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags);
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags); Memory::Virtual().Map(VirtualAddress, PhysicalAddress, Flags);
} }
void UnmapMemory(void *VirtualAddress) void UnmapMemory(void *VirtualAddress)
{ {
SmartLock(DriverDisplayPrintLock); SmartLock(DriverDisplayPrintLock);
drvdbg("Unmapping %#lx...", (unsigned long)VirtualAddress); debug("Unmapping %#lx...", (unsigned long)VirtualAddress);
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress); Memory::Virtual().Unmap(VirtualAddress);
} }
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size) void *Drivermemcpy(void *Destination, void *Source, unsigned long Size)
{ {
SmartLock(DriverDisplayPrintLock); SmartLock(DriverDisplayPrintLock);
drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size, // debug("Copying %ld bytes from %#lx to %#lx...", Size, (unsigned long)Source, (unsigned long)Destination);
(unsigned long)Source, (unsigned long)Source + Size,
(unsigned long)Destination, (unsigned long)Destination + Size);
return memcpy(Destination, Source, Size); return memcpy(Destination, Source, Size);
} }
void *Drivermemset(void *Destination, int Value, unsigned long Size) void *Drivermemset(void *Destination, int Value, unsigned long Size)
{ {
SmartLock(DriverDisplayPrintLock); SmartLock(DriverDisplayPrintLock);
drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value, // debug("Setting %ld bytes from %#lx to %#x...", Size, (unsigned long)Destination, Value);
(unsigned long)Destination, (unsigned long)Destination + Size,
Size);
return memset(Destination, Value, Size); return memset(Destination, Value, Size);
} }
void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size) void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{ {
// This is useless I guess... DumpData("DriverNetSend", Data, Size);
if (NIManager)
NIManager->DrvSend(DriverID, Data, Size);
} }
void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size) void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{ {
if (NIManager) DumpData("DriverNetReceive", Data, Size);
NIManager->DrvReceive(DriverID, Data, Size);
} }
void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port) void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
{ {
DumpData("DriverDiskRead", Data, SectorCount * 512); DumpData("DriverDiskRead", Data, SectorCount * 512);
UNUSED(DriverID);
UNUSED(Sector);
UNUSED(Port);
} }
void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port) void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
{ {
DumpData("DriverDiskWrite", Data, SectorCount * 512); DumpData("DriverDiskWrite", Data, SectorCount * 512);
UNUSED(DriverID);
UNUSED(Sector);
UNUSED(Port);
} }
char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID) char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID)
{ {
UNUSED(VendorID);
UNUSED(DeviceID);
return (char *)"Unknown"; return (char *)"Unknown";
} }
unsigned int DriverGetWidth() KernelAPI KAPI = {
{
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
return Display->GetBuffer(0)->Width;
}
unsigned int DriverGetHeight()
{
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
return Display->GetBuffer(0)->Height;
}
void DriverSleep(unsigned long Milliseconds)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Sleeping for %ld milliseconds...", Milliseconds);
if (TaskManager)
TaskManager->Sleep(Milliseconds);
else
TimeManager->Sleep(Milliseconds, Time::Units::Milliseconds);
}
int Driversprintf(char *Buffer, const char *Format, ...)
{
va_list args;
va_start(args, Format);
int ret = vsprintf(Buffer, Format, args);
va_end(args);
return ret;
}
KernelAPI KernelAPITemplate = {
.Version = { .Version = {
.Major = 0, .Major = 0,
.Minor = 0, .Minor = 0,
@ -164,7 +99,6 @@ KernelAPI KernelAPITemplate = {
.Info = { .Info = {
.Offset = 0, .Offset = 0,
.DriverUID = 0, .DriverUID = 0,
.KernelDebug = false,
}, },
.Memory = { .Memory = {
.PageSize = PAGE_SIZE, .PageSize = PAGE_SIZE,
@ -181,8 +115,6 @@ KernelAPI KernelAPITemplate = {
.DisplayPrint = DriverDisplayPrint, .DisplayPrint = DriverDisplayPrint,
.memcpy = Drivermemcpy, .memcpy = Drivermemcpy,
.memset = Drivermemset, .memset = Drivermemset,
.Sleep = DriverSleep,
.sprintf = Driversprintf,
}, },
.Command = { .Command = {
.Network = { .Network = {
@ -196,8 +128,4 @@ KernelAPI KernelAPITemplate = {
}, },
}, },
}, },
.Display = {
.GetWidth = DriverGetWidth,
.GetHeight = DriverGetHeight,
},
}; };

View File

@ -1,73 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::DriverLoadBindInput(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
{
UNUSED(DrvExtHdr);
UNUSED(IsElf);
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
#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
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
{
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Input:
return BindInputInput(mem, fex);
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
delete mem, mem = nullptr;
return DriverCode::UNKNOWN_DRIVER_TYPE;
}
}
return DriverCode::OK;
}
}

View File

@ -1,85 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::DriverLoadBindInterrupt(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
{
UNUSED(DrvExtHdr);
UNUSED(IsElf);
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
#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
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
{
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Generic:
return BindInterruptGeneric(mem, fex);
case FexDriverType::FexDriverType_Display:
return BindInterruptDisplay(mem, fex);
case FexDriverType::FexDriverType_Network:
return BindInterruptNetwork(mem, fex);
case FexDriverType::FexDriverType_Storage:
return BindInterruptStorage(mem, fex);
case FexDriverType::FexDriverType_FileSystem:
return BindInterruptFileSystem(mem, fex);
case FexDriverType::FexDriverType_Input:
return BindInterruptInput(mem, fex);
case FexDriverType::FexDriverType_Audio:
return BindInterruptAudio(mem, fex);
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
delete mem, mem = nullptr;
return DriverCode::UNKNOWN_DRIVER_TYPE;
}
}
return DriverCode::OK;
}
}

View File

@ -1,201 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../api.hpp"
#include <ints.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"
namespace Driver
{
void Driver::MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice)
{
debug("Header Type: %d", PCIDevice->HeaderType);
switch (PCIDevice->HeaderType)
{
case 0: // PCI Header 0
{
uint32_t BAR[6] = {0};
size_t BARsSize[6] = {0};
BAR[0] = ((PCI::PCIHeader0 *)PCIDevice)->BAR0;
BAR[1] = ((PCI::PCIHeader0 *)PCIDevice)->BAR1;
BAR[2] = ((PCI::PCIHeader0 *)PCIDevice)->BAR2;
BAR[3] = ((PCI::PCIHeader0 *)PCIDevice)->BAR3;
BAR[4] = ((PCI::PCIHeader0 *)PCIDevice)->BAR4;
BAR[5] = ((PCI::PCIHeader0 *)PCIDevice)->BAR5;
#ifdef DEBUG
uintptr_t BAR_Type = BAR[0] & 1;
uintptr_t BAR_IOBase = BAR[1] & (~3);
uintptr_t BAR_MemoryBase = BAR[0] & (~15);
debug("Type: %d; IOBase: %#lx; MemoryBase: %#lx", BAR_Type, BAR_IOBase, BAR_MemoryBase);
#endif
/* BARs Size */
for (short i = 0; i < 6; i++)
{
if (BAR[i] == 0)
continue;
if ((BAR[i] & 1) == 0) // Memory Base
{
((PCI::PCIHeader0 *)PCIDevice)->BAR0 = 0xFFFFFFFF;
size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR0;
((PCI::PCIHeader0 *)PCIDevice)->BAR0 = BAR[i];
BARsSize[i] = size & (~15);
BARsSize[i] = ~BARsSize[i] + 1;
BARsSize[i] = BARsSize[i] & 0xFFFFFFFF;
debug("BAR%d %#lx size: %d", i, BAR[i], BARsSize[i]);
}
else if ((BAR[i] & 1) == 1) // I/O Base
{
((PCI::PCIHeader0 *)PCIDevice)->BAR1 = 0xFFFFFFFF;
size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR1;
((PCI::PCIHeader0 *)PCIDevice)->BAR1 = BAR[i];
BARsSize[i] = size & (~3);
BARsSize[i] = ~BARsSize[i] + 1;
BARsSize[i] = BARsSize[i] & 0xFFFF;
debug("BAR%d %#lx size: %d", i, BAR[i], BARsSize[i]);
}
}
/* Mapping the BARs */
for (short i = 0; i < 6; i++)
{
if (BAR[i] == 0)
continue;
if ((BAR[i] & 1) == 0) // Memory Base
{
uintptr_t BARBase = BAR[i] & (~15);
size_t BARSize = BARsSize[i];
debug("Mapping BAR%d %#lx-%#lx", i, BARBase, BARBase + BARSize);
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT);
}
else if ((BAR[i] & 1) == 1) // I/O Base
{
uintptr_t BARBase = BAR[i] & (~3);
size_t BARSize = BARsSize[i];
debug("Mapping BAR%d %#x-%#x", i, BARBase, BARBase + BARSize);
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT);
}
}
break;
}
case 1: // PCI Header 1 (PCI-to-PCI Bridge)
{
fixme("PCI Header 1 (PCI-to-PCI Bridge) not implemented yet");
break;
}
case 2: // PCI Header 2 (PCI-to-CardBus Bridge)
{
fixme("PCI Header 2 (PCI-to-CardBus Bridge) not implemented yet");
break;
}
default:
{
error("Unknown header type %d", PCIDevice->HeaderType);
return;
}
}
}
DriverCode Driver::DriverLoadBindPCI(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
{
UNUSED(IsElf);
for (unsigned long Vidx = 0; Vidx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[0]); Vidx++)
{
for (unsigned long Didx = 0; Didx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[0]); Didx++)
{
if (Vidx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) && Didx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID))
break;
if (((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[Vidx] == 0 || ((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[Didx] == 0)
continue;
std::vector<PCI::PCIDeviceHeader *> devices = PCIManager->FindPCIDevice(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[Vidx], ((FexExtended *)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);
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
#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
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI) + 1));
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
{
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s", fexExtended->Driver.Name);
MapPCIAddresses(PCIDevice);
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Generic:
return BindPCIGeneric(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_Display:
return BindPCIDisplay(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_Network:
return BindPCINetwork(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_Storage:
return BindPCIStorage(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_FileSystem:
return BindPCIFileSystem(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_Input:
return BindPCIInput(mem, fex, PCIDevice);
case FexDriverType::FexDriverType_Audio:
return BindPCIAudio(mem, fex, PCIDevice);
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
delete mem, mem = nullptr;
return DriverCode::UNKNOWN_DRIVER_TYPE;
}
}
}
}
}
return DriverCode::PCI_DEVICE_NOT_FOUND;
}
}

View File

@ -1,42 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::DriverLoadBindProcess(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
{
fixme("Process driver: %s", ((FexExtended *)DrvExtHdr)->Driver.Name);
UNUSED(Size);
UNUSED(DriverAddress);
UNUSED(IsElf);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInputAudio(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInputDisplay(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInputFileSystem(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInputGeneric(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,67 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInputInput(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
KernelCallback KCallback{};
fixme("Input driver: %s", fexExtended->Driver.Name);
KCallback.RawPtr = nullptr;
KCallback.Reason = CallbackReason::ConfigurationReason;
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
{
delete mem, mem = nullptr;
error("Driver %s is not implemented", fexExtended->Driver.Name);
return DriverCode::NOT_IMPLEMENTED;
}
else if (CallbackRet != DriverReturnCode::OK)
{
delete mem, mem = nullptr;
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
return DriverCode::DRIVER_RETURNED_ERROR;
}
fixme("Input driver: %s", fexExtended->Driver.Name);
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.MemTrk = mem,
};
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInputNetwork(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInputStorage(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInterruptAudio(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Audio driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInterruptDisplay(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Display driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInterruptFileSystem(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,88 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInterruptGeneric(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
DriversToRemove.push_back(Drv.DriverUID);
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Generic driver: %s", fexExtended->Driver.Name);
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,124 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.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"
namespace Driver
{
DriverCode Driver::BindInterruptInput(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("Searching for conflicting drivers...");
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if ((fe->Driver.TypeFlags & FexDriverInputTypes_Mouse &&
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Mouse) ||
(fe->Driver.TypeFlags & FexDriverInputTypes_Keyboard &&
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Keyboard))
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
DriversToRemove.push_back(Drv.DriverUID);
}
}
foreach (auto DrvID in DriversToRemove)
{
if (!this->UnloadDriver(DrvID))
{
error("Failed to unload conflicting driver %d", DrvID);
return DriverCode::DRIVER_CONFLICT;
}
}
}
else
{
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if ((fe->Driver.TypeFlags & FexDriverInputTypes_Mouse &&
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Mouse) ||
(fe->Driver.TypeFlags & FexDriverInputTypes_Keyboard &&
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Keyboard))
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
}
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
if (fexExtended->Driver.InterruptCallback)
{
for (unsigned long i = 0; i < sizeof(fexExtended->Driver.Bind.Interrupt.Vector) / sizeof(fexExtended->Driver.Bind.Interrupt.Vector[0]); i++)
{
if (fexExtended->Driver.Bind.Interrupt.Vector[i] == 0)
break;
DrvFile.InterruptHook[i] = new DriverInterruptHook(fexExtended->Driver.Bind.Interrupt.Vector[i], DrvFile);
}
}
KernelCallback KCallback{};
KCallback.RawPtr = nullptr;
KCallback.Reason = CallbackReason::ConfigurationReason;
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(&KCallback);
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
{
error("Driver %s is not implemented", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
else if (CallbackRet != DriverReturnCode::OK)
{
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

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