2 Commits

Author SHA1 Message Date
9b49f670bd Kernel/tasking-test 2024-11-20 05:18:19 +02:00
4a8e6eec5f Kernel/tasking-test 2024-11-20 05:17:41 +02:00
243 changed files with 8616 additions and 26247 deletions

View File

@ -1,61 +0,0 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow checks out code, performs a Codacy security scan
# and integrates the results with the
# GitHub Advanced Security code scanning feature. For more information on
# the Codacy security scan action usage and parameters, see
# https://github.com/codacy/codacy-analysis-cli-action.
# For more information on Codacy Analysis CLI in general, see
# https://github.com/codacy/codacy-analysis-cli.
name: Codacy Security Scan
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '27 22 * * 5'
permissions:
contents: read
jobs:
codacy-security-scan:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
name: Codacy Security Scan
runs-on: ubuntu-latest
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v3
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
verbose: true
output: results.sarif
format: sarif
# Adjust severity of non-security issues
gh-code-scanning-compat: true
# Force 0 exit code to allow SARIF file generation
# This will handover control about PR rejection to the GitHub side
max-allowed-issues: 2147483647
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: results.sarif

1
Kernel/.gitignore vendored
View File

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

View File

@ -1,9 +1,8 @@
{
"configurations": [
{
"name": "Fennix x64 (Linux, GCC, debug)",
"name": "Linux",
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/include/**"
],
"defines": [
@ -12,110 +11,37 @@
"KERNEL_VERSION=\"1.0\"",
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"a64",
"DEBUG=\"1\""
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/amd64-elf-gcc",
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "gcc-x64",
"configurationProvider": "ms-vscode.makefile-tools",
"compilerArgs": [
// Compiler flags
"-fno-pic",
"-fno-pie",
"-mno-red-zone",
"-march=core2",
"-pipe",
"-mcmodel=kernel",
"-fno-builtin",
// C++ flags
// "-m32",
"-mcmodel=kernel", /* 64-bit only */
"-fno-rtti",
"-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/**"
],
"defines": [
"__debug_vscode__",
"KERNEL_NAME=\"Fennix\"",
"KERNEL_VERSION=\"1.0\"",
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"a32",
"DEBUG=\"1\""
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i686-elf-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "gcc-x86",
"configurationProvider": "ms-vscode.makefile-tools",
"compilerArgs": [
// Compiler flags
"-fno-pic",
"-fno-pie",
"-mno-80387",
"-mno-mmx",
"-mno-3dnow",
"-mno-red-zone",
"-march=pentium",
"-mno-sse",
"-mno-sse2",
"-march=nehalem",
"-pipe",
"-msoft-float",
"-fno-builtin",
// C++ flags
"-fno-rtti",
"-fexceptions",
// Linker flags
"-T${workspaceFolder}/Architecture/i686/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++"
"-Wl,-static,--no-dynamic-linker,-ztext",
"-shared",
"-zmax-page-size=0x1000",
"-nostdinc++",
"-fsanitize=undefined"
]
}
],

View File

@ -1,13 +1,16 @@
{
"recommendations": [
"pejmannikram.vscode-auto-scroll",
"aaron-bond.better-comments",
"ms-vscode.cpptools",
"wayou.vscode-todo-highlight",
"gruntfuggly.todo-tree",
"13xforever.language-x86-64-assembly",
"webfreak.debug",
"zixuanwang.linkerscript",
"maziac.hex-hover-converter",
"streetsidesoftware.code-spell-checker",
"naumovs.color-highlight",
"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

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

View File

@ -1,6 +1,6 @@
#include <smp.hpp>
#include <ints.hpp>
#include <interrupts.hpp>
#include <memory.hpp>
#include <cpu.hpp>

View File

@ -1,41 +0,0 @@
[bits 32]
section .bootstrap.text
global DetectCPUID
DetectCPUID:
pushfd
pop eax
mov ecx, eax
xor eax, 1 << 21
push eax
popfd
pushfd
pop eax
push ecx
popfd
xor eax, ecx
jz .NoCPUID
ret
.NoCPUID:
; mov word [0xb8F00], 0xF00F ; .
.Loop:
cli
hlt
jmp .Loop
global Detect64Bit
Detect64Bit:
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb .NoLongMode
mov eax, 0x80000001
cpuid
test edx, 1 << 29
jz .NoLongMode
ret
.NoLongMode:
; mov word [0xb8F00], 0xF00A ; .
.Loop:
cli
hlt
jmp .Loop

View File

@ -1,152 +0,0 @@
; https://wiki.osdev.org/Creating_a_64-bit_kernel
; https://wiki.osdev.org/Entering_Long_Mode_Directly
KERNEL_VIRTUAL_BASE equ 0xFFFFFFFF80000000 ; 512GB
KERNEL_LMA equ 0x1000000 ; 16MB
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
extern Multiboot2Entry
extern BootPageTable
extern UpdatePageTable
extern UpdatePageTable64
extern DetectCPUID
extern Detect64Bit
extern LoadGDT32
global MB2_start
extern MB2_start_c
[bits 32]
section .bootstrap.data
global MB2_HeaderMagic
MB2_HeaderMagic:
times (0x64) dq 0
global MB2_HeaderInfo
MB2_HeaderInfo:
times (0x64) dq 0
section .bootstrap.text
MB2_start:
cli
; mov word [0xb8F00], 0x072E ; .
mov [MB2_HeaderMagic], eax
mov [MB2_HeaderInfo], ebx
; We need to check if the CPU supports 64-bit mode
call DetectCPUID
call Detect64Bit
; mov word [0xb8F02], 0x072E ; .
mov ecx, cr0
and ecx, 0x7fffffff ; Clear PG
mov cr0, ecx
mov ecx, cr4
or ecx, 0x10 ; Set PSE
or ecx, 0x20 ; Set PAE
mov cr4, ecx
; Load the GDT and update the page table
call LoadGDT32
call UpdatePageTable
; Load the new page table
mov edi, BootPageTable
mov cr3, edi
; mov word [0xb8F04], 0x072E ; .
; Enable long mode
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
mov cr0, ecx
lgdt [GDT64.Ptr]
; xor eax, eax
; sgdt [eax]
; test eax, eax
; jz .InvalidGDT
; .InvalidGDT:
; mov word [0xb8F07], 0x4 ; Red
; hlt
jmp GDT64.code:HigherHalfStart
[bits 64]
HigherHalfStart:
cli
; mov word [0xb8F06], 0x072E ; .
call UpdatePageTable64
; Load the new page table
mov rdi, BootPageTable
mov cr3, rdi
mov ax, GDT64.data
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; mov word [0xb8F08], 0x072E ; .
mov rsp, (KernelStack + KERNEL_STACK_SIZE)
mov rbp, (KernelStack + KERNEL_STACK_SIZE)
cld
cli
call Multiboot2Entry
.Loop:
hlt
jmp .Loop
section .bootstrap.bss
align 16
KernelStack:
resb KERNEL_STACK_SIZE
; 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

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,60 +0,0 @@
extern MB2_start
[bits 32]
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_ENTRY_TAG:
dw 3
dw 0
dd MB2_ENTRY_TAG_END - MB2_ENTRY_TAG
dd MB2_start
MB2_ENTRY_TAG_END:
align 8
MB2_FRAMEBUFFER_TAG_START:
dw 5
dw 1
dd MB2_FRAMEBUFFER_TAG_END - MB2_FRAMEBUFFER_TAG_START
dd 1280 ; Width
dd 720 ; Height
dd 32 ; Depth
MB2_FRAMEBUFFER_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,285 +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[511];
};
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[511];
};
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[511];
};
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[511];
} __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;
}
};
__always_inline inline SafeFunction NIF void 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();
{
void *ptr = PDPTEPtr;
int 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();
{
void *ptr = PDEPtr;
int 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();
{
void *ptr = PTEPtr;
int 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()
{
/*
TODO: this code corrupts the page table
*/
BPTable = (PageTable4 *)BootPageTable;
// for (size_t i = 0; i < 0x10000000; i += 0x1000)
// 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)
{
Map((void *)i, (void *)PhysicalStart, 0x3);
PhysicalStart += 0x1000;
}
asmv("mov %%cr3, %%rax\n"
"mov %%rax, %%cr3\n"
:
:
: "rax");
}

View File

@ -1,338 +0,0 @@
#include <types.h>
#include <boot/protocols/multiboot2.h>
#include <memory.hpp>
#include <io.h>
#include "../../../../kernel.h"
enum VideoType
{
VIDEO_TYPE_NONE = 0x00,
VIDEO_TYPE_COLOUR = 0x20,
VIDEO_TYPE_MONOCHROME = 0x30,
};
uint16_t GetBiosAreaHardware()
{
const uint16_t *BIOSDataAreaDetectedHardware = (const uint16_t *)0x410;
return *BIOSDataAreaDetectedHardware;
}
enum VideoType GetVideoType() { return (enum VideoType)(GetBiosAreaHardware() & 0x30); }
void GetSMBIOS()
{
unsigned char *SMBIOSAddress = (unsigned char *)0xF0000;
while ((unsigned int)(unsigned long)SMBIOSAddress < 0x100000)
{
if (SMBIOSAddress[0] == '_' &&
SMBIOSAddress[1] == 'S' &&
SMBIOSAddress[2] == 'M' &&
SMBIOSAddress[3] == '_')
{
unsigned char Checksum = 0;
int Length = SMBIOSAddress[5];
for (int i = 0; i < Length; i++)
Checksum += SMBIOSAddress[i];
if (Checksum == 0)
break;
}
SMBIOSAddress += 16;
}
if ((unsigned int)(unsigned long)SMBIOSAddress == 0x100000)
{
// No SMBIOS found
}
}
extern "C" unsigned int MB2_HeaderMagic;
extern "C" unsigned long MB2_HeaderInfo;
EXTERNC void Multiboot2Entry()
{
unsigned long Info = MB2_HeaderInfo;
unsigned int Magic = MB2_HeaderMagic;
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();
}
uint64_t div = 1193180 / 1000;
outb(0x43, 0xB6);
outb(0x42, (uint8_t)div);
outb(0x42, (uint8_t)(div >> 8));
uint8_t tmp = inb(0x61);
if (tmp != (tmp | 3))
outb(0x61, tmp | 3);
BootInfo mb2binfo;
uint8_t *VideoBuffer = (uint8_t *)0xB8F00;
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)))
{
VideoBuffer[pos++] = '.';
VideoBuffer[pos++] = 0x2;
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);
break;
}
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
{
multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag;
fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]",
meminfo->mem_lower, meminfo->mem_upper);
break;
}
case MULTIBOOT_TAG_TYPE_BOOTDEV:
{
multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag;
fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]",
bootdev->biosdev, bootdev->slice, bootdev->part);
break;
}
case MULTIBOOT_TAG_TYPE_MMAP:
{
multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag;
uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry);
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;
mb2binfo.Framebuffer[fb_count].MemoryModel = fb->common.framebuffer_type;
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;
}
}
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->[sections=%#lx num=%d, size=%d, entsize=%d, shndx=%d]",
&elf->sections, 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);
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,45 +0,0 @@
PAGE_TABLE_SIZE equ 0x8 ; 2GB
[bits 32]
section .bootstrap.bss
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, 11b | 10000000b ; 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

@ -6,7 +6,6 @@
#include <io.h>
#include "cpu/apic.hpp"
#include "../../kernel.h"
#define ACPI_TIMER 0x0001
#define ACPI_BUSMASTER 0x0010
@ -61,7 +60,6 @@ namespace ACPI
}
else if (Event & ACPI_POWER_BUTTON)
{
BeforeShutdown();
this->Shutdown();
Time::Clock tm = Time::ReadClock();
while (tm.Second == Time::ReadClock().Second)
@ -138,7 +136,7 @@ namespace ACPI
}
}
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt + CPU::x86::IRQ0)
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt + CPU::x64::IRQ0)
{
this->acpi = acpi;
uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt);

View File

@ -3,8 +3,8 @@
#include <debug.h>
#include <convert.h>
#include "../../../../tools/limine/limine.h"
#include "../../../kernel.h"
#include "../../../tools/limine/limine.h"
#include "../../kernel.h"
void init_limine();
@ -42,7 +42,7 @@ static volatile struct limine_smbios_request SmbiosRequest = {
.id = LIMINE_SMBIOS_REQUEST,
.revision = 0};
SafeFunction NIF void init_limine()
SafeFunction __no_instrument_function void init_limine()
{
struct BootInfo binfo;
struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response;

View File

@ -4,7 +4,7 @@
#include <types.h>
#include <boot/binfo.h>
#include <ints.hpp>
#include <interrupts.hpp>
#include <vector.hpp>
#include <cpu.hpp>

View File

@ -13,7 +13,6 @@
NewLock(APICLock);
using namespace CPU::x64;
using namespace CPU::x86;
/*
In constructor APIC::APIC::APIC(int):
@ -238,42 +237,13 @@ namespace APIC
this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u;
trace("APIC Address: %#lx", this->APICBaseAddress);
bool x2APICSupported = false;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
uint32_t rcx;
cpuid(1, 0, 0, &rcx, 0);
if (rcx & CPUID_FEAT_RCX_x2APIC)
{
#if defined(a64)
CPU::x64::AMD::CPUID0x1 cpuid1amd;
#elif defined(a32)
CPU::x32::AMD::CPUID0x1 cpuid1amd;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
: "a"(0x1));
#endif
// FIXME: Not sure if I configured this correctly or something else is wrong
// x2APICSupported = cpuid1amd.ECX.x2APIC;
fixme("AMD does even support x2APIC? ECX->Reserved10: %#lx", cpuid1amd.ECX.Reserved10);
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
#if defined(a64)
CPU::x64::Intel::CPUID0x1 cpuid1intel;
#elif defined(a32)
CPU::x32::Intel::CPUID0x1 cpuid1intel;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
: "a"(0x1));
#endif
x2APICSupported = cpuid1intel.ECX.x2APIC;
}
if (x2APICSupported)
{
this->x2APICSupported = true;
wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
// this->x2APICSupported = true;
warn("x2APIC not supported yet.");
// wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
BaseStruct.EN = 1;
wrmsr(MSR_APIC_BASE, BaseStruct.raw);
}
@ -331,7 +301,7 @@ namespace APIC
APIC::~APIC() {}
void Timer::OnInterruptReceived(TrapFrame *Frame) { UNUSED(Frame); }
void Timer::OnInterruptReceived(TrapFrame *Frame) {}
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
{
@ -358,7 +328,7 @@ namespace APIC
this->lapic->Write(APIC_TDCR, Divider);
this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
TimeManager->Sleep(1);
TimeManager->Sleep(10);
// Mask the timer
this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);

View File

@ -75,7 +75,7 @@ namespace GlobalDescriptorTable
// tss
{}};
GlobalDescriptorTableEntries GDTEntries[MAX_CPU];
static GlobalDescriptorTableEntries GDTEntries[MAX_CPU];
GlobalDescriptorTableDescriptor gdt[MAX_CPU];
TaskStateSegment tss[MAX_CPU] = {
@ -85,7 +85,6 @@ namespace GlobalDescriptorTable
{0, 0, 0, 0, 0, 0, 0},
0,
0,
0,
};
void *CPUStackPointer[MAX_CPU];
@ -115,8 +114,6 @@ namespace GlobalDescriptorTable
: "memory", "rax");
CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
memset(CPUStackPointer[Core], 0, STACK_SIZE);
debug("CPU %d Stack Pointer: %#lx", Core, CPUStackPointer[Core]);
uint64_t Base = (uint64_t)&tss[Core];
uint64_t Limit = Base + sizeof(TaskStateSegment);
@ -133,32 +130,24 @@ namespace GlobalDescriptorTable
tss[Core].InterruptStackTable[0] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
tss[Core].InterruptStackTable[1] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
tss[Core].InterruptStackTable[2] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
memset((void *)(tss[Core].InterruptStackTable[0] - STACK_SIZE), 0, STACK_SIZE);
memset((void *)(tss[Core].InterruptStackTable[1] - STACK_SIZE), 0, STACK_SIZE);
memset((void *)(tss[Core].InterruptStackTable[2] - STACK_SIZE), 0, STACK_SIZE);
CPU::x64::ltr(GDT_TSS);
asmv("mov %%rsp, %0"
: "=r"(tss[Core].StackPointer[0]));
debug("GDT_KERNEL_CODE: %#lx", GDT_KERNEL_CODE);
debug("GDT_KERNEL_DATA: %#lx", GDT_KERNEL_DATA);
debug("GDT_USER_CODE: %#lx", GDT_USER_CODE);
debug("GDT_USER_DATA: %#lx", GDT_USER_DATA);
debug("GDT_TSS: %#lx", GDT_TSS);
debug("Global Descriptor Table initialized");
trace("GDT_KERNEL_CODE: %#lx", GDT_KERNEL_CODE);
trace("GDT_KERNEL_DATA: %#lx", GDT_KERNEL_DATA);
trace("GDT_USER_CODE: %#lx", GDT_USER_CODE);
trace("GDT_USER_DATA: %#lx", GDT_USER_DATA);
trace("GDT_TSS: %#lx", GDT_TSS);
trace("Global Descriptor Table initialized");
}
SafeFunction void SetKernelStack(void *Stack)
{
long CPUID = GetCurrentCPU()->ID;
if (Stack != nullptr)
tss[CPUID].StackPointer[0] = (uint64_t)Stack;
if (Stack)
tss[GetCurrentCPU()->ID].StackPointer[0] = (uint64_t)Stack;
else
tss[CPUID].StackPointer[0] = (uint64_t)CPUStackPointer[CPUID] + STACK_SIZE;
// TODO: This may cause problems in the future I guess? This should be checked later
asmv("mov %%rsp, %0"
: "=r"(tss[CPUID].StackPointer[0]));
tss[GetCurrentCPU()->ID].StackPointer[0] = (uint64_t)CPUStackPointer[GetCurrentCPU()->ID] + STACK_SIZE;
}
}

View File

@ -1,6 +1,5 @@
#include "idt.hpp"
#include <memory.hpp>
#include <cpu.hpp>
#include <debug.h>
#include <io.h>
@ -94,27 +93,13 @@ namespace InterruptDescriptorTable
// "swapgs\n"
// ".skip_swap_check_2:\n"
"iretq"); // pop CS RIP RFLAGS SS RSP
"iretq"); // pop CS RIP RFLAGS SS ESP
}
extern "C" void WarnSwapgs() { warn("swapgs"); }
// void *OriginalCR3;
extern "C" __attribute__((naked, used, no_stack_protector)) void InterruptHandlerStub()
{
// // Store cr3 to OriginalCR3
// asmv("mov %%cr3, %0"
// : "=q"(OriginalCR3)
// :
// : "memory");
// // Set cr3 to KPT (Kernel Page Table)
// asmv("mov %0, %%cr3"
// :
// : "q"(KPT)
// : "memory");
// GlobalDescriptorTable::SetKernelStack(nullptr);
asm(
// "cmp $0x1000, %rsp\n"
// "jng .skip_swap_check__1\n"
@ -142,28 +127,9 @@ namespace InterruptDescriptorTable
"pushq %r15\n"
"movq %rsp, %rdi\n"
"call MainInterruptHandler\n");
"call MainInterruptHandler\n"
// // Check if the current cr3 is the same as the KPT
// // If not, then we need to restore the cr3
// asmv("pushq %rax\n" // push rax
// "pushq %rbx\n" // push rbx
// "movq %cr3, %rbx\n"); // mov cr3 to rbx
// asmv("movq %0, %%rax\n" // mov KPT to rax
// :
// : "q"(KPT)
// : "memory");
// asmv("cmpq %rax, %rbx\n" // compare cr3 to rax
// "jne .skip_restore_cr3\n"); // if not equal, skip restore cr3
// asmv("movq %0, %%cr3\n" // restore cr3
// :
// : "q"(OriginalCR3)
// : "memory");
// asm(".skip_restore_cr3:\n" // skip restore cr3 label
// "popq %rax\n" // KPT
// "popq %rbx\n"); // cr3
asm("popq %r15\n"
"popq %r15\n"
"popq %r14\n"
"popq %r13\n"
"popq %r12\n"
@ -487,7 +453,6 @@ namespace InterruptDescriptorTable
void Init(int Core)
{
UNUSED(Core);
static int once = 0;
if (!once++)
{

View File

@ -1,6 +1,6 @@
#include <smp.hpp>
#include <ints.hpp>
#include <interrupts.hpp>
#include <memory.hpp>
#include <assert.h>
#include <cpu.hpp>
@ -27,30 +27,34 @@ volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
SafeFunction CPUData *GetCPU(long id) { return &CPUs[id]; }
SafeFunction CPUData *GetCurrentCPU()
CPUData *GetCPU(long id) { return &CPUs[id]; }
CPUData *GetCurrentCPU()
{
if (unlikely(!Interrupts::apic[0]))
return &CPUs[0]; /* No APIC means we are on the BSP. */
int CoreID = ((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24;
CPUData *data = (CPUData *)CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE);
if (unlikely((&CPUs[CoreID])->IsActive != true))
if (data == nullptr && Interrupts::apic[0])
data = &CPUs[((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24];
if (data == nullptr)
return nullptr; // The caller should handle this.
if (!data->IsActive)
{
error("CPU %d is not active!", CoreID);
assert((&CPUs[0])->IsActive == true); /* We can't continue without the BSP. */
error("CPU %d is not active!", data->ID);
if ((&CPUs[0])->IsActive)
return &CPUs[0];
else
return nullptr; // We are in trouble.
}
assert((&CPUs[CoreID])->Checksum == CPU_DATA_CHECKSUM); /* This should never happen. */
return &CPUs[CoreID];
assert(data->Checksum == CPU_DATA_CHECKSUM); // This should never happen.
return data;
}
extern "C" void StartCPU()
{
CPU::Interrupts(CPU::Disable);
CPU::InitializeFeatures();
uint64_t CoreID = (int)*reinterpret_cast<int *>(CORE);
CPU::InitializeFeatures(CoreID);
// Initialize GDT and IDT
Interrupts::Initialize(CoreID);
Interrupts::Enable(CoreID);
@ -68,6 +72,12 @@ namespace SMP
void Initialize(void *madt)
{
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) == 0)
{
KPrint("VirtualBox detected, disabling SMP");
return;
}
int Cores = ((ACPI::MADT *)madt)->CPUCores + 1;
if (Config.Cores > ((ACPI::MADT *)madt)->CPUCores + 1)

View File

@ -3,7 +3,7 @@
#include <types.h>
#include <ints.hpp>
#include <interrupts.hpp>
#include <cpu.hpp>
namespace 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

@ -92,8 +92,7 @@ namespace GlobalDescriptorTable
uint64_t StackPointer[3];
uint64_t Reserved1;
uint64_t InterruptStackTable[7];
uint64_t Reserved2;
uint16_t Reserved3;
uint16_t Reserved2;
uint16_t IOMapBaseAddressOffset;
} __attribute__((packed)) TaskStateSegment;
@ -132,7 +131,6 @@ namespace GlobalDescriptorTable
} __attribute__((packed)) GlobalDescriptorTableDescriptor;
extern void *CPUStackPointer[];
extern TaskStateSegment tss[];
void Init(int Core);
void SetKernelStack(void *Stack);
}

View File

@ -1,53 +1,35 @@
OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64)
KERNEL_LMA = 16M;
KERNEL_VMA = 0xFFFFFFFF80000000;
ENTRY(_start)
SECTIONS
{
. = KERNEL_LMA;
.multiboot2 :
{
*(.multiboot2 .multiboot2.*)
}
.bootstrap :
{
*(.bootstrap.text .bootstrap.text.*)
*(.bootstrap.data .bootstrap.data.*)
*(.bootstrap.rodata .bootstrap.rodata.*)
*(.bootstrap.bss .bootstrap.bss.*)
}
. += KERNEL_VMA;
. = 0xffffffff80000000;
_kernel_start = .;
.text : AT(ADDR(.text) - KERNEL_VMA)
.text :
{
*(.text .text.*)
}
_kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.data : AT(ADDR(.data) - KERNEL_VMA)
.data :
{
*(.data .data.*)
}
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.rodata : AT(ADDR(.rodata) - KERNEL_VMA)
.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 = .);
KEEP(*(.init_array .ctors))
@ -55,7 +37,7 @@ SECTIONS
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array : AT(ADDR(.fini_array) - KERNEL_VMA)
.fini_array :
{
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
@ -64,7 +46,8 @@ SECTIONS
}
. += CONSTANT(MAXPAGESIZE);
.bss : AT(ADDR(.bss) - KERNEL_VMA)
.bss :
{
*(COMMON)
*(.bss .bss.*)

View File

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

View File

@ -158,7 +158,7 @@ int __ctzdi2(arith64_u64 a)
arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c)
{
if (b > a)
if (b > a) //
{
if (c)
*c = a;
@ -283,45 +283,3 @@ int __gedf2(double a, double b) { return a >= b; }
int __fixdfsi(double a) { return (int)a; }
long __fixdfdi(double a) { return (long)a; }
int __ledf2(double a, double b) { return a <= b; }
/* 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,54 +0,0 @@
; https://wiki.osdev.org/Higher_Half_x86_Bare_Bones
; https://wiki.osdev.org/Higher_Half_x86_Bare_Bones_(Backup)
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
extern Multiboot2Entry
extern BootPageTable
global MB2_start
section .text
MB2_start:
cli
mov word [0xb8F00], 0x072E ; .
mov ecx, (BootPageTable - KERNEL_VIRTUAL_BASE)
mov cr3, ecx
mov word [0xb8F02], 0x072E ; .
mov ecx, cr4
or ecx, 0x00000010 ; Set PSE in CR4
mov cr4, ecx
mov word [0xb8F04], 0x072E ; .
mov ecx, cr0
or ecx, 0x80000000 ; Set PG in CR0
mov cr0, ecx
mov word [0xb8F06], 0x072E ; .
lea ecx, [HigherHalfStart]
jmp ecx
HigherHalfStart:
mov word [0xb8F08], 0x072E ; .
mov dword [BootPageTable], 0
invlpg [0]
mov esp, KernelStack + KERNEL_STACK_SIZE
push eax ; Multiboot2 Magic
add ebx, KERNEL_VIRTUAL_BASE
push ebx ; Multiboot2 Header
call Multiboot2Entry
Loop:
hlt
jmp Loop
section .bss
align 16
KernelStack:
resb KERNEL_STACK_SIZE

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,13 +0,0 @@
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB
KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; 768
section .data
global BootPageTable
align 0x1000
BootPageTable:
dd 0x00000083
dd 0x00000083
times (KERNEL_PAGE_NUMBER - 2) dd 0
dd 0x00000083
dd 0x00000083
times (1024 - KERNEL_PAGE_NUMBER - 2) dd 0

View File

@ -1,12 +1,9 @@
#include <types.h>
#include <boot/protocols/multiboot2.h>
#include <memory.hpp>
#include <io.h>
#include "../../../kernel.h"
BootInfo mb2binfo;
#include "../../kernel.h"
enum VideoType
{
@ -50,52 +47,72 @@ void GetSMBIOS()
}
}
void ProcessMB2(unsigned long Info)
struct multiboot_info
{
uint8_t *VideoBuffer = (uint8_t *)0xB8F00 + 0xC0000000;
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)))
{
VideoBuffer[pos++] = '.';
VideoBuffer[pos++] = 0x2;
multiboot_uint32_t Size;
multiboot_uint32_t Reserved;
struct multiboot_tag *Tag;
};
if (Tag->type == MULTIBOOT_TAG_TYPE_END)
EXTERNC void x32Multiboot2Entry(multiboot_info *Info, unsigned int Magic)
{
if (Info == NULL || Magic == NULL)
{
debug("End of multiboot2 tags");
break;
if (Magic == NULL)
error("Multiboot magic is NULL");
if (Info == NULL)
error("Multiboot info is NULL");
CPU::Stop();
}
else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC)
{
error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC);
trace("Hello, World!");
CPU::Stop();
}
uint64_t div = 1193180 / 1000;
outb(0x43, 0xB6);
outb(0x42, (uint8_t)div);
outb(0x42, (uint8_t)(div >> 8));
uint8_t tmp = inb(0x61);
if (tmp != (tmp | 3))
outb(0x61, tmp | 3);
BootInfo binfo;
uint32_t Itr = 0;
for (uint32_t i = 8; i < Info->Size; i += Itr)
{
multiboot_tag *Tag = (multiboot_tag *)((uint8_t *)Info + i);
if (Tag->type == MULTIBOOT_TAG_TYPE_END)
break;
switch (Tag->type)
{
case MULTIBOOT_TAG_TYPE_CMDLINE:
{
strncpy(mb2binfo.Kernel.CommandLine,
strncpy(binfo.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,
strncpy(binfo.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 *)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,
binfo.Modules[module_count++].Address = (void *)module->mod_start;
binfo.Modules[module_count++].Size = module->size;
strncpy(binfo.Modules[module_count++].Path, "(null)", 6);
strncpy(binfo.Modules[module_count++].CommandLine, module->cmdline,
strlen(module->cmdline));
debug("Module: %s", mb2binfo.Modules[module_count++].Path);
break;
}
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
@ -116,7 +133,8 @@ void ProcessMB2(unsigned long Info)
{
multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag;
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++)
{
if (EntryCount > MAX_MEMORY_ENTRIES)
@ -124,45 +142,42 @@ void ProcessMB2(unsigned long Info)
warn("Too many memory entries, skipping the rest...");
break;
}
multiboot_mmap_entry entry = mmap->entries[i];
mb2binfo.Memory.Size += entry.len;
binfo.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;
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.Memory.Entry[i].Type = Usable;
break;
case MULTIBOOT_MEMORY_RESERVED:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = Reserved;
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.Memory.Entry[i].Type = Reserved;
break;
case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = ACPIReclaimable;
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.Memory.Entry[i].Type = ACPIReclaimable;
break;
case MULTIBOOT_MEMORY_NVS:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = ACPINVS;
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.Memory.Entry[i].Type = ACPINVS;
break;
case MULTIBOOT_MEMORY_BADRAM:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = BadMemory;
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.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;
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
binfo.Memory.Entry[i].Length = entry.len;
binfo.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;
}
@ -177,12 +192,14 @@ void ProcessMB2(unsigned long Info)
{
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;
mb2binfo.Framebuffer[fb_count].MemoryModel = fb->common.framebuffer_type;
binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width;
binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height;
binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch;
binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp;
binfo.Framebuffer[fb_count].MemoryModel = fb->common.framebuffer_type;
switch (fb->common.framebuffer_type)
{
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
@ -192,12 +209,12 @@ void ProcessMB2(unsigned long Info)
}
case MULTIBOOT_FRAMEBUFFER_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;
binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size;
binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position;
binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size;
binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position;
binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size;
binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
@ -206,11 +223,12 @@ void ProcessMB2(unsigned long Info)
break;
}
}
debug("Framebuffer %d: %dx%d %d bpp", Tag, 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",
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;
}
@ -248,14 +266,12 @@ void ProcessMB2(unsigned long Info)
}
case MULTIBOOT_TAG_TYPE_ACPI_OLD:
{
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
debug("OLD ACPI RSDP: %p", mb2binfo.RSDP);
binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->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);
binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
break;
}
case MULTIBOOT_TAG_TYPE_NETWORK:
@ -291,49 +307,37 @@ void ProcessMB2(unsigned long Info)
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 *)load_base_addr->load_base_addr;
mb2binfo.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);
binfo.Kernel.PhysicalBase = (void *)load_base_addr->load_base_addr;
binfo.Kernel.VirtualBase = (void *)(load_base_addr->load_base_addr + 0xC0000000);
break;
}
}
Itr = Tag->size;
if ((Itr % 8) != 0)
Itr += (8 - Itr % 8);
}
}
EXTERNC void Multiboot2Entry(unsigned long Info, unsigned int Magic)
{
if (Info == NULL || Magic == NULL)
{
if (Magic == NULL)
error("Multiboot magic is NULL");
if (Info == NULL)
error("Multiboot info is NULL");
CPU::Stop();
}
else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC)
{
error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC);
CPU::Stop();
}
uint64_t div = 1193180 / 1000;
outb(0x43, 0xB6);
outb(0x42, (uint8_t)div);
outb(0x42, (uint8_t)(div >> 8));
uint8_t tmp = inb(0x61);
if (tmp != (tmp | 3))
outb(0x61, tmp | 3);
ProcessMB2(Info);
tmp = inb(0x61) & 0xFC;
outb(0x61, tmp);
int *vm = (int *)0xb8000;
// "Not supported yet"
vm[0] = 0x054E;
vm[1] = 0x056F;
vm[2] = 0x0574;
vm[3] = 0x0520;
vm[4] = 0x0573;
vm[5] = 0x0575;
vm[6] = 0x0570;
vm[7] = 0x0570;
vm[8] = 0x0572;
vm[9] = 0x056F;
vm[10] = 0x0574;
vm[11] = 0x0520;
vm[12] = 0x0579;
vm[13] = 0x0565;
vm[14] = 0x0574;
CPU::Stop();
Entry(&mb2binfo);
// Entry(&binfo);
}

View File

@ -1,99 +0,0 @@
#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,6 +1,6 @@
#include <smp.hpp>
#include <ints.hpp>
#include <interrupts.hpp>
#include <memory.hpp>
#include <assert.h>
#include <cpu.hpp>

View File

@ -3,7 +3,7 @@
#include <types.h>
#include <ints.hpp>
#include <interrupts.hpp>
#include <cpu.hpp>
namespace APIC
@ -324,7 +324,7 @@ namespace APIC
private:
APIC *lapic;
uint64_t Ticks = 0;
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
public:
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

@ -5,141 +5,7 @@
namespace GlobalDescriptorTable
{
/** @brief The GDT Access Table
* @details For more information, see https://wiki.osdev.org/Global_Descriptor_Table
*/
union GlobalDescriptorTableAccess
{
struct
{
/** @brief Access bit.
* @note The CPU sets this bit to 1 when the segment is accessed.
*/
uint8_t A : 1;
/** @brief Readable bit for code segments, writable bit for data segments.
* @details For code segments, this bit must be 1 for the segment to be readable.
* @details For data segments, this bit must be 1 for the segment to be writable.
*/
uint8_t RW : 1;
/** @brief Direction bit for data segments, conforming bit for code segments.
* @details For data segments, this bit must be 1 for the segment to grow up (higher addresses).
* @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level.
*/
uint8_t DC : 1;
/** @brief Executable bit.
* @details This bit must be 1 for code-segment descriptors.
* @details This bit must be 0 for data-segment and system descriptors.
*/
uint8_t E : 1;
/** @brief Descriptor type.
* @details This bit must be 0 for system descriptors.
* @details This bit must be 1 for code or data segment descriptor.
*/
uint8_t S : 1;
/** @brief Descriptor privilege level.
* @details This field determines the privilege level of the segment.
* @details 0 = kernel mode, 3 = user mode.
*/
uint8_t DPL : 2;
/** @brief Present bit.
* @details This bit must be 1 for all valid descriptors.
*/
uint8_t P : 1;
} __attribute__((packed));
uint8_t Raw;
};
union GlobalDescriptorTableFlags
{
// TODO: Add more flags.
struct
{
/** @brief Unknown. */
uint8_t Unknown : 5;
/** @brief Long mode.
* @details If the long mode bit is clear, the segment is in 32-bit protected mode.
* @details If the long mode bit is set, the segment is in 64-bit long mode.
*/
uint8_t L : 1;
} __attribute__((packed));
uint8_t Raw;
};
typedef struct _TaskStateSegmentEntry
{
/* LOW */
uint16_t Length;
uint16_t BaseLow;
uint8_t BaseMiddle;
GlobalDescriptorTableAccess Flags;
uint8_t Granularity;
uint8_t BaseHigh;
/* HIGH */
uint32_t BaseUpper;
uint32_t Reserved;
} __attribute__((packed)) TaskStateSegmentEntry;
typedef struct _TaskStateSegment
{
uint32_t Reserved0 __attribute__((aligned(16)));
uint64_t StackPointer[3];
uint64_t Reserved1;
uint64_t InterruptStackTable[7];
uint16_t Reserved2;
uint16_t IOMapBaseAddressOffset;
} __attribute__((packed)) TaskStateSegment;
typedef struct _GlobalDescriptorTableEntry
{
/** @brief Length */
uint16_t Length;
/** @brief Low Base */
uint16_t BaseLow;
/** @brief Middle Base */
uint8_t BaseMiddle;
/** @brief Access */
GlobalDescriptorTableAccess Access;
/** @brief Flags */
GlobalDescriptorTableFlags Flags;
/** @brief High Base */
uint8_t BaseHigh;
} __attribute__((packed)) GlobalDescriptorTableEntry;
typedef struct _GlobalDescriptorTableEntries
{
GlobalDescriptorTableEntry Null;
GlobalDescriptorTableEntry Code;
GlobalDescriptorTableEntry Data;
GlobalDescriptorTableEntry UserData;
GlobalDescriptorTableEntry UserCode;
TaskStateSegmentEntry TaskStateSegment;
} __attribute__((packed)) GlobalDescriptorTableEntries;
typedef struct _GlobalDescriptorTableDescriptor
{
/** @brief GDT entries length */
uint16_t Length;
/** @brief GDT entries address */
GlobalDescriptorTableEntries *Entries;
} __attribute__((packed)) GlobalDescriptorTableDescriptor;
extern void *CPUStackPointer[];
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,7 +1,7 @@
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386)
ENTRY(MB2_start)
ENTRY(_start)
SECTIONS
{
@ -27,23 +27,6 @@ SECTIONS
}
_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 = .);
}
. += CONSTANT(MAXPAGESIZE);
.bss ALIGN (4096) : AT(ADDR(.bss) - 0xC0000000)
{
*(COMMON)

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

@ -3,30 +3,27 @@
#include <memory.hpp>
#include <convert.h>
#include <debug.h>
#include <smp.hpp>
#include "../kernel.h"
namespace CPU
{
static bool SSEEnabled = false;
char *Vendor()
{
static char Vendor[13];
#if defined(a64)
uint32_t eax, ebx, ecx, edx;
x64::cpuid(0x0, &eax, &ebx, &ecx, &edx);
memcpy_unsafe(Vendor + 0, &ebx, 4);
memcpy_unsafe(Vendor + 4, &edx, 4);
memcpy_unsafe(Vendor + 8, &ecx, 4);
#elif defined(a32)
uint32_t eax, ebx, ecx, edx;
x32::cpuid(0x0, &eax, &ebx, &ecx, &edx);
memcpy_unsafe(Vendor + 0, &ebx, 4);
memcpy_unsafe(Vendor + 4, &edx, 4);
memcpy_unsafe(Vendor + 8, &ecx, 4);
#elif defined(aa64)
#if defined(__amd64__)
uint32_t rax, rbx, rcx, rdx;
x64::cpuid(0x0, &rax, &rbx, &rcx, &rdx);
memcpy(Vendor + 0, &rbx, 4);
memcpy(Vendor + 4, &rdx, 4);
memcpy(Vendor + 8, &rcx, 4);
#elif defined(__i386__)
uint32_t rax, rbx, rcx, rdx;
x32::cpuid(0x0, &rax, &rbx, &rcx, &rdx);
memcpy(Vendor + 0, &rbx, 4);
memcpy(Vendor + 4, &rdx, 4);
memcpy(Vendor + 8, &rcx, 4);
#elif defined(__aarch64__)
asmv("mrs %0, MIDR_EL1"
: "=r"(Vendor[0]));
#endif
@ -36,41 +33,41 @@ namespace CPU
char *Name()
{
static char Name[49];
#if defined(a64)
uint32_t eax, ebx, ecx, edx;
x64::cpuid(0x80000002, &eax, &ebx, &ecx, &edx);
memcpy_unsafe(Name + 0, &eax, 4);
memcpy_unsafe(Name + 4, &ebx, 4);
memcpy_unsafe(Name + 8, &ecx, 4);
memcpy_unsafe(Name + 12, &edx, 4);
x64::cpuid(0x80000003, &eax, &ebx, &ecx, &edx);
memcpy_unsafe(Name + 16, &eax, 4);
memcpy_unsafe(Name + 20, &ebx, 4);
memcpy_unsafe(Name + 24, &ecx, 4);
memcpy_unsafe(Name + 28, &edx, 4);
x64::cpuid(0x80000004, &eax, &ebx, &ecx, &edx);
memcpy_unsafe(Name + 32, &eax, 4);
memcpy_unsafe(Name + 36, &ebx, 4);
memcpy_unsafe(Name + 40, &ecx, 4);
memcpy_unsafe(Name + 44, &edx, 4);
#elif defined(a32)
uint32_t eax, ebx, ecx, edx;
x32::cpuid(0x80000002, &eax, &ebx, &ecx, &edx);
memcpy_unsafe(Name + 0, &eax, 4);
memcpy_unsafe(Name + 4, &ebx, 4);
memcpy_unsafe(Name + 8, &ecx, 4);
memcpy_unsafe(Name + 12, &edx, 4);
x32::cpuid(0x80000003, &eax, &ebx, &ecx, &edx);
memcpy_unsafe(Name + 16, &eax, 4);
memcpy_unsafe(Name + 20, &ebx, 4);
memcpy_unsafe(Name + 24, &ecx, 4);
memcpy_unsafe(Name + 28, &edx, 4);
x32::cpuid(0x80000004, &eax, &ebx, &ecx, &edx);
memcpy_unsafe(Name + 32, &eax, 4);
memcpy_unsafe(Name + 36, &ebx, 4);
memcpy_unsafe(Name + 40, &ecx, 4);
memcpy_unsafe(Name + 44, &edx, 4);
#elif defined(aa64)
#if defined(__amd64__)
uint32_t rax, rbx, rcx, rdx;
x64::cpuid(0x80000002, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 0, &rax, 4);
memcpy(Name + 4, &rbx, 4);
memcpy(Name + 8, &rcx, 4);
memcpy(Name + 12, &rdx, 4);
x64::cpuid(0x80000003, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 16, &rax, 4);
memcpy(Name + 20, &rbx, 4);
memcpy(Name + 24, &rcx, 4);
memcpy(Name + 28, &rdx, 4);
x64::cpuid(0x80000004, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 32, &rax, 4);
memcpy(Name + 36, &rbx, 4);
memcpy(Name + 40, &rcx, 4);
memcpy(Name + 44, &rdx, 4);
#elif defined(__i386__)
uint32_t rax, rbx, rcx, rdx;
x32::cpuid(0x80000002, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 0, &rax, 4);
memcpy(Name + 4, &rbx, 4);
memcpy(Name + 8, &rcx, 4);
memcpy(Name + 12, &rdx, 4);
x32::cpuid(0x80000003, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 16, &rax, 4);
memcpy(Name + 20, &rbx, 4);
memcpy(Name + 24, &rcx, 4);
memcpy(Name + 28, &rdx, 4);
x32::cpuid(0x80000004, &rax, &rbx, &rcx, &rdx);
memcpy(Name + 32, &rax, 4);
memcpy(Name + 36, &rbx, 4);
memcpy(Name + 40, &rcx, 4);
memcpy(Name + 44, &rdx, 4);
#elif defined(__aarch64__)
asmv("mrs %0, MIDR_EL1"
: "=r"(Name[0]));
#endif
@ -80,19 +77,19 @@ namespace CPU
char *Hypervisor()
{
static char Hypervisor[13];
#if defined(a64)
uint32_t eax, ebx, ecx, edx;
x64::cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
memcpy_unsafe(Hypervisor + 0, &ebx, 4);
memcpy_unsafe(Hypervisor + 4, &ecx, 4);
memcpy_unsafe(Hypervisor + 8, &edx, 4);
#elif defined(a32)
uint32_t eax, ebx, ecx, edx;
x64::cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
memcpy_unsafe(Hypervisor + 0, &ebx, 4);
memcpy_unsafe(Hypervisor + 4, &ecx, 4);
memcpy_unsafe(Hypervisor + 8, &edx, 4);
#elif defined(aa64)
#if defined(__amd64__)
uint32_t rax, rbx, rcx, rdx;
x64::cpuid(0x40000000, &rax, &rbx, &rcx, &rdx);
memcpy(Hypervisor + 0, &rbx, 4);
memcpy(Hypervisor + 4, &rcx, 4);
memcpy(Hypervisor + 8, &rdx, 4);
#elif defined(__i386__)
uint32_t rax, rbx, rcx, rdx;
x64::cpuid(0x40000000, &rax, &rbx, &rcx, &rdx);
memcpy(Hypervisor + 0, &rbx, 4);
memcpy(Hypervisor + 4, &rcx, 4);
memcpy(Hypervisor + 8, &rdx, 4);
#elif defined(__aarch64__)
asmv("mrs %0, MIDR_EL1"
: "=r"(Hypervisor[0]));
#endif
@ -105,37 +102,39 @@ namespace CPU
{
case Check:
{
uintptr_t Flags;
#if defined(a64)
#if defined(__amd64__)
uint64_t rflags;
asmv("pushfq");
asmv("popq %0"
: "=r"(Flags));
return Flags & (1 << 9);
#elif defined(a32)
: "=r"(rflags));
return rflags & (1 << 9);
#elif defined(__i386__)
uint32_t rflags;
asmv("pushfl");
asmv("popl %0"
: "=r"(Flags));
return Flags & (1 << 9);
#elif defined(aa64)
: "=r"(rflags));
return rflags & (1 << 9);
#elif defined(__aarch64__)
uint64_t daif;
asmv("mrs %0, daif"
: "=r"(Flags));
return !(Flags & (1 << 2));
: "=r"(daif));
return !(daif & (1 << 2));
#endif
}
case Enable:
{
#if defined(a64) || defined(a32)
#if defined(__amd64__) || defined(__i386__)
asmv("sti");
#elif defined(aa64)
#elif defined(__aarch64__)
asmv("msr daifclr, #2");
#endif
return true;
}
case Disable:
{
#if defined(a64) || defined(a32)
#if defined(__amd64__) || defined(__i386__)
asmv("cli");
#elif defined(aa64)
#elif defined(__aarch64__)
asmv("msr daifset, #2");
#endif
return true;
@ -146,7 +145,7 @@ namespace CPU
void *PageTable(void *PT)
{
#if defined(a64)
#if defined(__amd64__)
if (PT)
asmv("movq %0, %%cr3"
:
@ -154,7 +153,7 @@ namespace CPU
else
asmv("movq %%cr3, %0"
: "=r"(PT));
#elif defined(a32)
#elif defined(__i386__)
if (PT)
asmv("movl %0, %%cr3"
:
@ -162,7 +161,7 @@ namespace CPU
else
asmv("movl %%cr3, %0"
: "=r"(PT));
#elif defined(aa64)
#elif defined(__aarch64__)
if (PT)
asmv("msr ttbr0_el1, %0"
:
@ -174,57 +173,15 @@ namespace CPU
return PT;
}
void InitializeFeatures(long Core)
void InitializeFeatures()
{
bool PGESupport = false;
bool SSESupport = false;
#if defined(a64)
#if defined(__amd64__)
static int BSP = 0;
x64::CR0 cr0 = x64::readcr0();
x64::CR4 cr4 = x64::readcr4();
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
#if defined(a64)
CPU::x64::AMD::CPUID0x1 cpuid1amd;
#elif defined(a32)
CPU::x32::AMD::CPUID0x1 cpuid1amd;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
: "a"(0x1));
#endif
if (cpuid1amd.EDX.PGE)
PGESupport = true;
if (cpuid1amd.EDX.SSE)
SSESupport = true;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
#if defined(a64)
CPU::x64::Intel::CPUID0x1 cpuid1intel;
#elif defined(a32)
CPU::x32::Intel::CPUID0x1 cpuid1intel;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
: "a"(0x1));
#endif
if (cpuid1intel.EDX.PGE)
PGESupport = true;
if (cpuid1intel.EDX.SSE)
SSESupport = true;
}
if (Config.SIMD == false)
{
debug("Disabling SSE support...");
SSESupport = false;
}
if (PGESupport)
uint32_t rax, rbx, rcx, rdx;
x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx);
if (rdx & x64::CPUID_FEAT_RDX_PGE)
{
debug("Enabling global pages support...");
if (!BSP)
@ -232,12 +189,7 @@ namespace CPU
cr4.PGE = 1;
}
bool SSEEnableAfter = false;
/* 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)
if (rdx & x64::CPUID_FEAT_RDX_SSE)
{
debug("Enabling SSE support...");
if (!BSP)
@ -246,16 +198,6 @@ namespace CPU
cr0.MP = 1;
cr4.OSFXSR = 1;
cr4.OSXMMEXCPT = 1;
CPUData *CoreData = GetCPU(Core);
CoreData->Data.FPU = (CPU::x64::FXState *)KernelAllocator.RequestPages(TO_PAGES(sizeof(CPU::x64::FXState)));
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)
@ -267,46 +209,39 @@ namespace CPU
x64::writecr0(cr0);
// FIXME: I don't think this is reporting correctly. This has to be fixed asap.
debug("Enabling UMIP, SMEP & SMAP support...");
uint32_t eax, ebx, ecx, edx;
x64::cpuid(0x1, &eax, &ebx, &ecx, &edx);
if (edx & (1 << 2)) // https://en.wikipedia.org/wiki/Control_register
x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx);
if (rdx & x64::CPUID_FEAT_RDX_UMIP)
{
if (!BSP)
KPrint("UMIP is supported.");
debug("UMIP is supported.");
fixme("Not going to enable UMIP.");
// cr4.UMIP = 1;
}
if (edx & (1 << 7)) // https://en.wikipedia.org/wiki/Control_register#SMEP
// https://web.archive.org/web/20160312223150/http://ncsi.com/nsatc11/presentations/wednesday/emerging_technologies/fischer.pdf
if (rdx & x64::CPUID_FEAT_RDX_SMEP)
{
if (!BSP)
KPrint("SMEP is supported.");
debug("SMEP is supported.");
fixme("Not going to enable SMEP.");
// cr4.SMEP = 1;
}
if (edx & (1 << 20)) // https://en.wikipedia.org/wiki/Supervisor_Mode_Access_Prevention
if (rdx & x64::CPUID_FEAT_RDX_SMAP)
{
if (!BSP)
KPrint("SMAP is supported.");
debug("SMAP is supported.");
fixme("Not going to enable SMAP.");
// cr4.SMAP = 1;
}
if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0 &&
strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
{
debug("Writing CR4...");
x64::writecr4(cr4);
debug("Wrote CR4.");
}
else
{
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");
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");
}
}
@ -314,176 +249,26 @@ namespace CPU
x64::wrmsr(x64::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16));
if (!BSP++)
trace("Features for BSP initialized.");
if (SSEEnableAfter)
SSEEnabled = true;
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#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)
uintptr_t Counter;
#if defined(a64)
#if defined(__amd64__)
uint64_t counter;
asmv("rdtsc"
: "=A"(Counter));
#elif defined(a32)
asmv("rdtsc"
: "=A"(Counter));
#elif defined(aa64)
: "=A"(counter));
return counter;
#elif defined(__i386__)
return 0;
#elif defined(__aarch64__)
uint64_t counter;
asmv("mrs %0, cntvct_el0"
: "=r"(Counter));
: "=r"(counter));
return counter;
#endif
return Counter;
}
x86SIMDType CheckSIMD()
{
#if defined(a32)
return SIMD_NONE; /* TODO: Support x86 SIMD on x32 */
#endif
if (unlikely(!SSEEnabled))
return SIMD_NONE;
static x86SIMDType SIMDType = SIMD_NONE;
if (likely(SIMDType != SIMD_NONE))
return SIMDType;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
#if defined(a64)
CPU::x64::AMD::CPUID0x1 cpuid1amd;
#elif defined(a32)
CPU::x32::AMD::CPUID0x1 cpuid1amd;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
: "a"(0x1));
#endif
if (cpuid1amd.ECX.SSE4_2)
SIMDType = SIMD_SSE42;
else if (cpuid1amd.ECX.SSE4_1)
SIMDType = SIMD_SSE41;
else if (cpuid1amd.ECX.SSE3)
SIMDType = SIMD_SSE3;
else if (cpuid1amd.EDX.SSE2)
SIMDType = SIMD_SSE2;
else if (cpuid1amd.EDX.SSE)
SIMDType = SIMD_SSE;
#ifdef DEBUG
if (cpuid1amd.ECX.SSE4_2)
debug("SSE4.2 is supported.");
if (cpuid1amd.ECX.SSE4_1)
debug("SSE4.1 is supported.");
if (cpuid1amd.ECX.SSE3)
debug("SSE3 is supported.");
if (cpuid1amd.EDX.SSE2)
debug("SSE2 is supported.");
if (cpuid1amd.EDX.SSE)
debug("SSE is supported.");
#endif
return SIMDType;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
#if defined(a64)
CPU::x64::Intel::CPUID0x1 cpuid1intel;
#elif defined(a32)
CPU::x32::Intel::CPUID0x1 cpuid1intel;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
: "a"(0x1));
#endif
if (cpuid1intel.ECX.SSE4_2)
SIMDType = SIMD_SSE42;
else if (cpuid1intel.ECX.SSE4_1)
SIMDType = SIMD_SSE41;
else if (cpuid1intel.ECX.SSE3)
SIMDType = SIMD_SSE3;
else if (cpuid1intel.EDX.SSE2)
SIMDType = SIMD_SSE2;
else if (cpuid1intel.EDX.SSE)
SIMDType = SIMD_SSE;
#ifdef DEBUG
if (cpuid1intel.ECX.SSE4_2)
debug("SSE4.2 is supported.");
if (cpuid1intel.ECX.SSE4_1)
debug("SSE4.1 is supported.");
if (cpuid1intel.ECX.SSE3)
debug("SSE3 is supported.");
if (cpuid1intel.EDX.SSE2)
debug("SSE2 is supported.");
if (cpuid1intel.EDX.SSE)
debug("SSE is supported.");
#endif
return SIMDType;
}
return SIMD_NONE;
}
bool CheckSIMD(x86SIMDType Type)
{
if (unlikely(!SSEEnabled))
return false;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
#if defined(a64)
CPU::x64::AMD::CPUID0x1 cpuid1amd;
#elif defined(a32)
CPU::x32::AMD::CPUID0x1 cpuid1amd;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
: "a"(0x1));
#endif
if (Type == SIMD_SSE42)
return cpuid1amd.ECX.SSE4_2;
else if (Type == SIMD_SSE41)
return cpuid1amd.ECX.SSE4_1;
else if (Type == SIMD_SSE3)
return cpuid1amd.ECX.SSE3;
else if (Type == SIMD_SSE2)
return cpuid1amd.EDX.SSE2;
else if (Type == SIMD_SSE)
return cpuid1amd.EDX.SSE;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
#if defined(a64)
CPU::x64::Intel::CPUID0x1 cpuid1intel;
#elif defined(a32)
CPU::x32::Intel::CPUID0x1 cpuid1intel;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
: "a"(0x1));
#endif
if (Type == SIMD_SSE42)
return cpuid1intel.ECX.SSE4_2;
else if (Type == SIMD_SSE41)
return cpuid1intel.ECX.SSE4_1;
else if (Type == SIMD_SSE3)
return cpuid1intel.ECX.SSE3;
else if (Type == SIMD_SSE2)
return cpuid1intel.EDX.SSE2;
else if (Type == SIMD_SSE)
return cpuid1intel.EDX.SSE;
}
return false;
}
}

View File

@ -7,15 +7,15 @@
#include <smp.hpp>
#include <cpu.hpp>
#if defined(a64)
#if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#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 page and caused a protection fault\n",
"Supervisory process tried to write to a non-present page entry\n",
@ -28,92 +28,49 @@ static const char *PageFaultDescriptions[8] = {
SafeFunction void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Divide by zero exception\n");
UNUSED(Frame);
}
SafeFunction void DebugExceptionHandler(CHArchTrapFrame *Frame)
{
CrashHandler::EHPrint("\eDD2920System crashed!\n");
CrashHandler::EHPrint("Kernel triggered debug exception.\n");
UNUSED(Frame);
}
SafeFunction void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("NMI 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 NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame) { fixme("NMI exception"); }
SafeFunction void BreakpointExceptionHandler(CHArchTrapFrame *Frame) { fixme("Breakpoint exception"); }
SafeFunction void OverflowExceptionHandler(CHArchTrapFrame *Frame) { fixme("Overflow exception"); }
SafeFunction void BoundRangeExceptionHandler(CHArchTrapFrame *Frame) { fixme("Bound range exception"); }
SafeFunction void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame)
{
CrashHandler::EHPrint("\eDD2920System crashed!\n");
CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n");
UNUSED(Frame);
}
SafeFunction void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame)
{
fixme("Device not available exception");
UNUSED(Frame);
}
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 DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame) { fixme("Device not available exception"); }
SafeFunction void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame) { fixme("Double fault exception"); }
SafeFunction void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame) { fixme("Coprocessor segment overrun exception"); }
SafeFunction void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame) { fixme("Invalid TSS exception"); }
SafeFunction void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame) { fixme("Segment not present exception"); }
SafeFunction void StackFaultExceptionHandler(CHArchTrapFrame *Frame)
{
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
#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);
#elif defined(a32)
#elif defined(__i386__)
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->eip);
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
CrashHandler::EHPrint("External: %d\n", SelCode.External);
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
CrashHandler::EHPrint("Error code: %#lx\n", Frame->ErrorCode);
}
SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame)
{
// staticbuffer(descbuf);
// staticbuffer(desc_ext);
// staticbuffer(desc_table);
// staticbuffer(desc_idx);
// staticbuffer(desc_tmp);
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
// switch (SelCode.Table)
// {
@ -133,20 +90,22 @@ SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame)
// memcpy(desc_tmp, "Unknown", 7);
// break;
// }
CrashHandler::EHPrint("\eDD2920System crashed!\n");
CrashHandler::EHPrint("Kernel performed an illegal operation.\n");
CrashHandler::EHPrint("More info about the exception:\n");
CrashHandler::EHPrint("External: %d\n", SelCode.External);
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
}
SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
{
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
#if defined(a64)
CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->rip);
#elif defined(a32)
CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->eip);
#elif defined(aa64)
CrashHandler::EHPrint("\eDD2920System crashed!\n\eFFFFFF");
#if defined(__amd64__)
CrashHandler::EHPrint("An exception occurred at %#lx by %#lx\n", CPU::x64::readcr2().PFLA, Frame->rip);
#elif defined(__i386__)
CrashHandler::EHPrint("An exception occurred at %#lx by %#lx\n", CPU::x64::readcr2().PFLA, Frame->eip);
#elif defined(__aarch64__)
#endif
CrashHandler::EHPrint("Page: %s\n", params.P ? "Present" : "Not Present");
CrashHandler::EHPrint("Write Operation: %s\n", params.W ? "Read-Only" : "Read-Write");
@ -159,166 +118,12 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
if (Frame->ErrorCode & 0x00000008)
CrashHandler::EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n");
else
CrashHandler::EHPrint(PageFaultDescriptions[Frame->ErrorCode & 0b111]);
#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)
#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)
#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);
CrashHandler::EHPrint(PagefaultDescriptions[Frame->ErrorCode & 0b111]);
}
SafeFunction void x87FloatingPointExceptionHandler(CHArchTrapFrame *Frame) { fixme("x87 floating point exception"); }
SafeFunction void AlignmentCheckExceptionHandler(CHArchTrapFrame *Frame) { fixme("Alignment check exception"); }
SafeFunction void MachineCheckExceptionHandler(CHArchTrapFrame *Frame) { fixme("Machine check exception"); }
SafeFunction void SIMDFloatingPointExceptionHandler(CHArchTrapFrame *Frame) { fixme("SIMD floating point exception"); }
SafeFunction void VirtualizationExceptionHandler(CHArchTrapFrame *Frame) { fixme("Virtualization exception"); }
SafeFunction void SecurityExceptionHandler(CHArchTrapFrame *Frame) { fixme("Security exception"); }
SafeFunction void UnknownExceptionHandler(CHArchTrapFrame *Frame) { fixme("Unknown exception"); }

View File

@ -6,34 +6,42 @@
#include <convert.h>
#include <printf.h>
#include <lock.hpp>
#include <rand.hpp>
#include <uart.hpp>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#include <io.h>
#if defined(a64)
#if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp"
#include "../Architecture/amd64/cpu/apic.hpp"
#elif defined(a32)
#include "../../Architecture/i686/cpu/gdt.hpp"
#include "../Architecture/i686/cpu/apic.hpp"
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../kernel.h"
#include "../../DAPI.hpp"
NewLock(UserInputLock);
#define TRACE_PAGE_TABLE(x, itr, depth) \
EHPrint("\e888888#%s\eAABBCC%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PS:%s G:%s Address:\e888888%#lx\n", \
depth, \
itr, \
x.Value.Present ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.ReadWrite ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.UserSupervisor ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.WriteThrough ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.CacheDisable ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.Accessed ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.Dirty ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.PageSize ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.Global ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.GetAddress() << 12); \
Display->SetBuffer(SBIdx);
namespace CrashHandler
{
uintptr_t PageFaultAddress = 0;
void *EHIntFrames[INT_FRAMES_MAX];
static bool ExceptionOccurred = false;
int SBIdx = 255;
SafeFunction void printfWrapper(char c, void *unused)
{
Display->Print(c, SBIdx, true);
@ -48,42 +56,6 @@ namespace CrashHandler
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)
{
char *end;
@ -152,70 +124,6 @@ namespace CrashHandler
EHPrint(" \eAAF00F%s", CPU::Vendor());
EHPrint(" \eAA00FF%s", CPU::Name());
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()
@ -316,24 +224,18 @@ namespace CrashHandler
EHPrint("exit - Shutdown the OS.\n");
EHPrint("reboot - Reboot the OS.\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(" - \eFF4400WARNING: This can crash the system if a wrong buffer is selected.\eFAFAFA\n");
EHPrint("ifr <COUNT> - Show interrupt frames.\n");
EHPrint("tlb <ADDRESS> - Print the page table entries\n");
EHPrint("bitmap - Print the memory bitmap\n");
EHPrint("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("details - Show the details screen.\n");
EHPrint("frames - Show the stack frame screen.\n");
EHPrint("tasks - Show the tasks screen.\n");
EHPrint("console - Show the console screen.\n");
EHPrint("Also, you can use the arrow keys to navigate between the screens.\n");
EHPrint("Also, you can use the arrow keys to navigate the menu.\n");
EHPrint("=========================================================================\n");
EHPrint("Kernel Compiled at: %s %s with C++ Standard: %d\n", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
EHPrint("C++ Language Version (__cplusplus): %ld\n", __cplusplus);
@ -352,7 +254,7 @@ namespace CrashHandler
Display->SetBuffer(SBIdx);
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);
int tmpidx = SBIdx;
@ -366,19 +268,19 @@ namespace CrashHandler
else if (strncmp(Input, "ifr", 3) == 0)
{
char *arg = TrimWhiteSpace(Input + 3);
int CountI = atoi(arg);
int TotalCount = sizeof(EHIntFrames) / sizeof(EHIntFrames[0]);
uint64_t CountI = atoi(arg);
uint64_t TotalCount = sizeof(EHIntFrames) / sizeof(EHIntFrames[0]);
debug("Printing %ld interrupt frames.", CountI);
if (CountI > TotalCount)
{
EHPrint("\eFF4400Count too big! Maximum allowed is %ld\eFAFAFA\n", TotalCount);
EHPrint("eFF4400Count too big! Maximum allowed is %ld\eFAFAFA\n", TotalCount);
Display->SetBuffer(SBIdx);
}
else
{
for (int i = 0; i < CountI; i++)
for (uint64_t i = 0; i < CountI; i++)
{
if (EHIntFrames[i])
{
@ -386,13 +288,13 @@ namespace CrashHandler
continue;
EHPrint("\n\e2565CC%p", EHIntFrames[i]);
EHPrint("\e7925CC-");
#if defined(a64)
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
#elif defined(a32)
if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
#elif defined(aa64)
#if defined(__amd64__)
if ((uint64_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(__i386__)
if ((uint64_t)EHIntFrames[i] >= 0xC0000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(__aarch64__)
#endif
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i]));
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uint64_t)EHIntFrames[i]));
else
EHPrint("\eFF4CA9Outside Kernel");
for (int i = 0; i < 20000; i++)
@ -405,88 +307,52 @@ namespace CrashHandler
else if (strncmp(Input, "tlb", 3) == 0)
{
char *arg = TrimWhiteSpace(Input + 3);
uintptr_t Address = NULL;
uint64_t Address = NULL;
Address = strtol(arg, NULL, 16);
debug("Converted %s to %#lx", arg, Address);
Memory::PageTable4 *BasePageTable = (Memory::PageTable4 *)Address;
Memory::PageTable *BasePageTable = (Memory::PageTable *)Address;
if (Memory::Virtual().Check(BasePageTable))
for (int Index = 0; Index < 512; Index++)
{
for (int PMLIndex = 0; PMLIndex < 512; PMLIndex++)
if (BasePageTable->Entries[Index].Value.raw == 0)
continue;
TRACE_PAGE_TABLE(BasePageTable->Entries[Index], Index, "");
for (int i = 0; i < 10000; i++)
inb(0x80);
if (BasePageTable->Entries[Index].GetFlag(Memory::PTFlag::P))
{
Memory::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",
PMLIndex, 0, 0, 0,
PML4.Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PML4.ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PML4.UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PML4.WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PML4.CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PML4.Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PML4.ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PML4.GetAddress() << 12);
Display->SetBuffer(SBIdx);
if (PML4.Present)
Memory::PageTable *PDP = (Memory::PageTable *)((uint64_t)BasePageTable->Entries[Index].GetAddress() << 12);
for (int PDPIndex = 0; PDPIndex < 512; PDPIndex++)
{
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
if (PDPTE)
if (PDP->Entries[PDPIndex].Value.raw == 0)
continue;
TRACE_PAGE_TABLE(PDP->Entries[PDPIndex], PDPIndex, " ");
for (int i = 0; i < 10000; i++)
inb(0x80);
if (PDP->Entries[PDPIndex].GetFlag(Memory::PTFlag::P))
{
for (int PDPTEIndex = 0; PDPTEIndex < 512; PDPTEIndex++)
Memory::PageTable *PD = (Memory::PageTable *)((uint64_t)PDP->Entries[PDPIndex].GetAddress() << 12);
for (int PDIndex = 0; PDIndex < 512; PDIndex++)
{
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, 0, 0,
PDPTE->Entries[PDPTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDPTE->Entries[PDPTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDPTE->Entries[PDPTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDPTE->Entries[PDPTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDPTE->Entries[PDPTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDPTE->Entries[PDPTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDPTE->Entries[PDPTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
PDPTE->Entries[PDPTEIndex].GetAddress() << 12);
Display->SetBuffer(SBIdx);
if ((PDPTE->Entries[PDPTEIndex].Present))
if (PD->Entries[PDIndex].Value.raw == 0)
continue;
TRACE_PAGE_TABLE(PD->Entries[PDIndex], PDIndex, " ");
for (int i = 0; i < 10000; i++)
inb(0x80);
if (PD->Entries[PDIndex].GetFlag(Memory::PTFlag::P))
{
Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[PDPTEIndex].GetAddress() << 12);
if (PDE)
Memory::PageTable *PT = (Memory::PageTable *)((uint64_t)PD->Entries[PDIndex].GetAddress() << 12);
for (int PIndex = 0; PIndex < 512; PIndex++)
{
for (int PDEIndex = 0; PDEIndex < 512; PDEIndex++)
{
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);
}
}
}
}
if (PT->Entries[PIndex].Value.raw == 0)
continue;
TRACE_PAGE_TABLE(PT->Entries[PIndex], PIndex, " ");
for (int i = 0; i < 10000; i++)
inb(0x80);
}
}
}
@ -499,8 +365,8 @@ namespace CrashHandler
{
Bitmap bm = KernelAllocator.GetPageBitmap();
EHPrint("\n\eFAFAFA[0%%] %08ld: ", 0);
for (size_t i = 0; i < bm.Size; i++)
EHPrint("\n\eFAFAFA%08ld: ", 0);
for (uint64_t i = 0; i < bm.Size; i++)
{
if (bm.Get(i))
EHPrint("\eFF00001");
@ -508,207 +374,13 @@ namespace CrashHandler
EHPrint("\e00FF000");
if (i % 128 == 127)
{
short Percentage = (i * 100) / bm.Size;
EHPrint("\n\eFAFAFA[%03ld%%] %08ld: ", Percentage, i);
EHPrint("\n\eFAFAFA%08ld: ", i);
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);
}
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 = (Used * 100) / Total;
int ReservedProgress = (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
{
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);
}
}
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 = (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)
{
SBIdx = 255;
@ -744,78 +416,44 @@ namespace CrashHandler
DisplayConsoleScreen(crashdata);
Display->SetBuffer(SBIdx);
}
else if (strlen(Input) > 0)
else
{
if (strlen(Input) > 0)
EHPrint("Unknown command: %s", Input);
}
DisplayBottomOverlay();
Display->SetBuffer(SBIdx);
}
SafeFunction void StopAllCores()
{
#if defined(a64) || defined(a32)
/* 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)
{
// TODO: SUPPORT SMP
CPU::Interrupts(CPU::Disable);
SBIdx = 255;
CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data;
#if defined(a64)
error("An exception occurred!");
error("Exception: %#llx", Frame->InterruptNumber);
for (size_t i = 0; i < INT_FRAMES_MAX; 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)
{
debug("Exception in kernel mode (ip: %#lx (%s), cr2: %#lx)", Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol", PageFaultAddress);
debug("Exception in kernel mode");
if (TaskManager)
TaskManager->Panic();
ForceUnlock = true;
debug("ePanicSchedStop");
Display->CreateBuffer(0, 0, SBIdx);
StopAllCores();
debug("e0");
}
else
{
debug("Exception in user mode (ip: %#lx (%s), cr2: %#lx)", Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol", PageFaultAddress);
debug("Exception in user mode");
CPUData *data = GetCurrentCPU();
if (!data)
{
ForceUnlock = true;
Display->CreateBuffer(0, 0, SBIdx);
StopAllCores();
EHPrint("\eFF0000Cannot get CPU data! This results in a kernel crash!");
error("Cannot get CPU data! This results in a kernel crash!");
error("This should never happen!");
@ -823,16 +461,7 @@ namespace CrashHandler
else
{
debug("CPU %ld data is valid", data->ID);
if (data->CurrentThread->Security.IsCritical)
{
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
if (data->CurrentThread)
{
debug("Current thread is valid %#lx", data->CurrentThread);
UserModeExceptionHandler(Frame);
@ -845,20 +474,22 @@ namespace CrashHandler
{
SBIdx = 255;
Display->ClearBuffer(SBIdx);
debug("e0-1");
Display->SetBufferCursor(SBIdx, 0, 0);
debug("e0-2");
CPU::x64::CR0 cr0 = CPU::x64::readcr0();
CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress};
CPU::x64::CR2 cr2 = CPU::x64::readcr2();
CPU::x64::CR3 cr3 = CPU::x64::readcr3();
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
CPU::x64::CR8 cr8 = CPU::x64::readcr8();
CPU::x64::EFER efer;
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
uintptr_t ds;
uint64_t ds;
asmv("mov %%ds, %0"
: "=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),
Frame->ss, Frame->cs, ds);
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
@ -898,24 +529,21 @@ namespace CrashHandler
EHPrint("\nException occurred while handling exception! HALTED!");
Display->SetBuffer(SBIdx);
Interrupts::RemoveAll();
CPU::Stop();
}
ExceptionOccurred = true;
if (DriverManager)
DriverManager->UnloadAllDrivers();
Interrupts::RemoveAll();
debug("Reading control registers...");
crashdata.Frame = Frame;
crashdata.cr0 = CPU::x64::readcr0();
crashdata.cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress};
crashdata.cr2 = CPU::x64::readcr2();
crashdata.cr3 = CPU::x64::readcr3();
crashdata.cr4 = CPU::x64::readcr4();
crashdata.cr8 = CPU::x64::readcr8();
crashdata.efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
uintptr_t ds;
uint64_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
@ -961,8 +589,8 @@ namespace CrashHandler
if (TaskManager && cpudata != nullptr)
{
crashdata.Process = cpudata->CurrentProcess.Load();
crashdata.Thread = cpudata->CurrentThread.Load();
crashdata.Process = cpudata->CurrentProcess;
crashdata.Thread = cpudata->CurrentThread;
error("Current Process: %s(%ld)",
cpudata->CurrentProcess->Name,
@ -1028,8 +656,8 @@ namespace CrashHandler
}
goto CrashEnd;
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
CrashEnd:

View File

@ -9,10 +9,10 @@
#include <cpu.hpp>
#include <io.h>
#if defined(a64)
#if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../kernel.h"
@ -77,7 +77,7 @@ static inline int GetLetterFromScanCode(uint8_t ScanCode)
namespace CrashHandler
{
CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(CPU::x86::IRQ1)
CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(CPU::x64::IRQ1)
{
while (inb(0x64) & 0x1)
inb(0x60);
@ -102,15 +102,14 @@ namespace CrashHandler
int BackSpaceLimit = 0;
static char UserInputBuffer[1024];
#if defined(a64)
#if defined(__amd64__)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
#elif defined(a32)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
#elif defined(aa64)
#elif defined(__i386__)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(void *Frame)
#elif defined(__aarch64__)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(void *Frame)
#endif
{
UNUSED(Frame);
uint8_t scanCode = inb(0x60);
if (scanCode == KEY_D_TAB ||
scanCode == KEY_D_LCTRL ||

View File

@ -7,10 +7,10 @@
#include <smp.hpp>
#include <cpu.hpp>
#if defined(a64)
#if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../kernel.h"
@ -20,78 +20,55 @@ namespace CrashHandler
struct StackFrame
{
struct StackFrame *rbp;
uintptr_t rip;
uint64_t rip;
};
SafeFunction void TraceFrames(CHArchTrapFrame *Frame, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel)
SafeFunction void TraceFrames(CHArchTrapFrame *Frame, int Count)
{
if (!Memory::Virtual().Check(Frame))
{
EHPrint("Invalid frame pointer: %p\n", Frame);
return;
}
#if defined(a64)
#if defined(__amd64__)
struct StackFrame *frames = (struct StackFrame *)Frame->rbp; // (struct StackFrame *)__builtin_frame_address(0);
if (!Memory::Virtual().Check((void *)Frame->rbp))
#elif defined(a32)
#elif defined(__i386__)
struct StackFrame *frames = (struct StackFrame *)Frame->ebp; // (struct StackFrame *)__builtin_frame_address(0);
if (!Memory::Virtual().Check((void *)Frame->ebp))
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
{
#if defined(a64)
EHPrint("Invalid rbp pointer: %p\n", Frame->rbp);
#elif defined(a32)
EHPrint("Invalid ebp pointer: %p\n", Frame->ebp);
#elif defined(aa64)
#endif
return;
}
if (!Memory::Virtual().Check(SymHandle))
{
EHPrint("Invalid symbol handle: %p\n", SymHandle);
return;
}
debug("\nStack tracing... %p %d %p %d", Frame, Count, frames, Kernel);
debug("Stack tracing...");
EHPrint("\e7981FC\nStack Trace:\n");
if (!frames || !frames->rip || !frames->rbp)
{
#if defined(a64)
#if defined(__amd64__)
EHPrint("\e2565CC%p", (void *)Frame->rip);
#elif defined(a32)
#elif defined(__i386__)
EHPrint("\e2565CC%p", (void *)Frame->eip);
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
EHPrint("\e7925CC-");
#if defined(a64)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->rip));
#elif defined(a32)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->eip));
#elif defined(aa64)
#if defined(__amd64__)
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
#elif defined(__i386__)
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->eip));
#elif defined(__aarch64__)
#endif
EHPrint("\e7981FC <- Exception");
EHPrint("\eFF0000\n< No stack trace available. >\n");
}
else
{
#if defined(a64)
#if defined(__amd64__)
EHPrint("\e2565CC%p", (void *)Frame->rip);
EHPrint("\e7925CC-");
if ((Frame->rip >= 0xFFFFFFFF80000000 && Frame->rip <= (uintptr_t)&_kernel_end) || !Kernel)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->rip));
if (Frame->rip >= 0xFFFFFFFF80000000 && Frame->rip <= (uint64_t)&_kernel_end)
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
else
EHPrint("Outside Kernel");
#elif defined(a32)
#elif defined(__i386__)
EHPrint("\e2565CC%p", (void *)Frame->eip);
EHPrint("\e7925CC-");
if ((Frame->eip >= 0xC0000000 && Frame->eip <= (uintptr_t)&_kernel_end) || !Kernel)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->eip));
if (Frame->eip >= 0xC0000000 && Frame->eip <= (uint64_t)&_kernel_end)
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->eip));
else
EHPrint("Outside Kernel");
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
EHPrint("\e7981FC <- Exception");
for (int frame = 0; frame < Count; ++frame)
@ -100,13 +77,13 @@ namespace CrashHandler
break;
EHPrint("\n\e2565CC%p", (void *)frames->rip);
EHPrint("\e7925CC-");
#if defined(a64)
if ((frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel)
#elif defined(a32)
if ((frames->rip >= 0xC0000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel)
#elif defined(aa64)
#if defined(__amd64__)
if (frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uint64_t)&_kernel_end)
#elif defined(__i386__)
if (frames->rip >= 0xC0000000 && frames->rip <= (uint64_t)&_kernel_end)
#elif defined(__aarch64__)
#endif
EHPrint("\e25CCC9%s", SymHandle->GetSymbolFromAddress(frames->rip));
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress(frames->rip));
else
EHPrint("\eFF4CA9Outside Kernel");
@ -115,6 +92,5 @@ namespace CrashHandler
frames = frames->rbp;
}
}
EHPrint("\n");
}
}

View File

@ -7,10 +7,10 @@
#include <smp.hpp>
#include <cpu.hpp>
#if defined(a64)
#if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../../kernel.h"
@ -20,6 +20,5 @@ namespace CrashHandler
SafeFunction void DisplayConsoleScreen(CRData data)
{
EHPrint("TODO");
UNUSED(data);
}
}

View File

@ -7,10 +7,10 @@
#include <smp.hpp>
#include <cpu.hpp>
#if defined(a64)
#if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../../kernel.h"
@ -28,46 +28,48 @@ namespace CrashHandler
data.Thread->Name,
data.Thread->ID);
EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", data.ID);
uintptr_t ds;
#if defined(a64)
#if defined(__amd64__)
CPUData *cpu = (CPUData *)data.CPUData;
if (cpu)
{
EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu);
EHPrint("Syscalls Stack: %#lx, TempStack: %#lx\n", cpu->SystemCallStack, cpu->TempStack);
EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", cpu->Stack, cpu->ID, cpu->ErrorCode);
EHPrint("Syscalls Stack: %#lx\n", cpu->SystemCallStack);
EHPrint("TempStack: %#lx\n", cpu->TempStack);
EHPrint("Core Stack: %#lx\n", cpu->Stack);
EHPrint("Core ID: %ld\n", cpu->ID);
EHPrint("Error Code: %ld\n", cpu->ErrorCode);
EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false");
EHPrint("Current Process: %#lx, 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("Checksum: 0x%X\n", cpu->Checksum);
}
uint64_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
#elif defined(a32)
#elif defined(__i386__)
uint32_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
#if defined(a64)
EHPrint("\e7981FCFS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
data.Frame->ss, data.Frame->cs, ds);
#if defined(__amd64__)
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", data.Frame->r8, data.Frame->r9, data.Frame->r10, data.Frame->r11);
EHPrint("R12=%#llx R13=%#llx R14=%#llx R15=%#llx\n", data.Frame->r12, data.Frame->r13, data.Frame->r14, data.Frame->r15);
EHPrint("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx\n", data.Frame->rax, data.Frame->rbx, data.Frame->rcx, data.Frame->rdx);
EHPrint("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx\n", data.Frame->rsi, data.Frame->rdi, data.Frame->rbp, data.Frame->rsp);
EHPrint("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", data.Frame->rip, data.Frame->rflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw);
#elif defined(a32)
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);
#elif defined(__i386__)
EHPrint("EAX=%#llx EBX=%#llx ECX=%#llx EDX=%#llx\n", data.Frame->eax, data.Frame->ebx, data.Frame->ecx, data.Frame->edx);
EHPrint("ESI=%#llx EDI=%#llx EBP=%#llx ESP=%#llx\n", data.Frame->esi, data.Frame->edi, data.Frame->ebp, data.Frame->esp);
EHPrint("EIP=%#llx EFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", data.Frame->eip, data.Frame->eflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw);
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
EHPrint("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx\n", data.cr0.raw, data.cr2.raw, data.cr3.raw, data.cr4.raw, data.cr8.raw);
EHPrint("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx\n", data.dr0, data.dr1, data.dr2, data.dr3, data.dr6, data.dr7.raw);
@ -90,16 +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.LA57 ? "True " : "False", data.cr4.VMXE ? "True " : "False", data.cr4.SMXE ? "True " : "False", data.cr4.PCIDE ? "True " : "False",
data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False",
#if defined(a64)
#if defined(__amd64__)
data.cr4.Reserved0, data.cr4.Reserved1, data.cr4.Reserved2);
#elif defined(a32)
#elif defined(__i386__)
data.cr4.Reserved0, data.cr4.Reserved1, 0);
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL);
#if defined(a64)
#if defined(__amd64__)
EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n",
data.Frame->rflags.CF ? "True " : "False", data.Frame->rflags.PF ? "True " : "False", data.Frame->rflags.AF ? "True " : "False", data.Frame->rflags.ZF ? "True " : "False",
data.Frame->rflags.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False",
@ -107,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.ID ? "True " : "False", data.Frame->rflags.AlwaysOne,
data.Frame->rflags.Reserved0, data.Frame->rflags.Reserved1, data.Frame->rflags.Reserved2, data.Frame->rflags.Reserved3);
#elif defined(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",
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",
@ -115,7 +117,7 @@ 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.ID ? "True " : "False", data.Frame->eflags.AlwaysOne,
data.Frame->eflags.Reserved0, data.Frame->eflags.Reserved1, data.Frame->eflags.Reserved2);
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
EHPrint("\eA0F0F0DR7: LDR0:%s GDR0:%s LDR1:%s GDR1:%s\n LDR2:%s GDR2:%s LDR3:%s GDR3:%s\n CDR0:%s SDR0:%s CDR1:%s SDR1:%s\n CDR2:%s SDR2:%s CDR3:%s SDR3:%s\n R:%#x\n",
@ -132,107 +134,107 @@ namespace CrashHandler
switch (data.Frame->InterruptNumber)
{
case CPU::x86::DivideByZero:
case CPU::x64::DivideByZero:
{
DivideByZeroExceptionHandler(data.Frame);
break;
}
case CPU::x86::Debug:
case CPU::x64::Debug:
{
DebugExceptionHandler(data.Frame);
break;
}
case CPU::x86::NonMaskableInterrupt:
case CPU::x64::NonMaskableInterrupt:
{
NonMaskableInterruptExceptionHandler(data.Frame);
break;
}
case CPU::x86::Breakpoint:
case CPU::x64::Breakpoint:
{
BreakpointExceptionHandler(data.Frame);
break;
}
case CPU::x86::Overflow:
case CPU::x64::Overflow:
{
OverflowExceptionHandler(data.Frame);
break;
}
case CPU::x86::BoundRange:
case CPU::x64::BoundRange:
{
BoundRangeExceptionHandler(data.Frame);
break;
}
case CPU::x86::InvalidOpcode:
case CPU::x64::InvalidOpcode:
{
InvalidOpcodeExceptionHandler(data.Frame);
break;
}
case CPU::x86::DeviceNotAvailable:
case CPU::x64::DeviceNotAvailable:
{
DeviceNotAvailableExceptionHandler(data.Frame);
break;
}
case CPU::x86::DoubleFault:
case CPU::x64::DoubleFault:
{
DoubleFaultExceptionHandler(data.Frame);
break;
}
case CPU::x86::CoprocessorSegmentOverrun:
case CPU::x64::CoprocessorSegmentOverrun:
{
CoprocessorSegmentOverrunExceptionHandler(data.Frame);
break;
}
case CPU::x86::InvalidTSS:
case CPU::x64::InvalidTSS:
{
InvalidTSSExceptionHandler(data.Frame);
break;
}
case CPU::x86::SegmentNotPresent:
case CPU::x64::SegmentNotPresent:
{
SegmentNotPresentExceptionHandler(data.Frame);
break;
}
case CPU::x86::StackSegmentFault:
case CPU::x64::StackSegmentFault:
{
StackFaultExceptionHandler(data.Frame);
break;
}
case CPU::x86::GeneralProtectionFault:
case CPU::x64::GeneralProtectionFault:
{
GeneralProtectionExceptionHandler(data.Frame);
break;
}
case CPU::x86::PageFault:
case CPU::x64::PageFault:
{
PageFaultExceptionHandler(data.Frame);
break;
}
case CPU::x86::x87FloatingPoint:
case CPU::x64::x87FloatingPoint:
{
x87FloatingPointExceptionHandler(data.Frame);
break;
}
case CPU::x86::AlignmentCheck:
case CPU::x64::AlignmentCheck:
{
AlignmentCheckExceptionHandler(data.Frame);
break;
}
case CPU::x86::MachineCheck:
case CPU::x64::MachineCheck:
{
MachineCheckExceptionHandler(data.Frame);
break;
}
case CPU::x86::SIMDFloatingPoint:
case CPU::x64::SIMDFloatingPoint:
{
SIMDFloatingPointExceptionHandler(data.Frame);
break;
}
case CPU::x86::Virtualization:
case CPU::x64::Virtualization:
{
VirtualizationExceptionHandler(data.Frame);
break;
}
case CPU::x86::Security:
case CPU::x64::Security:
{
SecurityExceptionHandler(data.Frame);
break;

View File

@ -7,10 +7,10 @@
#include <smp.hpp>
#include <cpu.hpp>
#if defined(a64)
#if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../../kernel.h"
@ -44,67 +44,67 @@ namespace CrashHandler
switch (Frame->InterruptNumber)
{
case CPU::x86::DivideByZero:
case CPU::x64::DivideByZero:
{
EHPrint("Exception: Divide By Zero\n");
EHPrint("The processor attempted to divide a number by zero.\n");
break;
}
case CPU::x86::Debug:
case CPU::x64::Debug:
{
EHPrint("Exception: Debug\n");
EHPrint("A debug exception has occurred.\n");
break;
}
case CPU::x86::NonMaskableInterrupt:
case CPU::x64::NonMaskableInterrupt:
{
EHPrint("Exception: Non-Maskable Interrupt\n");
EHPrint("A non-maskable interrupt was received.\n");
break;
}
case CPU::x86::Breakpoint:
case CPU::x64::Breakpoint:
{
EHPrint("Exception: Breakpoint\n");
EHPrint("The processor encountered a breakpoint.\n");
break;
}
case CPU::x86::Overflow:
case CPU::x64::Overflow:
{
EHPrint("Exception: Overflow\n");
EHPrint("The processor attempted to add a number to a number that was too large.\n");
break;
}
case CPU::x86::BoundRange:
case CPU::x64::BoundRange:
{
EHPrint("Exception: Bound Range\n");
EHPrint("The processor attempted to access an array element that is out of bounds.\n");
break;
}
case CPU::x86::InvalidOpcode:
case CPU::x64::InvalidOpcode:
{
EHPrint("Exception: Invalid Opcode\n");
EHPrint("The processor attempted to execute an invalid opcode.\n");
break;
}
case CPU::x86::DeviceNotAvailable:
case CPU::x64::DeviceNotAvailable:
{
EHPrint("Exception: Device Not Available\n");
EHPrint("The processor attempted to use a device that is not available.\n");
break;
}
case CPU::x86::DoubleFault:
case CPU::x64::DoubleFault:
{
EHPrint("Exception: Double Fault\n");
EHPrint("The processor encountered a double fault.\n");
break;
}
case CPU::x86::CoprocessorSegmentOverrun:
case CPU::x64::CoprocessorSegmentOverrun:
{
EHPrint("Exception: Coprocessor Segment Overrun\n");
EHPrint("The processor attempted to access a segment that is not available.\n");
break;
}
case CPU::x86::InvalidTSS:
case CPU::x64::InvalidTSS:
{
EHPrint("Exception: Invalid TSS\n");
EHPrint("The processor attempted to access a task state segment that is not available or valid.\n");
@ -144,7 +144,7 @@ namespace CrashHandler
}
break;
}
case CPU::x86::SegmentNotPresent:
case CPU::x64::SegmentNotPresent:
{
EHPrint("Exception: Segment Not Present\n");
EHPrint("The processor attempted to access a segment that is not present.\n");
@ -184,7 +184,7 @@ namespace CrashHandler
}
break;
}
case CPU::x86::StackSegmentFault:
case CPU::x64::StackSegmentFault:
{
EHPrint("Exception: Stack Segment Fault\n");
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
@ -223,7 +223,7 @@ namespace CrashHandler
}
break;
}
case CPU::x86::GeneralProtectionFault:
case CPU::x64::GeneralProtectionFault:
{
EHPrint("Exception: General Protection Fault\n");
EHPrint("Kernel performed an illegal operation.\n");
@ -263,17 +263,17 @@ namespace CrashHandler
}
break;
}
case CPU::x86::PageFault:
case CPU::x64::PageFault:
{
EHPrint("Exception: Page Fault\n");
EHPrint("The processor attempted to access a page that is not present.\n");
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
#if defined(a64)
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->rip);
#elif defined(a32)
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->eip);
#elif defined(aa64)
#if defined(__amd64__)
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", CPU::x64::readcr2().PFLA, Frame->rip);
#elif defined(__i386__)
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", CPU::x64::readcr2().PFLA, Frame->eip);
#elif defined(__aarch64__)
#endif
EHPrint("Page: %s\eFAFAFA\n", params.P ? "\e058C19Present" : "\eE85230Not Present");
EHPrint("Write Operation: \e8888FF%s\eFAFAFA\n", params.W ? "Read-Only" : "Read-Write");
@ -291,37 +291,37 @@ namespace CrashHandler
EHPrint("\eFAFAFA");
break;
}
case CPU::x86::x87FloatingPoint:
case CPU::x64::x87FloatingPoint:
{
EHPrint("Exception: x87 Floating Point\n");
EHPrint("The x87 FPU generated an error.\n");
break;
}
case CPU::x86::AlignmentCheck:
case CPU::x64::AlignmentCheck:
{
EHPrint("Exception: Alignment Check\n");
EHPrint("The CPU detected an unaligned memory access.\n");
break;
}
case CPU::x86::MachineCheck:
case CPU::x64::MachineCheck:
{
EHPrint("Exception: Machine Check\n");
EHPrint("The CPU detected a hardware error.\n");
break;
}
case CPU::x86::SIMDFloatingPoint:
case CPU::x64::SIMDFloatingPoint:
{
EHPrint("Exception: SIMD Floating Point\n");
EHPrint("The CPU detected an error in the SIMD unit.\n");
break;
}
case CPU::x86::Virtualization:
case CPU::x64::Virtualization:
{
EHPrint("Exception: Virtualization\n");
EHPrint("The CPU detected a virtualization error.\n");
break;
}
case CPU::x86::Security:
case CPU::x64::Security:
{
EHPrint("Exception: Security\n");
EHPrint("The CPU detected a security violation.\n");
@ -335,11 +335,11 @@ namespace CrashHandler
}
}
#if defined(a64)
#if defined(__amd64__)
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);
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
}
}

View File

@ -1,17 +1,17 @@
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
#include <ints.hpp>
#include <interrupts.hpp>
#include <display.hpp>
#include <printf.h>
#include <debug.h>
#include <smp.hpp>
#include <cpu.hpp>
#if defined(a64)
#if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../../kernel.h"
@ -20,19 +20,10 @@ namespace CrashHandler
{
SafeFunction void DisplayStackFrameScreen(CRData data)
{
EHPrint("\eFAFAFATracing 10 frames...");
TraceFrames(data.Frame, 10, KernelSymbolTable, true);
if (data.Process)
{
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.Frame, 10, sh, false);
}
EHPrint("\n\eFAFAFATracing interrupt frames...");
for (short i = 0; i < 8; i++)
EHPrint("\eFAFAFATracing 40 frames...\n");
TraceFrames(data.Frame, 40);
EHPrint("\n\n\eFAFAFATracing interrupt frames...\n");
for (uint64_t i = 0; i < 8; i++)
{
if (EHIntFrames[i])
{
@ -40,42 +31,16 @@ namespace CrashHandler
continue;
EHPrint("\n\e2565CC%p", EHIntFrames[i]);
EHPrint("\e7925CC-");
#if defined(a64)
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
#elif defined(a32)
if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
#elif defined(aa64)
#if defined(__amd64__)
if ((uint64_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(__i386__)
if ((uint64_t)EHIntFrames[i] >= 0xC0000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
#elif defined(__aarch64__)
#endif
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i]));
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uint64_t)EHIntFrames[i]));
else
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

@ -7,10 +7,10 @@
#include <smp.hpp>
#include <cpu.hpp>
#if defined(a64)
#if defined(__amd64__)
#include "../../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../../kernel.h"
@ -44,11 +44,11 @@ namespace CrashHandler
if (TaskManager)
{
if (data.Thread)
#if defined(a64)
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip);
#elif defined(a32)
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->eip);
#elif defined(aa64)
#if defined(__amd64__)
EHPrint("\eFAFAFACrash occured in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip);
#elif defined(__i386__)
EHPrint("\eFAFAFACrash occured in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->eip);
#elif defined(__aarch64__)
#endif
EHPrint("\eFAFAFAProcess list (%ld):\n", Plist.size());

View File

@ -7,10 +7,10 @@
#include <smp.hpp>
#include <cpu.hpp>
#if defined(a64)
#if defined(__amd64__)
#include "../../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../../kernel.h"
@ -34,9 +34,8 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
CPUData *CurCPU = GetCurrentCPU();
{
#if defined(a64)
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::CR4 cr4 = CPU::x64::readcr4();
CPU::x64::CR8 cr8 = CPU::x64::readcr8();
@ -44,42 +43,30 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
error("Technical Informations on CPU %lld:", CurCPU->ID);
uintptr_t ds;
#if defined(__amd64__)
uint64_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
#elif defined(a32)
CPU::x32::CR0 cr0 = CPU::x32::readcr0();
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;
#elif defined(__i386__)
uint32_t ds;
asmv("mov %%ds, %0"
: "=r"(ds));
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
#if defined(a64)
error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx",
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
Frame->ss, Frame->cs, ds);
#if defined(__amd64__)
error("R8=%#llx R9=%#llx R10=%#llx R11=%#llx", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
error("R12=%#llx R13=%#llx R14=%#llx R15=%#llx", Frame->r12, Frame->r13, Frame->r14, Frame->r15);
error("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
#elif defined(a32)
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);
#elif defined(__i386__)
error("EAX=%#llx EBX=%#llx ECX=%#llx EDX=%#llx", Frame->eax, Frame->ebx, Frame->ecx, Frame->edx);
error("ESI=%#llx EDI=%#llx EBP=%#llx ESP=%#llx", Frame->esi, Frame->edi, Frame->ebp, Frame->esp);
error("EIP=%#llx EFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw);
@ -95,7 +82,6 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
error("CR3: PWT:%s PCD:%s PDBR:%#llx",
cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR);
#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",
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",
@ -103,19 +89,10 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False",
cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False",
cr4.Reserved0, cr4.Reserved1, cr4.Reserved2);
#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
error("CR8: TPL:%d", cr8.TPL);
#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",
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",
@ -123,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.ID ? "True " : "False", Frame->rflags.AlwaysOne,
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",
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",
@ -131,7 +108,7 @@ 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.ID ? "True " : "False", Frame->eflags.AlwaysOne,
Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2);
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x",
@ -142,75 +119,70 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
switch (Frame->InterruptNumber)
{
case CPU::x86::DivideByZero:
case CPU::x64::DivideByZero:
{
break;
}
case CPU::x86::Debug:
case CPU::x64::Debug:
{
break;
}
case CPU::x86::NonMaskableInterrupt:
case CPU::x64::NonMaskableInterrupt:
{
break;
}
case CPU::x86::Breakpoint:
case CPU::x64::Breakpoint:
{
break;
}
case CPU::x86::Overflow:
case CPU::x64::Overflow:
{
break;
}
case CPU::x86::BoundRange:
case CPU::x64::BoundRange:
{
break;
}
case CPU::x86::InvalidOpcode:
case CPU::x64::InvalidOpcode:
{
break;
}
case CPU::x86::DeviceNotAvailable:
case CPU::x64::DeviceNotAvailable:
{
break;
}
case CPU::x86::DoubleFault:
case CPU::x64::DoubleFault:
{
break;
}
case CPU::x86::CoprocessorSegmentOverrun:
case CPU::x64::CoprocessorSegmentOverrun:
{
break;
}
case CPU::x86::InvalidTSS:
case CPU::x64::InvalidTSS:
{
break;
}
case CPU::x86::SegmentNotPresent:
case CPU::x64::SegmentNotPresent:
{
break;
}
case CPU::x86::StackSegmentFault:
case CPU::x64::StackSegmentFault:
{
break;
}
case CPU::x86::GeneralProtectionFault:
case CPU::x64::GeneralProtectionFault:
{
break;
}
case CPU::x86::PageFault:
case CPU::x64::PageFault:
{
uintptr_t CheckPageFaultAddress = 0;
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
#if defined(a64)
CheckPageFaultAddress = CrashHandler::PageFaultAddress;
if (CheckPageFaultAddress == 0)
CheckPageFaultAddress = Frame->rip;
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)
#if defined(__amd64__)
error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->rip);
#elif defined(__i386__)
error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->eip);
#elif defined(__aarch64__)
#endif
error("Page: %s", params.P ? "Present" : "Not Present");
error("Write Operation: %s", params.W ? "Read-Only" : "Read-Write");
@ -229,21 +201,21 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
if (CurCPU)
{
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",
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);
bool Present = vma.Check((void *)CPU::x64::readcr2().PFLA);
bool ReadWrite = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::RW);
bool User = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::US);
bool WriteThrough = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PWT);
bool CacheDisabled = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PCD);
bool Accessed = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::A);
bool Dirty = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::D);
bool Global = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::G);
/* ... */
debug("Page available: %s", Present ? "Yes" : "No");
@ -254,80 +226,12 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
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);
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
if (CurCPU)
if (CurCPU->CurrentThread->Stack->Expand(CrashHandler::PageFaultAddress))
if (CurCPU->CurrentThread->Stack->Expand(CPU::x64::readcr2().raw))
{
debug("Stack expanded");
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready;
@ -335,27 +239,27 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
}
break;
}
case CPU::x86::x87FloatingPoint:
case CPU::x64::x87FloatingPoint:
{
break;
}
case CPU::x86::AlignmentCheck:
case CPU::x64::AlignmentCheck:
{
break;
}
case CPU::x86::MachineCheck:
case CPU::x64::MachineCheck:
{
break;
}
case CPU::x86::SIMDFloatingPoint:
case CPU::x64::SIMDFloatingPoint:
{
break;
}
case CPU::x86::Virtualization:
case CPU::x64::Virtualization:
{
break;
}
case CPU::x86::Security:
case CPU::x64::Security:
{
break;
}
@ -366,7 +270,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
}
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated;
__sync;
__sync_synchronize();
error("End of report.");
CPU::Interrupts(CPU::Enable);
debug("Interrupts enabled back.");

View File

@ -3,11 +3,11 @@
#include <types.h>
#include <ints.hpp>
#include <interrupts.hpp>
#include <task.hpp>
#include <cpu.hpp>
#if defined(a64)
#if defined(__amd64__)
typedef struct CPU::x64::TrapFrame CHArchTrapFrame;
struct CRData
@ -20,7 +20,7 @@ struct CRData
CPU::x64::CR4 cr4;
CPU::x64::CR8 cr8;
CPU::x64::EFER efer;
uintptr_t dr0, dr1, dr2, dr3, dr6;
uint64_t dr0, dr1, dr2, dr3, dr6;
CPU::x64::DR7 dr7;
long ID;
@ -29,7 +29,7 @@ struct CRData
Tasking::TCB *Thread;
};
#elif defined(a32)
#elif defined(__i386__)
typedef struct CPU::x32::TrapFrame CHArchTrapFrame;
struct CRData
@ -42,14 +42,14 @@ struct CRData
CPU::x32::CR4 cr4;
CPU::x32::CR8 cr8;
CPU::x32::EFER efer;
uintptr_t dr0, dr1, dr2, dr3, dr6;
uint64_t dr0, dr1, dr2, dr3, dr6;
CPU::x32::DR7 dr7;
long ID;
Tasking::PCB *Process;
Tasking::TCB *Thread;
};
#elif defined(aa64)
#elif defined(__aarch64__)
typedef struct CPU::aarch64::TrapFrame CHArchTrapFrame;
#endif
@ -244,11 +244,11 @@ namespace CrashHandler
class CrashKeyboardDriver : public Interrupts::Handler
{
private:
#if defined(a64)
#if defined(__amd64__)
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
#elif defined(a32)
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
#elif defined(aa64)
#elif defined(__i386__)
void OnInterruptReceived(void *Frame);
#elif defined(__aarch64__)
void OnInterruptReceived(void *Frame);
#endif
public:
@ -256,7 +256,7 @@ namespace CrashHandler
~CrashKeyboardDriver();
};
void TraceFrames(CHArchTrapFrame *Frame, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel);
void TraceFrames(CHArchTrapFrame *Frame, int Count);
void ArrowInput(uint8_t key);
void UserInput(char *Input);

View File

@ -8,13 +8,13 @@ NewLock(DebuggerLock);
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);
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;
switch (Level)
@ -52,7 +52,7 @@ static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line,
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);
va_list args;
@ -61,29 +61,9 @@ namespace SysDbg
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);
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);
// SmartLock(DebuggerLock);
WritePrefix(Level, File, Line, Function);
va_list args;
va_start(args, Format);
@ -94,7 +74,7 @@ namespace SysDbg
}
// 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);
va_list args;
@ -104,7 +84,7 @@ extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Lin
}
// 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);
va_list args;
@ -113,26 +93,3 @@ extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int
va_end(args);
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

@ -30,7 +30,7 @@ namespace Disk
for (unsigned char ItrPort = 0; ItrPort < this->AvailablePorts; ItrPort++)
{
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);
// TODO: Implement disk type detection. Very useful in the future.
drive->MechanicalDisk = true;
@ -49,7 +49,7 @@ namespace Disk
memcpy(&drive->Table, RWBuffer, sizeof(PartitionTable));
/*
TODO: Add to devfs the disk
----> Add to devfs the disk
*/
if (drive->Table.GPT.Signature == GPT_MAGIC)
@ -98,10 +98,10 @@ namespace Disk
drive->Partitions.push_back(partition);
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;
@ -128,10 +128,10 @@ namespace Disk
drive->Partitions.push_back(partition);
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;
@ -153,6 +153,5 @@ namespace Disk
Manager::~Manager()
{
debug("Destructor called");
}
}

View File

@ -1,6 +1,6 @@
#include <driver.hpp>
#include <ints.hpp>
#include <interrupts.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
@ -28,201 +28,439 @@ namespace Driver
"Input",
"Audio"};
void Driver::UnloadAllDrivers()
{
size_t DriversNum = Drivers.size();
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
debug("driver size %ld", DriversNum);
for (size_t i = 0; i < DriversNum; i++)
{
DriverFile *drv = Drivers[i];
KernelCallback callback;
callback.Reason = StopReason;
debug("Stopping & unloading driver %ld [%#lx]", drv->DriverUID, drv->Address);
DriverManager->IOCB(drv->DriverUID, (void *)&callback);
delete drv->MemTrk, drv->MemTrk = nullptr;
for (size_t j = 0; j < sizeof(drv->InterruptHook) / sizeof(drv->InterruptHook[0]); j++)
{
if (!drv->InterruptHook[j])
continue;
delete drv->InterruptHook[j], drv->InterruptHook[j] = nullptr;
}
delete drv, drv = nullptr;
Drivers.remove(i);
}
}
bool Driver::UnloadDriver(unsigned long DUID)
{
debug("Searching for driver %ld", DUID);
for (size_t i = 0; i < Drivers.size(); i++)
{
DriverFile *drv = Drivers[i];
if (drv->DriverUID == DUID)
{
KernelCallback callback;
callback.Reason = StopReason;
debug("Stopping and unloading driver %ld [%#lx]", drv->DriverUID, drv->Address);
this->IOCB(drv->DriverUID, (void *)&callback);
delete drv->MemTrk, drv->MemTrk = nullptr;
for (size_t i = 0; i < sizeof(drv->InterruptHook) / sizeof(drv->InterruptHook[0]); i++)
{
if (!drv->InterruptHook[i])
continue;
delete drv->InterruptHook[i], drv->InterruptHook[i] = nullptr;
}
delete drv, drv = nullptr;
Drivers.remove(i);
return true;
}
}
return false;
}
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 *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS);
int ret = ((int (*)(void *))((uintptr_t)DrvExtHdr->Driver.Callback + (uintptr_t)Drv->Address))(KCB);
__sync;
return ret;
}
FexExtended *DrvExtHdr = (FexExtended *)((uint64_t)var->Address + EXTENDED_SECTION_ADDRESS);
return ((int (*)(void *))((uint64_t)DrvExtHdr->Driver.Callback + (uint64_t)var->Address))(KCB);
}
return -1;
}
DriverCode Driver::CallDriverEntryPoint(void *fex, 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;
((KernelAPI *)KAPIAddress)->Info.DriverUID = DriverUIDs++;
API->Info.Offset = (unsigned long)fex;
API->Info.DriverUID = DriverUIDs++;
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));
int ret = ((int (*)(KernelAPI *))((uint64_t)((Fex *)fex)->Pointer + (uint64_t)fex))(API);
if (DriverReturnCode::OK != ret)
return DriverCode::DRIVER_RETURNED_ERROR;
return DriverCode::OK;
}
DriverCode Driver::LoadDriver(uintptr_t DriverAddress, uintptr_t Size)
DriverCode Driver::LoadDriver(uint64_t DriverAddress, uint64_t Size)
{
Fex *DrvHdr = (Fex *)DriverAddress;
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
{
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;
else
{
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);
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; Pointer: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->Pointer);
if (DrvHdr->Type == FexFormatType::FexFormatType_Driver)
{
FexExtended *DrvExtHdr = (FexExtended *)((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);
if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
return this->DriverLoadBindPCI(DrvExtHdr, DriverAddress, Size);
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
return this->DriverLoadBindInterrupt(DrvExtHdr, DriverAddress, Size);
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
return this->DriverLoadBindProcess(DrvExtHdr, DriverAddress, Size);
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
return this->DriverLoadBindInput(DrvExtHdr, DriverAddress, Size);
{
for (unsigned long Vidx = 0; Vidx < sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) / sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID[0]); Vidx++)
for (unsigned long Didx = 0; Didx < sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID) / sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID[0]); Didx++)
{
if (Vidx >= sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) && Didx >= sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID))
break;
if (DrvExtHdr->Driver.Bind.PCI.VendorID[Vidx] == 0 || DrvExtHdr->Driver.Bind.PCI.DeviceID[Didx] == 0)
continue;
Vector<PCI::PCIDeviceHeader *> devices = PCIManager->FindPCIDevice(DrvExtHdr->Driver.Bind.PCI.VendorID[Vidx], DrvExtHdr->Driver.Bind.PCI.DeviceID[Didx]);
if (devices.size() == 0)
continue;
foreach (auto PCIDevice in devices)
{
debug("[%ld] VendorID: %#x; DeviceID: %#x", devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
Fex *fex = (Fex *)KernelAllocator.RequestPages(TO_PAGES(Size));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uint64_t)fex + EXTENDED_SECTION_ADDRESS);
#ifdef DEBUG
uint8_t *result = md5File((uint8_t *)fex, Size);
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
kfree(result);
#endif
if (CallDriverEntryPoint(fex) != DriverCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s", fexExtended->Driver.Name);
KernelCallback *KCallback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Generic:
{
fixme("Generic driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Display:
{
fixme("Display driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Network:
{
DriverInterruptHook *InterruptHook = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)devices[0])->InterruptLine) + 32, // x86
(void *)((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex),
KCallback);
KCallback->RawPtr = PCIDevice;
KCallback->Reason = CallbackReason::ConfigurationReason;
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
delete InterruptHook;
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
continue;
}
else if (callbackret == DriverReturnCode::OK)
trace("Device found for driver: %s", fexExtended->Driver.Name);
else
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
delete InterruptHook;
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
continue;
}
memset(KCallback, 0, sizeof(KernelCallback));
KCallback->Reason = CallbackReason::InterruptReason;
DriverFile *drvfile = new DriverFile;
drvfile->DriverUID = KAPI.Info.DriverUID;
drvfile->Address = (void *)fex;
drvfile->InterruptHook[0] = InterruptHook;
Drivers.push_back(drvfile);
break;
}
case FexDriverType::FexDriverType_Storage:
{
KCallback->RawPtr = PCIDevice;
KCallback->Reason = CallbackReason::ConfigurationReason;
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
continue;
}
else if (callbackret == DriverReturnCode::OK)
trace("Device found for driver: %s", fexExtended->Driver.Name);
else
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
continue;
}
DriverFile *drvfile = new DriverFile;
drvfile->DriverUID = KAPI.Info.DriverUID;
drvfile->Address = (void *)fex;
drvfile->InterruptHook[0] = nullptr;
Drivers.push_back(drvfile);
break;
}
case FexDriverType::FexDriverType_FileSystem:
{
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Input:
{
fixme("Input driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Audio:
{
fixme("Audio driver: %s", fexExtended->Driver.Name);
break;
}
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
break;
}
}
}
}
}
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
{
Fex *fex = (Fex *)KernelAllocator.RequestPages(TO_PAGES(Size));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uint64_t)fex + EXTENDED_SECTION_ADDRESS);
#ifdef DEBUG
uint8_t *result = md5File((uint8_t *)fex, Size);
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
kfree(result);
#endif
if (CallDriverEntryPoint(fex) != DriverCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
KernelCallback *KCallback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Generic:
{
fixme("Generic driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Display:
{
fixme("Display driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Network:
{
fixme("Network driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Storage:
{
for (unsigned long i = 0; i < sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector) / sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector[0]); i++)
{
if (DrvExtHdr->Driver.Bind.Interrupt.Vector[i] == 0)
break;
fixme("TODO: MULTIPLE BIND INTERRUPT VECTORS %d", DrvExtHdr->Driver.Bind.Interrupt.Vector[i]);
}
fixme("Not implemented");
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
break;
KCallback->RawPtr = nullptr;
KCallback->Reason = CallbackReason::ConfigurationReason;
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
break;
}
else if (callbackret != DriverReturnCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
break;
}
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
// DriverFile *drvfile = new DriverFile;
// Drivers.push_back(drvfile);
break;
}
case FexDriverType::FexDriverType_FileSystem:
{
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
break;
}
case FexDriverType::FexDriverType_Input:
{
DriverInterruptHook *InterruptHook = nullptr;
if (DrvExtHdr->Driver.Bind.Interrupt.Vector[0] != 0)
InterruptHook = new DriverInterruptHook(DrvExtHdr->Driver.Bind.Interrupt.Vector[0] + 32, // x86
(void *)((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex),
KCallback);
for (unsigned long i = 0; i < sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector) / sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector[0]); i++)
{
if (DrvExtHdr->Driver.Bind.Interrupt.Vector[i] == 0)
break;
// InterruptHook = new DriverInterruptHook(DrvExtHdr->Driver.Bind.Interrupt.Vector[i] + 32, // x86
// (void *)((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex),
// KCallback);
fixme("TODO: MULTIPLE BIND INTERRUPT VECTORS %d", DrvExtHdr->Driver.Bind.Interrupt.Vector[i]);
}
KCallback->RawPtr = nullptr;
KCallback->Reason = CallbackReason::ConfigurationReason;
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
break;
}
else if (callbackret != DriverReturnCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
break;
}
memset(KCallback, 0, sizeof(KernelCallback));
KCallback->Reason = CallbackReason::InterruptReason;
DriverFile *drvfile = new DriverFile;
drvfile->DriverUID = KAPI.Info.DriverUID;
drvfile->Address = (void *)fex;
drvfile->InterruptHook[0] = InterruptHook;
Drivers.push_back(drvfile);
break;
}
case FexDriverType::FexDriverType_Audio:
{
fixme("Audio driver: %s", fexExtended->Driver.Name);
break;
}
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
break;
}
}
}
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
{
fixme("Process driver: %s", DrvExtHdr->Driver.Name);
}
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
{
Fex *fex = (Fex *)KernelAllocator.RequestPages(TO_PAGES(Size));
memcpy(fex, (void *)DriverAddress, Size);
FexExtended *fexExtended = (FexExtended *)((uint64_t)fex + EXTENDED_SECTION_ADDRESS);
#ifdef DEBUG
uint8_t *result = md5File((uint8_t *)fex, Size);
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
kfree(result);
#endif
if (CallDriverEntryPoint(fex) != DriverCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
return DriverCode::DRIVER_RETURNED_ERROR;
}
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
KernelCallback *KCallback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
switch (fexExtended->Driver.Type)
{
case FexDriverType::FexDriverType_Input:
{
fixme("Input driver: %s", fexExtended->Driver.Name);
KCallback->RawPtr = nullptr;
break;
KCallback->Reason = CallbackReason::ConfigurationReason;
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
break;
}
else if (callbackret != DriverReturnCode::OK)
{
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
break;
}
KernelAllocator.FreePages(fex, TO_PAGES(Size));
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
DriverFile *drvfile = new DriverFile;
drvfile->DriverUID = KAPI.Info.DriverUID;
drvfile->Address = (void *)fex;
drvfile->InterruptHook[0] = nullptr;
Drivers.push_back(drvfile);
break;
}
default:
{
warn("Unknown driver type: %d", fexExtended->Driver.Type);
break;
}
}
}
else
{
error("Unknown driver bind type: %d", DrvExtHdr->Driver.Bind.Type);
}
}
else
return DriverCode::NOT_DRIVER;
return DriverCode::ERROR;
return DriverCode::OK;
}
Driver::Driver()
{
SmartCriticalSection(DriverInitLock);
shared_ptr<VirtualFileSystem::File> DriverDirectory = vfs->Open(Config.DriverDirectory);
if (DriverDirectory->Status == VirtualFileSystem::FileStatus::OK)
{
foreach (auto driver in DriverDirectory->node->Children)
if (driver->Flags == VirtualFileSystem::NodeFlags::FILE)
FileSystem::FILE *DriverDirectory = vfs->Open(Config.DriverDirectory);
if (DriverDirectory->Status == FileSystem::FileStatus::OK)
foreach (auto driver in DriverDirectory->Node->Children)
if (driver->Flags == FileSystem::NodeFlags::FS_FILE)
if (cwk_path_has_extension(driver->Name))
{
const char *extension;
cwk_path_get_extension(driver->Name, &extension, nullptr);
debug("Driver: %s; Extension: %s", driver->Name, extension);
if (strcmp(extension, ".fex") == 0 || strcmp(extension, ".elf") == 0)
if (!strcmp(extension, ".fex"))
{
uintptr_t ret = this->LoadDriver(driver->Address, driver->Length);
char RetString[128];
uint64_t ret = this->LoadDriver(driver->Address, driver->Length);
char retstring[128];
if (ret == DriverCode::OK)
strncpy(RetString, "\e058C19OK", 10);
else if (ret == DriverCode::NOT_AVAILABLE)
strncpy(RetString, "\eFF7900NOT AVAILABLE", 21);
strncpy(retstring, "\e058C19OK", 64);
else
sprintf(RetString, "\eE85230FAILED (%#lx)", ret);
KPrint("%s %s", driver->Name, RetString);
sprintf_(retstring, "\eE85230FAILED (%#lx)", ret);
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);
}
Driver::~Driver()
{
debug("Destructor called");
this->UnloadAllDrivers();
}
#if defined(a64)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
#elif defined(a32)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
#elif defined(aa64)
SafeFunction void DriverInterruptHook::OnInterruptReceived(void *Frame)
#if defined(__amd64__)
void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
#elif defined(__i386__)
void DriverInterruptHook::OnInterruptReceived(void *Frame)
#elif defined(__aarch64__)
void DriverInterruptHook::OnInterruptReceived(void *Frame)
#endif
{
SmartLock(DriverInterruptLock);
SmartCriticalSection(DriverInterruptLock);
((int (*)(void *))(Handle))(Data);
UNUSED(Frame);
}
DriverInterruptHook::DriverInterruptHook(int Interrupt, void *Address, void *ParamData) : Interrupts::Handler(Interrupt)

View File

@ -7,18 +7,13 @@
#include "../../Fex.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);
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)
{
@ -29,117 +24,74 @@ void DriverDisplayPrint(char *String)
void *RequestPage(unsigned long Size)
{
SmartLock(DriverDisplayPrintLock);
// debug("Requesting %ld pages from the kernel...", Size);
void *ret = KernelAllocator.RequestPages(Size);
drvdbg("Allocated %ld pages (%#lx-%#lx)", Size, (unsigned long)ret, (unsigned long)ret + FROM_PAGES(Size));
// debug("Got %#lx", ret);
return ret;
}
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);
debug("Freeing %ld pages from the address %#lx...", Size, (unsigned long)Page);
KernelAllocator.FreePages(Page, Size);
}
void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags)
{
SmartLock(DriverDisplayPrintLock);
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().Map(VirtualAddress, PhysicalAddress, Flags);
}
void UnmapMemory(void *VirtualAddress)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Unmapping %#lx...", (unsigned long)VirtualAddress);
debug("Unmapping %#lx...", (unsigned long)VirtualAddress);
Memory::Virtual().Unmap(VirtualAddress);
}
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
(unsigned long)Source, (unsigned long)Source + Size,
(unsigned long)Destination, (unsigned long)Destination + Size);
// debug("Copying %ld bytes from %#lx to %#lx...", Size, (unsigned long)Source, (unsigned long)Destination);
return memcpy(Destination, Source, Size);
}
void *Drivermemset(void *Destination, int Value, unsigned long Size)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
(unsigned long)Destination, (unsigned long)Destination + Size,
Size);
// debug("Setting %ld bytes from %#lx to %#x...", Size, (unsigned long)Destination, Value);
return memset(Destination, Value, Size);
}
void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{
// This is useless I guess...
if (NIManager)
NIManager->DrvSend(DriverID, Data, Size);
DumpData("DriverNetSend", Data, Size);
}
void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
{
if (NIManager)
NIManager->DrvReceive(DriverID, Data, Size);
DumpData("DriverNetReceive", Data, Size);
}
void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
{
DumpData("DriverDiskRead", Data, SectorCount * 512);
UNUSED(DriverID);
UNUSED(Sector);
UNUSED(Port);
}
void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
{
DumpData("DriverDiskWrite", Data, SectorCount * 512);
UNUSED(DriverID);
UNUSED(Sector);
UNUSED(Port);
}
char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID)
{
UNUSED(VendorID);
UNUSED(DeviceID);
return (char *)"Unknown";
}
unsigned int DriverGetWidth()
{
/* 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);
}
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 = {
KernelAPI KAPI = {
.Version = {
.Major = 0,
.Minor = 0,
@ -163,8 +115,6 @@ KernelAPI KernelAPITemplate = {
.DisplayPrint = DriverDisplayPrint,
.memcpy = Drivermemcpy,
.memset = Drivermemset,
.Sleep = DriverSleep,
.sprintf = Driversprintf,
},
.Command = {
.Network = {
@ -178,8 +128,4 @@ KernelAPI KernelAPITemplate = {
},
},
},
.Display = {
.GetWidth = DriverGetWidth,
.GetHeight = DriverGetHeight,
},
};

View File

@ -1,120 +0,0 @@
#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)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindInputDisplay(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindInputNetwork(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindInputStorage(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindInputFileSystem(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindInputInput(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
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 = new DriverFile;
DrvFile->Enabled = true;
DrvFile->DriverUID = this->DriverUIDs - 1;
DrvFile->Address = (void *)fex;
DrvFile->MemTrk = mem;
DrvFile->InterruptHook[0] = nullptr;
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
DriverCode Driver::BindInputAudio(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
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));
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)));
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,469 +0,0 @@
#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)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
fixme("Generic driver: %s", fexExtended->Driver.Name);
DriverFile *DrvFile = new DriverFile;
DrvFile->Enabled = true;
DrvFile->DriverUID = this->DriverUIDs - 1;
DrvFile->Address = (void *)fex;
DrvFile->MemTrk = mem;
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
DriverCode Driver::BindInterruptDisplay(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
fixme("Display driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindInterruptNetwork(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
fixme("Network driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindInterruptStorage(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED; // FIXME
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
UNUSED(KCallback); // Shut up clang
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;
fixme("TODO: MULTIPLE BIND INTERRUPT VECTORS %d", fexExtended->Driver.Bind.Interrupt.Vector[i]);
}
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;
}
DriverFile *DrvFile = new DriverFile;
DrvFile->Enabled = true;
DrvFile->DriverUID = this->DriverUIDs - 1;
DrvFile->Address = (void *)fex;
DrvFile->MemTrk = mem;
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
DriverCode Driver::BindInterruptFileSystem(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
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)
{
Vector<int> DriversToRemove = Vector<int>();
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;
}
}
}
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
DriverInterruptHook *InterruptHook = nullptr;
if (fexExtended->Driver.Bind.Interrupt.Vector[0] != 0)
InterruptHook = new DriverInterruptHook(fexExtended->Driver.Bind.Interrupt.Vector[0] + 32, // x86
(void *)((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex),
KCallback);
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;
// InterruptHook = new DriverInterruptHook((fexExtended->Driver.Bind.Interrupt.Vector[i] + 32, // x86
// (void *)((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex),
// KCallback);
fixme("TODO: MULTIPLE BIND INTERRUPT VECTORS %d", fexExtended->Driver.Bind.Interrupt.Vector[i]);
}
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 InterruptHook, InterruptHook = nullptr;
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
else if (CallbackRet != DriverReturnCode::OK)
{
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
delete InterruptHook, InterruptHook = nullptr;
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
memset(KCallback, 0, sizeof(KernelCallback));
KCallback->Reason = CallbackReason::InterruptReason;
DriverFile *DrvFile = new DriverFile;
DrvFile->Enabled = true;
DrvFile->DriverUID = this->DriverUIDs - 1;
DrvFile->Address = (void *)fex;
DrvFile->MemTrk = mem;
DrvFile->InterruptHook[0] = InterruptHook;
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
DriverCode Driver::BindInterruptAudio(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
fixme("Audio driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::DriverLoadBindInterrupt(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
{
UNUSED(IsElf);
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size));
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)));
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,600 +0,0 @@
#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)
{
Memory::Virtual vma = Memory::Virtual(nullptr);
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;
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);
for (size_t i = 0; i < 6; i++)
{
if (BAR[i] == 0)
continue;
debug("BAR%d: %#lx", i, BAR[i]);
}
/* BARs Size */
for (size_t 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%dSize: %#lx", 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%dSize: %#lx", i, BARsSize[i]);
}
}
/* Mapping the BARs */
for (size_t 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 from %#lx to %#lx", i, BARBase, BARBase + BARSize);
for (uintptr_t j = BARBase;
j < (BARBase + BARSize);
j += PAGE_SIZE)
{
vma.Map((void *)j, (void *)j, Memory::PTFlag::RW | Memory::PTFlag::PWT);
}
}
else if ((BAR[i] & 1) == 1) // I/O Base
{
uintptr_t BARBase = BAR[i] & (~3);
uintptr_t BARSize = BARsSize[i];
debug("Mapping BAR%d from %#x to %#x", i, BARBase, BARBase + BARSize);
for (uintptr_t j = BARBase;
j < (BARBase + BARSize);
j += PAGE_SIZE)
{
vma.Map((void *)j, (void *)j, 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::BindPCIGeneric(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
fixme("Generic driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindPCIDisplay(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
fixme("Display driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindPCINetwork(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
DriverInterruptHook *InterruptHook = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine) + 32, // x86
(void *)((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex),
KCallback);
KCallback->RawPtr = PCIDevice;
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;
delete InterruptHook, InterruptHook = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
else if (CallbackRet == DriverReturnCode::OK)
trace("Device found for driver: %s", fexExtended->Driver.Name);
else
{
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
delete mem, mem = nullptr;
delete InterruptHook, InterruptHook = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
memset(KCallback, 0, sizeof(KernelCallback));
KCallback->Reason = CallbackReason::InterruptReason;
DriverFile *DrvFile = new DriverFile;
DrvFile->Enabled = true;
DrvFile->DriverUID = this->DriverUIDs - 1;
DrvFile->Address = (void *)fex;
DrvFile->MemTrk = mem;
DrvFile->InterruptHook[0] = InterruptHook;
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
DriverCode Driver::BindPCIStorage(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
KCallback->RawPtr = PCIDevice;
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)
trace("Device found for driver: %s", fexExtended->Driver.Name);
else
{
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
DriverFile *DrvFile = new DriverFile;
DrvFile->Enabled = true;
DrvFile->DriverUID = this->DriverUIDs - 1;
DrvFile->Address = (void *)fex;
DrvFile->MemTrk = mem;
DrvFile->InterruptHook[0] = nullptr;
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
DriverCode Driver::BindPCIFileSystem(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindPCIInput(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
fixme("Input driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindPCIAudio(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
Vector<int> DriversToRemove = Vector<int>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
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));
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
if (fe->Driver.OverrideOnConflict)
return DriverCode::DRIVER_CONFLICT;
}
}
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
DriverInterruptHook *InterruptHook = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine) + 32, // x86
(void *)((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex),
KCallback);
KCallback->RawPtr = PCIDevice;
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)
trace("Device found for driver: %s", fexExtended->Driver.Name);
else
{
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
delete mem, mem = nullptr;
return DriverCode::DRIVER_RETURNED_ERROR;
}
memset(KCallback, 0, sizeof(KernelCallback));
KCallback->Reason = CallbackReason::InterruptReason;
DriverFile *DrvFile = new DriverFile;
DrvFile->Enabled = true;
DrvFile->DriverUID = this->DriverUIDs - 1;
DrvFile->Address = (void *)fex;
DrvFile->MemTrk = mem;
DrvFile->InterruptHook[0] = InterruptHook;
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
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;
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));
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)));
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,60 +0,0 @@
#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::BindProcessGeneric(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindProcessDisplay(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindProcessNetwork(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindProcessStorage(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindProcessFileSystem(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindProcessInput(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
DriverCode Driver::BindProcessAudio(Memory::MemMgr *mem, void *fex)
{
return DriverCode::NOT_IMPLEMENTED;
}
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

@ -5,6 +5,6 @@
#include "../../DAPI.hpp"
extern KernelAPI KernelAPITemplate;
extern KernelAPI KAPI;
#endif // !__FENNIX_KERNEL_DRIVER_API_H__

View File

@ -1,47 +1,46 @@
#include <ints.hpp>
#include <interrupts.hpp>
#include <syscalls.hpp>
#include <vector.hpp>
#include <hashmap.hpp>
#include <smp.hpp>
#include <io.h>
#if defined(a64)
#if defined(__amd64__)
#include "../Architecture/amd64/cpu/gdt.hpp"
#include "../Architecture/amd64/cpu/idt.hpp"
#include "../Architecture/amd64/acpi.hpp"
#include "../Architecture/amd64/cpu/apic.hpp"
#elif defined(a32)
#elif defined(__i386__)
#include "../Architecture/i686/cpu/gdt.hpp"
#include "../Architecture/i686/cpu/idt.hpp"
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
#include "crashhandler.hpp"
#include "../crashhandler.hpp"
#include "../kernel.h"
extern "C" SafeFunction void ExceptionHandler(void *Data) { CrashHandler::Handle(Data); }
namespace Interrupts
{
struct Event
{
int ID;
void *Data;
};
Vector<Event> RegisteredEvents;
HashMap<int, uint64_t> *RegisteredEvents;
#if defined(a64)
#if defined(__amd64__)
/* APIC::APIC */ void *apic[MAX_CPU];
/* APIC::Timer */ void *apicTimer[MAX_CPU];
#elif defined(a32)
#elif defined(__i386__)
/* APIC::APIC */ void *apic[MAX_CPU];
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
void *InterruptFrames[INT_FRAMES_MAX];
void Initialize(int Core)
{
#if defined(a64)
static int once = 0;
if (!once++)
RegisteredEvents = new HashMap<int, uint64_t>;
#if defined(__amd64__)
GlobalDescriptorTable::Init(Core);
InterruptDescriptorTable::Init(Core);
CPUData *CoreData = GetCPU(Core);
@ -50,8 +49,8 @@ namespace Interrupts
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core;
CoreData->IsActive = true;
CoreData->SystemCallStack = (uint8_t *)((uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE);
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
CoreData->SystemCallStack = (uint8_t *)((uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE);
CoreData->Stack = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{
KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
@ -60,21 +59,20 @@ namespace Interrupts
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
asmv("movq %0, %%rsp" ::"r"(CoreData->Stack));
InitializeSystemCalls();
#elif defined(a32)
#elif defined(__i386__)
warn("i386 is not supported yet");
#elif defined(aa64)
#elif defined(__aarch64__)
warn("aarch64 is not supported yet");
#endif
}
void Enable(int Core)
{
#if defined(a64)
#if defined(__amd64__)
if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr)
{
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
apic[Core] = new APIC::APIC(Core);
if (Core == Config.IOAPICInterruptCore) // Redirect IRQs to the specified core.
((APIC::APIC *)apic[Core])->RedirectIRQs(Core);
}
else
@ -82,9 +80,9 @@ namespace Interrupts
error("LAPIC not found");
// TODO: PIC
}
#elif defined(a32)
#elif defined(__i386__)
warn("i386 is not supported yet");
#elif defined(aa64)
#elif defined(__aarch64__)
warn("aarch64 is not supported yet");
#endif
}
@ -92,28 +90,29 @@ namespace Interrupts
void InitializeTimer(int Core)
{
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
#if defined(a64)
#if defined(__amd64__)
if (apic[Core] != nullptr)
apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]);
else
{
fixme("apic not found");
}
#elif defined(a32)
#elif defined(__i386__)
warn("i386 is not supported yet");
#elif defined(aa64)
#elif defined(__aarch64__)
warn("aarch64 is not supported yet");
#endif
}
SafeFunction void RemoveAll()
void RemoveAll()
{
RegisteredEvents.clear();
for (int i = 0; i < CPU::x64::IRQ223; i++)
RegisteredEvents->DeleteNode(i);
}
extern "C" SafeFunction void MainInterruptHandler(void *Data)
{
#if defined(a64)
#if defined(__amd64__)
CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data;
memmove(InterruptFrames + 1, InterruptFrames, sizeof(InterruptFrames) - sizeof(InterruptFrames[0]));
@ -124,32 +123,14 @@ namespace Interrupts
if (likely(CoreData != nullptr))
Core = CoreData->ID;
/* If this is false, we have a big problem. */
if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 && Frame->InterruptNumber > CPU::x86::ISR0))
// If this is false, we have a big problem.
if (likely(Frame->InterruptNumber < CPU::x64::IRQ223 && Frame->InterruptNumber > CPU::x64::ISR0))
{
/* Halt core interrupt */
if (unlikely(Frame->InterruptNumber == CPU::x86::IRQ29))
CPU::Stop();
bool InterruptHandled = false;
foreach (auto ev in RegisteredEvents)
{
if (ev.ID == static_cast<int>(Frame->InterruptNumber))
{
((Handler *)ev.Data)->OnInterruptReceived(Frame);
InterruptHandled = true;
}
}
if (!InterruptHandled)
{
error("IRQ%ld is unhandled on CPU %d.", Frame->InterruptNumber - 32, Core);
if (Frame->InterruptNumber == CPU::x86::IRQ1)
{
uint8_t scancode = inb(0x60);
warn("IRQ1 is the keyboard interrupt. Scancode: %#x", scancode);
}
}
Handler *handler = (Handler *)RegisteredEvents->Get(Frame->InterruptNumber);
if (likely(handler != (Handler *)0xdeadbeef))
handler->OnInterruptReceived(Frame);
else
error("Unhandled IRQ%ld on CPU %d.", Frame->InterruptNumber - 32, Core);
if (likely(apic[Core]))
{
@ -159,9 +140,9 @@ namespace Interrupts
}
// TODO: PIC
}
#elif defined(a32)
#elif defined(__i386__)
void *Frame = Data;
#elif defined(aa64)
#elif defined(__aarch64__)
void *Frame = Data;
#endif
error("HALT HALT HALT HALT HALT HALT HALT HALT HALT");
@ -170,42 +151,33 @@ namespace Interrupts
Handler::Handler(int InterruptNumber)
{
foreach (auto ev in RegisteredEvents)
{
if (ev.ID == InterruptNumber)
if (RegisteredEvents->Get(InterruptNumber) != (uint64_t)0xdeadbeef)
{
warn("IRQ%d is already registered.", InterruptNumber - 32);
}
return;
}
debug("Registering interrupt handler for IRQ%d.", InterruptNumber - 32);
this->InterruptNumber = InterruptNumber;
RegisteredEvents.push_back({InterruptNumber, this});
RegisteredEvents->AddNode(InterruptNumber, (uint64_t)this);
}
Handler::~Handler()
{
debug("Unregistering interrupt handler for IRQ%d.", InterruptNumber - 32);
for (size_t i = 0; i < RegisteredEvents.size(); i++)
{
if (RegisteredEvents[i].ID == InterruptNumber)
{
RegisteredEvents.remove(i);
return;
}
}
warn("Event %d not found.", InterruptNumber);
if (RegisteredEvents->DeleteNode(InterruptNumber) == 0xdeadbeef)
warn("Node %d not found.", InterruptNumber);
}
#if defined(a64)
#if defined(__amd64__)
void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
{
trace("Unhandled interrupt IRQ%d", Frame->InterruptNumber - 32);
#elif defined(a32)
void Handler::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
#elif defined(__i386__)
void Handler::OnInterruptReceived(void *Frame)
{
trace("Unhandled interrupt received");
#elif defined(aa64)
#elif defined(__aarch64__)
void Handler::OnInterruptReceived(void *Frame)
{
trace("Unhandled interrupt received");

View File

@ -5,39 +5,26 @@
#include "../kernel.h"
bool ForceUnlock = false;
Atomic<size_t> LocksCount = 0;
size_t GetLocksCount() { return LocksCount; }
void LockClass::DeadLock(SpinLockData Lock)
{
if (ForceUnlock)
{
warn("Unlocking lock '%s' which it was held by '%s'...", Lock.AttemptingToGet, Lock.CurrentHolder);
this->DeadLocks = 0;
this->Unlock();
return;
}
CPUData *CoreData = GetCurrentCPU();
long CCore = 0xdead;
if (CoreData != nullptr)
CCore = CoreData->ID;
warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld is being held by %ld. (%ld times happened)",
warn("Potential deadlock in lock '%s' held by '%s'! %ld locks in queue. Core %ld is being held by %ld. (%ld times happened)",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, Lock.Count > 1 ? "locks" : "lock",
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
CCore, Lock.Core, this->DeadLocks);
Lock.Count, CCore, Lock.Core,
this->DeadLocks);
// TODO: Print on screen too.
this->DeadLocks++;
if (Config.UnlockDeadLock && this->DeadLocks.Load() > 10)
if (Config.UnlockDeadLock && this->DeadLocks > 10)
{
warn("Unlocking lock '%s' to prevent deadlock. (this is enabled in the kernel config)", Lock.AttemptingToGet);
warn("Unlocking lock '%s' held by '%s'! %ld locks in queue. Core %ld is being held by %ld.",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, CCore, Lock.Core);
this->DeadLocks = 0;
this->Unlock();
}
@ -48,91 +35,53 @@ void LockClass::DeadLock(SpinLockData Lock)
int LockClass::Lock(const char *FunctionName)
{
// LockData.AttemptingToGet = FunctionName;
// SpinLock_Lock(&LockData.LockData);
// LockData.Count++;
// LockData.CurrentHolder = FunctionName;
// CPUData *CoreData = GetCurrentCPU();
// if (CoreData != nullptr)
// LockData.Core = CoreData->ID;
// __sync_synchronize();
// while (!__sync_bool_compare_and_swap(&IsLocked, false, true))
// CPU::Pause();
// __sync_synchronize();
LockData.AttemptingToGet = FunctionName;
LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0);
Retry:
unsigned int i = 0;
while (IsLocked.Exchange(true, MemoryOrder::Acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000))
while (__atomic_exchange_n(&IsLocked, true, __ATOMIC_ACQUIRE) && ++i < 0x10000000)
CPU::Pause();
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
if (i >= 0x10000000)
{
DeadLock(LockData);
goto Retry;
}
LockData.Count++;
LockData.CurrentHolder = FunctionName;
LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0);
CPUData *CoreData = GetCurrentCPU();
if (CoreData != nullptr)
LockData.Core = CoreData->ID;
LocksCount++;
__sync;
__sync_synchronize();
return 0;
}
int LockClass::Unlock()
{
__sync;
IsLocked.Store(false, MemoryOrder::Release);
// SpinLock_Unlock(&LockData.LockData);
// LockData.Count--;
// __sync_synchronize();
// __sync_synchronize();
// __atomic_store_n(&IsLocked, false, __ATOMIC_SEQ_CST);
// IsLocked = false;
__sync_synchronize();
__atomic_store_n(&IsLocked, false, __ATOMIC_RELEASE);
LockData.Count--;
IsLocked = false;
LocksCount--;
return 0;
}
void LockClass::TimeoutDeadLock(SpinLockData Lock, uint64_t Timeout)
{
CPUData *CoreData = GetCurrentCPU();
long CCore = 0xdead;
if (CoreData != nullptr)
CCore = CoreData->ID;
uint64_t Counter = TimeManager->GetCounter();
warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld is being held by %ld. Timeout in %ld (%ld ticks remaining).",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, Lock.Count > 1 ? "locks" : "lock",
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
CCore, Lock.Core, Timeout, Timeout - Counter);
if (Timeout < Counter)
{
warn("Unlocking lock '%s' because of timeout. (%ld < %ld)", Lock.AttemptingToGet, Timeout, Counter);
this->Unlock();
}
if (TaskManager)
TaskManager->Schedule();
}
int LockClass::TimeoutLock(const char *FunctionName, uint64_t Timeout)
{
if (!TimeManager)
return Lock(FunctionName);
LockData.AttemptingToGet = FunctionName;
LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0);
Atomic<uint64_t> Target = 0;
Retry:
unsigned int i = 0;
while (IsLocked.Exchange(true, MemoryOrder::Acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000))
CPU::Pause();
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
{
if (Target.Load() == 0)
Target.Store(TimeManager->CalculateTarget(Timeout));
TimeoutDeadLock(LockData, Target.Load());
goto Retry;
}
LockData.Count++;
LockData.CurrentHolder = FunctionName;
LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0);
CPUData *CoreData = GetCurrentCPU();
if (CoreData != nullptr)
LockData.Core = CoreData->ID;
LocksCount++;
__sync;
return 0;
}

View File

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

View File

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

View File

@ -1,137 +0,0 @@
# Xalloc
Xalloc is a custom memory allocator designed for hobby operating systems. It is written in C++ and provides a simple and efficient way to manage memory in your hobby OS.
#### ❗ This project is still in development and is not ready for use in production environments. ❗
---
## Features
- **Simple API** - Xalloc provides a simple API for allocating and freeing memory. It is designed to be easy to use and understand.
- [ ] todo complete this
---
## Getting Started
### Implementing missing functions
You will need to implement the following functions in your OS:
##### Wrapper.cpp
```cpp
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages)
{
// ...
}
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages)
{
// ...
}
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags)
{
// ...
}
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
{
// ...
}
```
##### Xalloc.hpp
```cpp
#define Xalloc_PAGE_SIZE <page size> /* <-- Replace with your page size */
#define Xalloc_trace(m, ...) <trace function>
#define Xalloc_warn(m, ...) <warning function>
#define Xalloc_err(m, ...) <error function>
#define Xalloc_def <define a lock> /* eg. std::mutex Xalloc_lock; */
#define Xalloc_lock <lock function>
#define Xalloc_unlock <unlock function>
```
### Typical usage
```cpp
#include "Xalloc.hpp"
Xalloc::V1 *XallocV1Allocator = nullptr;
int main()
{
/* Virtual Base User SMAP */
XallocV1Allocator = new Xalloc::V1((void *)0xFFFFA00000000000, false, false);
void *p = XallocV1Allocator->malloc(1234);
/* ... */
XallocV1Allocator->free(p);
delete XallocV1Allocator;
return 0;
}
```
or
```cpp
#include "Xalloc.hpp"
int main()
{
/* Virtual Base User SMAP */
Xalloc::V1 XallocV1Allocator((void *)0xFFFFA00000000000, false, false);
void *p = XallocV1Allocator.malloc(1234);
/* ... */
XallocV1Allocator.free(p);
return 0;
}
```
---
## API
### Xalloc::V1
```cpp
void *malloc(Xsize_t Size);
```
Allocates a block of memory of size `Size` bytes.
If `Size` is 0, then `nullptr` is returned.
- `Size` - The size of the block to allocate in bytes.
<br><br>
```cpp
void free(void *Address);
```
Frees the memory block pointed to by `Address`.
If `Address` is `nullptr`, then no operation is performed.
- `Address` - The address of the memory block to free.
<br><br>
```cpp
void *calloc(Xsize_t NumberOfBlocks, Xsize_t Size);
```
Allocates a block of memory for an array of `NumberOfBlocks` elements, each of them `Size` bytes long.
If `NumberOfBlocks` or `Size` is 0, then `nullptr` is returned.
- `NumberOfBlocks` - The number of elements to allocate.
- `Size` - The size of each element in bytes.
<br><br>
```cpp
void *realloc(void *Address, Xsize_t Size);
```
Changes the size of the memory block pointed to by `Address` to `Size` bytes.
If `Address` is `nullptr`, then the call is equivalent to `malloc(Size)`.
If `Size` is equal to zero, and `Address` is not `nullptr`, then the call is equivalent to `free(Address)`.
- `Address` - The address of the memory block to resize.
- `Size` - The new size of the memory block in bytes.
---

View File

@ -1,23 +0,0 @@
#include "Xalloc.hpp"
#include <memory.hpp>
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages)
{
return KernelAllocator.RequestPages(Pages);
}
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages)
{
KernelAllocator.FreePages(Address, Pages);
}
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags)
{
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
}
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
{
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
}

View File

@ -1,102 +0,0 @@
#ifndef __FENNIX_KERNEL_Xalloc_H__
#define __FENNIX_KERNEL_Xalloc_H__
#include <memory.hpp>
#include <lock.hpp>
#include <debug.h>
typedef long unsigned Xuint64_t;
typedef long unsigned Xsize_t;
#define Xalloc_StopOnFail true
#define Xalloc_PAGE_SIZE PAGE_SIZE
#define Xalloc_trace(m, ...) trace(m, ##__VA_ARGS__)
#define Xalloc_warn(m, ...) warn(m, ##__VA_ARGS__)
#define Xalloc_err(m, ...) error(m, ##__VA_ARGS__)
#define Xalloc_def NewLock(XallocLock)
#define Xalloc_lock XallocLock.Lock(__FUNCTION__)
#define Xalloc_unlock XallocLock.Unlock()
namespace Xalloc
{
class V1
{
private:
void *BaseVirtualAddress = nullptr;
void *FirstBlock = nullptr;
void *LastBlock = nullptr;
bool UserMapping = false;
bool SMAPUsed = false;
public:
/** @brief Execute "stac" instruction if the kernel has SMAP enabled */
void Xstac();
/** @brief Execute "clac" instruction if the kernel has SMAP enabled */
void Xclac();
/**
* @brief Arrange the blocks to optimize the memory usage
* The allocator is not arranged by default
* to avoid performance issues.
* This function will defragment the memory
* and free the unused blocks.
*
* You should call this function when the
* kernel is idle or when is not using
* the allocator.
*/
void Arrange();
/**
* @brief Allocate a new memory block
*
* @param Size Size of the block to allocate.
* @return void* Pointer to the allocated block.
*/
void *malloc(Xsize_t Size);
/**
* @brief Free a previously allocated block
*
* @param Address Address of the block to free.
*/
void free(void *Address);
/**
* @brief Allocate a new memory block
*
* @param NumberOfBlocks Number of blocks to allocate.
* @param Size Size of the block to allocate.
* @return void* Pointer to the allocated block.
*/
void *calloc(Xsize_t NumberOfBlocks, Xsize_t Size);
/**
* @brief Reallocate a previously allocated block
*
* @param Address Address of the block to reallocate.
* @param Size New size of the block.
* @return void* Pointer to the reallocated block.
*/
void *realloc(void *Address, Xsize_t Size);
/**
* @brief Construct a new Allocator object
*
* @param BaseVirtualAddress Virtual address to map the pages.
* @param UserMode Map the new pages with USER flag?
* @param SMAPEnabled Does the kernel has Supervisor Mode Access Prevention enabled?
*/
V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled);
/**
* @brief Destroy the Allocator object
*
*/
~V1();
};
}
#endif // !__FENNIX_KERNEL_Xalloc_H__

View File

@ -1,271 +0,0 @@
#include "Xalloc.hpp"
Xalloc_def;
#define XALLOC_CONCAT(x, y) x##y
#define XStoP(x) (x / Xalloc_PAGE_SIZE + 1)
#define XPtoS(x) (x * Xalloc_PAGE_SIZE)
#define Xalloc_BlockChecksum 0xA110C
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages);
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages);
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags);
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress);
// TODO: Change memcpy with an optimized version
void *Xmemcpy(void *__restrict__ Destination, const void *__restrict__ Source, Xuint64_t Length)
{
unsigned char *dst = (unsigned char *)Destination;
const unsigned char *src = (const unsigned char *)Source;
for (Xuint64_t i = 0; i < Length; i++)
dst[i] = src[i];
return Destination;
}
// TODO: Change memset with an optimized version
void *Xmemset(void *__restrict__ Destination, int Data, Xuint64_t Length)
{
unsigned char *Buffer = (unsigned char *)Destination;
for (Xuint64_t i = 0; i < Length; i++)
Buffer[i] = (unsigned char)Data;
return Destination;
}
namespace Xalloc
{
class Block
{
public:
void *Address = nullptr;
int Checksum = Xalloc_BlockChecksum;
Xsize_t Size = 0;
Block *Next = nullptr;
Block *Last = nullptr;
bool IsFree = true;
bool Check()
{
if (this->Checksum != Xalloc_BlockChecksum)
return false;
return true;
}
Block(Xsize_t Size)
{
this->Address = Xalloc_REQUEST_PAGES(XStoP(Size));
this->Size = Size;
Xmemset(this->Address, 0, Size);
}
~Block()
{
Xalloc_FREE_PAGES(this->Address, XStoP(this->Size));
}
/**
* @brief Overload new operator to allocate memory from the heap
* @param Size Unused
* @return void* Pointer to the allocated memory
*/
void *operator new(Xsize_t Size)
{
void *ptr = Xalloc_REQUEST_PAGES(XStoP(sizeof(Block)));
return ptr;
}
/**
* @brief Overload delete operator to free memory from the heap
* @param Address Pointer to the memory to free
*/
void operator delete(void *Address)
{
Xalloc_FREE_PAGES(Address, XStoP(sizeof(Block)));
}
} __attribute__((packed, aligned((16))));
class SmartSMAPClass
{
private:
V1 *allocator = nullptr;
public:
SmartSMAPClass(V1 *allocator)
{
this->allocator = allocator;
this->allocator->Xstac();
}
~SmartSMAPClass() { this->allocator->Xclac(); }
};
#define SmartSMAP SmartSMAPClass XALLOC_CONCAT(SmartSMAP##_, __COUNTER__)(this)
void V1::Xstac()
{
if (this->SMAPUsed)
{
#if defined(a64) || defined(a32)
asm volatile("stac" ::
: "cc");
#endif
}
}
void V1::Xclac()
{
if (this->SMAPUsed)
{
#if defined(a64) || defined(a32)
asm volatile("clac" ::
: "cc");
#endif
}
}
void V1::Arrange()
{
Xalloc_err("Arrange() is not implemented yet!");
}
void *V1::malloc(Xsize_t Size)
{
if (Size == 0)
{
Xalloc_warn("Attempted to allocate 0 bytes!");
return nullptr;
}
SmartSMAP;
Xalloc_lock;
if (this->FirstBlock == nullptr)
{
this->FirstBlock = new Block(Size);
((Block *)this->FirstBlock)->IsFree = false;
Xalloc_unlock;
return ((Block *)this->FirstBlock)->Address;
}
Block *CurrentBlock = ((Block *)this->FirstBlock);
while (CurrentBlock != nullptr)
{
if (!CurrentBlock->Check())
{
Xalloc_err("Block %#lx has an invalid checksum! (%#x != %#x)",
(Xuint64_t)CurrentBlock, CurrentBlock->Checksum, Xalloc_BlockChecksum);
while (Xalloc_StopOnFail)
;
}
else if (CurrentBlock->IsFree && CurrentBlock->Size >= Size)
{
CurrentBlock->IsFree = false;
Xmemset(CurrentBlock->Address, 0, Size);
Xalloc_unlock;
return CurrentBlock->Address;
}
CurrentBlock = CurrentBlock->Next;
}
CurrentBlock = ((Block *)this->FirstBlock);
while (CurrentBlock->Next != nullptr)
CurrentBlock = CurrentBlock->Next;
CurrentBlock->Next = new Block(Size);
((Block *)CurrentBlock->Next)->Last = CurrentBlock;
((Block *)CurrentBlock->Next)->IsFree = false;
Xalloc_unlock;
return ((Block *)CurrentBlock->Next)->Address;
}
void V1::free(void *Address)
{
if (Address == nullptr)
{
Xalloc_warn("Attempted to free a null pointer!");
return;
}
SmartSMAP;
Xalloc_lock;
Block *CurrentBlock = ((Block *)this->FirstBlock);
while (CurrentBlock != nullptr)
{
if (!CurrentBlock->Check())
{
Xalloc_err("Block %#lx checksum failed!", (Xuint64_t)CurrentBlock);
while (Xalloc_StopOnFail)
;
}
else if (CurrentBlock->Address == Address)
{
if (CurrentBlock->IsFree)
{
Xalloc_warn("Attempted to free an already freed pointer!");
Xalloc_unlock;
return;
}
CurrentBlock->IsFree = true;
Xalloc_unlock;
return;
}
CurrentBlock = CurrentBlock->Next;
}
Xalloc_err("Invalid address.");
Xalloc_unlock;
}
void *V1::calloc(Xsize_t NumberOfBlocks, Xsize_t Size)
{
if (NumberOfBlocks == 0 || Size == 0)
{
Xalloc_warn("The %s%s%s is 0!",
NumberOfBlocks == 0 ? "NumberOfBlocks" : "",
NumberOfBlocks == 0 && Size == 0 ? " and " : "",
Size == 0 ? "Size" : "");
return nullptr;
}
return this->malloc(NumberOfBlocks * Size);
}
void *V1::realloc(void *Address, Xsize_t Size)
{
if (Address == nullptr)
return this->malloc(Size);
if (Size == 0)
{
this->free(Address);
return nullptr;
}
// SmartSMAP;
// Xalloc_lock;
// ...
// Xalloc_unlock;
// TODO: Implement realloc
this->free(Address);
return this->malloc(Size);
}
V1::V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled)
{
SmartSMAP;
Xalloc_lock;
this->SMAPUsed = SMAPEnabled;
this->UserMapping = UserMode;
this->BaseVirtualAddress = BaseVirtualAddress;
Xalloc_unlock;
}
V1::~V1()
{
SmartSMAP;
Xalloc_lock;
Xalloc_trace("Destructor not implemented yet.");
Xalloc_unlock;
}
}

View File

@ -1,88 +1,56 @@
#include <memory.hpp>
#include <convert.h>
#include <lock.hpp>
#include <debug.h>
#ifdef DEBUG
#include <uart.hpp>
#endif
#include "HeapAllocators/Xalloc/Xalloc.hpp"
#include "HeapAllocators/Xalloc.hpp"
#include "../Library/liballoc_1_1.h"
#include "../../kernel.h"
// #define DEBUG_ALLOCATIONS_SL 1
// #define DEBUG_ALLOCATIONS 1
#ifdef DEBUG_ALLOCATIONS
#define memdbg(m, ...) \
debug(m, ##__VA_ARGS__); \
__sync
#else
#define memdbg(m, ...)
#endif
using namespace Memory;
#ifdef DEBUG_ALLOCATIONS_SL
NewLock(AllocatorLock);
NewLock(OperatorAllocatorLock);
#endif
Physical KernelAllocator;
PageTable4 *KernelPageTable = nullptr;
PageTable4 *UserspaceKernelOnlyPageTable = nullptr;
void *KPT = nullptr;
PageTable *KernelPageTable = nullptr;
PageTable *UserspaceKernelOnlyPageTable = nullptr;
static MemoryAllocatorType AllocatorType = MemoryAllocatorType::None;
Xalloc::V1 *XallocV1Allocator = nullptr;
Xalloc::AllocatorV1 *XallocV1Allocator = nullptr;
#ifdef DEBUG
NIF void tracepagetable(PageTable4 *pt)
__no_instrument_function void tracepagetable(PageTable *pt)
{
for (int i = 0; i < 512; i++)
{
#if defined(a64)
if (pt->Entries[i].Present)
debug("Entry %03d: %x %x %x %x %x %x %x %p-%#llx", i,
pt->Entries[i].Present, pt->Entries[i].ReadWrite,
pt->Entries[i].UserSupervisor, pt->Entries[i].WriteThrough,
pt->Entries[i].CacheDisable, pt->Entries[i].Accessed,
pt->Entries[i].ExecuteDisable, pt->Entries[i].Address << 12,
pt->Entries[i]);
#elif defined(a32)
#elif defined(aa64)
#if defined(__amd64__)
if (pt->Entries[i].Value.Present)
debug("Entry %03d: %x %x %x %x %x %x %x %x %x %x %x %p-%#llx", i,
pt->Entries[i].Value.Present, pt->Entries[i].Value.ReadWrite,
pt->Entries[i].Value.UserSupervisor, pt->Entries[i].Value.WriteThrough,
pt->Entries[i].Value.CacheDisable, pt->Entries[i].Value.Accessed,
pt->Entries[i].Value.Dirty, pt->Entries[i].Value.PageSize,
pt->Entries[i].Value.Global, pt->Entries[i].Value.PageAttributeTable,
pt->Entries[i].Value.ExecuteDisable, pt->Entries[i].GetAddress(),
pt->Entries[i].Value);
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
}
}
#endif
NIF void MapFromZero(PageTable4 *PT, BootInfo *Info)
__no_instrument_function void MapFromZero(PageTable *PT, BootInfo *Info)
{
static int once = 0;
if (!once++)
{
Virtual va = Virtual(PT);
void *NullAddress = KernelAllocator.RequestPage();
memset(NullAddress, 0, PAGE_SIZE); // TODO: If the CPU instruction pointer hits this page, there should be function to handle it. (memcpy assembly code?)
va.Map((void *)0, (void *)NullAddress, PTFlag::RW | PTFlag::US);
uintptr_t VirtualOffsetNormalVMA = NORMAL_VMA_OFFSET;
size_t MemSize = Info->Memory.Size;
for (size_t t = 0; t < MemSize; t += PAGE_SIZE)
uint64_t VirtualOffsetNormalVMA = NORMAL_VMA_OFFSET;
uint64_t MemSize = Info->Memory.Size;
for (uint64_t t = 0; t < MemSize; t += PAGE_SIZE)
{
va.Map((void *)t, (void *)t, PTFlag::RW /* | PTFlag::US */);
// va.Map((void *)VirtualOffsetNormalVMA, (void *)t, PTFlag::RW /* | PTFlag::US */);
// VirtualOffsetNormalVMA += PAGE_SIZE;
}
}
else
{
error("MapFromZero() called more than once!");
CPU::Stop();
va.Map((void *)VirtualOffsetNormalVMA, (void *)t, PTFlag::RW /* | PTFlag::US */);
VirtualOffsetNormalVMA += PAGE_SIZE;
}
}
NIF void MapFramebuffer(PageTable4 *PT, BootInfo *Info)
__no_instrument_function void MapFramebuffer(PageTable *PT, BootInfo *Info)
{
Virtual va = Virtual(PT);
int itrfb = 0;
@ -91,28 +59,28 @@ NIF void MapFramebuffer(PageTable4 *PT, BootInfo *Info)
if (!Info->Framebuffer[itrfb].BaseAddress)
break;
for (uintptr_t fb_base = (uintptr_t)Info->Framebuffer[itrfb].BaseAddress;
fb_base < ((uintptr_t)Info->Framebuffer[itrfb].BaseAddress + ((Info->Framebuffer[itrfb].Pitch * Info->Framebuffer[itrfb].Height) + PAGE_SIZE));
for (uint64_t fb_base = (uint64_t)Info->Framebuffer[itrfb].BaseAddress;
fb_base < ((uint64_t)Info->Framebuffer[itrfb].BaseAddress + ((Info->Framebuffer[itrfb].Pitch * Info->Framebuffer[itrfb].Height) + PAGE_SIZE));
fb_base += PAGE_SIZE)
va.Map((void *)fb_base, (void *)fb_base, PTFlag::RW | PTFlag::US | PTFlag::G);
va.Map((void *)(fb_base + NORMAL_VMA_OFFSET), (void *)fb_base, PTFlag::RW | PTFlag::US | PTFlag::G);
itrfb++;
}
}
NIF void MapKernel(PageTable4 *PT, BootInfo *Info)
__no_instrument_function void MapKernel(PageTable *PT, BootInfo *Info)
{
/* KernelStart KernelTextEnd KernelRoDataEnd KernelEnd
Kernel Start & Text Start ------ Text End ------ Kernel Rodata End ------ Kernel Data End & Kernel End
*/
Virtual va = Virtual(PT);
uintptr_t KernelStart = (uintptr_t)&_kernel_start;
uintptr_t KernelTextEnd = (uintptr_t)&_kernel_text_end;
uintptr_t KernelDataEnd = (uintptr_t)&_kernel_data_end;
uintptr_t KernelRoDataEnd = (uintptr_t)&_kernel_rodata_end;
uintptr_t KernelEnd = (uintptr_t)&_kernel_end;
uint64_t KernelStart = (uint64_t)&_kernel_start;
uint64_t KernelTextEnd = (uint64_t)&_kernel_text_end;
uint64_t KernelDataEnd = (uint64_t)&_kernel_data_end;
uint64_t KernelRoDataEnd = (uint64_t)&_kernel_rodata_end;
uint64_t KernelEnd = (uint64_t)&_kernel_end;
uintptr_t BaseKernelMapAddress = (uintptr_t)Info->Kernel.PhysicalBase;
uintptr_t k;
uint64_t BaseKernelMapAddress = (uint64_t)Info->Kernel.PhysicalBase;
uint64_t k;
for (k = KernelStart; k < KernelTextEnd; k += PAGE_SIZE)
{
@ -146,14 +114,14 @@ NIF void MapKernel(PageTable4 *PT, BootInfo *Info)
KernelStart, KernelTextEnd, KernelRoDataEnd, KernelEnd, Info->Kernel.PhysicalBase, BaseKernelMapAddress - PAGE_SIZE);
}
NIF void InitializeMemoryManagement(BootInfo *Info)
__no_instrument_function void InitializeMemoryManagement(BootInfo *Info)
{
#ifdef DEBUG
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
{
uintptr_t Base = reinterpret_cast<uintptr_t>(Info->Memory.Entry[i].BaseAddress);
uintptr_t Length = Info->Memory.Entry[i].Length;
uintptr_t End = Base + Length;
uint64_t Base = reinterpret_cast<uint64_t>(Info->Memory.Entry[i].BaseAddress);
uint64_t Length = Info->Memory.Entry[i].Length;
uint64_t End = Base + Length;
const char *Type = "Unknown";
switch (Info->Memory.Entry[i].Type)
@ -193,8 +161,9 @@ NIF void InitializeMemoryManagement(BootInfo *Info)
Type);
}
#endif
trace("Initializing Physical Memory Manager");
// KernelAllocator = Physical(); <- Already called in the constructor
KernelAllocator = Physical();
KernelAllocator.Init(Info);
debug("Memory Info: %lldMB / %lldMB (%lldMB reserved)",
TO_MB(KernelAllocator.GetUsedMemory()),
@ -204,16 +173,17 @@ NIF void InitializeMemoryManagement(BootInfo *Info)
AllocatorType = MemoryAllocatorType::Pages;
trace("Initializing Virtual Memory Manager");
KernelPageTable = (PageTable4 *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
KernelPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
memset(KernelPageTable, 0, PAGE_SIZE);
UserspaceKernelOnlyPageTable = (PageTable4 *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
UserspaceKernelOnlyPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
memset(UserspaceKernelOnlyPageTable, 0, PAGE_SIZE);
debug("Mapping from 0x0 to %#llx", Info->Memory.Size);
MapFromZero(KernelPageTable, Info);
debug("Mapping from 0x0 %#llx for Userspace Page Table", Info->Memory.Size);
UserspaceKernelOnlyPageTable[0] = KernelPageTable[0];
UserspaceKernelOnlyPageTable[0] = KernelPageTable[0]; // TODO: This is a hack to speed up the boot process
// MapFromZero(UserspaceKernelOnlyPageTable, Info);
/* Mapping Framebuffer address */
debug("Mapping Framebuffer");
@ -234,16 +204,15 @@ NIF void InitializeMemoryManagement(BootInfo *Info)
debug("Userspace:");
tracepagetable(UserspaceKernelOnlyPageTable);
#endif
KPT = KernelPageTable;
#if defined(a64) || defined(a32)
asmv("mov %0, %%cr3" ::"r"(KPT));
#elif defined(aa64)
asmv("msr ttbr0_el1, %0" ::"r"(KPT));
#if defined(__amd64__) || defined(__i386__)
asmv("mov %0, %%cr3" ::"r"(KernelPageTable));
#elif defined(__aarch64__)
asmv("msr ttbr0_el1, %0" ::"r"(KernelPageTable));
#endif
debug("Page table updated.");
if (strstr(Info->Kernel.CommandLine, "xallocv1"))
{
XallocV1Allocator = new Xalloc::V1((void *)KERNEL_HEAP_BASE, false, false);
XallocV1Allocator = new Xalloc::AllocatorV1((void *)KERNEL_HEAP_BASE, false, false);
AllocatorType = MemoryAllocatorType::XallocV1;
trace("XallocV1 Allocator initialized (%p)", XallocV1Allocator);
}
@ -253,79 +222,40 @@ NIF void InitializeMemoryManagement(BootInfo *Info)
}
}
void *HeapMalloc(size_t Size)
void *HeapMalloc(uint64_t Size)
{
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("malloc(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
void *ret = nullptr;
switch (AllocatorType)
{
case MemoryAllocatorType::Pages:
{
ret = KernelAllocator.RequestPages(TO_PAGES(Size));
memset(ret, 0, Size);
break;
}
case unlikely(MemoryAllocatorType::Pages):
return KernelAllocator.RequestPages(TO_PAGES(Size));
case MemoryAllocatorType::XallocV1:
{
ret = XallocV1Allocator->malloc(Size);
break;
void *ret = XallocV1Allocator->Malloc(Size);
memset(ret, 0, Size);
return ret;
}
case MemoryAllocatorType::liballoc11:
{
ret = PREFIX(malloc)(Size);
void *ret = PREFIX(malloc)(Size);
memset(ret, 0, Size);
break;
return ret;
}
default:
throw;
}
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "malloc( %ld )=%p~%p\n\r",
Size,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret;
}
void *HeapCalloc(size_t n, size_t Size)
void *HeapCalloc(uint64_t n, uint64_t Size)
{
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("calloc(%d, %d)->[%s]", n, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
void *ret = nullptr;
switch (AllocatorType)
{
case MemoryAllocatorType::Pages:
{
ret = KernelAllocator.RequestPages(TO_PAGES(n * Size));
memset(ret, 0, n * Size);
break;
}
case unlikely(MemoryAllocatorType::Pages):
return KernelAllocator.RequestPages(TO_PAGES(n * Size));
case MemoryAllocatorType::XallocV1:
{
ret = XallocV1Allocator->calloc(n, Size);
break;
void *ret = XallocV1Allocator->Calloc(n, Size);
memset(ret, 0, n * Size);
return ret;
}
case MemoryAllocatorType::liballoc11:
{
@ -336,49 +266,19 @@ void *HeapCalloc(size_t n, size_t Size)
default:
throw;
}
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "calloc( %ld %ld )=%p~%p\n\r",
n, Size,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret;
}
void *HeapRealloc(void *Address, size_t Size)
void *HeapRealloc(void *Address, uint64_t Size)
{
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("realloc(%#lx, %d)->[%s]", Address, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
void *ret = nullptr;
switch (AllocatorType)
{
case unlikely(MemoryAllocatorType::Pages):
{
ret = KernelAllocator.RequestPages(TO_PAGES(Size)); // WARNING: Potential memory leak
memset(ret, 0, Size);
break;
}
return KernelAllocator.RequestPages(TO_PAGES(Size)); // WARNING: Potential memory leak
case MemoryAllocatorType::XallocV1:
{
ret = XallocV1Allocator->realloc(Address, Size);
break;
void *ret = XallocV1Allocator->Realloc(Address, Size);
memset(ret, 0, Size);
return ret;
}
case MemoryAllocatorType::liballoc11:
{
@ -389,291 +289,54 @@ void *HeapRealloc(void *Address, size_t Size)
default:
throw;
}
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "realloc( %p %ld )=%p~%p\n\r",
Address, Size,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret;
}
void HeapFree(void *Address)
{
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("free(%#lx)->[%s]", Address, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
switch (AllocatorType)
{
case unlikely(MemoryAllocatorType::Pages):
{
KernelAllocator.FreePage(Address); // WARNING: Potential memory leak
break;
}
case MemoryAllocatorType::XallocV1:
{
XallocV1Allocator->free(Address);
if (XallocV1Allocator)
XallocV1Allocator->Free(Address);
break;
}
case MemoryAllocatorType::liballoc11:
{
PREFIX(free)
(Address);
break;
}
default:
throw;
}
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "free( %p )~%p\n\r",
Address,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
}
void *operator new(size_t Size)
{
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("new(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
void *ret = HeapMalloc(Size);
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "new( %ld )=%p~%p\n\r",
Size,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret;
return HeapMalloc(Size);
}
void *operator new[](size_t Size)
{
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("new[](%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
void *ret = HeapMalloc(Size);
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "new[]( %ld )=%p~%p\n\r",
Size,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret;
return HeapMalloc(Size);
}
void *operator new(unsigned long Size, std::align_val_t Alignment)
{
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("new(%d, %d)->[%s]", Size, Alignment, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
fixme("operator new with alignment(%#lx) is not implemented", Alignment);
void *ret = HeapMalloc(Size);
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "new( %ld %#lx )=%p~%p\n\r",
Size, (uintptr_t)Alignment,
ret, __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return ret;
return HeapMalloc(Size);
}
void operator delete(void *Pointer)
{
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("delete(%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
HeapFree(Pointer);
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "delete( %p )~%p\n\r",
Pointer,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
}
void operator delete[](void *Pointer)
{
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("delete[](%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
HeapFree(Pointer);
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "delete[]( %p )~%p\n\r",
Pointer,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
}
void operator delete(void *Pointer, long unsigned int Size)
{
UNUSED(Size);
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("delete(%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
HeapFree(Pointer);
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "delete( %p %ld )~%p\n\r",
Pointer, Size,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
}
void operator delete[](void *Pointer, long unsigned int Size)
{
UNUSED(Size);
#ifdef DEBUG_ALLOCATIONS_SL
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
#endif
memdbg("delete[](%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
HeapFree(Pointer);
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "delete[]( %p %ld )~%p\n\r",
Pointer, Size,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
}

View File

@ -1,220 +0,0 @@
#include <memory.hpp>
#include <debug.h>
#include "../../kernel.h"
namespace Memory
{
ReadFSFunction(MEM_Read)
{
if (!Size)
Size = node->Length;
if (Offset > node->Length)
return 0;
if (Offset + Size > node->Length)
Size = node->Length - Offset;
memcpy(Buffer, (uint8_t *)(node->Address + Offset), Size);
return Size;
}
WriteFSFunction(MEM_Write)
{
if (!Size)
Size = node->Length;
if (Offset > node->Length)
return 0;
if (Offset + Size > node->Length)
Size = node->Length - Offset;
memcpy((uint8_t *)(node->Address + Offset), Buffer, Size);
return Size;
}
VirtualFileSystem::FileSystemOperations mem_op = {
.Name = "mem",
.Read = MEM_Read,
.Write = MEM_Write,
};
uint64_t MemMgr::GetAllocatedMemorySize()
{
uint64_t Size = 0;
foreach (auto ap in AllocatedPagesList)
Size += ap.PageCount;
return FROM_PAGES(Size);
}
bool MemMgr::Add(void *Address, size_t Count)
{
if (Address == nullptr)
{
error("Address is null!");
return false;
}
if (Count == 0)
{
error("Count is 0!");
return false;
}
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
{
if (AllocatedPagesList[i].Address == Address)
{
error("Address already exists!");
return false;
}
else if ((uintptr_t)Address < (uintptr_t)AllocatedPagesList[i].Address)
{
if ((uintptr_t)Address + (Count * PAGE_SIZE) > (uintptr_t)AllocatedPagesList[i].Address)
{
error("Address intersects with an allocated page!");
return false;
}
}
else
{
if ((uintptr_t)AllocatedPagesList[i].Address + (AllocatedPagesList[i].PageCount * PAGE_SIZE) > (uintptr_t)Address)
{
error("Address intersects with an allocated page!");
return false;
}
}
}
if (this->Directory)
{
char FileName[64];
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory);
if (n)
{
n->Address = (uintptr_t)Address;
n->Length = Count * PAGE_SIZE;
n->Operator = &mem_op;
}
}
AllocatedPagesList.push_back({Address, Count});
return true;
}
void *MemMgr::RequestPages(size_t Count, bool User)
{
void *Address = KernelAllocator.RequestPages(Count);
for (size_t i = 0; i < Count; i++)
{
int Flags = Memory::PTFlag::RW;
if (User)
Flags |= Memory::PTFlag::US;
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), Flags);
}
if (this->Directory)
{
char FileName[64];
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory);
if (n) // If null, error or file already exists
{
n->Address = (uintptr_t)Address;
n->Length = Count * PAGE_SIZE;
n->Operator = &mem_op;
}
}
AllocatedPagesList.push_back({Address, Count});
/* For security reasons, we clear the memory
if the page is user accessible. */
if (User)
memset(Address, 0, Count * PAGE_SIZE);
return Address;
}
void MemMgr::FreePages(void *Address, size_t Count)
{
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
if (AllocatedPagesList[i].Address == Address)
{
/** TODO: Advanced checks. Allow if the page count is less than the requested one.
* This will allow the user to free only a part of the allocated pages.
*
* But this will be in a separate function because we need to specify if we
* want to free from the start or from the end and return the new address.
*/
if (AllocatedPagesList[i].PageCount != Count)
{
error("Page count mismatch! (Allocated: %lld, Requested: %lld)", AllocatedPagesList[i].PageCount, Count);
return;
}
KernelAllocator.FreePages(Address, Count);
for (size_t i = 0; i < Count; i++)
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), Memory::PTFlag::RW);
// Memory::Virtual(this->PageTable).Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
if (this->Directory)
{
char FileName[64];
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
VirtualFileSystem::FileStatus s = vfs->Delete(FileName, false, this->Directory);
if (s != VirtualFileSystem::FileStatus::OK)
error("Failed to delete file %s", FileName);
}
AllocatedPagesList.remove(i);
return;
}
}
void MemMgr::DetachAddress(void *Address)
{
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
if (AllocatedPagesList[i].Address == Address)
{
if (this->Directory)
{
char FileName[64];
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, AllocatedPagesList[i].PageCount);
VirtualFileSystem::FileStatus s = vfs->Delete(FileName, false, this->Directory);
if (s != VirtualFileSystem::FileStatus::OK)
error("Failed to delete file %s", FileName);
}
AllocatedPagesList.remove(i);
return;
}
}
MemMgr::MemMgr(PageTable4 *PageTable, VirtualFileSystem::Node *Directory)
{
if (PageTable)
this->PageTable = PageTable;
else
#if defined(a64)
this->PageTable = (PageTable4 *)CPU::x64::readcr3().raw;
#elif defined(a32)
this->PageTable = (PageTable4 *)CPU::x32::readcr3().raw;
#endif
this->Directory = Directory;
debug("+ %#lx", this);
}
MemMgr::~MemMgr()
{
foreach (auto ap in AllocatedPagesList)
{
KernelAllocator.FreePages(ap.Address, ap.PageCount);
for (size_t i = 0; i < ap.PageCount; i++)
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), (void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), Memory::PTFlag::RW);
}
if (this->Directory)
foreach (auto Child in this->Directory->Children)
vfs->Delete(Child, true);
debug("- %#lx", this);
}
}

View File

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

View File

@ -2,27 +2,27 @@
namespace Memory
{
Virtual::PageMapIndexer::PageMapIndexer(uintptr_t VirtualAddress)
Virtual::PageMapIndexer::PageMapIndexer(uint64_t VirtualAddress)
{
#if defined(a64)
uintptr_t Address = VirtualAddress;
#if defined(__amd64__)
uint64_t Address = VirtualAddress;
Address >>= 12;
this->PTEIndex = Address & 0x1FF;
this->PIndex = Address & 0x1FF;
Address >>= 9;
this->PDEIndex = Address & 0x1FF;
this->PTIndex = Address & 0x1FF;
Address >>= 9;
this->PDPTEIndex = Address & 0x1FF;
this->PDIndex = Address & 0x1FF;
Address >>= 9;
this->PMLIndex = Address & 0x1FF;
#elif defined(a32)
uintptr_t Address = VirtualAddress;
this->PDPIndex = Address & 0x1FF;
#elif defined(__i386__)
uint64_t Address = VirtualAddress;
Address >>= 12;
this->PTEIndex = Address & 0x3FF;
this->PIndex = Address & 0x3FF;
Address >>= 10;
this->PDEIndex = Address & 0x3FF;
this->PTIndex = Address & 0x3FF;
Address >>= 10;
this->PDPTEIndex = Address & 0x3FF;
#elif defined(aa64)
this->PDIndex = Address & 0x3FF;
#elif defined(__aarch64__)
#endif
}
}

View File

@ -1,13 +1,6 @@
#include <memory.hpp>
#include <debug.h>
#ifdef DEBUG
#include <uart.hpp>
#endif
#include "../../kernel.h"
extern "C" char BootPageTable[]; // 0x10000 in length
namespace Memory
{
@ -41,10 +34,10 @@ namespace Memory
return false;
}
bool Physical::SwapPages(void *Address, size_t PageCount)
bool Physical::SwapPages(void *Address, uint64_t PageCount)
{
for (size_t i = 0; i < PageCount; i++)
if (!this->SwapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE))))
for (uint64_t i = 0; i < PageCount; i++)
if (!this->SwapPage((void *)((uint64_t)Address + (i * PAGE_SIZE))))
return false;
return false;
}
@ -55,10 +48,10 @@ namespace Memory
return false;
}
bool Physical::UnswapPages(void *Address, size_t PageCount)
bool Physical::UnswapPages(void *Address, uint64_t PageCount)
{
for (size_t i = 0; i < PageCount; i++)
if (!this->UnswapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE))))
for (uint64_t i = 0; i < PageCount; i++)
if (!this->UnswapPage((void *)((uint64_t)Address + (i * PAGE_SIZE))))
return false;
return false;
}
@ -77,34 +70,15 @@ namespace Memory
if (this->SwapPage((void *)(PageBitmapIndex * PAGE_SIZE)))
{
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "RequestPage( )=%p~%p\n\r",
(void *)(PageBitmapIndex * PAGE_SIZE), __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
CPU::Stop();
__builtin_unreachable();
CPU::Halt(true);
return nullptr;
}
void *Physical::RequestPages(size_t Count)
void *Physical::RequestPages(uint64_t Count)
{
SmartLock(this->MemoryLock);
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
@ -117,31 +91,11 @@ namespace Memory
if (PageBitmap[Index] == true)
continue;
for (size_t i = 0; i < Count; i++)
for (uint64_t i = 0; i < Count; i++)
if (PageBitmap[Index + i] == true)
goto NextPage;
this->LockPages((void *)(Index * PAGE_SIZE), Count);
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "RequestPages( %ld )=%p~%p\n\r",
Count,
(void *)(Index * PAGE_SIZE), __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return (void *)(Index * PAGE_SIZE);
NextPage:
@ -153,32 +107,12 @@ namespace Memory
if (this->SwapPages((void *)(PageBitmapIndex * PAGE_SIZE), Count))
{
this->LockPages((void *)(PageBitmapIndex * PAGE_SIZE), Count);
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "RequestPages( %ld )=%p~%p\n\r",
Count,
(void *)(PageBitmapIndex * PAGE_SIZE), __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
CPU::Halt(true);
__builtin_unreachable();
return nullptr;
}
void Physical::FreePage(void *Address)
@ -189,7 +123,7 @@ namespace Memory
warn("Null pointer passed to FreePage.");
return;
}
size_t Index = (size_t)Address / PAGE_SIZE;
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == false))
return;
@ -200,58 +134,18 @@ namespace Memory
if (PageBitmapIndex > Index)
PageBitmapIndex = Index;
}
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "FreePage( %p )~%p\n\r",
Address,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
}
void Physical::FreePages(void *Address, size_t Count)
void Physical::FreePages(void *Address, uint64_t Count)
{
if (unlikely(Address == nullptr || Count == 0))
{
warn("%s%s%s passed to FreePages.", Address == nullptr ? "Null pointer " : "", Address == nullptr && Count == 0 ? "and " : "", Count == 0 ? "Zero count" : "");
warn("%s%s passed to FreePages.", Address == nullptr ? "Null pointer" : "", Count == 0 ? "Zero count" : "");
return;
}
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "!FreePages( %p %ld )~%p\n\r",
Address, Count,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
for (size_t t = 0; t < Count; t++)
this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
for (uint64_t t = 0; t < Count; t++)
this->FreePage((void *)((uint64_t)Address + (t * PAGE_SIZE)));
}
void Physical::LockPage(void *Address)
@ -259,7 +153,7 @@ namespace Memory
if (unlikely(Address == nullptr))
warn("Trying to lock null address.");
uintptr_t Index = (uintptr_t)Address / PAGE_SIZE;
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == true))
return;
if (PageBitmap.Set(Index, true))
@ -269,13 +163,13 @@ namespace Memory
}
}
void Physical::LockPages(void *Address, size_t PageCount)
void Physical::LockPages(void *Address, uint64_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to lock %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
for (size_t i = 0; i < PageCount; i++)
this->LockPage((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
for (uint64_t i = 0; i < PageCount; i++)
this->LockPage((void *)((uint64_t)Address + (i * PAGE_SIZE)));
}
void Physical::ReservePage(void *Address)
@ -283,7 +177,7 @@ namespace Memory
if (unlikely(Address == nullptr))
warn("Trying to reserve null address.");
uintptr_t Index = (uintptr_t)Address / PAGE_SIZE;
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == true))
return;
@ -294,13 +188,13 @@ namespace Memory
}
}
void Physical::ReservePages(void *Address, size_t PageCount)
void Physical::ReservePages(void *Address, uint64_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to reserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
for (size_t t = 0; t < PageCount; t++)
this->ReservePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
for (uint64_t t = 0; t < PageCount; t++)
this->ReservePage((void *)((uint64_t)Address + (t * PAGE_SIZE)));
}
void Physical::UnreservePage(void *Address)
@ -308,7 +202,7 @@ namespace Memory
if (unlikely(Address == nullptr))
warn("Trying to unreserve null address.");
uintptr_t Index = (uintptr_t)Address / PAGE_SIZE;
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == false))
return;
@ -321,13 +215,13 @@ namespace Memory
}
}
void Physical::UnreservePages(void *Address, size_t PageCount)
void Physical::UnreservePages(void *Address, uint64_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to unreserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
for (size_t t = 0; t < PageCount; t++)
this->UnreservePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
for (uint64_t t = 0; t < PageCount; t++)
this->UnreservePage((void *)((uint64_t)Address + (t * PAGE_SIZE)));
}
void Physical::Init(BootInfo *Info)
@ -359,24 +253,22 @@ namespace Memory
CPU::Stop();
}
size_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1;
uint64_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1;
trace("Initializing Bitmap at %llp-%llp (%lld Bytes)",
LargestFreeMemorySegment,
(void *)((uintptr_t)LargestFreeMemorySegment + BitmapSize),
(void *)((uint64_t)LargestFreeMemorySegment + BitmapSize),
BitmapSize);
PageBitmap.Size = BitmapSize;
PageBitmap.Buffer = (uint8_t *)LargestFreeMemorySegment;
for (size_t i = 0; i < BitmapSize; i++)
for (uint64_t i = 0; i < BitmapSize; i++)
*(uint8_t *)(PageBitmap.Buffer + i) = 0;
trace("Reserving pages...");
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
if (Info->Memory.Entry[i].Type != Usable)
this->ReservePages((void *)Info->Memory.Entry[i].BaseAddress, Info->Memory.Entry[i].Length / PAGE_SIZE + 1);
this->ReservePages(0, 0x100);
this->ReservePages(BootPageTable, TO_PAGES(0x10000));
trace("Locking bitmap pages...");
this->ReservePages(0, 0x100);
this->LockPages(PageBitmap.Buffer, PageBitmap.Size / PAGE_SIZE + 1);
}

View File

@ -4,7 +4,7 @@
namespace Memory
{
StackGuard::StackGuard(bool User, PageTable4 *Table)
StackGuard::StackGuard(bool User, PageTable *Table)
{
this->UserMode = User;
this->Table = Table;
@ -13,28 +13,22 @@ namespace Memory
void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE));
debug("AllocatedStack: %p", AllocatedStack);
memset(AllocatedStack, 0, USER_STACK_SIZE);
for (size_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
for (uint64_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
{
Virtual(Table).Map((void *)(USER_STACK_BASE + (i * PAGE_SIZE)),
(void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)),
Virtual(Table).Map((void *)((uint64_t)AllocatedStack + (i * PAGE_SIZE)),
(void *)(USER_STACK_BASE + (i * PAGE_SIZE)),
PTFlag::RW | PTFlag::US);
debug("Mapped %p to %p", (void *)(USER_STACK_BASE + (i * PAGE_SIZE)),
(void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)));
}
this->StackBottom = (void *)USER_STACK_BASE;
this->StackTop = (void *)(USER_STACK_BASE + USER_STACK_SIZE);
this->StackPhyiscalBottom = AllocatedStack;
this->StackPhyiscalTop = (void *)((uintptr_t)AllocatedStack + USER_STACK_SIZE);
this->Size = USER_STACK_SIZE;
}
else
{
this->StackBottom = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
this->StackPhyiscalBottom = this->StackBottom;
debug("StackBottom: %p", this->StackBottom);
memset(this->StackBottom, 0, STACK_SIZE);
this->StackTop = (void *)((uintptr_t)this->StackBottom + STACK_SIZE);
this->StackPhyiscalTop = this->StackTop;
this->StackTop = (void *)((uint64_t)this->StackBottom + STACK_SIZE);
this->Size = STACK_SIZE;
}
trace("Allocated stack at %p", this->StackBottom);
@ -47,12 +41,12 @@ namespace Memory
// debug("Freed stack at %p", this->StackBottom);
}
bool StackGuard::Expand(uintptr_t FaultAddress)
bool StackGuard::Expand(uint64_t FaultAddress)
{
if (this->UserMode)
{
if (FaultAddress < (uintptr_t)this->StackBottom - USER_STACK_SIZE ||
FaultAddress > (uintptr_t)this->StackTop)
if (FaultAddress < (uint64_t)this->StackBottom - USER_STACK_SIZE ||
FaultAddress > (uint64_t)this->StackTop)
{
return false; // It's not about the stack.
}
@ -61,12 +55,9 @@ namespace Memory
void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE));
debug("AllocatedStack: %p", AllocatedStack);
memset(AllocatedStack, 0, USER_STACK_SIZE);
for (uintptr_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
{
Virtual(this->Table).Map((void *)((uintptr_t)this->StackBottom - (i * PAGE_SIZE)), (void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)), PTFlag::RW | PTFlag::US);
debug("Mapped %p to %p", (void *)((uintptr_t)this->StackBottom - (i * PAGE_SIZE)), (void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)));
}
this->StackBottom = (void *)((uintptr_t)this->StackBottom - USER_STACK_SIZE);
for (uint64_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
Virtual(this->Table).Map((void *)((uint64_t)AllocatedStack + (i * PAGE_SIZE)), (void *)((uint64_t)this->StackBottom - (i * PAGE_SIZE)), PTFlag::RW | PTFlag::US);
this->StackBottom = (void *)((uint64_t)this->StackBottom - USER_STACK_SIZE);
this->Size += USER_STACK_SIZE;
info("Stack expanded to %p", this->StackBottom);
return true;

View File

@ -8,35 +8,37 @@ namespace Memory
bool Virtual::Check(void *VirtualAddress, PTFlag Flag)
{
// 0x1000 aligned
uintptr_t Address = (uintptr_t)VirtualAddress;
uint64_t Address = (uint64_t)VirtualAddress;
Address &= 0xFFFFFFFFFFFFF000;
PageMapIndexer Index = PageMapIndexer(Address);
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
PageMapIndexer Index = PageMapIndexer((uint64_t)Address);
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex];
PageTable *PDP = nullptr;
PageTable *PD = nullptr;
PageTable *PT = nullptr;
if (PDE.GetFlag(Flag))
PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
else
return false;
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
PageDirectoryEntryPtr *PDE = nullptr;
PageTableEntryPtr *PTE = nullptr;
PDE = PDP->Entries[Index.PDIndex];
if (PDE.GetFlag(Flag))
PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
else
return false;
if ((PML4.raw & Flag) > 0)
{
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
if (PDPTE)
if ((PDPTE->Entries[Index.PDPTEIndex].Present))
{
PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
if (PDE)
if ((PDE->Entries[Index.PDEIndex].Present))
{
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
if (PTE)
if ((PTE->Entries[Index.PTEIndex].Present))
{
PDE = PD->Entries[Index.PTIndex];
if (PDE.GetFlag(Flag))
PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
else
return false;
PDE = PT->Entries[Index.PIndex];
if (PDE.GetFlag(Flag))
return true;
}
}
}
}
else
return false;
return false;
}
@ -48,64 +50,60 @@ namespace Memory
error("No page table");
return;
}
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 = this->Table->Entries[Index.PMLIndex];
PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr;
if (!PML4.Present)
PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress);
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex];
PageTable *PDP = nullptr;
if (!PDE.GetFlag(PTFlag::P))
{
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)KernelAllocator.RequestPage();
memset(PDPTEPtr, 0, PAGE_SIZE);
PML4.Present = true;
PML4.SetAddress((uintptr_t)PDPTEPtr >> 12);
PDP = (PageTable *)KernelAllocator.RequestPage();
memset(PDP, 0, PAGE_SIZE);
PDE.SetFlag(PTFlag::P, true);
PDE.AddFlag(Flags);
PDE.SetAddress((uint64_t)PDP >> 12);
this->Table->Entries[Index.PDPIndex] = PDE;
}
else
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
PML4.raw |= DirectoryFlags;
this->Table->Entries[Index.PMLIndex] = PML4;
PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex];
PageDirectoryEntryPtr *PDEPtr = nullptr;
if (!PDPTE.Present)
PDE = PDP->Entries[Index.PDIndex];
PageTable *PD = nullptr;
if (!PDE.GetFlag(PTFlag::P))
{
PDEPtr = (PageDirectoryEntryPtr *)KernelAllocator.RequestPage();
memset(PDEPtr, 0, PAGE_SIZE);
PDPTE.Present = true;
PDPTE.SetAddress((uintptr_t)PDEPtr >> 12);
PD = (PageTable *)KernelAllocator.RequestPage();
memset(PD, 0, PAGE_SIZE);
PDE.SetFlag(PTFlag::P, true);
PDE.AddFlag(Flags);
PDE.SetAddress((uint64_t)PD >> 12);
PDP->Entries[Index.PDIndex] = PDE;
}
else
PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.GetAddress() << 12);
PDPTE.raw |= DirectoryFlags;
PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE;
PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex];
PageTableEntryPtr *PTEPtr = nullptr;
if (!PDE.Present)
PDE = PD->Entries[Index.PTIndex];
PageTable *PT = nullptr;
if (!PDE.GetFlag(PTFlag::P))
{
PTEPtr = (PageTableEntryPtr *)KernelAllocator.RequestPage();
memset(PTEPtr, 0, PAGE_SIZE);
PDE.Present = true;
PDE.SetAddress((uintptr_t)PTEPtr >> 12);
PT = (PageTable *)KernelAllocator.RequestPage();
memset(PT, 0, PAGE_SIZE);
PDE.SetFlag(PTFlag::P, true);
PDE.AddFlag(Flags);
PDE.SetAddress((uint64_t)PT >> 12);
PD->Entries[Index.PTIndex] = PDE;
}
else
PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12);
PDE.raw |= DirectoryFlags;
PDEPtr->Entries[Index.PDEIndex] = PDE;
PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
PTE.Present = true;
PTE.raw |= Flags;
PTE.SetAddress((uintptr_t)PhysicalAddress >> 12);
PTEPtr->Entries[Index.PTEIndex] = PTE;
PDE = PT->Entries[Index.PIndex];
PDE.SetFlag(PTFlag::P, true);
PDE.AddFlag(Flags);
PDE.SetAddress((uint64_t)PhysicalAddress >> 12);
PT->Entries[Index.PIndex] = PDE;
#if defined(a64)
#if defined(__amd64__)
CPU::x64::invlpg(VirtualAddress);
#elif defined(a32)
#elif defined(__i386__)
CPU::x32::invlpg(VirtualAddress);
#elif defined(aa64)
#elif defined(__aarch64__)
asmv("dsb sy");
asmv("tlbi vae1is, %0"
:
@ -129,14 +127,14 @@ namespace Memory
(byte & 0x01 ? '1' : '0')
if (!this->Check(VirtualAddress, (PTFlag)Flags)) // quick workaround just to see where it fails
warn("Failed to map %#lx - %#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags));
warn("Failed to map %#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, BYTE_TO_BINARY(Flags));
#endif
}
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, size_t PageCount, uint64_t Flags)
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t PageCount, uint64_t Flags)
{
for (size_t i = 0; i < PageCount; i++)
this->Map((void *)((uintptr_t)VirtualAddress + (i * PAGE_SIZE)), (void *)((uintptr_t)PhysicalAddress + (i * PAGE_SIZE)), Flags);
for (uint64_t i = 0; i < PageCount; i++)
this->Map((void *)((uint64_t)VirtualAddress + (i * PAGE_SIZE)), (void *)((uint64_t)PhysicalAddress + (i * PAGE_SIZE)), Flags);
}
void Virtual::Unmap(void *VirtualAddress)
@ -148,43 +146,38 @@ namespace Memory
return;
}
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
if (!PML4.Present)
PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress);
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex];
if (PDE.GetFlag(PTFlag::P))
{
error("Page not present");
return;
PageTable *PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PDP->Entries[Index.PDIndex];
if (PDE.GetFlag(PTFlag::P))
{
PageTable *PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PD->Entries[Index.PTIndex];
if (PDE.GetFlag(PTFlag::P))
{
PageTable *PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PT->Entries[Index.PIndex];
if (PDE.GetFlag(PTFlag::P))
{
PDE.ClearFlags();
// debug("Unmapped %#lx", VirtualAddress);
}
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.Address << 12);
PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex];
if (!PDPTE.Present)
{
error("Page not present");
return;
}
PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.Address << 12);
PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex];
if (!PDE.Present)
{
error("Page not present");
return;
}
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE.Address << 12);
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
if (!PTE.Present)
{
error("Page not present");
return;
}
PTE.Present = false;
PTEPtr->Entries[Index.PTEIndex] = PTE;
#if defined(a64)
#if defined(__amd64__)
CPU::x64::invlpg(VirtualAddress);
#elif defined(a32)
#elif defined(__i386__)
CPU::x32::invlpg(VirtualAddress);
#elif defined(aa64)
#elif defined(__aarch64__)
asmv("dsb sy");
asmv("tlbi vae1is, %0"
:
@ -195,10 +188,10 @@ namespace Memory
#endif
}
void Virtual::Unmap(void *VirtualAddress, size_t PageCount)
void Virtual::Unmap(void *VirtualAddress, uint64_t PageCount)
{
for (size_t i = 0; i < PageCount; i++)
this->Unmap((void *)((uintptr_t)VirtualAddress + (i * PAGE_SIZE)));
for (uint64_t i = 0; i < PageCount; i++)
this->Unmap((void *)((uint64_t)VirtualAddress + (i * PAGE_SIZE)));
}
void Virtual::Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
@ -207,12 +200,12 @@ namespace Memory
this->Map(VirtualAddress, PhysicalAddress, Flags);
}
Virtual::Virtual(PageTable4 *Table)
Virtual::Virtual(PageTable *Table)
{
if (Table)
this->Table = Table;
else
this->Table = (PageTable4 *)CPU::PageTable();
this->Table = (PageTable *)CPU::PageTable();
}
Virtual::~Virtual() {}

View File

@ -2,10 +2,10 @@
#include <memory.hpp>
#include <power.hpp>
#if defined(a64)
#if defined(__amd64__)
#include "../Architecture/amd64/acpi.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../kernel.h"
@ -14,34 +14,42 @@ namespace PCI
{
namespace Descriptors
{
char HexToStringOutput8[128];
const char *u8ToHexString(uint8_t Value)
{
static char Buffer[3];
memset(Buffer, 0, 3);
for (size_t i = 0; i < 2; i++)
uint8_t *ValuePtr = &Value;
uint8_t *Ptr;
uint8_t Temp;
uint8_t Size = 1 * 2 - 1;
for (uint8_t i = 0; i < Size; i++)
{
uint8_t Digit = (Value >> (4 - (i * 4))) & 0xF;
if (Digit < 10)
Buffer[i] = '0' + Digit;
else
Buffer[i] = 'A' + (Digit - 10);
Ptr = ((uint8_t *)ValuePtr + i);
Temp = ((*Ptr & 0xF0) >> 4);
HexToStringOutput8[Size - (i * 2 + 1)] = Temp + (Temp > 9 ? 55 : '0');
Temp = ((*Ptr & 0x0F));
HexToStringOutput8[Size - (i * 2)] = Temp + (Temp > 9 ? 55 : '0');
}
return Buffer;
HexToStringOutput8[Size + 1] = 0;
return HexToStringOutput8;
}
char HexToStringOutput32[128];
const char *u32ToHexString(uint32_t Value)
{
static char Buffer[9];
memset(Buffer, 0, 9);
for (size_t i = 0; i < 8; i++)
uint32_t *ValuePtr = &Value;
uint8_t *Ptr;
uint8_t Temp;
uint8_t Size = 4 * 2 - 1;
for (uint8_t i = 0; i < Size; i++)
{
uint8_t Digit = (Value >> (28 - (i * 4))) & 0xF;
if (Digit < 10)
Buffer[i] = '0' + Digit;
else
Buffer[i] = 'A' + (Digit - 10);
Ptr = ((uint8_t *)ValuePtr + i);
Temp = ((*Ptr & 0xF0) >> 4);
HexToStringOutput32[Size - (i * 2 + 1)] = Temp + (Temp > 9 ? 55 : '0');
Temp = ((*Ptr & 0x0F));
HexToStringOutput32[Size - (i * 2)] = Temp + (Temp > 9 ? 55 : '0');
}
return Buffer;
HexToStringOutput32[Size + 1] = 0;
return HexToStringOutput32;
}
const char *MassStorageControllerSubclassName(uint8_t SubclassCode)
@ -386,13 +394,13 @@ namespace PCI
case 0x000B:
return "QEMU PCIe Expander bridge";
case 0x000C:
return "QEMU PCIe Root Port";
return "QEMU PCIe Root port";
case 0x000D:
return "QEMU XHCI Host Controller";
case 0x0010:
return "QEMU NVM Express Controller";
case 0x0100:
return "QXL Paravirtual Graphic Card";
return "QXL paravirtual graphic card";
case 0x1AF41100:
return "QEMU Virtual Machine";
default:
@ -755,8 +763,7 @@ namespace PCI
#ifdef DEBUG
void e(PCIDeviceHeader *hdr)
{
debug("%#x:%#x\t\t%s / %s / %s / %s / %s",
hdr->VendorID, hdr->DeviceID,
debug("%s / %s / %s / %s / %s",
Descriptors::GetVendorName(hdr->VendorID),
Descriptors::GetDeviceName(hdr->VendorID, hdr->DeviceID),
Descriptors::DeviceClasses[hdr->Class],
@ -765,10 +772,10 @@ namespace PCI
}
#endif
void PCI::EnumerateFunction(uintptr_t DeviceAddress, uint64_t Function)
void PCI::EnumerateFunction(uint64_t DeviceAddress, uint64_t Function)
{
uintptr_t Offset = Function << 12;
uintptr_t FunctionAddress = DeviceAddress + Offset;
uint64_t Offset = Function << 12;
uint64_t FunctionAddress = DeviceAddress + Offset;
Memory::Virtual().Map((void *)FunctionAddress, (void *)FunctionAddress, Memory::PTFlag::RW);
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)FunctionAddress;
if (PCIDeviceHdr->DeviceID == 0)
@ -781,24 +788,24 @@ namespace PCI
#endif
}
void PCI::EnumerateDevice(uintptr_t BusAddress, uint64_t Device)
void PCI::EnumerateDevice(uint64_t BusAddress, uint64_t Device)
{
uintptr_t Offset = Device << 15;
uintptr_t DeviceAddress = BusAddress + Offset;
uint64_t Offset = Device << 15;
uint64_t DeviceAddress = BusAddress + Offset;
Memory::Virtual().Map((void *)DeviceAddress, (void *)DeviceAddress, Memory::PTFlag::RW);
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)DeviceAddress;
if (PCIDeviceHdr->DeviceID == 0)
return;
if (PCIDeviceHdr->DeviceID == 0xFFFF)
return;
for (uintptr_t Function = 0; Function < 8; Function++)
for (uint64_t Function = 0; Function < 8; Function++)
EnumerateFunction(DeviceAddress, Function);
}
void PCI::EnumerateBus(uintptr_t BaseAddress, uint64_t Bus)
void PCI::EnumerateBus(uint64_t BaseAddress, uint64_t Bus)
{
uintptr_t Offset = Bus << 20;
uintptr_t BusAddress = BaseAddress + Offset;
uint64_t Offset = Bus << 20;
uint64_t BusAddress = BaseAddress + Offset;
Memory::Virtual().Map((void *)BusAddress, (void *)BusAddress, Memory::PTFlag::RW);
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)BusAddress;
if (Bus != 0) // TODO: VirtualBox workaround (UNTESTED ON REAL HARDWARE!)
@ -808,12 +815,12 @@ namespace PCI
if (PCIDeviceHdr->DeviceID == 0xFFFF)
return;
}
debug("PCI Bus DeviceID:%#llx VendorID:%#llx BIST:%#llx Cache:%#llx Class:%#llx Cmd:%#llx HdrType:%#llx LatencyTimer:%#llx ProgIF:%#llx RevID:%#llx Status:%#llx SubClass:%#llx ",
trace("PCI Bus DeviceID:%#llx VendorID:%#llx BIST:%#llx Cache:%#llx Class:%#llx Cmd:%#llx HdrType:%#llx LatencyTimer:%#llx ProgIF:%#llx RevID:%#llx Status:%#llx SubClass:%#llx ",
PCIDeviceHdr->DeviceID, PCIDeviceHdr->VendorID, PCIDeviceHdr->BIST,
PCIDeviceHdr->CacheLineSize, PCIDeviceHdr->Class, PCIDeviceHdr->Command,
PCIDeviceHdr->HeaderType, PCIDeviceHdr->LatencyTimer, PCIDeviceHdr->ProgIF,
PCIDeviceHdr->RevisionID, PCIDeviceHdr->Status, PCIDeviceHdr->Subclass);
for (uintptr_t Device = 0; Device < 32; Device++)
for (uint64_t Device = 0; Device < 32; Device++)
EnumerateDevice(BusAddress, Device);
}
@ -837,20 +844,20 @@ namespace PCI
PCI::PCI()
{
#if defined(a64)
#if defined(__amd64__)
int Entries = ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig);
for (int t = 0; t < Entries; t++)
{
DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uintptr_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uint64_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
Memory::Virtual().Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW);
debug("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress,
trace("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress,
NewDeviceConfig->StartBus, NewDeviceConfig->EndBus);
for (uintptr_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++)
for (uint64_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++)
EnumerateBus(NewDeviceConfig->BaseAddress, Bus);
}
#elif defined(a32)
#elif defined(__i386__)
error("PCI not implemented on i386");
#elif defined(aa64)
#elif defined(__aarch64__)
error("PCI not implemented on aarch64");
#endif
}

View File

@ -5,7 +5,7 @@
#include "../kernel.h"
#if defined(a64)
#if defined(__amd64__)
#include <io.h>
#include "../Architecture/amd64/acpi.hpp"
@ -71,11 +71,10 @@ namespace Power
Power::~Power()
{
debug("Destructor called");
}
}
#elif defined(a32)
#elif defined(__i386__)
namespace Power
{
@ -99,7 +98,7 @@ namespace Power
}
}
#elif defined(aa64)
#elif defined(__aarch64__)
namespace Power
{

View File

@ -1,5 +1,4 @@
#include <rand.hpp>
#include <cpu.hpp>
namespace Random
{
@ -7,150 +6,22 @@ namespace Random
uint16_t rand16()
{
int RDRANDFlag = 0;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
#if defined(a64)
CPU::x64::AMD::CPUID0x1 cpuid1amd;
#elif defined(a32)
CPU::x32::AMD::CPUID0x1 cpuid1amd;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
: "a"(0x1));
#endif
RDRANDFlag = cpuid1amd.ECX.RDRAND;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
#if defined(a64)
CPU::x64::Intel::CPUID0x1 cpuid1intel;
#elif defined(a32)
CPU::x32::Intel::CPUID0x1 cpuid1intel;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
: "a"(0x1));
#endif
RDRANDFlag = cpuid1intel.ECX.RDRAND;
}
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
RDRANDFlag = 0;
#if defined(a64) || defined(a32)
if (RDRANDFlag)
{
uint16_t RDRANDValue = 0;
asmv("1: rdrand %0; jnc 1b"
: "=r"(RDRANDValue));
return RDRANDValue;
}
#endif
Seed = Seed * 1103515245 + 12345;
return (uint16_t)(Seed / 65536) % __UINT16_MAX__;
}
uint32_t rand32()
{
int RDRANDFlag = 0;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
#if defined(a64)
CPU::x64::AMD::CPUID0x1 cpuid1amd;
#elif defined(a32)
CPU::x32::AMD::CPUID0x1 cpuid1amd;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
: "a"(0x1));
#endif
RDRANDFlag = cpuid1amd.ECX.RDRAND;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
#if defined(a64)
CPU::x64::Intel::CPUID0x1 cpuid1intel;
#elif defined(a32)
CPU::x32::Intel::CPUID0x1 cpuid1intel;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
: "a"(0x1));
#endif
RDRANDFlag = cpuid1intel.ECX.RDRAND;
}
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
RDRANDFlag = 0;
#if defined(a64) || defined(a32)
if (RDRANDFlag)
{
uint32_t RDRANDValue = 0;
asmv("1: rdrand %0; jnc 1b"
: "=r"(RDRANDValue));
return RDRANDValue;
}
#endif
Seed = Seed * 1103515245 + 12345;
return (uint32_t)(Seed / 65536) % __UINT16_MAX__;
return (uint32_t)(Seed / 65536) % __UINT32_MAX__;
}
uint64_t rand64()
{
int RDRANDFlag = 0;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
#if defined(a64)
CPU::x64::AMD::CPUID0x1 cpuid1amd;
#elif defined(a32)
CPU::x32::AMD::CPUID0x1 cpuid1amd;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
: "a"(0x1));
#endif
RDRANDFlag = cpuid1amd.ECX.RDRAND;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
#if defined(a64)
CPU::x64::Intel::CPUID0x1 cpuid1intel;
#elif defined(a32)
CPU::x32::Intel::CPUID0x1 cpuid1intel;
#endif
#if defined(a64) || defined(a32)
asmv("cpuid"
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
: "a"(0x1));
#endif
RDRANDFlag = cpuid1intel.ECX.RDRAND;
}
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
RDRANDFlag = 0;
#if defined(a64) || defined(a32)
if (RDRANDFlag)
{
uint64_t RDRANDValue = 0;
asmv("1: rdrand %0; jnc 1b"
: "=r"(RDRANDValue));
return RDRANDValue;
}
#endif
Seed = Seed * 1103515245 + 12345;
return (uint64_t)(Seed / 65536) % __UINT16_MAX__;
return (uint64_t)(Seed / 65536) % __UINT64_MAX__;
}
void ChangeSeed(uint64_t CustomSeed) { Seed = CustomSeed; }
void changeseed(uint64_t CustomSeed) { Seed = CustomSeed; }
}

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

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

View File

@ -1,79 +0,0 @@
#include <types.h>
#include <debug.h>
#include <rand.hpp>
#include "../kernel.h"
/* EXTERNC */ __attribute__((weak)) uintptr_t __stack_chk_guard = 0;
EXTERNC __attribute__((weak, no_stack_protector)) uintptr_t __stack_chk_guard_init(void)
{
int MaxRetries = 0;
#if UINTPTR_MAX == UINT32_MAX
uint32_t num;
Retry:
num = Random::rand32();
if (num < 0x1000 && MaxRetries++ < 10)
goto Retry;
return num;
#else
uint64_t num;
Retry:
num = Random::rand64();
if (num < 0x100000 && MaxRetries++ < 10)
goto Retry;
return num;
#endif
}
EXTERNC __attribute__((constructor, no_stack_protector)) void __guard_setup(void)
{
debug("StackGuard: __guard_setup");
if (__stack_chk_guard == 0)
__stack_chk_guard = __stack_chk_guard_init();
debug("Stack guard value: %ld", __stack_chk_guard);
}
EXTERNC __attribute__((weak, noreturn, no_stack_protector)) void __stack_chk_fail(void)
{
TaskingPanic();
for (short i = 0; i < 10; i++)
error("Stack smashing detected!");
debug("Current stack check guard value: %#lx", __stack_chk_guard);
KPrint("\eFF0000Stack smashing detected!");
#if defined(a64) || defined(a32)
void *Stack = nullptr;
#if defined(a64)
asmv("movq %%rsp, %0"
: "=r"(Stack));
#elif defined(a32)
asmv("movl %%esp, %0"
: "=r"(Stack));
#endif
error("Stack address: %#lx", Stack);
while (1)
asmv("cli; hlt");
#elif defined(aa64)
asmv("wfe");
#endif
CPU::Stop();
}
// https://github.com/gcc-mirror/gcc/blob/master/libssp/ssp.c
EXTERNC __attribute__((weak, noreturn, no_stack_protector)) void __chk_fail(void)
{
TaskingPanic();
for (short i = 0; i < 10; i++)
error("Buffer overflow detected!");
KPrint("\eFF0000Buffer overflow detected!");
#if defined(a64) || defined(a32)
while (1)
asmv("cli; hlt");
#elif defined(aa64)
asmv("wfe");
#endif
}

View File

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

View File

@ -38,16 +38,16 @@ namespace SMBIOS
SMBIOSEntryPoint *Header = (SMBIOSEntryPoint *)bInfo->SMBIOSPtr;
debug("Getting SMBIOS header for type %d", Type);
struct SMBIOSHeader *hdr = (SMBIOSHeader *)(uintptr_t)Header->TableAddress;
struct SMBIOSHeader *hdr = (SMBIOSHeader *)(uint64_t)Header->TableAddress;
for (int i = 0; i <= 11; i++)
{
if (hdr < (void *)(uintptr_t)(Header->TableAddress + Header->TableLength))
if (hdr < (void *)(uint64_t)(Header->TableAddress + Header->TableLength))
if (hdr->Type == Type)
{
debug("Found SMBIOS header for type %d at %#lx", Type, hdr);
return hdr;
}
hdr = (struct SMBIOSHeader *)((uintptr_t)hdr + SMBIOSTableLength(hdr));
hdr = (struct SMBIOSHeader *)((uint64_t)hdr + SMBIOSTableLength(hdr));
}
return nullptr;
}

View File

@ -1,5 +1,4 @@
#include <time.hpp>
#include <debug.h>
#include <io.h>
namespace Time
@ -7,7 +6,7 @@ namespace Time
Clock ReadClock()
{
Clock tm;
#if defined(a64) || defined(a32)
#if defined(__amd64__) || defined(__i386__)
uint32_t t = 0;
outb(0x70, 0x00);
t = inb(0x71);
@ -28,7 +27,7 @@ namespace Time
t = inb(0x71);
tm.Year = ((t & 0x0F) + ((t >> 4) * 10));
tm.Counter = 0;
#elif defined(aa64)
#elif defined(__aarch64__)
tm.Year = 0;
tm.Month = 0;
tm.Day = 0;
@ -39,50 +38,4 @@ namespace Time
#endif
return tm;
}
Clock ConvertFromUnix(int Timestamp)
{
Clock result;
uint64_t Seconds = Timestamp;
uint64_t Minutes = Seconds / 60;
uint64_t Hours = Minutes / 60;
uint64_t Days = Hours / 24;
result.Year = 1970;
while (Days >= 365)
{
if (result.Year % 4 == 0 && (result.Year % 100 != 0 || result.Year % 400 == 0))
{
if (Days >= 366)
{
Days -= 366;
result.Year++;
}
else
break;
}
else
{
Days -= 365;
result.Year++;
}
}
int DaysInMonth[] = {31, result.Year % 4 == 0 ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
for (result.Month = 0; result.Month < 12; result.Month++)
{
if (Days < static_cast<uint64_t>(DaysInMonth[result.Month]))
break;
Days -= DaysInMonth[result.Month];
}
result.Month++;
result.Day = static_cast<int>(Days) + 1;
result.Hour = static_cast<int>(Hours % 24);
result.Minute = static_cast<int>(Minutes % 60);
result.Second = static_cast<int>(Seconds % 60);
result.Counter = static_cast<uint64_t>(Timestamp);
return result;
}
}

View File

@ -4,48 +4,21 @@
#include <debug.h>
#include <io.h>
#if defined(a64)
#if defined(__amd64__)
#include "../Architecture/amd64/acpi.hpp"
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
#include "../kernel.h"
namespace Time
{
void time::Sleep(uint64_t Milliseconds)
{
#if defined(a64) || defined(a32)
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000000) / clk;
#ifdef DEBUG
uint64_t Counter = mminq(&((HPET *)hpet)->MainCounterValue);
while (Counter < Target)
{
Counter = mminq(&((HPET *)hpet)->MainCounterValue);
CPU::Pause();
}
#else
#if defined(__amd64__) || defined(__i386__)
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000) / clk;
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
CPU::Pause();
#endif
#elif defined(aa64)
#endif
}
uint64_t time::GetCounter()
{
#if defined(a64) || defined(a32)
return mminq(&((HPET *)hpet)->MainCounterValue);
#elif defined(aa64)
#endif
}
uint64_t time::CalculateTarget(uint64_t Milliseconds)
{
#if defined(a64) || defined(a32)
return mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000000) / clk;
#elif defined(aa64)
#elif defined(__aarch64__)
#endif
}
@ -53,7 +26,7 @@ namespace Time
{
if (_acpi)
{
#if defined(a64)
#if defined(__amd64__)
this->acpi = _acpi;
ACPI::ACPI *acpi = (ACPI::ACPI *)this->acpi;
if (acpi->HPET)
@ -71,19 +44,15 @@ namespace Time
}
else
{
// For now, we need HPET.
error("HPET not found");
KPrint("\eFF2200HPET not found");
CPU::Stop();
trace("HPET not found");
}
#elif defined(a32)
#elif defined(aa64)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
}
}
time::~time()
{
debug("Destructor called");
}
}

View File

@ -30,313 +30,63 @@ __ubsan_handle_pointer_overflow_abort
__ubsan_handle_cfi_check_fail
*/
extern void __asan_report_load1(void *unknown)
{
ubsan("load1");
UNUSED(unknown);
}
extern void __asan_report_load1(void *unknown) { ubsan("load1"); }
extern void __asan_report_load2(void *unknown) { ubsan("load2"); }
extern void __asan_report_load4(void *unknown) { ubsan("load4"); }
extern void __asan_report_load8(void *unknown) { ubsan("load8"); }
extern void __asan_report_load16(void *unknown) { ubsan("load16"); }
extern void __asan_report_load_n(void *unknown, uintptr_t size) { ubsan("loadn"); }
extern void __asan_report_load2(void *unknown)
{
ubsan("load2");
UNUSED(unknown);
}
extern void __asan_report_store1(void *unknown) { ubsan("store1"); }
extern void __asan_report_store2(void *unknown) { ubsan("store2"); }
extern void __asan_report_store4(void *unknown) { ubsan("store4"); }
extern void __asan_report_store8(void *unknown) { ubsan("store8"); }
extern void __asan_report_store16(void *unknown) { ubsan("store16"); }
extern void __asan_report_store_n(void *unknown, uintptr_t size) { ubsan("storen"); }
extern void __asan_report_load4(void *unknown)
{
ubsan("load4");
UNUSED(unknown);
}
extern void __asan_report_load1_noabort(void *unknown) { ubsan("load1"); }
extern void __asan_report_load2_noabort(void *unknown) { ubsan("load2"); }
extern void __asan_report_load4_noabort(void *unknown) { ubsan("load4"); }
extern void __asan_report_load8_noabort(void *unknown) { ubsan("load8"); }
extern void __asan_report_load16_noabort(void *unknown) { ubsan("load16"); }
extern void __asan_report_load_n_noabort(void *unknown, uintptr_t size) { ubsan("loadn"); }
extern void __asan_report_load8(void *unknown)
{
ubsan("load8");
UNUSED(unknown);
}
extern void __asan_report_store1_noabort(void *unknown) { ubsan("store1"); }
extern void __asan_report_store2_noabort(void *unknown) { ubsan("store2"); }
extern void __asan_report_store4_noabort(void *unknown) { ubsan("store4"); }
extern void __asan_report_store8_noabort(void *unknown) { ubsan("store8"); }
extern void __asan_report_store16_noabort(void *unknown) { ubsan("store16"); }
extern void __asan_report_store_n_noabort(void *unknown, uintptr_t size) { ubsan("storen"); }
extern void __asan_report_load16(void *unknown)
{
ubsan("load16");
UNUSED(unknown);
}
extern void __asan_stack_malloc_0(uintptr_t size) { ubsan("stack malloc 0"); }
extern void __asan_stack_malloc_1(uintptr_t size) { ubsan("stack malloc 1"); }
extern void __asan_stack_malloc_2(uintptr_t size) { ubsan("stack malloc 2"); }
extern void __asan_stack_malloc_3(uintptr_t size) { ubsan("stack malloc 3"); }
extern void __asan_stack_malloc_4(uintptr_t size) { ubsan("stack malloc 4"); }
extern void __asan_stack_malloc_5(uintptr_t size) { ubsan("stack malloc 5"); }
extern void __asan_stack_malloc_6(uintptr_t size) { ubsan("stack malloc 6"); }
extern void __asan_stack_malloc_7(uintptr_t size) { ubsan("stack malloc 7"); }
extern void __asan_stack_malloc_8(uintptr_t size) { ubsan("stack malloc 8"); }
extern void __asan_stack_malloc_9(uintptr_t size) { ubsan("stack malloc 9"); }
extern void __asan_report_load_n(void *unknown, uintptr_t size)
{
ubsan("loadn");
UNUSED(unknown);
UNUSED(size);
}
extern void __asan_stack_free_0(void *ptr, uintptr_t size) { ubsan("stack free 0"); }
extern void __asan_stack_free_1(void *ptr, uintptr_t size) { ubsan("stack free 1"); }
extern void __asan_stack_free_2(void *ptr, uintptr_t size) { ubsan("stack free 2"); }
extern void __asan_stack_free_3(void *ptr, uintptr_t size) { ubsan("stack free 3"); }
extern void __asan_stack_free_4(void *ptr, uintptr_t size) { ubsan("stack free 4"); }
extern void __asan_stack_free_5(void *ptr, uintptr_t size) { ubsan("stack free 5"); }
extern void __asan_stack_free_6(void *ptr, uintptr_t size) { ubsan("stack free 6"); }
extern void __asan_stack_free_7(void *ptr, uintptr_t size) { ubsan("stack free 7"); }
extern void __asan_stack_free_8(void *ptr, uintptr_t size) { ubsan("stack free 8"); }
extern void __asan_stack_free_9(void *ptr, uintptr_t size) { ubsan("stack free 9"); }
extern void __asan_report_store1(void *unknown)
{
ubsan("store1");
UNUSED(unknown);
}
extern void __asan_report_store2(void *unknown)
{
ubsan("store2");
UNUSED(unknown);
}
extern void __asan_report_store4(void *unknown)
{
ubsan("store4");
UNUSED(unknown);
}
extern void __asan_report_store8(void *unknown)
{
ubsan("store8");
UNUSED(unknown);
}
extern void __asan_report_store16(void *unknown)
{
ubsan("store16");
UNUSED(unknown);
}
extern void __asan_report_store_n(void *unknown, uintptr_t size)
{
ubsan("storen");
UNUSED(unknown);
UNUSED(size);
}
extern void __asan_report_load1_noabort(void *unknown)
{
ubsan("load1");
UNUSED(unknown);
}
extern void __asan_report_load2_noabort(void *unknown)
{
ubsan("load2");
UNUSED(unknown);
}
extern void __asan_report_load4_noabort(void *unknown)
{
ubsan("load4");
UNUSED(unknown);
}
extern void __asan_report_load8_noabort(void *unknown)
{
ubsan("load8");
UNUSED(unknown);
}
extern void __asan_report_load16_noabort(void *unknown)
{
ubsan("load16");
UNUSED(unknown);
}
extern void __asan_report_load_n_noabort(void *unknown, uintptr_t size)
{
ubsan("loadn");
UNUSED(unknown);
UNUSED(size);
}
extern void __asan_report_store1_noabort(void *unknown)
{
ubsan("store1");
UNUSED(unknown);
}
extern void __asan_report_store2_noabort(void *unknown)
{
ubsan("store2");
UNUSED(unknown);
}
extern void __asan_report_store4_noabort(void *unknown)
{
ubsan("store4");
UNUSED(unknown);
}
extern void __asan_report_store8_noabort(void *unknown)
{
ubsan("store8");
UNUSED(unknown);
}
extern void __asan_report_store16_noabort(void *unknown)
{
ubsan("store16");
UNUSED(unknown);
}
extern void __asan_report_store_n_noabort(void *unknown, uintptr_t size)
{
ubsan("storen");
UNUSED(unknown);
UNUSED(size);
}
extern void __asan_stack_malloc_0(uintptr_t size)
{
ubsan("stack malloc 0");
UNUSED(size);
}
extern void __asan_stack_malloc_1(uintptr_t size)
{
ubsan("stack malloc 1");
UNUSED(size);
}
extern void __asan_stack_malloc_2(uintptr_t size)
{
ubsan("stack malloc 2");
UNUSED(size);
}
extern void __asan_stack_malloc_3(uintptr_t size)
{
ubsan("stack malloc 3");
UNUSED(size);
}
extern void __asan_stack_malloc_4(uintptr_t size)
{
ubsan("stack malloc 4");
UNUSED(size);
}
extern void __asan_stack_malloc_5(uintptr_t size)
{
ubsan("stack malloc 5");
UNUSED(size);
}
extern void __asan_stack_malloc_6(uintptr_t size)
{
ubsan("stack malloc 6");
UNUSED(size);
}
extern void __asan_stack_malloc_7(uintptr_t size)
{
ubsan("stack malloc 7");
UNUSED(size);
}
extern void __asan_stack_malloc_8(uintptr_t size)
{
ubsan("stack malloc 8");
UNUSED(size);
}
extern void __asan_stack_malloc_9(uintptr_t size)
{
ubsan("stack malloc 9");
UNUSED(size);
}
extern void __asan_stack_free_0(void *ptr, uintptr_t size)
{
ubsan("stack free 0");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_1(void *ptr, uintptr_t size)
{
ubsan("stack free 1");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_2(void *ptr, uintptr_t size)
{
ubsan("stack free 2");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_3(void *ptr, uintptr_t size)
{
ubsan("stack free 3");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_4(void *ptr, uintptr_t size)
{
ubsan("stack free 4");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_5(void *ptr, uintptr_t size)
{
ubsan("stack free 5");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_6(void *ptr, uintptr_t size)
{
ubsan("stack free 6");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_7(void *ptr, uintptr_t size)
{
ubsan("stack free 7");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_8(void *ptr, uintptr_t size)
{
ubsan("stack free 8");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_9(void *ptr, uintptr_t size)
{
ubsan("stack free 9");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_poison_stack_memory(void *addr, uintptr_t size)
{
ubsan("poison stack memory");
UNUSED(addr);
UNUSED(size);
}
extern void __asan_unpoison_stack_memory(void *addr, uintptr_t size)
{
ubsan("unpoison stack memory");
UNUSED(addr);
UNUSED(size);
}
extern void __asan_before_dynamic_init(const char *module_name)
{
ubsan("before dynamic init");
UNUSED(module_name);
}
extern void __asan_poison_stack_memory(void *addr, uintptr_t size) { ubsan("poison stack memory"); }
extern void __asan_unpoison_stack_memory(void *addr, uintptr_t size) { ubsan("unpoison stack memory"); }
extern void __asan_before_dynamic_init(const char *module_name) { ubsan("before dynamic init"); }
extern void __asan_after_dynamic_init(void) { ubsan("after dynamic init"); }
extern void __asan_register_globals(void *unknown, size_t size)
{
ubsan("register_globals");
UNUSED(unknown);
UNUSED(size);
}
extern void __asan_register_globals(void *unknown, size_t size) { ubsan("register_globals"); }
extern void __asan_unregister_globals(void) { ubsan("unregister_globals"); }
extern void __asan_init(void) { ubsan("init"); }
@ -370,11 +120,11 @@ bool UBSANMsg(const char *file, uint32_t line, uint32_t column)
// blacklist
// if (strstr(file, "liballoc") ||
// strstr(file, "cwalk") ||
// strstr(file, "AdvancedConfigurationAndPowerInterface") ||
// strstr(file, "AdvancedConfigurationandPowerInterface") ||
// strstr(file, "SystemManagementBIOS"))
// return false;
if (strstr(file, "AdvancedConfigurationAndPowerInterface.cpp") &&
if (strstr(file, "AdvancedConfigurationandPowerInterface.cpp") &&
(line == 17 && column == 47))
return false;
@ -399,9 +149,6 @@ bool UBSANMsg(const char *file, uint32_t line, uint32_t column)
(line == 48 && column == 28))
return false;
if (strstr(file, "Task.cpp") && line > 500)
return false;
ubsan("\t\tIn File: %s:%i:%i", file, line, column);
return true;
}
@ -533,5 +280,4 @@ void __ubsan_handle_dynamic_type_cache_miss(struct dynamic_type_cache_miss_data
{
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
ubsan("Dynamic type cache miss.");
UNUSED(ptr);
}

View File

@ -6,8 +6,8 @@
volatile bool serialports[8] = {false, false, false, false, false, false, false, false};
Vector<UniversalAsynchronousReceiverTransmitter::Events *> RegisteredEvents;
#if defined(a64) || defined(a32)
NIF __always_inline inline uint8_t NoProfiler_inportb(uint16_t Port)
#if defined(__amd64__) || defined(__i386__)
__no_instrument_function uint8_t NoProfiler_inportb(uint16_t Port)
{
uint8_t Result;
asm("in %%dx, %%al"
@ -16,7 +16,7 @@ NIF __always_inline inline uint8_t NoProfiler_inportb(uint16_t Port)
return Result;
}
NIF __always_inline inline void NoProfiler_outportb(uint16_t Port, uint8_t Data)
__no_instrument_function void NoProfiler_outportb(uint16_t Port, uint8_t Data)
{
asmv("out %%al, %%dx"
:
@ -27,19 +27,13 @@ NIF __always_inline inline void NoProfiler_outportb(uint16_t Port, uint8_t Data)
namespace UniversalAsynchronousReceiverTransmitter
{
#define SERIAL_ENABLE_DLAB 0x80
#define SERIAL_RATE_115200_LO 0x01
#define SERIAL_RATE_115200_HI 0x00
#define SERIAL_RATE_57600_LO 0x02
#define SERIAL_RATE_57600_HI 0x00
#define SERIAL_RATE_38400_LO 0x03
#define SERIAL_RATE_38400_HI 0x00
#define SERIAL_BUFFER_EMPTY 0x20
/* TODO: Serial Port implementation needs reword. https://wiki.osdev.org/Serial_Ports */
SafeFunction NIF UART::UART(SerialPorts Port)
SafeFunction __no_instrument_function UART::UART(SerialPorts Port)
{
#if defined(a64) || defined(a32)
#if defined(__amd64__) || defined(__i386__)
if (Port == COMNULL)
return;
@ -82,8 +76,8 @@ namespace UniversalAsynchronousReceiverTransmitter
// Initialize the serial port
NoProfiler_outportb(Port + 1, 0x00); // Disable all interrupts
NoProfiler_outportb(Port + 3, SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor)
NoProfiler_outportb(Port + 0, SERIAL_RATE_115200_LO); // Set divisor to 1 (lo byte) 115200 baud
NoProfiler_outportb(Port + 1, SERIAL_RATE_115200_HI); // (hi byte)
NoProfiler_outportb(Port + 0, SERIAL_RATE_38400_LO); // Set divisor to 3 (lo byte) 38400 baud
NoProfiler_outportb(Port + 1, SERIAL_RATE_38400_HI); // (hi byte)
NoProfiler_outportb(Port + 3, 0x03); // 8 bits, no parity, one stop bit
NoProfiler_outportb(Port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
NoProfiler_outportb(Port + 4, 0x0B); // IRQs enabled, RTS/DSR set
@ -104,11 +98,11 @@ namespace UniversalAsynchronousReceiverTransmitter
#endif
}
SafeFunction NIF UART::~UART() {}
SafeFunction __no_instrument_function UART::~UART() {}
SafeFunction NIF void UART::Write(uint8_t Char)
SafeFunction __no_instrument_function void UART::Write(uint8_t Char)
{
#if defined(a64) || defined(a32)
#if defined(__amd64__) || defined(__i386__)
while ((NoProfiler_inportb(Port + 5) & SERIAL_BUFFER_EMPTY) == 0)
;
NoProfiler_outportb(Port, Char);
@ -118,9 +112,9 @@ namespace UniversalAsynchronousReceiverTransmitter
e->OnSent(Char);
}
SafeFunction NIF uint8_t UART::Read()
SafeFunction __no_instrument_function uint8_t UART::Read()
{
#if defined(a64) || defined(a32)
#if defined(__amd64__) || defined(__i386__)
while ((NoProfiler_inportb(Port + 5) & 1) == 0)
;
return NoProfiler_inportb(Port);
@ -129,22 +123,22 @@ namespace UniversalAsynchronousReceiverTransmitter
{
if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL)
{
#if defined(a64) || defined(a32)
#if defined(__amd64__) || defined(__i386__)
e->OnReceived(NoProfiler_inportb(Port));
#endif
}
}
}
SafeFunction NIF Events::Events(SerialPorts Port)
SafeFunction __no_instrument_function Events::Events(SerialPorts Port)
{
this->Port = Port;
RegisteredEvents.push_back(this);
}
SafeFunction NIF Events::~Events()
SafeFunction __no_instrument_function Events::~Events()
{
for (uintptr_t i = 0; i < RegisteredEvents.size(); i++)
for (uint64_t i = 0; i < RegisteredEvents.size(); i++)
if (RegisteredEvents[i] == this)
{
RegisteredEvents.remove(i);

View File

@ -3,177 +3,14 @@
#include <uart.hpp>
#include <debug.h>
extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start;
extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end;
extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_size;
extern uint64_t _binary_Files_ter_powerline_v12n_psf_start;
extern uint64_t _binary_Files_ter_powerline_v12n_psf_end;
extern uint64_t _binary_Files_ter_powerline_v12n_psf_size;
NewLock(PrintLock);
namespace Video
{
Font *Display::GetCurrentFont()
{
return CurrentFont;
}
void Display::SetCurrentFont(Font *Font)
{
CurrentFont = Font;
}
void Display::CreateBuffer(uint32_t Width, uint32_t Height, int Index)
{
if (Width == 0 && Height == 0)
{
Width = this->framebuffer.Width;
Height = this->framebuffer.Height;
debug("No width and height specified, using %ldx%lld", Width, Height);
}
size_t Size = this->framebuffer.Pitch * Height;
if (this->Buffers[Index])
{
if (this->Buffers[Index]->Checksum == 0xDEAD)
{
warn("Buffer %d already exists, skipping creation", Index);
return;
}
}
ScreenBuffer *buffer = new ScreenBuffer;
buffer->Buffer = KernelAllocator.RequestPages(TO_PAGES(Size));
buffer->Width = Width;
buffer->Height = Height;
buffer->Size = Size;
buffer->Color = 0xFFFFFF;
buffer->CursorX = 0;
buffer->CursorY = 0;
buffer->Brightness = 100;
this->Buffers[Index] = buffer;
memset(this->Buffers[Index]->Buffer, 0, Size);
this->Buffers[Index]->Checksum = 0xDEAD;
debug("Created buffer %d, address %#lx", Index, buffer);
}
void Display::SetBuffer(int Index)
{
if (this->Buffers[Index]->Brightness != 100)
this->SetBrightness(this->Buffers[Index]->Brightness, Index);
if (this->Buffers[Index]->Brightness == 0) /* Just clear the buffer */
memset(this->Buffers[Index]->Buffer, 0, this->Buffers[Index]->Size);
memcpy(this->framebuffer.BaseAddress, this->Buffers[Index]->Buffer, this->Buffers[Index]->Size);
}
ScreenBuffer *Display::GetBuffer(int Index)
{
return this->Buffers[Index];
}
void Display::ClearBuffer(int Index)
{
memset(this->Buffers[Index]->Buffer, 0, this->Buffers[Index]->Size);
}
void Display::DeleteBuffer(int Index)
{
if (this->Buffers[Index] == nullptr)
return;
KernelAllocator.FreePages(this->Buffers[Index]->Buffer, TO_PAGES(this->Buffers[Index]->Size));
this->Buffers[Index]->Buffer = nullptr;
this->Buffers[Index]->Checksum = 0; // Making sure that the buffer is not used anymore
delete this->Buffers[Index], this->Buffers[Index] = nullptr;
}
void Display::SetBrightness(int Value, int Index)
{
if (this->Buffers[Index] == nullptr)
return;
if (Value > 100)
Value = 100;
else if (Value < 0)
Value = 0;
ScreenBuffer *buffer = this->Buffers[Index];
uint32_t *pixel = (uint32_t *)buffer->Buffer;
for (uint32_t y = 0; y < buffer->Height; y++)
{
for (uint32_t x = 0; x < buffer->Width; x++)
{
uint32_t color = pixel[y * buffer->Width + x];
uint8_t r = color & 0xff;
uint8_t g = (color >> 8) & 0xff;
uint8_t b = (color >> 16) & 0xff;
r = (r * Value) / 100;
g = (g * Value) / 100;
b = (b * Value) / 100;
pixel[y * buffer->Width + x] = (b << 16) | (g << 8) | r;
}
}
buffer->Brightness = Value;
}
void Display::SetBufferCursor(int Index, uint32_t X, uint32_t Y)
{
this->Buffers[Index]->CursorX = X;
this->Buffers[Index]->CursorY = Y;
}
void Display::GetBufferCursor(int Index, uint32_t *X, uint32_t *Y)
{
*X = this->Buffers[Index]->CursorX;
*Y = this->Buffers[Index]->CursorY;
}
void Display::SetPixel(uint32_t X, uint32_t Y, uint32_t Color, int Index)
{
if (unlikely(X >= this->Buffers[Index]->Width))
X = this->Buffers[Index]->Width - 1;
if (unlikely(Y >= this->Buffers[Index]->Height))
Y = this->Buffers[Index]->Height - 1;
uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index]->Buffer + (Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8));
*Pixel = Color;
}
uint32_t Display::GetPixel(uint32_t X, uint32_t Y, int Index)
{
if (unlikely(X >= this->Buffers[Index]->Width || Y >= this->Buffers[Index]->Height))
return 0;
uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index]->Buffer + (Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8));
return *Pixel;
}
uint16_t Display::GetBitsPerPixel()
{
return this->framebuffer.BitsPerPixel;
}
uint64_t Display::GetPitch()
{
return this->framebuffer.Pitch;
}
void Display::Scroll(int Index, int Lines)
{
if (Lines == 0)
return;
if (Lines > 0)
{
uint32_t LineSize = this->Buffers[Index]->Width * (this->framebuffer.BitsPerPixel / 8);
uint32_t BytesToMove = LineSize * Lines * this->CurrentFont->GetInfo().Height;
uint32_t BytesToClear = this->Buffers[Index]->Size - BytesToMove;
memmove(this->Buffers[Index]->Buffer, (uint8_t *)this->Buffers[Index]->Buffer + BytesToMove, BytesToClear);
memset((uint8_t *)this->Buffers[Index]->Buffer + BytesToClear, 0, BytesToMove);
}
}
char Display::Print(char Char, int Index, bool WriteToUART)
{
// SmartLock(PrintLock);
@ -230,7 +67,7 @@ namespace Video
for (unsigned long Y = this->Buffers[Index]->CursorY; Y < this->Buffers[Index]->CursorY + fonthdrHeight; Y++)
for (unsigned long X = this->Buffers[Index]->CursorX - fonthdrWidth; X < this->Buffers[Index]->CursorX; X++)
*(uint32_t *)((uintptr_t)this->Buffers[Index]->Buffer +
*(uint32_t *)((uint64_t)this->Buffers[Index]->Buffer +
(Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8)) = 0;
break;
}
@ -262,18 +99,16 @@ namespace Video
}
}
uint32_t FontHeight = this->GetCurrentFont()->GetInfo().Height;
if (this->Buffers[Index]->CursorY + this->GetCurrentFont()->GetInfo().Height >= this->Buffers[Index]->Height)
{
this->Buffers[Index]->CursorY -= this->GetCurrentFont()->GetInfo().Height;
this->Scroll(Index, 1);
}
if (this->Buffers[Index]->CursorX + this->GetCurrentFont()->GetInfo().Width >= this->Buffers[Index]->Width)
{
this->Buffers[Index]->CursorX = 0;
this->Buffers[Index]->CursorY += FontHeight;
}
if (this->Buffers[Index]->CursorY + FontHeight >= this->Buffers[Index]->Height)
{
this->Buffers[Index]->CursorY -= FontHeight;
this->Scroll(Index, 1);
this->Buffers[Index]->CursorY += this->GetCurrentFont()->GetInfo().Height;
}
switch (this->CurrentFont->GetInfo().Type)
@ -298,30 +133,24 @@ namespace Video
// if (this->CurrentFont->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE
// Char = this->CurrentFont->PSF2Font->GlyphBuffer[Char];
int BytesPerLine = (this->CurrentFont->GetInfo().PSF2Font->Header->width + 7) / 8;
char *FontAddress = (char *)this->CurrentFont->GetInfo().StartAddress;
uint32_t FontHeaderSize = this->CurrentFont->GetInfo().PSF2Font->Header->headersize;
uint32_t FontCharSize = this->CurrentFont->GetInfo().PSF2Font->Header->charsize;
uint32_t FontLength = this->CurrentFont->GetInfo().PSF2Font->Header->length;
char *FontPtr = FontAddress + FontHeaderSize + (Char > 0 && (uint32_t)Char < FontLength ? Char : 0) * FontCharSize;
char *FontPtr = (char *)this->CurrentFont->GetInfo().StartAddress +
this->CurrentFont->GetInfo().PSF2Font->Header->headersize +
(Char > 0 && (unsigned char)Char < this->CurrentFont->GetInfo().PSF2Font->Header->length ? Char : 0) *
this->CurrentFont->GetInfo().PSF2Font->Header->charsize;
uint32_t FontHdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width;
uint32_t FontHdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height;
uint32_t fonthdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width;
uint32_t fonthdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height;
for (size_t Y = this->Buffers[Index]->CursorY; Y < this->Buffers[Index]->CursorY + FontHdrHeight; Y++)
{
for (size_t X = this->Buffers[Index]->CursorX; X < this->Buffers[Index]->CursorX + FontHdrWidth; X++)
for (uint64_t Y = this->Buffers[Index]->CursorY; Y < this->Buffers[Index]->CursorY + fonthdrHeight; Y++)
{
for (uint64_t X = this->Buffers[Index]->CursorX; X < this->Buffers[Index]->CursorX + fonthdrWidth; X++)
if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index]->CursorX))) > 0)
{
void *FramebufferAddress = (void *)((uintptr_t)this->Buffers[Index]->Buffer +
(Y * this->Buffers[Index]->Width + X) *
(this->framebuffer.BitsPerPixel / 8));
*(uint32_t *)FramebufferAddress = this->Buffers[Index]->Color;
}
}
*(uint32_t *)((uint64_t)this->Buffers[Index]->Buffer +
(Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8)) = this->Buffers[Index]->Color;
FontPtr += BytesPerLine;
}
this->Buffers[Index]->CursorX += FontHdrWidth;
this->Buffers[Index]->CursorX += fonthdrWidth;
break;
}
default:
@ -331,21 +160,12 @@ namespace Video
return Char;
}
void Display::DrawString(const char *String, uint32_t X, uint32_t Y, int Index, bool WriteToUART)
{
this->Buffers[Index]->CursorX = X;
this->Buffers[Index]->CursorY = Y;
for (int i = 0; String[i] != '\0'; i++)
this->Print(String[i], Index, WriteToUART);
}
Display::Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont)
{
this->framebuffer = Info;
if (LoadDefaultFont)
{
this->CurrentFont = new Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, FontType::PCScreenFont2);
this->CurrentFont = new Font(&_binary_Files_ter_powerline_v12n_psf_start, &_binary_Files_ter_powerline_v12n_psf_end, FontType::PCScreenFont2);
FontInfo Info = this->CurrentFont->GetInfo();
debug("Font loaded: %dx%d %s",
Info.Width, Info.Height, Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2");
@ -355,11 +175,7 @@ namespace Video
Display::~Display()
{
debug("Destructor called");
this->ClearBuffer(0);
this->SetBuffer(0);
for (size_t i = 0; i < sizeof(this->Buffers) / sizeof(this->Buffers[0]); i++)
this->DeleteBuffer(i);
for (int i = 0; i < 16; i++)
DeleteBuffer(i);
}
}

View File

@ -4,7 +4,7 @@
namespace Video
{
Font::Font(uintptr_t *Start, uintptr_t *End, FontType Type)
Font::Font(uint64_t *Start, uint64_t *End, FontType Type)
{
trace("Initializing font with start %#llx and end %#llx Type: %d", Start, End, Type);
this->Info.StartAddress = Start;
@ -14,9 +14,9 @@ namespace Video
{
this->Info.PSF2Font = new PSF2_FONT;
uintptr_t FontDataLength = End - Start;
uint64_t FontDataLength = End - Start;
PSF2_HEADER *font2 = (PSF2_HEADER *)KernelAllocator.RequestPages(FontDataLength / PAGE_SIZE + 1);
for (uintptr_t i = 0; i < FontDataLength / PAGE_SIZE + 1; i++)
for (uint64_t i = 0; i < FontDataLength / PAGE_SIZE + 1; i++)
Memory::Virtual().Map((void *)(font2 + (i * PAGE_SIZE)), (void *)(font2 + (i * PAGE_SIZE)), Memory::PTFlag::RW);
memcpy((void *)font2, Start, FontDataLength);
@ -26,7 +26,7 @@ namespace Video
error("Font2 magic mismatch.");
this->Info.PSF2Font->Header = font2;
this->Info.PSF2Font->GlyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(Start) + sizeof(PSF2_HEADER));
this->Info.PSF2Font->GlyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uint64_t>(Start) + sizeof(PSF2_HEADER));
}
else if (Type == FontType::PCScreenFont1)
{
@ -37,7 +37,7 @@ namespace Video
uint32_t glyphBufferSize = font1->charsize * 256;
if (font1->mode == 1) // 512 glyph mode
glyphBufferSize = font1->charsize * 512;
void *glyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(Start) + sizeof(PSF1_HEADER));
void *glyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uint64_t>(Start) + sizeof(PSF1_HEADER));
this->Info.PSF1Font->Header = font1;
this->Info.PSF1Font->GlyphBuffer = glyphBuffer;
UNUSED(glyphBufferSize); // TODO: Use this in the future?

View File

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

View File

@ -1,17 +1,6 @@
#ifndef __FENNIX_DRIVER_API_H__
#define __FENNIX_DRIVER_API_H__
/**
* @brief The driver API is a set of functions that the kernel provides to the drivers.
*
* - The driver is responsible for the memory management.
* - The kernel will NOT free any memory allocated by the driver. On @see StopReason the driver must free all the memory it allocated and disable the hardware it uses.
* - The driver image will be freed after the driver is unloaded.
* - The kernel will unbind the interrupt handlers and the process handlers.
* - Kernel API will be freed after the driver is unloaded.
*
*/
enum DriverReturnCode
{
ERROR,
@ -23,13 +12,10 @@ enum DriverReturnCode
NOT_AUTHORIZED,
NOT_VALID,
NOT_ACCEPTED,
INVALID_PCI_BAR,
INVALID_KERNEL_API,
INVALID_MEMORY_ALLOCATION,
INVALID_DATA,
DEVICE_NOT_SUPPORTED,
SYSTEM_NOT_SUPPORTED,
KERNEL_API_VERSION_NOT_SUPPORTED,
KERNEL_API_VERSION_NOT_SUPPORTED
};
enum DriverBindType
@ -76,8 +62,6 @@ struct KernelAPI
void (*DisplayPrint)(char *Value);
void *(*memcpy)(void *Destination, void *Source, unsigned long Size);
void *(*memset)(void *Destination, int Value, unsigned long Size);
void (*Sleep)(unsigned long Milliseconds);
int (*sprintf)(char *Buffer, const char *Format, ...);
} Util;
struct KAPIDriverTalk
@ -100,94 +84,25 @@ struct KernelAPI
} Disk;
} Command;
struct KAPIDisplay
{
unsigned int (*GetWidth)(void);
unsigned int (*GetHeight)(void);
/* TODO: Add more */
} Display;
} __attribute__((packed));
enum CallbackReason
{
/**
* @brief This is used to detect memory corruption, not used.
*/
UnknownReason,
/**
* @brief This is called once the kernel is ready to use the driver and call @see ConfigurationReason .
*/
AcknowledgeReason,
/**
* @brief This is used after the driver is loaded and the kernel is ready to use the driver.
*
* For PCI drivers, @see RawPtr will be the PCI device address.
*/
SendReason,
ReceiveReason,
ConfigurationReason,
/**
* @brief This will be called when the registered interrupt is triggered.
*/
FetchReason,
BindReason,
UnbindReason,
InterruptReason,
/**
* @brief This is used when the kernel wants to stop the driver.
*
* The memory allocated by the driver will be freed automatically.
*/
StopReason,
ProcessReason,
InputReason,
/* Kernel reserved callbacks. */
/* ------------------------------------------------------- */
/* Driver callbacks for basic usage. */
/**
* @brief This is used when the kernel sends data.
*
* - Network
* - Packet
* - Audio
* - PCM Data
*/
SendReason,
/**
* @brief This is used when the kernel wants to receive data.
* Currently not used.
*/
ReceiveReason,
/**
* @brief This is used to adjust driver settings.
*
* - Audio
* - Volume
* - PCM Encoding
*/
AdjustReason,
/**
* @brief This is used when the kernel wants to fetch information about the driver.
*
* - Input
* - Mouse
* - Position
* - Buttons
* - Keyboard
* - Key
*/
FetchReason,
};
union KernelCallback
struct KernelCallback
{
struct
{
CallbackReason Reason;
void *RawPtr;
unsigned long RawData;
@ -195,17 +110,8 @@ union KernelCallback
/** @brief When the kernel wants to send a packet. */
struct
{
struct
{
unsigned char *Data;
void *Data;
unsigned long Length;
} Send;
struct
{
char Name[128];
unsigned long MAC;
} Fetch;
} NetworkCallback;
/** @brief When the kernel wants to write to disk. */
@ -227,7 +133,6 @@ union KernelCallback
} Fetch;
} DiskCallback;
/** @brief When the kernel wants to get mouse position / keyboard key */
struct
{
struct
@ -244,108 +149,10 @@ union KernelCallback
} Mouse;
} InputCallback;
struct
{
struct
{
bool _Volume;
bool _Encoding;
bool _SampleRate;
bool _Channels;
/**
* @brief Adjust the volume.
*
* 0 - 100
*/
unsigned char Volume;
/**
* @brief Adjust the encoding.
*
* 0 - None, use default
*
* 1 - Signed PCM 8-bit
* 2 - Unsigned PCM 8-bit
*
* 3 - Signed PCM 16-bit Little Endian
* 4 - Signed PCM 20-bit Little Endian
* 5 - Signed PCM 24-bit Little Endian
* 6 - Signed PCM 32-bit Little Endian
*
* 7 - Unsigned PCM 16-bit Little Endian
* 8 - Unsigned PCM 20-bit Little Endian
* 9 - Unsigned PCM 24-bit Little Endian
* 10 - Unsigned PCM 32-bit Little Endian
*
* 11 - Signed PCM 16-bit Big Endian
* 12 - Signed PCM 20-bit Big Endian
* 13 - Signed PCM 24-bit Big Endian
* 14 - Signed PCM 32-bit Big Endian
*
* 15 - Unsigned PCM 16-bit Big Endian
* 16 - Unsigned PCM 20-bit Big Endian
* 17 - Unsigned PCM 24-bit Big Endian
* 18 - Unsigned PCM 32-bit Big Endian
*
* 19 - Float PCM 32-bit Little Endian
* 20 - Float PCM 64-bit Little Endian
*
* 21 - Float PCM 32-bit Big Endian
* 22 - Float PCM 64-bit Big Endian
*
* 23 - PCM A-law
* 24 - PCM Mu-law
*
* ... - More
*/
unsigned short Encoding;
/**
* @brief Adjust the sample rate.
*
* 0 - 8000 Hz
* 1 - 11025 Hz
* 2 - 16000 Hz
* 3 - 22050 Hz
* 4 - 32000 Hz
* 5 - 44100 Hz
* 6 - 48000 Hz
* 7 - 88200 Hz
* 8 - 96000 Hz
*/
unsigned char SampleRate;
/**
* @brief Adjust the channels.
*
* 0 - Mono
* 1 - Stereo
*/
unsigned char Channels;
} Adjust;
struct
{
unsigned char *Data;
unsigned long Length;
} Send;
struct
{
unsigned char Volume;
unsigned short Encoding;
unsigned char SampleRate;
unsigned char Channels;
} Fetch;
} AudioCallback;
struct
{
unsigned char Vector;
} InterruptInfo;
};
unsigned long raw;
} __attribute__((packed));
#endif // !__FENNIX_DRIVER_API_H__

View File

@ -1,217 +0,0 @@
#include <exec.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <msexec.h>
#include <cwalk.h>
#include <elf.h>
#include <abi.h>
#include "../../kernel.h"
#include "../../Fex.hpp"
using namespace Tasking;
using VirtualFileSystem::File;
using VirtualFileSystem::FileStatus;
using VirtualFileSystem::NodeFlags;
namespace Execute
{
/* Passing arguments as a sanity check and debugging. */
void ELFInterpreterIPCThread(PCB *Process, char *Path, void *MemoryImage, Vector<String> NeededLibraries)
{
debug("Interpreter thread started for %s", Path);
// Interpreter will create an IPC with token "LOAD".
char UniqueToken[16] = {'L', 'O', 'A', 'D', '\0'};
InterProcessCommunication::IPCHandle *Handle = nullptr;
while (Handle == nullptr)
{
debug("Searching for IPC with token %s", UniqueToken);
Handle = Process->IPC->SearchByToken(UniqueToken);
if (Handle == nullptr)
debug("Failed");
TaskManager->Sleep(100);
if (Handle == nullptr)
debug("Retrying...");
}
debug("IPC found, sending data...");
RetryIPCWrite:
uintptr_t *TmpBuffer = new uintptr_t[0x1000];
*(int *)TmpBuffer = 2545;
InterProcessCommunication::IPCErrorCode ret = Process->IPC->Write(Handle->ID, TmpBuffer, 0x1000);
delete[] TmpBuffer, TmpBuffer = nullptr;
debug("Write returned %d", ret);
if (ret == InterProcessCommunication::IPCErrorCode::IPCNotListening)
{
debug("IPC not listening, retrying...");
TaskManager->Sleep(100);
goto RetryIPCWrite;
}
CPU::Halt(true);
}
PCB *InterpreterTargetProcess;
String *InterpreterTargetPath; /* We can't have String as a constructor :( */
void *InterpreterMemoryImage;
Vector<String> InterpreterNeededLibraries;
void ELFInterpreterThreadWrapper()
{
ELFInterpreterIPCThread(InterpreterTargetProcess, (char *)InterpreterTargetPath->c_str(), InterpreterMemoryImage, InterpreterNeededLibraries);
delete InterpreterTargetPath, InterpreterTargetPath = nullptr;
return;
}
ELFBaseLoad ELFLoad(char *Path, const char **argv, const char **envp, Tasking::TaskCompatibility Compatibility)
{
/* We get the base name ("app.elf") */
const char *BaseName;
cwk_path_get_basename(Path, &BaseName, nullptr);
TaskArchitecture Arch = TaskArchitecture::UnknownArchitecture;
shared_ptr<File> ExFile = vfs->Open(Path);
if (ExFile->Status != FileStatus::OK)
{
vfs->Close(ExFile);
error("Failed to open file: %s", Path);
return {};
}
else
{
if (ExFile->node->Flags != NodeFlags::FILE)
{
vfs->Close(ExFile);
error("Invalid file path: %s", Path);
return {};
}
else if (GetBinaryType(Path) != BinaryType::BinTypeELF)
{
vfs->Close(ExFile);
error("Invalid file type: %s", Path);
return {};
}
}
size_t ExFileSize = ExFile->node->Length;
/* Allocate elf in memory */
void *ElfFile = KernelAllocator.RequestPages(TO_PAGES(ExFileSize));
/* Copy the file to the allocated memory */
memcpy(ElfFile, (void *)ExFile->node->Address, ExFileSize);
debug("Image Size: %#lx - %#lx (length: %ld)", ElfFile, (uintptr_t)ElfFile + ExFileSize, ExFileSize);
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
switch (ELFHeader->e_machine)
{
case EM_386:
Arch = TaskArchitecture::x32;
break;
case EM_X86_64:
Arch = TaskArchitecture::x64;
break;
case EM_ARM:
Arch = TaskArchitecture::ARM32;
break;
case EM_AARCH64:
Arch = TaskArchitecture::ARM64;
break;
default:
break;
}
// TODO: This shouldn't be ignored
if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32)
{
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
fixme("ELF32 LSB");
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
fixme("ELF32 MSB");
else
fixme("ELF32 Unknown");
}
else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64)
{
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
fixme("ELF64 LSB");
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
fixme("ELF64 MSB");
else
fixme("ELF64 Unknown");
}
else
fixme("Unknown ELF");
/* ------------------------------------------------------------------------------------------------------------------------------ */
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User, ElfFile);
Memory::Virtual pV = Memory::Virtual(Process->PageTable);
for (size_t i = 0; i < TO_PAGES(ExFileSize); i++)
pV.Remap((void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)), (void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
// for (size_t i = 0; i < TO_PAGES(ElfLazyResolverSize); i++)
// pV.Remap((void *)((uintptr_t)ElfLazyResolver + (i * PAGE_SIZE)), (void *)((uintptr_t)ElfLazyResolver + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
ELFBaseLoad bl;
switch (ELFHeader->e_type)
{
case ET_REL:
bl = ELFLoadRel(ElfFile, ExFile.Get(), Process);
break;
case ET_EXEC:
bl = ELFLoadExec(ElfFile, ExFile.Get(), Process);
break;
case ET_DYN:
bl = ELFLoadDyn(ElfFile, ExFile.Get(), Process);
break;
case ET_CORE:
{
fixme("ET_CORE not implemented");
TaskManager->RevertProcessCreation(Process);
vfs->Close(ExFile);
return {};
}
case ET_NONE:
default:
{
error("Unknown ELF Type: %d", ELFHeader->e_type);
vfs->Close(ExFile);
TaskManager->RevertProcessCreation(Process);
return {};
}
}
if (bl.Interpreter)
{
InterpreterTargetProcess = Process;
InterpreterTargetPath = new String(Path); /* We store in a String because Path may get changed while outside ELFLoad(). */
InterpreterMemoryImage = bl.MemoryImage;
InterpreterNeededLibraries = bl.NeededLibraries;
__sync;
TCB *InterpreterIPCThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)ELFInterpreterThreadWrapper);
InterpreterIPCThread->Rename("ELF Interpreter IPC Thread");
InterpreterIPCThread->SetPriority(TaskPriority::Low);
}
TCB *Thread = TaskManager->CreateThread(Process,
bl.InstructionPointer,
argv, envp, bl.auxv,
(IPOffset)0 /* ProgramHeader->p_offset */, // I guess I don't need this
Arch,
Compatibility);
foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList())
{
Thread->Memory->Add(p.Address, p.PageCount);
bl.TmpMem->DetachAddress(p.Address);
}
delete bl.TmpMem, bl.TmpMem = nullptr;
bl.sd.Process = Process;
bl.sd.Thread = Thread;
bl.sd.Status = ExStatus::OK;
vfs->Close(ExFile);
return bl;
}
}

View File

@ -1,24 +0,0 @@
#include <exec.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <msexec.h>
#include <cwalk.h>
#include <elf.h>
#include <abi.h>
#include "../../kernel.h"
#include "../../Fex.hpp"
using namespace Tasking;
namespace Execute
{
ELFBaseLoad ELFLoadDyn(void *BaseImage,
VirtualFileSystem::File *ExFile,
Tasking::PCB *Process)
{
fixme("Not implemented");
return {};
}
}

View File

@ -1,206 +0,0 @@
#include <exec.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <msexec.h>
#include <cwalk.h>
#include <elf.h>
#include <abi.h>
#include "../../kernel.h"
#include "../../Fex.hpp"
using namespace Tasking;
namespace Execute
{
ELFBaseLoad ELFLoadExec(void *ElfFile,
VirtualFileSystem::File *ExFile,
Tasking::PCB *Process)
{
debug("Executable");
ELFBaseLoad ELFBase = {};
/* This should be deleted inside BaseLoad.cpp */
ELFBase.TmpMem = new Memory::MemMgr(Process->PageTable);
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
Memory::Virtual pV(Process->PageTable);
uintptr_t BaseAddress = UINTPTR_MAX;
uint64_t ElfAppSize = 0;
uintptr_t EntryPoint = ELFHeader->e_entry;
Elf64_Phdr ItrPhdr;
/* Get base address */
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
{
memcpy(&ItrPhdr,
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
sizeof(Elf64_Phdr));
BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr);
}
/* Get size */
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
{
memcpy(&ItrPhdr,
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
sizeof(Elf64_Phdr));
uintptr_t SegmentEnd;
SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz;
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
}
debug("BaseAddress: %#lx | ElfAppSize: %#lx (%ld, %ld KB)", BaseAddress, ElfAppSize, ElfAppSize, TO_KB(ElfAppSize));
/* If required, MemoryImage will be at virtual address. (unless has PIE)
*
* tl;dr this is where the code is stored. */
void *MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, pV, ElfFile, ElfAppSize);
debug("Solving symbols for address: %#llx", (uintptr_t)ElfFile);
Elf64_Shdr *ElfSections = (Elf64_Shdr *)((uintptr_t)ElfFile + ELFHeader->e_shoff);
Elf64_Shdr *DynamicString = nullptr;
Elf64_Shdr *StringTable = nullptr;
for (Elf64_Half i = 0; i < ELFHeader->e_shnum; i++)
{
char *DynamicStringTable = (char *)((uintptr_t)ElfFile + ElfSections[ELFHeader->e_shstrndx].sh_offset + ElfSections[i].sh_name);
if (strcmp(DynamicStringTable, ".dynstr") == 0)
{
DynamicString = &ElfSections[i];
debug("Found .dynstr");
}
else if (strcmp(DynamicStringTable, ".strtab") == 0)
{
StringTable = &ElfSections[i];
debug("Found .strtab");
}
}
if (!DynamicString)
DynamicString = StringTable;
/* Calculate entry point */
memcpy(&ItrPhdr, (uint8_t *)ElfFile + ELFHeader->e_phoff, sizeof(Elf64_Phdr));
if (ItrPhdr.p_vaddr == 0)
EntryPoint += (uintptr_t)MemoryImage;
char InterpreterPath[256];
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
{
memcpy(&ItrPhdr,
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
sizeof(Elf64_Phdr));
switch (ItrPhdr.p_type)
{
case PT_NULL:
fixme("PT_NULL");
break;
case PT_LOAD:
{
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
uintptr_t MAddr = (ItrPhdr.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage;
fixme("Address: %#lx %s%s%s", MAddr,
(ItrPhdr.p_flags & PF_R) ? "R" : "",
(ItrPhdr.p_flags & PF_W) ? "W" : "",
(ItrPhdr.p_flags & PF_X) ? "X" : "");
memcpy((void *)MAddr, (uint8_t *)ElfFile + ItrPhdr.p_offset, ItrPhdr.p_filesz);
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)ElfFile + ItrPhdr.p_offset, MAddr, ItrPhdr.p_filesz);
break;
}
case PT_DYNAMIC:
{
debug("PT_DYNAMIC - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)ElfFile + ItrPhdr.p_offset);
for (size_t i = 0; i < ItrPhdr.p_filesz / sizeof(Elf64_Dyn); i++)
{
if (Dynamic[i].d_tag == DT_NEEDED)
{
if (!DynamicString)
{
error("DynamicString is null");
break;
}
String ReqLib = (char *)((uintptr_t)ElfFile + DynamicString->sh_offset + Dynamic[i].d_un.d_val);
debug("DT_NEEDED - Name[%ld]: %s", i, ReqLib.c_str());
ELFBase.NeededLibraries.push_back(ReqLib);
}
else if (Dynamic[i].d_tag == DT_NULL)
break;
}
break;
}
case PT_INTERP:
{
debug("PT_INTERP - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
memcpy((void *)InterpreterPath, (uint8_t *)ElfFile + ItrPhdr.p_offset, 256);
debug("Interpreter: %s", InterpreterPath);
shared_ptr<VirtualFileSystem::File> InterpreterFile = vfs->Open(InterpreterPath);
if (InterpreterFile->Status != VirtualFileSystem::FileStatus::OK)
warn("Failed to open interpreter file: %s", InterpreterPath);
vfs->Close(InterpreterFile);
break;
}
/* ... */
case PT_PHDR:
{
debug("PT_PHDR - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
break;
}
default:
{
warn("Unknown or unsupported program header type: %d", ItrPhdr.p_type);
break;
}
}
}
if (strlen(InterpreterPath) > 1)
{
EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, pV, InterpreterPath);
ELFBase.Interpreter = true;
}
debug("Entry Point: %#lx", EntryPoint);
char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true);
strcpy(aux_platform, "x86_64");
ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)vfs->GetPathFromNode(ExFile->node).Get()}}});
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}});
ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}});
ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage}}});
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}});
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}});
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}});
ELFBase.InstructionPointer = EntryPoint;
ELFBase.MemoryImage = MemoryImage;
ELFBase.Success = true;
return ELFBase;
}
}

View File

@ -1,284 +0,0 @@
#include <exec.hpp>
#include <msexec.h>
#include "../../kernel.h"
#include "../../Fex.hpp"
namespace Execute
{
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header)
{
return (Elf64_Shdr *)((uintptr_t)Header + Header->e_shoff);
}
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index)
{
return &GetELFSheader(Header)[Index];
}
char *GetELFStringTable(Elf64_Ehdr *Header)
{
if (Header->e_shstrndx == SHN_UNDEF)
return nullptr;
return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset;
}
char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset)
{
char *StringTable = GetELFStringTable(Header);
if (StringTable == nullptr)
return nullptr;
return StringTable + Offset;
}
void *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name)
{
Elf64_Shdr *SymbolTable = nullptr;
Elf64_Shdr *StringTable = nullptr;
Elf64_Sym *Symbol = nullptr;
char *String = nullptr;
for (Elf64_Half i = 0; i < Header->e_shnum; i++)
{
Elf64_Shdr *shdr = GetELFSection(Header, i);
switch (shdr->sh_type)
{
case SHT_SYMTAB:
SymbolTable = shdr;
StringTable = GetELFSection(Header, shdr->sh_link);
break;
}
}
if (SymbolTable == nullptr || StringTable == nullptr)
return nullptr;
for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++)
{
Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
if (strcmp(String, Name) == 0)
return (void *)Symbol->st_value;
}
return nullptr;
}
uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index)
{
if (Table == SHN_UNDEF || Index == SHN_UNDEF)
return 0;
Elf64_Shdr *SymbolTable = GetELFSection(Header, Table);
uint64_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize;
if (Index >= STEntries)
{
error("Symbol index out of range %d-%u.", Table, Index);
return 0xdead;
}
uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset;
Elf64_Sym *Symbol = &((Elf64_Sym *)SymbolAddress)[Index];
if (Symbol->st_shndx == SHN_UNDEF)
{
Elf64_Shdr *StringTable = GetELFSection(Header, SymbolTable->sh_link);
const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name;
void *Target = ELFLookupSymbol(Header, Name);
if (Target == nullptr)
{
if (ELF64_ST_BIND(Symbol->st_info) & STB_WEAK)
return 0;
else
{
error("Undefined external symbol \"%s\".", Name);
return 0xdead;
}
}
else
return (uintptr_t)Target;
}
else if (Symbol->st_shndx == SHN_ABS)
return Symbol->st_value;
else
{
Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx);
return (uintptr_t)Header + Symbol->st_value + Target->sh_offset;
}
}
Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag)
{
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
Elf64_Phdr ItrPhdr;
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
{
memcpy(&ItrPhdr, (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr));
if (ItrPhdr.p_type == PT_DYNAMIC)
{
Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)ElfFile + ItrPhdr.p_offset);
for (size_t i = 0; i < ItrPhdr.p_filesz / sizeof(Elf64_Dyn); i++)
{
if (Dynamic[i].d_tag == Tag)
{
debug("Found dynamic tag %d at %#lx [d_val: %#lx].", Tag, &Dynamic[i], Dynamic[i].d_un.d_val);
return &Dynamic[i];
}
if (Dynamic[i].d_tag == DT_NULL)
{
debug("Reached end of dynamic tag list for tag %d.", Tag);
return nullptr;
}
}
}
}
debug("Dynamic tag %d not found.", Tag);
return nullptr;
}
void *ELFCreateMemoryImage(Memory::MemMgr *mem, Memory::Virtual &pV, void *ElfFile, size_t Length)
{
void *MemoryImage = nullptr;
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
/* TODO: Not sure what I am supposed to do with this.
* It is supposed to detect if it's PIC or not but I
* don't know if it's right. */
if (ELFGetDynamicTag(ElfFile, DT_TEXTREL))
{
fixme("Text relocation is not(?) tested yet!");
MemoryImage = (uint8_t *)mem->RequestPages(TO_PAGES(Length), true);
memset(MemoryImage, 0, Length);
return MemoryImage;
}
Elf64_Phdr ItrPhdr;
uintptr_t FirstProgramHeaderVirtualAddress = 0x0;
bool FirstProgramHeader = false;
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
{
memcpy(&ItrPhdr,
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
sizeof(Elf64_Phdr));
if (ItrPhdr.p_type == PT_LOAD && !FirstProgramHeader)
{
FirstProgramHeaderVirtualAddress = ItrPhdr.p_vaddr;
FirstProgramHeader = true;
}
if (ItrPhdr.p_type == PT_LOAD && ItrPhdr.p_vaddr == 0)
{
debug("p_vaddr is 0, allocating %ld pages for image", TO_PAGES(Length));
MemoryImage = mem->RequestPages(TO_PAGES(Length), true);
memset(MemoryImage, 0, Length);
return MemoryImage;
}
}
debug("Allocating %ld pages for image", TO_PAGES(Length));
MemoryImage = mem->RequestPages(TO_PAGES(Length));
memset(MemoryImage, 0, Length);
if (FirstProgramHeaderVirtualAddress != 0)
FirstProgramHeaderVirtualAddress &= 0xFFFFFFFFFFFFF000;
else
FirstProgramHeaderVirtualAddress = (uintptr_t)MemoryImage;
for (size_t i = 0; i < TO_PAGES(Length); i++)
{
pV.Remap((void *)((uintptr_t)FirstProgramHeaderVirtualAddress + (i * PAGE_SIZE)), (void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
debug("Remapped: %#lx -> %#lx", (uintptr_t)FirstProgramHeaderVirtualAddress + (i * PAGE_SIZE), (uintptr_t)MemoryImage + (i * PAGE_SIZE));
}
return MemoryImage;
}
uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, Memory::Virtual &pV, const char *Interpreter)
{
if (GetBinaryType((char *)Interpreter) != BinaryType::BinTypeELF)
{
error("Interpreter \"%s\" is not an ELF file.", Interpreter);
return 0;
}
/* No need to check if it's valid, the GetBinaryType() call above does that. */
shared_ptr<VirtualFileSystem::File> File = vfs->Open(Interpreter);
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)File->node->Address;
#ifdef DEBUG
const char *InterpreterType[6] = {
"ET_NONE",
"ET_REL",
"ET_EXEC",
"ET_DYN",
"ET_CORE",
"ET_LOPROC - ET_HIPROC"};
Elf64_Half IntType = ELFHeader->e_type;
if (IntType > 5)
IntType = 5;
debug("Interpreter type: %s - %#x", InterpreterType[IntType], ELFHeader->e_type);
#endif
uintptr_t BaseAddress = UINTPTR_MAX;
uint64_t ElfAppSize = 0;
Elf64_Phdr ItrPhdr;
/* Get base address */
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
{
memcpy(&ItrPhdr,
(uint8_t *)File->node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
sizeof(Elf64_Phdr));
BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr);
}
/* Get size */
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
{
memcpy(&ItrPhdr,
(uint8_t *)File->node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
sizeof(Elf64_Phdr));
uintptr_t SegmentEnd;
SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz;
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
}
void *MemoryImage = ELFCreateMemoryImage(mem, pV, (void *)File->node->Address, ElfAppSize);
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
{
memcpy(&ItrPhdr,
(uint8_t *)File->node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
sizeof(Elf64_Phdr));
if (ItrPhdr.p_type == PT_LOAD)
{
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
uintptr_t MAddr = (ItrPhdr.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage;
fixme("Address: %#lx %s%s%s", MAddr,
(ItrPhdr.p_flags & PF_R) ? "R" : "",
(ItrPhdr.p_flags & PF_W) ? "W" : "",
(ItrPhdr.p_flags & PF_X) ? "X" : "");
memcpy((void *)MAddr, (uint8_t *)File->node->Address + ItrPhdr.p_offset, ItrPhdr.p_filesz);
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)File->node->Address + ItrPhdr.p_offset, MAddr, ItrPhdr.p_filesz);
}
}
vfs->Close(File);
debug("Interpreter entry point: %#lx (%#lx + %#lx)", (uintptr_t)MemoryImage + ELFHeader->e_entry,
(uintptr_t)MemoryImage, ELFHeader->e_entry);
return (uintptr_t)MemoryImage + ELFHeader->e_entry;
}
}

View File

@ -1,93 +0,0 @@
#include <exec.hpp>
#include <msexec.h>
#include "../../kernel.h"
#include "../../Fex.hpp"
namespace Execute
{
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
ELFBaseLoad ELFLoadRel(void *BaseImage,
VirtualFileSystem::File *ExFile,
Tasking::PCB *Process)
{
debug("Relocatable");
/* TODO: I have to fully implement this, but for now I will leave it as it is now. */
warn("Relocatable ELF is not fully supported yet");
/* This should be deleted after with kfree */
ELFBaseLoad ELFBase = {};
/* This should be deleted inside BaseLoad.cpp */
ELFBase.TmpMem = new Memory::MemMgr(Process->PageTable);
Elf64_Shdr *shdr = GetELFSheader(((Elf64_Ehdr *)BaseImage));
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++)
{
Elf64_Shdr *Section = &shdr[i];
if (Section->sh_type == SHT_NOBITS)
{
if (!Section->sh_size)
continue;
if (Section->sh_flags & SHF_ALLOC)
{
void *Buffer = KernelAllocator.RequestPages(TO_PAGES(Section->sh_size));
memset(Buffer, 0, Section->sh_size);
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
for (size_t i = 0; i < TO_PAGES(Section->sh_size); i++)
pva.Map((void *)((uintptr_t)Buffer + (i * PAGE_SIZE)), (void *)((uintptr_t)Buffer + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
Section->sh_offset = (uintptr_t)Buffer - (uintptr_t)BaseImage;
debug("Section %ld", Section->sh_size);
}
}
}
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++)
{
Elf64_Shdr *Section = &shdr[i];
if (Section->sh_type == SHT_REL)
{
for (size_t Index = 0; Index < Section->sh_size / Section->sh_entsize; Index++)
{
Elf64_Rel *RelTable = &((Elf64_Rel *)((uintptr_t)BaseImage + Section->sh_offset))[Index];
Elf64_Shdr *Target = GetELFSection(((Elf64_Ehdr *)BaseImage), Section->sh_info);
uintptr_t *RelAddress = (uintptr_t *)(((uintptr_t)BaseImage + Target->sh_offset) + RelTable->r_offset);
uint64_t SymbolValue = 0;
if (ELF64_R_SYM(RelTable->r_info) != SHN_UNDEF)
{
SymbolValue = ELFGetSymbolValue(((Elf64_Ehdr *)BaseImage), Section->sh_link, ELF64_R_SYM(RelTable->r_info));
if (SymbolValue == 0xdead)
{
delete ELFBase.TmpMem, ELFBase.TmpMem = nullptr;
return {};
}
}
switch (ELF64_R_TYPE(RelTable->r_info))
{
case R_386_NONE:
break;
case R_386_32:
*RelAddress = DO_64_64(SymbolValue, *RelAddress);
break;
case R_386_PC32:
*RelAddress = DO_64_PC32(SymbolValue, *RelAddress, (uintptr_t)RelAddress);
break;
default:
{
error("Unsupported relocation type: %d", ELF64_R_TYPE(RelTable->r_info));
delete ELFBase.TmpMem, ELFBase.TmpMem = nullptr;
return {};
}
}
debug("Symbol value: %#lx", SymbolValue);
}
}
}
return ELFBase;
}
}

View File

@ -1,115 +0,0 @@
#include <exec.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <msexec.h>
#include <cwalk.h>
#include <elf.h>
#include <abi.h>
#ifdef DEBUG
#include <dumper.hpp>
#endif
#include "../../kernel.h"
#include "../../Fex.hpp"
using namespace Tasking;
NewLock(ExecuteServiceLock);
namespace Execute
{
Memory::MemMgr *mem = nullptr;
Vector<SharedLibraries> Libs;
void StartExecuteService()
{
mem = new Memory::MemMgr;
// return;
while (true)
{
ExecuteServiceLock.Lock(__FUNCTION__);
foreach (auto &Lib in Libs)
{
if (Lib.RefCount > 0)
{
Lib.Timeout = TimeManager->CalculateTarget(600000);
debug("Reset timeout for %s", Lib.Identifier);
continue;
}
if (Lib.Timeout < TimeManager->GetCounter())
{
// TODO: Remove
fixme("Removed library %s because of timeout", Lib.Identifier);
}
else
debug("Timeout for %s is %ld", Lib.Identifier, Lib.Timeout);
}
debug("Waiting 10 seconds...");
ExecuteServiceLock.Unlock();
TaskManager->Sleep(10000);
}
}
SharedLibraries *AddLibrary(char *Identifier, void *ElfImage, size_t Length, const Memory::Virtual &pV)
{
SmartLock(ExecuteServiceLock);
SharedLibraries sl;
strcpy(sl.Identifier, Identifier);
sl.Timeout = TimeManager->CalculateTarget(600000); /* 10 minutes */
sl.RefCount = 0;
void *LibFile = mem->RequestPages(TO_PAGES(Length), true);
memcpy(LibFile, (void *)ElfImage, Length);
Memory::Virtual ncpV = pV;
sl.MemoryImage = ELFCreateMemoryImage(mem, ncpV, LibFile, Length);
{
uintptr_t BaseAddress = UINTPTR_MAX;
Elf64_Phdr ItrProgramHeader;
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_phnum; i++)
{
memcpy(&ItrProgramHeader, (uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_phoff + ((Elf64_Ehdr *)LibFile)->e_phentsize * i, sizeof(Elf64_Phdr));
BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr);
}
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_phnum; i++)
{
memcpy(&ItrProgramHeader, (uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_phoff + ((Elf64_Ehdr *)LibFile)->e_phentsize * i, sizeof(Elf64_Phdr));
if (ItrProgramHeader.p_type != PT_LOAD)
continue;
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
ItrProgramHeader.p_offset, ItrProgramHeader.p_vaddr,
ItrProgramHeader.p_filesz, ItrProgramHeader.p_memsz, ItrProgramHeader.p_align);
uintptr_t MAddr = (ItrProgramHeader.p_vaddr - BaseAddress) + (uintptr_t)sl.MemoryImage;
fixme("Address: %#lx %s%s%s", MAddr,
(ItrProgramHeader.p_flags & PF_R) ? "R" : "",
(ItrProgramHeader.p_flags & PF_W) ? "W" : "",
(ItrProgramHeader.p_flags & PF_X) ? "X" : "");
memcpy((void *)MAddr, (uint8_t *)LibFile + ItrProgramHeader.p_offset, ItrProgramHeader.p_filesz);
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)LibFile + ItrProgramHeader.p_offset, (uintptr_t)MAddr, ItrProgramHeader.p_filesz);
break;
}
}
sl.Address = LibFile;
sl.Length = Length;
debug("Library %s loaded at %#lx (full file: %#lx)", Identifier, sl.MemoryImage, LibFile);
Libs.push_back(sl);
return &Libs[Libs.size() - 1];
}
void SearchLibrary(char *Identifier)
{
SmartLock(ExecuteServiceLock);
}
}

View File

@ -1,21 +0,0 @@
#include <exec.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <msexec.h>
#include <cwalk.h>
#include <elf.h>
#include <abi.h>
#include "../../kernel.h"
#include "../../Fex.hpp"
using namespace Tasking;
namespace Execute
{
void FEXLoad()
{
}
}

View File

@ -7,77 +7,227 @@
namespace Execute
{
BinaryType GetBinaryType(void *Image)
BinaryType GetBinaryType(char *Path)
{
Fex *FexHdr = (Fex *)Image;
BinaryType Type = BinaryType::BinTypeInvalid;
FileSystem::FILE *ExFile = vfs->Open(Path);
/* Elf64_Ehdr and Elf32_Ehdr are very similar (Elf64_Half and
Elf32_Half are the same size type) so we can use directly Elf64_Ehdr. */
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)Image;
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Image;
/* Check Fex magic */
if (ExFile->Status == FileSystem::FileStatus::OK)
{
if (ExFile->Node->Flags == FileSystem::NodeFlags::FS_FILE)
{
Fex *FexHdr = (Fex *)ExFile->Node->Address;
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ExFile->Node->Address;
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)ExFile->Node->Address;
if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0')
{
/* If the fex type is driver, we shouldn't return as Fex. */
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
{
debug("Image - Fex");
return BinaryType::BinTypeFex;
trace("%s - Fex", Path);
Type = BinaryType::BinTypeFex;
goto Exit;
}
else if (FexHdr->Type == FexFormatType::FexFormatType_Driver)
debug("Fex Driver is not supposed to be executed.");
}
/* Check ELF magic. */
else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
{
debug("Image - ELF");
return BinaryType::BinTypeELF;
trace("%s - ELF", Path);
Type = BinaryType::BinTypeELF;
goto Exit;
}
/* Every Windows executable starts with MZ header. */
else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE)
{
IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Image) + MZHeader->e_lfanew);
IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Image) + MZHeader->e_lfanew);
/* TODO: LE, EDOS */
if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)ExFile->Node->Address) + MZHeader->e_lfanew);
IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)ExFile->Node->Address) + MZHeader->e_lfanew);
if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
{
debug("Image - PE");
return BinaryType::BinTypePE;
trace("%s - NE", Path);
Type = BinaryType::BinTypeNE;
}
else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
else if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
{
debug("Image - NE");
return BinaryType::BinTypeNE;
trace("%s - PE", Path);
Type = BinaryType::BinTypePE;
}
else
{
debug("Image - MZ");
return BinaryType::BinTypeMZ;
trace("%s - MZ", Path);
Type = BinaryType::BinTypeMZ;
}
goto Exit;
}
/* ... */
return BinaryType::BinTypeUnknown;
Type = BinaryType::BinTypeUnknown;
}
BinaryType GetBinaryType(char *Path)
{
BinaryType Type = BinaryType::BinTypeInvalid;
shared_ptr<VirtualFileSystem::File> ExFile = vfs->Open(Path);
if (ExFile->Status == VirtualFileSystem::FileStatus::OK)
{
debug("File opened: %s", Path);
Type = GetBinaryType((void *)ExFile->node->Address);
}
Exit:
vfs->Close(ExFile);
return Type;
}
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
static inline Elf64_Shdr *GetElfSheader(Elf64_Ehdr *Header) { return (Elf64_Shdr *)((uint64_t)Header + Header->e_shoff); }
static inline Elf64_Shdr *GetElfSection(Elf64_Ehdr *Header, uint64_t Index) { return &GetElfSheader(Header)[Index]; }
static inline char *GetElfStringTable(Elf64_Ehdr *Header)
{
if (Header->e_shstrndx == SHN_UNDEF)
return nullptr;
return (char *)Header + GetElfSection(Header, Header->e_shstrndx)->sh_offset;
}
static inline char *elf_lookup_string(Elf64_Ehdr *Header, uint64_t Offset)
{
char *StringTable = GetElfStringTable(Header);
if (StringTable == nullptr)
return nullptr;
return StringTable + Offset;
}
static void *ElfLookupSymbol(Elf64_Ehdr *Header, const char *Name)
{
Elf64_Shdr *SymbolTable = nullptr;
Elf64_Shdr *StringTable = nullptr;
Elf64_Sym *Symbol = nullptr;
char *String = nullptr;
for (Elf64_Half i = 0; i < Header->e_shnum; i++)
{
Elf64_Shdr *shdr = GetElfSection(Header, i);
switch (shdr->sh_type)
{
case SHT_SYMTAB:
SymbolTable = shdr;
StringTable = GetElfSection(Header, shdr->sh_link);
break;
}
}
if (SymbolTable == nullptr || StringTable == nullptr)
return nullptr;
for (uint64_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++)
{
Symbol = (Elf64_Sym *)((uint64_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
String = (char *)((uint64_t)Header + StringTable->sh_offset + Symbol->st_name);
if (strcmp(String, Name) == 0)
return (void *)Symbol->st_value;
}
return nullptr;
}
static uint64_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint32_t Index)
{
if (Table == SHN_UNDEF || Index == SHN_UNDEF)
return 0;
Elf64_Shdr *SymbolTable = GetElfSection(Header, Table);
uint32_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize;
if (Index >= STEntries)
{
error("Symbol index out of range %d-%u.", Table, Index);
return 0xdead;
}
uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset;
Elf32_Sym *Symbol = &((Elf32_Sym *)SymbolAddress)[Index];
if (Symbol->st_shndx == SHN_UNDEF)
{
Elf64_Shdr *StringTable = GetElfSection(Header, SymbolTable->sh_link);
const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name;
void *Target = ElfLookupSymbol(Header, Name);
if (Target == nullptr)
{
if (ELF32_ST_BIND(Symbol->st_info) & STB_WEAK)
return 0;
else
{
error("Undefined external symbol \"%s\".", Name);
return 0xdead;
}
}
else
return (uint64_t)Target;
}
else if (Symbol->st_shndx == SHN_ABS)
return Symbol->st_value;
else
{
Elf64_Shdr *Target = GetElfSection(Header, Symbol->st_shndx);
return (uint64_t)Header + Symbol->st_value + Target->sh_offset;
}
}
void *ELFLoadRel(Elf64_Ehdr *Header)
{
Elf64_Shdr *shdr = GetElfSheader(Header);
for (uint64_t i = 0; i < Header->e_shnum; i++)
{
Elf64_Shdr *Section = &shdr[i];
if (Section->sh_type == SHT_NOBITS)
{
if (!Section->sh_size)
continue;
if (Section->sh_flags & SHF_ALLOC)
{
void *Buffer = KernelAllocator.RequestPages(TO_PAGES(Section->sh_size));
memset(Buffer, 0, Section->sh_size);
Memory::Virtual pva = Memory::Virtual(/* TODO TODO TODO TODO TODO TODO */);
for (uint64_t i = 0; i < TO_PAGES(Section->sh_size); i++)
pva.Map((void *)((uint64_t)Buffer + (i * PAGE_SIZE)), (void *)((uint64_t)Buffer + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
Section->sh_offset = (uint64_t)Buffer - (uint64_t)Header;
debug("Section %ld", Section->sh_size);
}
}
}
for (uint64_t i = 0; i < Header->e_shnum; i++)
{
Elf64_Shdr *Section = &shdr[i];
if (Section->sh_type == SHT_REL)
{
for (uint64_t Index = 0; Index < Section->sh_size / Section->sh_entsize; Index++)
{
Elf64_Rel *RelTable = &((Elf64_Rel *)((uint64_t)Header + Section->sh_offset))[Index];
Elf64_Shdr *Target = GetElfSection(Header, Section->sh_info);
uint64_t *RelAddress = (uint64_t *)(((uint64_t)Header + Target->sh_offset) + RelTable->r_offset);
uint64_t SymbolValue = 0;
if (ELF64_R_SYM(RelTable->r_info) != SHN_UNDEF)
{
SymbolValue = ELFGetSymbolValue(Header, Section->sh_link, ELF64_R_SYM(RelTable->r_info));
if (SymbolValue == 0xdead)
return (void *)0xdeadbeef;
}
switch (ELF64_R_TYPE(RelTable->r_info))
{
case R_386_NONE:
break;
case R_386_32:
*RelAddress = DO_64_64(SymbolValue, *RelAddress);
break;
case R_386_PC32:
*RelAddress = DO_64_PC32(SymbolValue, *RelAddress, (uint64_t)RelAddress);
break;
default:
error("Unsupported relocation type: %d", ELF64_R_TYPE(RelTable->r_info));
return (void *)0xdeadbeef;
}
debug("Symbol value: %#lx", SymbolValue);
}
}
}
return (void *)Header->e_entry;
}
}

View File

@ -19,39 +19,36 @@ namespace Execute
SpawnData ret = {.Status = ExStatus::Unknown,
.Process = nullptr,
.Thread = nullptr};
shared_ptr<VirtualFileSystem::File> ExFile = vfs->Open(Path);
if (ExFile->Status == VirtualFileSystem::FileStatus::OK)
FileSystem::FILE *ExFile = vfs->Open(Path);
if (ExFile->Status == FileSystem::FileStatus::OK)
{
if (ExFile->node->Flags != VirtualFileSystem::NodeFlags::FILE)
if (ExFile->Node->Flags == FileSystem::NodeFlags::FS_FILE)
{
ret.Status = ExStatus::InvalidFilePath;
goto Exit;
}
switch (GetBinaryType(Path))
BinaryType Type = GetBinaryType(Path);
switch (Type)
{
case BinaryType::BinTypeFex:
{
Fex *FexHdr = (Fex *)ExFile->node->Address;
#if defined(__amd64__)
Fex *FexHdr = (Fex *)ExFile->Node->Address;
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
{
const char *BaseName;
cwk_path_get_basename(Path, &BaseName, nullptr);
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User);
void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->node->Length));
memcpy(BaseImage, (void *)ExFile->node->Address, ExFile->node->Length);
void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->Node->Length));
memcpy(BaseImage, (void *)ExFile->Node->Address, ExFile->Node->Length);
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
for (size_t i = 0; i < TO_PAGES(ExFile->node->Length); i++)
pva.Map((void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), (void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++)
pva.Map((void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), (void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
Vector<AuxiliaryVector> auxv; // TODO!
TCB *Thread = TaskManager->CreateThread(Process,
(IP)FexHdr->EntryPoint,
(IP)FexHdr->Pointer,
argv, envp, auxv,
(IPOffset)BaseImage,
TaskArchitecture::x64,
@ -59,35 +56,189 @@ namespace Execute
ret.Process = Process;
ret.Thread = Thread;
ret.Status = ExStatus::OK;
#elif defined(__i386__)
if (1)
{
#elif defined(__aarch64__)
if (1)
{
#endif
goto Exit;
}
ret.Status = ExStatus::InvalidFileHeader;
goto Exit;
}
case BinaryType::BinTypeELF:
{
ELFBaseLoad bl = ELFLoad(Path, argv, envp);
if (!bl.Success)
#if defined(__amd64__)
const char *BaseName;
cwk_path_get_basename(Path, &BaseName, nullptr);
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User);
void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->Node->Length));
memcpy(BaseImage, (void *)ExFile->Node->Address, ExFile->Node->Length);
debug("Image Size: %#lx - %#lx (length: %ld)", BaseImage, (uint64_t)BaseImage + ExFile->Node->Length, ExFile->Node->Length);
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++)
pva.Remap((void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), (void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)BaseImage;
TaskArchitecture Arch = TaskArchitecture::x64;
TaskCompatibility Comp = TaskCompatibility::Native;
if (ELFHeader->e_machine == EM_386)
Arch = TaskArchitecture::x32;
else if (ELFHeader->e_machine == EM_AMD64)
Arch = TaskArchitecture::x64;
else if (ELFHeader->e_machine == EM_AARCH64)
Arch = TaskArchitecture::ARM64;
else
Arch = TaskArchitecture::UnknownArchitecture;
// TODO: Should I care about this?
if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32)
{
ret.Status = ExStatus::GenericError;
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
fixme("ELF32 LSB");
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
fixme("ELF32 MSB");
else
fixme("ELF32 Unknown");
}
else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64)
{
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
fixme("ELF64 LSB");
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
fixme("ELF64 MSB");
else
fixme("ELF64 Unknown");
}
else
fixme("Unknown ELF");
if (ELFHeader->e_type == ET_EXEC)
{
trace("Executable");
Elf64_Phdr *pheader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff);
debug("p_paddr: %#lx | p_vaddr: %#lx | p_filesz: %#lx | p_memsz: %#lx | p_offset: %#lx", pheader->p_paddr, pheader->p_vaddr, pheader->p_filesz, pheader->p_memsz, pheader->p_offset);
void *Address = nullptr;
for (int i = 0; i < ELFHeader->e_phnum; i++, pheader++)
{
if (pheader->p_type != PT_LOAD)
continue;
Address = (void *)((uint64_t)pheader->p_vaddr + pheader->p_memsz);
}
void *Offset = KernelAllocator.RequestPages(TO_PAGES((uint64_t)Address));
pheader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff);
for (uint64_t i = 0; i < TO_PAGES((uint64_t)Address); i++)
{
pva.Remap((void *)((uint64_t)pheader->p_vaddr + (i * PAGE_SIZE)), (void *)((uint64_t)Offset + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
// debug("Mapping: %#lx -> %#lx", (uint64_t)pheader->p_vaddr + (i * PAGE_SIZE), (uint64_t)Offset + (i * PAGE_SIZE));
}
pheader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff);
for (int i = 0; i < ELFHeader->e_phnum; i++, pheader++)
{
if (pheader->p_type != PT_LOAD)
continue;
void *dst = (void *)((uint64_t)pheader->p_vaddr + (uint64_t)Offset);
memset(dst, 0, pheader->p_memsz);
memcpy(dst, ((char *)BaseImage) + pheader->p_offset, pheader->p_filesz);
}
debug("Entry Point: %#lx", ELFHeader->e_entry);
Vector<AuxiliaryVector> auxv;
pheader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff);
auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}});
auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}});
auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}});
auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)Offset}}});
auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)ELFHeader->e_entry + (uint64_t)pheader->p_offset}}});
auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t) "x86_64"}}});
auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)Path}}});
TCB *Thread = TaskManager->CreateThread(Process,
(IP)ELFHeader->e_entry,
argv, envp, auxv,
(IPOffset)pheader->p_offset,
Arch,
Comp);
ret.Process = Process;
ret.Thread = Thread;
ret.Status = ExStatus::OK;
goto Exit;
}
ret = bl.sd;
else if (ELFHeader->e_type == ET_DYN)
{
fixme("Shared Object");
}
else if (ELFHeader->e_type == ET_REL)
{
trace("Relocatable");
void *EP = ELFLoadRel(ELFHeader);
if (EP == (void *)0xdeadbeef || EP == 0x0)
{
ret.Status = ExStatus::InvalidFileEntryPoint;
goto Exit;
}
Vector<AuxiliaryVector> auxv;
fixme("auxv");
TCB *Thread = TaskManager->CreateThread(Process,
(IP)EP,
argv, envp, auxv,
(IPOffset)BaseImage,
Arch,
Comp);
ret.Process = Process;
ret.Thread = Thread;
ret.Status = ExStatus::OK;
goto Exit;
}
else if (ELFHeader->e_type == ET_CORE)
{
fixme("Core");
}
else
{
fixme("Unknown");
}
ret.Status = ExStatus::InvalidFileHeader;
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
goto Exit;
}
default:
{
ret.Status = ExStatus::Unsupported;
goto Exit;
}
goto Exit;
}
}
else if (ExFile->Status == VirtualFileSystem::FileStatus::NotFound)
else if (ExFile->Status == FileSystem::FileStatus::NOT_FOUND)
{
ret.Status = ExStatus::InvalidFilePath;
goto Exit;
}
else
{
ret.Status = ExStatus::InvalidFile;
goto Exit;
}
Exit:
if (ret.Status != ExStatus::OK)
if (ret.Process)
ret.Process->Status = TaskStatus::Terminated;
vfs->Close(ExFile);
return ret;
}

View File

@ -43,23 +43,15 @@ enum FexDriverType
/* ... */
};
enum FexDriverInputTypes
{
FexDriverInputTypes_None = 0b00000000,
FexDriverInputTypes_Mouse = 0b00000001,
FexDriverInputTypes_Keyboard = 0b00000010,
/* ... */
};
struct Fex
{
char Magic[4];
enum FexFormatType Type : 4;
enum FexOSType OS : 4;
int (*EntryPoint)(void *);
int (*Pointer)(void *);
} __attribute__((packed));
union KernelCallback;
struct KernelCallback;
struct FexExtended
{
@ -72,9 +64,7 @@ struct FexExtended
{
char Name[64];
enum FexDriverType Type : 4;
enum FexDriverInputTypes TypeFlags : 4;
bool OverrideOnConflict : 1;
int (*Callback)(union KernelCallback *);
int (*Callback)(struct KernelCallback *);
struct DriverBind
{
@ -100,8 +90,8 @@ struct FexExtended
struct
{
char AttachToMouse;
char AttachToKeyboard;
bool AttachToMouse;
bool AttachToKeyboard;
} Input;
} Bind;
} Driver;
@ -112,7 +102,7 @@ struct FexExtended
*
* @param FormatType FexFormatType
* @param OperatingSystem FexOSType
* @param Address EntryPoint to the start function
* @param Address Pointer to the start function
*
* @note Must include ".header : { *(.header .header.*) }" in linker script
*/
@ -121,6 +111,6 @@ struct FexExtended
.Magic = {'F', 'E', 'X', '\0'}, \
.Type = FormatType, \
.OS = OperatingSystem, \
.EntryPoint = Address}
.Pointer = Address}
#endif // !__FENNIX_FILE_FEX_H__

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