refactor: Fix build on i386
Some checks failed
CodeQL Advanced / Analyze (${{ matrix.language }}) (manual, c-cpp) (push) Has been cancelled
Deploy Documentation / Deploy Documentation to GitHub Pages (push) Has been cancelled
Build OS / Build Cross-Compiler & Toolchain (push) Has been cancelled
Build OS / Build amd64 (push) Has been cancelled
Build OS / Build i386 (push) Has been cancelled
Build OS / Build aarch64 (push) Has been cancelled

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
EnderIce2 2025-01-07 17:49:37 +02:00
parent 463d16f8bc
commit 2bb997597e
No known key found for this signature in database
GPG Key ID: 2EE20AF089811A5A
57 changed files with 1489 additions and 923 deletions

View File

@ -146,10 +146,10 @@ static_assert(sizeof(blkcnt_t) == 8, "blkcnt_t must be 64 bits");
#else #else
static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits"); static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits");
static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits"); static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits");
static_assert(sizeof(mode_t) == 2, "mode_t must be 16 bits"); static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits");
static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits"); static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits");
static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits"); static_assert(sizeof(uid_t) == 4, "uid_t must be 32 bits");
static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits"); static_assert(sizeof(gid_t) == 4, "gid_t must be 32 bits");
static_assert(sizeof(off_t) == 4, "off_t must be 32 bits"); static_assert(sizeof(off_t) == 4, "off_t must be 32 bits");
static_assert(sizeof(time_t) == 4, "time_t must be 32 bits"); static_assert(sizeof(time_t) == 4, "time_t must be 32 bits");
static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits"); static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits");

View File

@ -75,7 +75,7 @@ extern "C"
: "dN"(Port), "a"(Data)); : "dN"(Port), "a"(Data));
} }
static inline uint8_t mmioin8(uint64_t Address) static inline uint8_t mmioin8(uintptr_t Address)
{ {
__asm__ volatile("" :: __asm__ volatile("" ::
: "memory"); : "memory");
@ -85,7 +85,7 @@ extern "C"
return Result; return Result;
} }
static inline uint16_t mmioin16(uint64_t Address) static inline uint16_t mmioin16(uintptr_t Address)
{ {
__asm__ volatile("" :: __asm__ volatile("" ::
: "memory"); : "memory");
@ -95,7 +95,7 @@ extern "C"
return Result; return Result;
} }
static inline uint32_t mmioin32(uint64_t Address) static inline uint32_t mmioin32(uintptr_t Address)
{ {
__asm__ volatile("" :: __asm__ volatile("" ::
: "memory"); : "memory");
@ -105,17 +105,17 @@ extern "C"
return Result; return Result;
} }
static inline uint64_t mmioin64(uint64_t Address) static inline uintptr_t mmioin64(uintptr_t Address)
{ {
__asm__ volatile("" :: __asm__ volatile("" ::
: "memory"); : "memory");
uint64_t Result = *(volatile uint64_t *)Address; uintptr_t Result = *(volatile uintptr_t *)Address;
__asm__ volatile("" :: __asm__ volatile("" ::
: "memory"); : "memory");
return Result; return Result;
} }
static inline void mmioout8(uint64_t Address, uint8_t Data) static inline void mmioout8(uintptr_t Address, uint8_t Data)
{ {
__asm__ volatile("" :: __asm__ volatile("" ::
: "memory"); : "memory");
@ -124,7 +124,7 @@ extern "C"
: "memory"); : "memory");
} }
static inline void mmioout16(uint64_t Address, uint16_t Data) static inline void mmioout16(uintptr_t Address, uint16_t Data)
{ {
__asm__ volatile("" :: __asm__ volatile("" ::
: "memory"); : "memory");
@ -133,7 +133,7 @@ extern "C"
: "memory"); : "memory");
} }
static inline void mmioout32(uint64_t Address, uint32_t Data) static inline void mmioout32(uintptr_t Address, uint32_t Data)
{ {
__asm__ volatile("" :: __asm__ volatile("" ::
: "memory"); : "memory");
@ -142,11 +142,11 @@ extern "C"
: "memory"); : "memory");
} }
static inline void mmioout64(uint64_t Address, uint64_t Data) static inline void mmioout64(uintptr_t Address, uintptr_t Data)
{ {
__asm__ volatile("" :: __asm__ volatile("" ::
: "memory"); : "memory");
*(volatile uint64_t *)Address = Data; *(volatile uintptr_t *)Address = Data;
__asm__ volatile("" :: __asm__ volatile("" ::
: "memory"); : "memory");
} }
@ -175,10 +175,10 @@ extern "C"
: "memory"); : "memory");
} }
static inline void mmoutq(void *Address, uint64_t Value) static inline void mmoutq(void *Address, uintptr_t Value)
{ {
__asm__ volatile("mov %1, %0" __asm__ volatile("mov %1, %0"
: "=m"((*(uint64_t *)(Address))) : "=m"((*(uintptr_t *)(Address)))
: "r"(Value) : "r"(Value)
: "memory"); : "memory");
} }
@ -213,12 +213,12 @@ extern "C"
return Result; return Result;
} }
static inline uint64_t mminq(void *Address) static inline uintptr_t mminq(void *Address)
{ {
uint64_t Result; uintptr_t Result;
__asm__ volatile("mov %1, %0" __asm__ volatile("mov %1, %0"
: "=r"(Result) : "=r"(Result)
: "m"((*(uint64_t *)(Address))) : "m"((*(uintptr_t *)(Address)))
: "memory"); : "memory");
return Result; return Result;
} }

View File

@ -33,10 +33,16 @@
static inline scarg syscall0(scarg syscall) static inline scarg syscall0(scarg syscall)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall) : "a"(syscall)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -52,10 +58,16 @@ static inline scarg syscall0(scarg syscall)
static inline scarg syscall1(scarg syscall, scarg arg1) static inline scarg syscall1(scarg syscall, scarg arg1)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1) : "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -72,10 +84,16 @@ static inline scarg syscall1(scarg syscall, scarg arg1)
static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2) static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2) : "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -93,10 +111,16 @@ static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3) static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -115,11 +139,17 @@ static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4) static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4; register scarg r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -139,12 +169,18 @@ static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5) static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4; register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5; register scarg r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -165,6 +201,7 @@ static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6) static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4; register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5; register scarg r8 __asm__("r8") = arg5;
register scarg r9 __asm__("r9") = arg6; register scarg r9 __asm__("r9") = arg6;
@ -172,6 +209,11 @@ static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }

View File

@ -71,7 +71,7 @@ typedef uint32_t uid_t;
typedef uint32_t gid_t; typedef uint32_t gid_t;
typedef int64_t clock_t; typedef int64_t clock_t;
typedef int32_t pid_t; typedef int32_t pid_t;
#elif defined(__LP32__) #else
typedef int32_t off_t; typedef int32_t off_t;
typedef long long off64_t; typedef long long off64_t;
typedef __INT32_TYPE__ mode_t; typedef __INT32_TYPE__ mode_t;

View File

@ -107,6 +107,8 @@ typedef struct
#define MESSAGE_RECV_PAYLOAD ToMsg(MSG_RECVPAYLOAD) #define MESSAGE_RECV_PAYLOAD ToMsg(MSG_RECVPAYLOAD)
#define MESSAGE_RECV_STATUS ToMsg(MSG_RECVSTATUS) #define MESSAGE_RECV_STATUS ToMsg(MSG_RECVSTATUS)
#if defined(__amd64__)
#define VM_PORT(cmd, in_ebx, isi, idi, \ #define VM_PORT(cmd, in_ebx, isi, idi, \
flags, magic, \ flags, magic, \
ax, bx, cx, dx, si, di) \ ax, bx, cx, dx, si, di) \
@ -169,6 +171,23 @@ typedef struct
"D"(idi), \ "D"(idi), \
"r"(bp) : "memory", "cc") "r"(bp) : "memory", "cc")
#elif defined(__i386__)
#define VM_PORT(cmd, in_ebx, isi, idi, \
flags, magic, \
ax, bx, cx, dx, si, di)
#define VM_PORT_HB_OUT(cmd, in_ecx, isi, idi, \
flags, \
magic, bp, ax, \
bx, cx, dx, si, di)
#define VM_PORT_HB_IN(cmd, in_ecx, isi, idi, \
flags, magic, bp, \
ax, bx, cx, dx, si, di)
#endif
/* TODO: /* TODO:
- use vmcall or vmmcall instead of "out" and "in" if available - use vmcall or vmmcall instead of "out" and "in" if available
*/ */

View File

@ -32,7 +32,7 @@ WARNCFLAG = -Wall -Wextra \
-Wfloat-equal -Wpointer-arith -Wcast-align \ -Wfloat-equal -Wpointer-arith -Wcast-align \
-Wredundant-decls -Winit-self -Wswitch-default \ -Wredundant-decls -Winit-self -Wswitch-default \
-Wstrict-overflow=5 -Wno-error=cpp -Werror \ -Wstrict-overflow=5 -Wno-error=cpp -Werror \
-Wno-unused-parameter -Wno-unused-parameter -Wno-error=format
CFLAG_STACK_PROTECTOR := -fstack-protector-all CFLAG_STACK_PROTECTOR := -fstack-protector-all

View File

@ -0,0 +1,46 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <display.hpp>
#include <bitmap.hpp>
#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(__amd64__)
#include "../../arch/amd64/cpu/gdt.hpp"
#include "../arch/amd64/cpu/apic.hpp"
#elif defined(__i386__)
#include "../../arch/i386/cpu/gdt.hpp"
#include "../arch/i386/cpu/apic.hpp"
#elif defined(__aarch64__)
#endif
#include "../../../../kernel.h"
extern void ExPrint(const char *Format, ...);
arch nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame)
{
ExPrint("\nException Frame:\n");
}

View File

@ -0,0 +1,134 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <display.hpp>
#include <bitmap.hpp>
#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>
#include "../../cpu/gdt.hpp"
#include "../../cpu/apic.hpp"
#include "../../../../kernel.h"
extern void ExPrint(const char *Format, ...);
static const char *x86PageFaultDescriptions[9] = {
"Supervisor tried to read a non-present page entry\n",
"Supervisor tried to read a page and caused a protection fault\n",
"Supervisor tried to write to a non-present page entry\n",
"Supervisor tried to write a page and caused a protection fault\n",
"User tried to read a non-present page entry\n",
"User tried to read a page and caused a protection fault\n",
"User tried to write to a non-present page entry\n",
"User tried to write a page and caused a protection fault\n",
"One or more page directory entries contain reserved bits which are set to 1.\n"};
arch nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame)
{
ExPrint("\nException Frame:\n");
ExPrint(" General Purpose Registers:\n");
ExPrint(" RAX: %#lx RBX: %#lx RCX: %#lx RDX: %#lx\n",
Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
ExPrint(" RSI: %#lx RDI: %#lx R8: %#lx R9: %#lx\n",
Frame->rsi, Frame->rdi, Frame->r8, Frame->r9);
ExPrint(" R10: %#lx R11: %#lx R12: %#lx R13: %#lx\n",
Frame->r10, Frame->r11, Frame->r12, Frame->r13);
ExPrint(" R14: %#lx R15: %#lx\n", Frame->r14, Frame->r15);
ExPrint(" Control Registers:\n");
ExPrint(" CR0: %#lx CR2: %#lx CR3: %#lx CR4: %#lx\n",
Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4);
ExPrint(" CR8: %#lx\n", Frame->cr8);
ExPrint(" Segment Registers:\n");
ExPrint(" CS: %#lx SS: %#lx DS: %#lx ES: %#lx FS: %#lx GS: %#lx\n",
Frame->cs, Frame->ss, Frame->ds, Frame->es, Frame->fs, Frame->gs);
ExPrint(" Debug Registers:\n");
ExPrint(" DR0: %#lx DR1: %#lx DR2: %#lx DR3: %#lx\n",
Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3);
ExPrint(" DR6: %#lx DR7: %#lx\n", Frame->dr6, Frame->dr7);
ExPrint(" Other:\n");
ExPrint(" INT: %#lx ERR: %#lx RIP: %#lx RFLAGS: %#lx\n",
Frame->InterruptNumber, Frame->ErrorCode,
Frame->rip, Frame->rflags.raw);
ExPrint(" RSP: %#lx RBP: %#lx\n",
Frame->rsp, Frame->rbp);
ExPrint("Exception Details:\n");
switch (Frame->InterruptNumber)
{
case CPU::x86::PageFault:
{
CPU::x64::PageFaultErrorCode pfCode = {.raw = (uint32_t)Frame->ErrorCode};
ExPrint("PFEC: P:%d W:%d U:%d R:%d I:%d PK:%d SS:%d SGX:%d\n",
pfCode.P, pfCode.W, pfCode.U, pfCode.R,
pfCode.I, pfCode.PK, pfCode.SS, pfCode.SGX);
{
Memory::Virtual vmm((Memory::PageTable *)Frame->cr3);
if (vmm.GetMapType((void *)Frame->cr2) != Memory::Virtual::FourKiB)
ExPrint("Can't display page %#lx\n", Frame->cr2);
else
{
Memory::PageTableEntry *pte = vmm.GetPTE((void *)Frame->cr2);
ExPrint("Page %#lx: P:%d W:%d U:%d G:%d CoW:%d KRsv:%d NX:%d\n",
ALIGN_DOWN(Frame->cr2, 0x1000), pte->Present, pte->ReadWrite,
pte->UserSupervisor, pte->Global, pte->CopyOnWrite,
pte->KernelReserve, pte->ExecuteDisable);
}
}
ExPrint("%s", x86PageFaultDescriptions[Frame->ErrorCode & 0b111]);
if (Frame->ErrorCode & 0x8)
ExPrint("%s", x86PageFaultDescriptions[8]);
break;
}
case CPU::x86::StackSegmentFault:
case CPU::x86::GeneralProtectionFault:
{
CPU::x64::SelectorErrorCode sCode = {.raw = Frame->ErrorCode};
ExPrint("Kernel performed an illegal operation.\n");
ExPrint("External: %d\n", sCode.External);
ExPrint("Table: %d\n", sCode.Table);
ExPrint("Index: %#x\n", sCode.Idx);
break;
}
default:
ExPrint("No additional information available for this exception.\n");
break;
}
if (!TaskManager)
return;
CPUData *core = GetCurrentCPU();
Tasking::PCB *proc = core->CurrentProcess.load();
Tasking::TCB *thread = core->CurrentThread.load();
ExPrint("Exception in %s process %s(%d) thread %s(%d)\n",
proc->Security.ExecutionMode == Tasking::User ? "user" : "kernel",
proc->Name, proc->ID,
thread->Name, thread->ID);
}

View File

@ -61,7 +61,7 @@ nsa CPUData *GetCurrentCPU()
Memory::SwapPT(KernelPageTable, thisPageTable); Memory::SwapPT(KernelPageTable, thisPageTable);
if (apic->x2APIC) if (apic->x2APIC)
CoreID = int(CPU::x64::rdmsr(CPU::x64::MSR_X2APIC_APICID)); CoreID = int(CPU::x86::rdmsr(CPU::x86::MSR_X2APIC_APICID));
else else
CoreID = apic->Read(APIC::APIC_ID) >> 24; CoreID = apic->Read(APIC::APIC_ID) >> 24;
} }
@ -151,7 +151,7 @@ namespace SMP
debug("Initializing CPU %d", lapic->APICId); debug("Initializing CPU %d", lapic->APICId);
uint8_t APIC_ID = 0; uint8_t APIC_ID = 0;
if (apic->x2APIC) if (apic->x2APIC)
APIC_ID = uint8_t(CPU::x64::rdmsr(CPU::x64::MSR_X2APIC_APICID)); APIC_ID = uint8_t(CPU::x86::rdmsr(CPU::x86::MSR_X2APIC_APICID));
else else
APIC_ID = uint8_t(apic->Read(APIC::APIC_ID) >> 24); APIC_ID = uint8_t(apic->Read(APIC::APIC_ID) >> 24);

View File

@ -22,7 +22,7 @@
namespace Memory namespace Memory
{ {
bool Virtual::Check(void *VirtualAddress, PTFlag Flag) bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type)
{ {
uintptr_t Address = (uintptr_t)VirtualAddress; uintptr_t Address = (uintptr_t)VirtualAddress;
Address &= 0xFFFFFFFFFFFFF000; Address &= 0xFFFFFFFFFFFFF000;

View File

@ -92,8 +92,8 @@ extern "C" __naked __used __no_stack_protector __aligned(16) void SystemCallHand
void InitializeSystemCalls() void InitializeSystemCalls()
{ {
wrmsr(MSR_EFER, rdmsr(MSR_EFER) | 1); CPU::x86::wrmsr(CPU::x86::MSR_EFER, CPU::x86::rdmsr(CPU::x86::MSR_EFER) | 1);
wrmsr(MSR_STAR, ((uint64_t)(GDT_KERNEL_CODE) << 32) | ((uint64_t)(GDT_KERNEL_DATA | 3) << 48)); CPU::x86::wrmsr(CPU::x86::MSR_STAR, ((uint64_t)(GDT_KERNEL_CODE) << 32) | ((uint64_t)(GDT_KERNEL_DATA | 3) << 48));
wrmsr(MSR_LSTAR, (uint64_t)SystemCallHandlerStub); CPU::x86::wrmsr(CPU::x86::MSR_LSTAR, (uint64_t)SystemCallHandlerStub);
wrmsr(MSR_SYSCALL_MASK, (uint64_t)(1 << 9)); CPU::x86::wrmsr(CPU::x86::MSR_SYSCALL_MASK, (uint64_t)(1 << 9));
} }

View File

@ -0,0 +1,172 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <signal.hpp>
#include <dumper.hpp>
#include <task.hpp>
#include <errno.h>
#include "../cpu/gdt.hpp"
/* subsystem/linux/syscall.cpp */
extern int ConvertSignalToLinux(signal_t sig);
namespace Tasking
{
bool Signal::HandleSignal(CPU::SchedulerFrame *tf, void *thread)
{
/* We don't want to do this in kernel mode */
if (tf->cs != GDT_USER_CODE)
return false;
if (Queue.empty())
return false;
debug("We have %d signals to handle", Queue.size());
SmartLock(SignalLock);
SignalInfo sigI = GetAvailableSignal(thread);
if (sigI.sig == SIGNULL)
return false;
uintptr_t _p_rsp = ((PCB *)ctx)->PageTable->Get(tf->rsp);
uint64_t paRsp = _p_rsp;
paRsp &= ~0xF; /* Align */
paRsp -= 128; /* Red zone */
/* Calculate the virtual rsp */
uintptr_t _v_rsp = tf->rsp;
_v_rsp &= ~0xF; /* Align */
_v_rsp -= 128; /* Red zone */
uint64_t *vRsp = (uint64_t *)(_v_rsp - sizeof(StackInfo));
vRsp--; /* Alignment */
vRsp--; /* Handler Address */
assert(!((uintptr_t)vRsp & 0xF));
/* Add the stack info */
StackInfo si{};
CPU::x86::fxsave(&si.fx);
si.tf = *tf;
si.GSBase = CPU::x86::rdmsr(CPU::x86::MSR_GS_BASE);
si.FSBase = CPU::x86::rdmsr(CPU::x86::MSR_FS_BASE);
si.ShadowGSBase = CPU::x86::rdmsr(CPU::x86::MSR_SHADOW_GS_BASE);
si.SignalMask = ((TCB *)thread)->Signals.Mask.to_ulong();
si.Compatibility = ((PCB *)ctx)->Info.Compatibility;
debug("gs: %#lx fs: %#lx shadow: %#lx",
si.GSBase, si.FSBase, si.ShadowGSBase);
/* Copy the stack info */
uint64_t *pRsp = (uint64_t *)(paRsp - sizeof(StackInfo));
memcpy(pRsp, &si, sizeof(StackInfo));
/* Set the handler address */
pRsp--; /* Alignment */
pRsp--;
*pRsp = uint64_t(sa[sigI.sig].sa_handler.Handler);
assert(!((uintptr_t)pRsp & 0xF));
int cSig = LinuxSig() ? ConvertSignalToLinux((signal_t)sigI.sig) : sigI.sig;
#ifdef DEBUG
DumpData("Stack Data", (void *)pRsp,
paRsp - uint64_t(pRsp));
debug("initial stack tf->rsp: %#lx after: %#lx",
tf->rsp, uint64_t(vRsp));
debug("sig: %d -> %d", sigI.sig, cSig);
#endif
tf->rsp = uint64_t(vRsp);
tf->rip = uint64_t(TrampAddr);
/* void func(int signo); */
/* void func(int signo, siginfo_t *info, void *context); */
tf->rdi = cSig;
if (sa[sigI.sig].Flags & SA_SIGINFO)
{
fixme("SA_SIGINFO not implemented");
siginfo_t *info = 0;
void *context = 0;
tf->rsi = uint64_t(info);
tf->rdx = uint64_t(context);
tf->rcx = 0;
tf->r8 = 0;
tf->r9 = 0;
}
else
{
tf->rsi = 0;
tf->rdx = 0;
tf->rcx = 0;
tf->r8 = 0;
tf->r9 = 0;
}
((TCB *)thread)->Signals.Mask = sa[sigI.sig].Mask;
assert(TrampAddr != nullptr);
return true;
}
void Signal::RestoreHandleSignal(SyscallsFrame *sf, void *thread)
{
debug("Restoring signal handler");
SmartLock(SignalLock);
gsTCB *gs = (gsTCB *)CPU::x86::rdmsr(CPU::x86::MSR_GS_BASE);
uint64_t *sp = (uint64_t *)((PCB *)ctx)->PageTable->Get(gs->TempStack);
sp++; /* Alignment */
sp++; /* Handler Address */
assert(!((uintptr_t)sp & 0xF));
StackInfo *si = (StackInfo *)sp;
assert(si != nullptr);
sf->r15 = si->tf.r15;
sf->r14 = si->tf.r14;
sf->r13 = si->tf.r13;
sf->r12 = si->tf.r12;
sf->r11 = si->tf.r11;
sf->r10 = si->tf.r10;
sf->r9 = si->tf.r9;
sf->r8 = si->tf.r8;
sf->bp = si->tf.rbp;
sf->di = si->tf.rdi;
sf->si = si->tf.rsi;
sf->dx = si->tf.rdx;
sf->cx = si->tf.rcx;
sf->bx = si->tf.rbx;
sf->ax = si->tf.rax;
sf->Flags = si->tf.rflags.raw;
sf->ReturnAddress = si->tf.rip;
gs->TempStack = (void *)si->tf.rsp;
((TCB *)thread)->Signals.Mask = si->SignalMask;
CPU::x86::fxrstor(&si->fx);
CPU::x86::wrmsr(CPU::x86::MSR_GS_BASE, si->ShadowGSBase);
CPU::x86::wrmsr(CPU::x86::MSR_FS_BASE, si->FSBase);
CPU::x86::wrmsr(CPU::x86::MSR_SHADOW_GS_BASE, si->GSBase);
debug("gs: %#lx fs: %#lx shadow: %#lx",
si->GSBase, si->FSBase, si->ShadowGSBase);
// ((PCB *)ctx)->GetContext()->Yield();
// __builtin_unreachable();
/* Return because we will restore at sysretq */
}
}

View File

@ -0,0 +1,131 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <display.hpp>
#include <bitmap.hpp>
#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>
#include "../../cpu/gdt.hpp"
#include "../../cpu/apic.hpp"
#include "../../../../kernel.h"
extern void ExPrint(const char *Format, ...);
static const char *x86PageFaultDescriptions[9] = {
"Supervisor tried to read a non-present page entry\n",
"Supervisor tried to read a page and caused a protection fault\n",
"Supervisor tried to write to a non-present page entry\n",
"Supervisor tried to write a page and caused a protection fault\n",
"User tried to read a non-present page entry\n",
"User tried to read a page and caused a protection fault\n",
"User tried to write to a non-present page entry\n",
"User tried to write a page and caused a protection fault\n",
"One or more page directory entries contain reserved bits which are set to 1.\n"};
arch nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame)
{
ExPrint("\nException Frame:\n");
ExPrint(" General Purpose Registers:\n");
ExPrint(" EAX: %#lx EBX: %#lx ECX: %#lx EDX: %#lx\n",
Frame->eax, Frame->ebx, Frame->ecx, Frame->edx);
ExPrint(" ESI: %#lx EDI: %#lx\n",
Frame->esi, Frame->edi);
ExPrint(" Control Registers:\n");
ExPrint(" CR0: %#lx CR2: %#lx CR3: %#lx CR4: %#lx\n",
Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4);
ExPrint(" CR8: %#lx\n", Frame->cr8);
ExPrint(" Segment Registers:\n");
ExPrint(" CS: %#lx SS: %#lx DS: %#lx ES: %#lx FS: %#lx GS: %#lx\n",
Frame->cs, Frame->ss, Frame->ds, Frame->es, Frame->fs, Frame->gs);
ExPrint(" Debug Registers:\n");
ExPrint(" DR0: %#lx DR1: %#lx DR2: %#lx DR3: %#lx\n",
Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3);
ExPrint(" DR6: %#lx DR7: %#lx\n", Frame->dr6, Frame->dr7);
ExPrint(" Other:\n");
ExPrint(" INT: %#lx ERR: %#lx EIP: %#lx RFLAGS: %#lx\n",
Frame->InterruptNumber, Frame->ErrorCode,
Frame->eip, Frame->eflags.raw);
ExPrint(" RSP: %#lx RBP: %#lx\n",
Frame->esp, Frame->ebp);
ExPrint("Exception Details:\n");
switch (Frame->InterruptNumber)
{
case CPU::x86::PageFault:
{
CPU::x64::PageFaultErrorCode pfCode = {.raw = (uint32_t)Frame->ErrorCode};
ExPrint("PFEC: P:%d W:%d U:%d R:%d I:%d PK:%d SS:%d SGX:%d\n",
pfCode.P, pfCode.W, pfCode.U, pfCode.R,
pfCode.I, pfCode.PK, pfCode.SS, pfCode.SGX);
{
Memory::Virtual vmm((Memory::PageTable *)Frame->cr3);
if (vmm.GetMapType((void *)Frame->cr2) != Memory::Virtual::FourKiB)
ExPrint("Can't display page %#lx\n", Frame->cr2);
else
{
Memory::PageTableEntry *pte = vmm.GetPTE((void *)Frame->cr2);
ExPrint("Page %#lx: P:%d W:%d U:%d G:%d CoW:%d KRsv:%d\n",
ALIGN_DOWN(Frame->cr2, 0x1000), pte->Present, pte->ReadWrite,
pte->UserSupervisor, pte->Global, pte->CopyOnWrite,
pte->KernelReserve);
}
}
ExPrint("%s", x86PageFaultDescriptions[Frame->ErrorCode & 0b111]);
if (Frame->ErrorCode & 0x8)
ExPrint("%s", x86PageFaultDescriptions[8]);
break;
}
case CPU::x86::StackSegmentFault:
case CPU::x86::GeneralProtectionFault:
{
CPU::x64::SelectorErrorCode sCode = {.raw = Frame->ErrorCode};
ExPrint("Kernel performed an illegal operation.\n");
ExPrint("External: %d\n", sCode.External);
ExPrint("Table: %d\n", sCode.Table);
ExPrint("Index: %#x\n", sCode.Idx);
break;
}
default:
ExPrint("No additional information available for this exception.\n");
break;
}
if (!TaskManager)
return;
CPUData *core = GetCurrentCPU();
Tasking::PCB *proc = core->CurrentProcess.load();
Tasking::TCB *thread = core->CurrentThread.load();
ExPrint("Exception in %s process %s(%d) thread %s(%d)\n",
proc->Security.ExecutionMode == Tasking::User ? "user" : "kernel",
proc->Name, proc->ID,
thread->Name, thread->ID);
}

View File

@ -55,7 +55,7 @@ nsa CPUData *GetCurrentCPU()
if (CPUEnabled.load(std::memory_order_acquire) == true) if (CPUEnabled.load(std::memory_order_acquire) == true)
{ {
if (apic->x2APIC) if (apic->x2APIC)
CoreID = int(CPU::x32::rdmsr(CPU::x32::MSR_X2APIC_APICID)); CoreID = int(CPU::x86::rdmsr(CPU::x86::MSR_X2APIC_APICID));
else else
CoreID = apic->Read(APIC::APIC_ID) >> 24; CoreID = apic->Read(APIC::APIC_ID) >> 24;
} }

View File

@ -29,7 +29,7 @@ namespace Memory
Address &= 0xFFFFF000; Address &= 0xFFFFF000;
PageMapIndexer Index = PageMapIndexer(Address); PageMapIndexer Index = PageMapIndexer(Address);
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex];
PageTableEntryPtr *PTE = nullptr; PageTableEntryPtr *PTE = nullptr;
if ((PDE->raw & Flag) > 0) if ((PDE->raw & Flag) > 0)
@ -54,7 +54,7 @@ namespace Memory
Address &= 0xFFFFF000; Address &= 0xFFFFF000;
PageMapIndexer Index = PageMapIndexer(Address); PageMapIndexer Index = PageMapIndexer(Address);
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex];
PageTableEntryPtr *PTE = nullptr; PageTableEntryPtr *PTE = nullptr;
if (PDE->Present) if (PDE->Present)
@ -80,7 +80,7 @@ namespace Memory
PageMapIndexer Index = PageMapIndexer(Address); PageMapIndexer Index = PageMapIndexer(Address);
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex];
PageTableEntryPtr *PTE = nullptr; PageTableEntryPtr *PTE = nullptr;
if (PDE->Present) if (PDE->Present)
@ -104,7 +104,7 @@ namespace Memory
Address &= 0xFFFFF000; Address &= 0xFFFFF000;
PageMapIndexer Index = PageMapIndexer(Address); PageMapIndexer Index = PageMapIndexer(Address);
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex];
if (PDE->Present) if (PDE->Present)
return PDE; return PDE;
return nullptr; return nullptr;
@ -116,7 +116,7 @@ namespace Memory
Address &= 0xFFFFF000; Address &= 0xFFFFF000;
PageMapIndexer Index = PageMapIndexer(Address); PageMapIndexer Index = PageMapIndexer(Address);
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex];
if (!PDE->Present) if (!PDE->Present)
return nullptr; return nullptr;
@ -130,7 +130,7 @@ namespace Memory
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type) void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
{ {
SmartLock(this->MemoryLock); SmartLock(this->MemoryLock);
if (unlikely(!this->Table)) if (unlikely(!this->pTable))
{ {
error("No page table"); error("No page table");
return; return;
@ -142,7 +142,7 @@ namespace Memory
// Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only // 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; uint64_t DirectoryFlags = Flags & 0x3F;
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex];
if (Type == MapType::FourMiB) if (Type == MapType::FourMiB)
{ {
PDE->raw |= (uintptr_t)Flags; PDE->raw |= (uintptr_t)Flags;
@ -191,14 +191,14 @@ namespace Memory
void Virtual::Unmap(void *VirtualAddress, MapType Type) void Virtual::Unmap(void *VirtualAddress, MapType Type)
{ {
SmartLock(this->MemoryLock); SmartLock(this->MemoryLock);
if (!this->Table) if (!this->pTable)
{ {
error("No page table"); error("No page table");
return; return;
} }
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress); PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex];
if (!PDE->Present) if (!PDE->Present)
{ {
warn("Page %#lx not present", PDE->GetAddress()); warn("Page %#lx not present", PDE->GetAddress());
@ -223,4 +223,18 @@ namespace Memory
PTEPtr->Entries[Index.PTEIndex] = PTE; PTEPtr->Entries[Index.PTEIndex] = PTE;
CPU::x32::invlpg(VirtualAddress); CPU::x32::invlpg(VirtualAddress);
} }
void Virtual::Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
{
SmartLock(this->MemoryLock);
if (unlikely(!this->pTable))
{
error("No page table");
return;
}
#warning "Remap is not properly implemented"
this->Unmap(VirtualAddress, Type);
this->Map(VirtualAddress, PhysicalAddress, Flags, Type);
}
} }

View File

@ -0,0 +1,160 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <signal.hpp>
#include <dumper.hpp>
#include <task.hpp>
#include <errno.h>
#include "../cpu/gdt.hpp"
/* subsystem/linux/syscall.cpp */
extern int ConvertSignalToLinux(signal_t sig);
namespace Tasking
{
bool Signal::HandleSignal(CPU::SchedulerFrame *tf, void *thread)
{
/* We don't want to do this in kernel mode */
if (tf->cs != GDT_USER_CODE)
return false;
if (Queue.empty())
return false;
debug("We have %d signals to handle", Queue.size());
SmartLock(SignalLock);
SignalInfo sigI = GetAvailableSignal(thread);
if (sigI.sig == SIGNULL)
return false;
uintptr_t _p_esp = ((PCB *)ctx)->PageTable->Get(tf->esp);
uint64_t paEsp = _p_esp;
paEsp &= ~0xF; /* Align */
paEsp -= 128; /* Red zone */
/* Calculate the virtual rsp */
uintptr_t _v_esp = tf->esp;
_v_esp &= ~0xF; /* Align */
_v_esp -= 128; /* Red zone */
uint64_t *vEsp = (uint64_t *)(_v_esp - sizeof(StackInfo));
vEsp--; /* Alignment */
vEsp--; /* Handler Address */
assert(!((uintptr_t)vEsp & 0xF));
/* Add the stack info */
StackInfo si{};
CPU::x86::fxsave(&si.fx);
si.tf = *tf;
si.GSBase = CPU::x86::rdmsr(CPU::x86::MSR_GS_BASE);
si.FSBase = CPU::x86::rdmsr(CPU::x86::MSR_FS_BASE);
si.ShadowGSBase = CPU::x86::rdmsr(CPU::x86::MSR_SHADOW_GS_BASE);
si.SignalMask = ((TCB *)thread)->Signals.Mask.to_ulong();
si.Compatibility = ((PCB *)ctx)->Info.Compatibility;
debug("gs: %#lx fs: %#lx shadow: %#lx",
si.GSBase, si.FSBase, si.ShadowGSBase);
/* Copy the stack info */
uint64_t *pEsp = (uint64_t *)(paEsp - sizeof(StackInfo));
memcpy(pEsp, &si, sizeof(StackInfo));
/* Set the handler address */
pEsp--; /* Alignment */
pEsp--;
*pEsp = uint64_t(sa[sigI.sig].sa_handler.Handler);
assert(!((uintptr_t)pEsp & 0xF));
int cSig = LinuxSig() ? ConvertSignalToLinux((signal_t)sigI.sig) : sigI.sig;
#ifdef DEBUG
DumpData("Stack Data", (void *)pEsp,
paEsp - uint64_t(pEsp));
debug("initial stack tf->rsp: %#lx after: %#lx",
tf->esp, uint64_t(vEsp));
debug("sig: %d -> %d", sigI.sig, cSig);
#endif
tf->esp = uint64_t(vEsp);
tf->eip = uint64_t(TrampAddr);
/* void func(int signo); */
/* void func(int signo, siginfo_t *info, void *context); */
tf->edi = cSig;
if (sa[sigI.sig].Flags & SA_SIGINFO)
{
fixme("SA_SIGINFO not implemented");
siginfo_t *info = 0;
void *context = 0;
tf->eax = uint64_t(info);
tf->edx = uint64_t(context);
tf->ecx = 0;
}
else
{
tf->eax = 0;
tf->edx = 0;
tf->ecx = 0;
}
((TCB *)thread)->Signals.Mask = sa[sigI.sig].Mask;
assert(TrampAddr != nullptr);
return true;
}
void Signal::RestoreHandleSignal(SyscallsFrame *sf, void *thread)
{
debug("Restoring signal handler");
SmartLock(SignalLock);
gsTCB *gs = (gsTCB *)CPU::x86::rdmsr(CPU::x86::MSR_GS_BASE);
uint64_t *sp = (uint64_t *)((PCB *)ctx)->PageTable->Get(gs->TempStack);
sp++; /* Alignment */
sp++; /* Handler Address */
assert(!((uintptr_t)sp & 0xF));
StackInfo *si = (StackInfo *)sp;
assert(si != nullptr);
sf->bp = si->tf.ebp;
sf->di = si->tf.edi;
sf->si = si->tf.esi;
sf->dx = si->tf.edx;
sf->cx = si->tf.ecx;
sf->bx = si->tf.ebx;
sf->ax = si->tf.eax;
sf->Flags = si->tf.eflags.raw;
sf->ReturnAddress = si->tf.eip;
gs->TempStack = (void *)si->tf.esp;
((TCB *)thread)->Signals.Mask = si->SignalMask;
CPU::x86::fxrstor(&si->fx);
CPU::x86::wrmsr(CPU::x86::MSR_GS_BASE, si->ShadowGSBase);
CPU::x86::wrmsr(CPU::x86::MSR_FS_BASE, si->FSBase);
CPU::x86::wrmsr(CPU::x86::MSR_SHADOW_GS_BASE, si->GSBase);
debug("gs: %#lx fs: %#lx shadow: %#lx",
si->GSBase, si->FSBase, si->ShadowGSBase);
// ((PCB *)ctx)->GetContext()->Yield();
// __builtin_unreachable();
/* Return because we will restore at sysretq */
}
}

View File

@ -0,0 +1,38 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
.code64
.global _sig_native_trampoline_start
_sig_native_trampoline_start:
int $0x3
.global _sig_native_trampoline_end
_sig_native_trampoline_end:
.global _sig_linux_trampoline_start
_sig_linux_trampoline_start:
movq %rsp, %rbp
movq (%rbp), %rax
call *%rax
mov %rbp, %rsp
/* rt_sigreturn = 15 */
movq $15, %rax
syscall
.global _sig_linux_trampoline_end
_sig_linux_trampoline_end:

View File

@ -313,7 +313,7 @@ namespace CPU
CoreData->Data.FPU.mxcsr = 0b0001111110000000; CoreData->Data.FPU.mxcsr = 0b0001111110000000;
CoreData->Data.FPU.mxcsrmask = 0b1111111110111111; CoreData->Data.FPU.mxcsrmask = 0b1111111110111111;
CoreData->Data.FPU.fcw = 0b0000001100111111; CoreData->Data.FPU.fcw = 0b0000001100111111;
fxrstor(&CoreData->Data.FPU); CPU::x86::fxrstor(&CoreData->Data.FPU);
SSEEnableAfter = true; SSEEnableAfter = true;
} }
@ -378,7 +378,7 @@ namespace CPU
debug("Updated CR4."); debug("Updated CR4.");
debug("Enabling PAT support..."); debug("Enabling PAT support...");
wrmsr(MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16)); CPU::x86::wrmsr(CPU::x86::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16));
if (!BSP++) if (!BSP++)
trace("Features for BSP initialized."); trace("Features for BSP initialized.");
if (SSEEnableAfter) if (SSEEnableAfter)

View File

@ -245,8 +245,8 @@ namespace Driver
debug("Driver %s has entry point %#lx and base %#lx", debug("Driver %s has entry point %#lx and base %#lx",
File->Name.c_str(), Drv.EntryPoint, Drv.BaseAddress); File->Name.c_str(), Drv.EntryPoint, Drv.BaseAddress);
Elf64_Shdr sht_strtab{}; Elf_Shdr sht_strtab{};
Elf64_Shdr sht_symtab{}; Elf_Shdr sht_symtab{};
Elf_Shdr shstrtab{}; Elf_Shdr shstrtab{};
Elf_Shdr shdr{}; Elf_Shdr shdr{};
__DriverInfo driverInfo{}; __DriverInfo driverInfo{};

View File

@ -114,13 +114,13 @@ namespace Interrupts
void Initialize(int Core) void Initialize(int Core)
{ {
#if defined(__amd64__) #if defined(__amd64__) || defined(__i386__)
GlobalDescriptorTable::Init(Core); GlobalDescriptorTable::Init(Core);
InterruptDescriptorTable::Init(Core); InterruptDescriptorTable::Init(Core);
CPUData *CoreData = GetCPU(Core); CPUData *CoreData = GetCPU(Core);
CoreData->Checksum = CPU_DATA_CHECKSUM; CoreData->Checksum = CPU_DATA_CHECKSUM;
CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, (uint64_t)CoreData); CPU::x86::wrmsr(CPU::x86::MSR_GS_BASE, (uint64_t)CoreData);
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData); CPU::x86::wrmsr(CPU::x86::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core; CoreData->ID = Core;
CoreData->IsActive = true; CoreData->IsActive = true;
CoreData->Stack = (uintptr_t)StackManager.Allocate(STACK_SIZE) + STACK_SIZE; CoreData->Stack = (uintptr_t)StackManager.Allocate(STACK_SIZE) + STACK_SIZE;
@ -133,24 +133,6 @@ namespace Interrupts
debug("Stack for core %d is %#lx (Address: %#lx)", debug("Stack for core %d is %#lx (Address: %#lx)",
Core, CoreData->Stack, CoreData->Stack - STACK_SIZE); Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
InitializeSystemCalls(); InitializeSystemCalls();
#elif defined(__i386__)
GlobalDescriptorTable::Init(Core);
InterruptDescriptorTable::Init(Core);
CPUData *CoreData = GetCPU(Core);
CoreData->Checksum = CPU_DATA_CHECKSUM;
CPU::x32::wrmsr(CPU::x32::MSR_GS_BASE, (uint64_t)CoreData);
CPU::x32::wrmsr(CPU::x32::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core;
CoreData->IsActive = true;
CoreData->Stack = (uintptr_t)StackManager.Allocate(STACK_SIZE) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{
KPrint("CPU %d checksum mismatch! %x != %x",
Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
CPU::Stop();
}
debug("Stack for core %d is %#lx (Address: %#lx)",
Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
#elif defined(__aarch64__) #elif defined(__aarch64__)
warn("aarch64 is not supported yet"); warn("aarch64 is not supported yet");
#endif #endif

View File

@ -551,7 +551,9 @@ struct heap_t
}; };
/* Keep in sync with heap_t inside rpmalloc_compat.cpp */ /* Keep in sync with heap_t inside rpmalloc_compat.cpp */
#ifndef __i386__
static_assert(sizeof(heap_t) == 56408, "heap_t size mismatch"); static_assert(sizeof(heap_t) == 56408, "heap_t size mismatch");
#endif // __i386__
// Size class for defining a block size bucket // Size class for defining a block size bucket
struct size_class_t struct size_class_t

View File

@ -73,7 +73,7 @@ namespace Memory
} }
} }
#else #else
#error "PageTable::Fork() not implemented for other architectures" #warning "PageTable::Fork() not implemented for other architectures"
#endif #endif
debug("Forked page table %#lx to %#lx", this, NewTable); debug("Forked page table %#lx to %#lx", this, NewTable);

View File

@ -236,7 +236,9 @@ namespace Memory
assert(pte->Present == true); assert(pte->Present == true);
pte->ReadWrite = sr.Write; pte->ReadWrite = sr.Write;
pte->UserSupervisor = sr.Read; pte->UserSupervisor = sr.Read;
#if defined(__amd64__)
pte->ExecuteDisable = sr.Exec; pte->ExecuteDisable = sr.Exec;
#endif
pte->CopyOnWrite = false; pte->CopyOnWrite = false;
debug("PFA %#lx is CoW (pt %#lx, flags %#lx)", debug("PFA %#lx is CoW (pt %#lx, flags %#lx)",

View File

@ -100,7 +100,7 @@ nsa void HaltAllCores()
if (SMP::CPUCores <= 1) if (SMP::CPUCores <= 1)
return; return;
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__)
if (Interrupts::apic[0] == nullptr) if (Interrupts::apic[0] == nullptr)
return; return;

View File

@ -140,9 +140,9 @@ nsa CrashXHCIKeyboardDriver::CrashXHCIKeyboardDriver(PCIDevice xhci)
debug("IO %d 64-BIT %d", BAR[0] & 0x1, BAR[0] & 0x4); debug("IO %d 64-BIT %d", BAR[0] & 0x1, BAR[0] & 0x4);
uintptr_t baseAddress = BAR[0]; uint64_t baseAddress = BAR[0];
if (BAR[0] & 0x4) if (BAR[0] & 0x4)
baseAddress |= (uintptr_t)BAR[1] << 32; baseAddress |= (uint64_t)BAR[1] << 32;
if (baseAddress & 0x1) if (baseAddress & 0x1)
baseAddress &= 0xFFFFFFFFFFFFFFFC; baseAddress &= 0xFFFFFFFFFFFFFFFC;
@ -158,7 +158,7 @@ nsa CrashXHCIKeyboardDriver::CrashXHCIKeyboardDriver(PCIDevice xhci)
runtime = (XHCIruntime *)(baseAddress + (caps->RTSOFF & ~0x1F)); runtime = (XHCIruntime *)(baseAddress + (caps->RTSOFF & ~0x1F));
doorbell = (XHCIdoorbell *)(baseAddress + (caps->DBOFF & ~0x3)); doorbell = (XHCIdoorbell *)(baseAddress + (caps->DBOFF & ~0x3));
uint16_t exCapOffset = caps->HCCPARAMS1.xHCIExtendedCapacitiesPointer << 2; uint16_t exCapOffset = caps->HCCPARAMS1.xHCIExtendedCapacitiesPointer << 2;
ExtendedCaps = (uintptr_t)caps + exCapOffset; ExtendedCaps = (uint64_t)caps + exCapOffset;
debug("ExtendedCaps: %#lx (%#lx + %#lx)", ExtendedCaps, caps, exCapOffset); debug("ExtendedCaps: %#lx (%#lx + %#lx)", ExtendedCaps, caps, exCapOffset);
#pragma GCC diagnostic push #pragma GCC diagnostic push

View File

@ -95,17 +95,6 @@ x86ExceptionName x86Exceptions[] = {
/*31*/ {"#r7", "Reserved", "Reserved"}, /*31*/ {"#r7", "Reserved", "Reserved"},
}; };
static const char *x86PageFaultDescriptions[9] = {
"Supervisor tried to read a non-present page entry\n",
"Supervisor tried to read a page and caused a protection fault\n",
"Supervisor tried to write to a non-present page entry\n",
"Supervisor tried to write a page and caused a protection fault\n",
"User tried to read a non-present page entry\n",
"User tried to read a page and caused a protection fault\n",
"User tried to write to a non-present page entry\n",
"User tried to write a page and caused a protection fault\n",
"One or more page directory entries contain reserved bits which are set to 1.\n"};
int ActiveScreen = 0; int ActiveScreen = 0;
char __modSym[20]; char __modSym[20];
@ -139,9 +128,19 @@ nsa const char *ExGetKSymbolByAddress(uintptr_t Address)
nsa const char *ExGetKSymbol(CPU::ExceptionFrame *Frame) nsa const char *ExGetKSymbol(CPU::ExceptionFrame *Frame)
{ {
#if defined(__amd64__)
if (Frame->rip < (uintptr_t)&_kernel_start && if (Frame->rip < (uintptr_t)&_kernel_start &&
Frame->rip > (uintptr_t)&_kernel_end) Frame->rip > (uintptr_t)&_kernel_end)
return "<OUTSIDE KERNEL>"; return "<OUTSIDE KERNEL>";
#elif defined(__i386__)
if (Frame->eip < (uintptr_t)&_kernel_start &&
Frame->eip > (uintptr_t)&_kernel_end)
return "<OUTSIDE KERNEL>";
#elif defined(__aarch64__)
if (Frame->pc < (uintptr_t)&_kernel_start &&
Frame->pc > (uintptr_t)&_kernel_end)
return "<OUTSIDE KERNEL>";
#endif
#if defined(__amd64__) #if defined(__amd64__)
return ExGetKSymbolByAddress(Frame->rip); return ExGetKSymbolByAddress(Frame->rip);
@ -338,94 +337,7 @@ nsa void DisplayMainScreen(CPU::ExceptionFrame *Frame)
ExPrint("\nUse command 'diag' to create a diagnostic report.\n"); ExPrint("\nUse command 'diag' to create a diagnostic report.\n");
} }
nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame) arch void DisplayDetailsScreen(CPU::ExceptionFrame *Frame);
{
ExPrint("\nException Frame:\n");
ExPrint(" General Purpose Registers:\n");
ExPrint(" RAX: %#lx RBX: %#lx RCX: %#lx RDX: %#lx\n",
Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
ExPrint(" RSI: %#lx RDI: %#lx R8: %#lx R9: %#lx\n",
Frame->rsi, Frame->rdi, Frame->r8, Frame->r9);
ExPrint(" R10: %#lx R11: %#lx R12: %#lx R13: %#lx\n",
Frame->r10, Frame->r11, Frame->r12, Frame->r13);
ExPrint(" R14: %#lx R15: %#lx\n", Frame->r14, Frame->r15);
ExPrint(" Control Registers:\n");
ExPrint(" CR0: %#lx CR2: %#lx CR3: %#lx CR4: %#lx\n",
Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4);
ExPrint(" CR8: %#lx\n", Frame->cr8);
ExPrint(" Segment Registers:\n");
ExPrint(" CS: %#lx SS: %#lx DS: %#lx ES: %#lx FS: %#lx GS: %#lx\n",
Frame->cs, Frame->ss, Frame->ds, Frame->es, Frame->fs, Frame->gs);
ExPrint(" Debug Registers:\n");
ExPrint(" DR0: %#lx DR1: %#lx DR2: %#lx DR3: %#lx\n",
Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3);
ExPrint(" DR6: %#lx DR7: %#lx\n", Frame->dr6, Frame->dr7);
ExPrint(" Other:\n");
ExPrint(" INT: %#lx ERR: %#lx RIP: %#lx RFLAGS: %#lx\n",
Frame->InterruptNumber, Frame->ErrorCode,
Frame->rip, Frame->rflags.raw);
ExPrint(" RSP: %#lx RBP: %#lx\n",
Frame->rsp, Frame->rbp);
ExPrint("Exception Details:\n");
switch (Frame->InterruptNumber)
{
case CPU::x86::PageFault:
{
CPU::x64::PageFaultErrorCode pfCode = {.raw = (uint32_t)Frame->ErrorCode};
ExPrint("PFEC: P:%d W:%d U:%d R:%d I:%d PK:%d SS:%d SGX:%d\n",
pfCode.P, pfCode.W, pfCode.U, pfCode.R,
pfCode.I, pfCode.PK, pfCode.SS, pfCode.SGX);
{
Memory::Virtual vmm((Memory::PageTable *)Frame->cr3);
if (vmm.GetMapType((void *)Frame->cr2) != Memory::Virtual::FourKiB)
ExPrint("Can't display page %#lx\n", Frame->cr2);
else
{
Memory::PageTableEntry *pte = vmm.GetPTE((void *)Frame->cr2);
ExPrint("Page %#lx: P:%d W:%d U:%d G:%d CoW:%d KRsv:%d NX:%d\n",
ALIGN_DOWN(Frame->cr2, 0x1000), pte->Present, pte->ReadWrite,
pte->UserSupervisor, pte->Global, pte->CopyOnWrite,
pte->KernelReserve, pte->ExecuteDisable);
}
}
ExPrint("%s", x86PageFaultDescriptions[Frame->ErrorCode & 0b111]);
if (Frame->ErrorCode & 0x8)
ExPrint("%s", x86PageFaultDescriptions[8]);
break;
}
case CPU::x86::StackSegmentFault:
case CPU::x86::GeneralProtectionFault:
{
CPU::x64::SelectorErrorCode sCode = {.raw = Frame->ErrorCode};
ExPrint("Kernel performed an illegal operation.\n");
ExPrint("External: %d\n", sCode.External);
ExPrint("Table: %d\n", sCode.Table);
ExPrint("Index: %#x\n", sCode.Idx);
break;
}
default:
ExPrint("No additional information available for this exception.\n");
break;
}
if (!TaskManager)
return;
CPUData *core = GetCurrentCPU();
Tasking::PCB *proc = core->CurrentProcess.load();
Tasking::TCB *thread = core->CurrentThread.load();
ExPrint("Exception in %s process %s(%d) thread %s(%d)\n",
proc->Security.ExecutionMode == Tasking::User ? "user" : "kernel",
proc->Name, proc->ID,
thread->Name, thread->ID);
}
nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame) nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
{ {

View File

@ -23,13 +23,13 @@
#include <cpu/x86/cpuid_intel.hpp> #include <cpu/x86/cpuid_intel.hpp>
#include <cpu/x86/cpuid_amd.hpp> #include <cpu/x86/cpuid_amd.hpp>
#include <cpu/x86/x32/cr.hpp> #include <cpu/x86/x32/cr.hpp>
#include <cpu/x86/x32/msr.hpp>
#include <cpu/x86/x64/cr.hpp> #include <cpu/x86/x64/cr.hpp>
#include <cpu/x86/x64/msr.hpp>
#include <cpu/x86/exceptions.hpp> #include <cpu/x86/exceptions.hpp>
#include <cpu/x86/interrupts.hpp> #include <cpu/x86/interrupts.hpp>
#include <cpu/signatures.hpp> #include <cpu/signatures.hpp>
#include <cpu/x86/msr.hpp>
#include <cpu/membar.hpp> #include <cpu/membar.hpp>
#include <assert.h>
#include <cstring> #include <cstring>
/** /**
@ -211,6 +211,41 @@ namespace CPU
/** @brief Get CPU counter value. */ /** @brief Get CPU counter value. */
uint64_t Counter(); uint64_t Counter();
namespace x86
{
nsa static inline void fxsave(void *FXSaveArea)
{
assert(FXSaveArea != nullptr);
#if defined(__amd64__)
asmv("fxsaveq (%0)"
:
: "r"(FXSaveArea)
: "memory");
#elif defined(__i386__)
asmv("fxsave (%0)"
:
: "r"(FXSaveArea)
: "memory");
#endif
}
nsa static inline void fxrstor(void *FXRstorArea)
{
assert(FXRstorArea != nullptr);
#if defined(__amd64__)
asmv("fxrstorq (%0)"
:
: "r"(FXRstorArea)
: "memory");
#elif defined(__i386__)
asmv("fxrstor (%0)"
:
: "r"(FXRstorArea)
: "memory");
#endif
}
}
namespace x32 namespace x32
{ {
/** /**
@ -294,24 +329,83 @@ namespace CPU
struct TrapFrame struct TrapFrame
{ {
uint32_t edi; // Destination index for string operations uint32_t edi; /* Destination index for string operations */
uint32_t esi; // Source index for string operations uint32_t esi; /* Source index for string operations */
uint32_t ebp; // Base Pointer (meant for stack frames) uint32_t ebp; /* Base Pointer (meant for stack frames) */
uint32_t esp; // Stack Pointer uint32_t ebx; /* Base */
uint32_t ebx; // Base uint32_t edx; /* Data (commonly extends the A register) */
uint32_t edx; // Data (commonly extends the A register) uint32_t ecx; /* Counter */
uint32_t ecx; // Counter uint32_t eax; /* Accumulator */
uint32_t eax; // Accumulator
uint32_t InterruptNumber; // Interrupt Number uint32_t InterruptNumber; /* Interrupt Number */
uint32_t ErrorCode; // Error code uint32_t ErrorCode; /* Error code */
uint32_t eip; // Instruction Pointer uint32_t eip; /* Instruction Pointer */
uint32_t cs; // Code Segment uint32_t cs; /* Code Segment */
EFLAGS eflags; // Register Flags EFLAGS eflags; /* Register Flags */
uint32_t esp; /* Stack Pointer */
uint32_t ss; /* Stack Segment */
};
uint32_t r3_esp; // Stack Pointer struct SchedulerFrame
uint32_t r3_ss; // Stack Segment {
uint32_t ppt; /* Process Page Table */
uint32_t opt; /* Original Page Table */
uint32_t ebp; /* Base Pointer (meant for stack frames) */
uint32_t edi; /* Destination index for string operations */
uint32_t esi; /* Source index for string operations */
uint32_t edx; /* Data (commonly extends the A register) */
uint32_t ecx; /* Counter */
uint32_t ebx; /* Base */
uint32_t eax; /* Accumulator */
uint32_t InterruptNumber; /* Interrupt Number */
uint32_t ErrorCode; /* Error code */
uint32_t eip; /* Instruction Pointer */
uint32_t cs; /* Code Segment */
EFLAGS eflags; /* Register Flags */
uint32_t esp; /* Stack Pointer */
uint32_t ss; /* Stack Segment */
};
struct ExceptionFrame
{
uint32_t cr0; /* Control Register 0 (system control) */
uint32_t cr2; /* Control Register 2 (page fault linear address) */
uint32_t cr3; /* Control Register 3 (page directory base) */
uint32_t cr4; /* Control Register 4 (system control) */
uint32_t cr8; /* Control Register 8 (task priority) */
uint32_t dr0; /* Debug Register */
uint32_t dr1; /* Debug Register */
uint32_t dr2; /* Debug Register */
uint32_t dr3; /* Debug Register */
uint32_t dr6; /* Debug Register */
uint32_t dr7; /* Debug Register */
uint32_t gs; /* General purpose */
uint32_t fs; /* General purpose */
uint32_t es; /* Extra Segment */
uint32_t ds; /* Data Segment */
uint32_t ebp; /* Base Pointer (meant for stack frames) */
uint32_t edi; /* Destination index for string operations */
uint32_t esi; /* Source index for string operations */
uint32_t edx; /* Data (commonly extends the A register) */
uint32_t ecx; /* Counter */
uint32_t ebx; /* Base */
uint32_t eax; /* Accumulator */
uint32_t InterruptNumber; /* Interrupt Number */
uint32_t ErrorCode; /* Error code */
uint32_t eip; /* Instruction Pointer */
uint32_t cs; /* Code Segment */
EFLAGS eflags; /* Register Flags */
uint32_t esp; /* Stack Pointer */
uint32_t ss; /* Stack Segment */
}; };
typedef union DR6 typedef union DR6
@ -319,27 +413,27 @@ namespace CPU
struct struct
{ {
/** @brief Breakpoint #0 Condition Detected */ /** @brief Breakpoint #0 Condition Detected */
uint64_t B0 : 1; uint32_t B0 : 1;
/** @brief Breakpoint #1 Condition Detected */ /** @brief Breakpoint #1 Condition Detected */
uint64_t B1 : 1; uint32_t B1 : 1;
/** @brief Breakpoint #2 Condition Detected */ /** @brief Breakpoint #2 Condition Detected */
uint64_t B2 : 1; uint32_t B2 : 1;
/** @brief Breakpoint #3 Condition Detected */ /** @brief Breakpoint #3 Condition Detected */
uint64_t B3 : 1; uint32_t B3 : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved0 : 8; uint32_t Reserved0 : 8;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved1 : 1; uint32_t Reserved1 : 1;
/** @brief Breakpoint Debug Access Detected */ /** @brief Breakpoint Debug Access Detected */
uint64_t BD : 1; uint32_t BD : 1;
/** @brief Breakpoint Single Step */ /** @brief Breakpoint Single Step */
uint64_t BS : 1; uint32_t BS : 1;
/** @brief Breakpoint Task Switch */ /** @brief Breakpoint Task Switch */
uint64_t BT : 1; uint32_t BT : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved2 : 15; uint32_t Reserved2 : 15;
}; };
uint64_t raw; uint32_t raw;
} DR6; } DR6;
typedef union DR7 typedef union DR7
@ -978,32 +1072,6 @@ namespace CPU
cpuid(0x0, &eax, &ebx, &ecx, &edx); cpuid(0x0, &eax, &ebx, &ecx, &edx);
return eax; return eax;
} }
nsa static inline void fxsave(void *FXSaveArea)
{
#ifdef __amd64__
if (!FXSaveArea || FXSaveArea >= (char *)0xfffffffffffff000)
return;
asmv("fxsaveq (%0)"
:
: "r"(FXSaveArea)
: "memory");
#endif
}
nsa static inline void fxrstor(void *FXRstorArea)
{
#ifdef __amd64__
if (!FXRstorArea || FXRstorArea >= (char *)0xfffffffffffff000)
return;
asmv("fxrstorq (%0)"
:
: "r"(FXRstorArea)
: "memory");
#endif
}
} }
namespace aarch64 namespace aarch64

View File

@ -1,18 +1,18 @@
/* /*
This file is part of Fennix Kernel. This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version. the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful, Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>. along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef __FENNIX_KERNEL_CPU_x64_MSR_H__ #ifndef __FENNIX_KERNEL_CPU_x64_MSR_H__
@ -22,7 +22,7 @@
namespace CPU namespace CPU
{ {
namespace x64 namespace x86
{ {
enum MSRID enum MSRID
{ {
@ -420,6 +420,25 @@ namespace CPU
: "c"(msr), "a"(Low), "d"(High) : "c"(msr), "a"(Low), "d"(High)
: "memory"); : "memory");
} }
#elif defined(__i386__)
nsa static inline uint64_t rdmsr(uint32_t msr)
{
uint32_t Low, High;
asmv("rdmsr"
: "=a"(Low), "=d"(High)
: "c"(msr)
: "memory");
return ((uint64_t)Low) | (((uint64_t)High) << 32);
}
nsa static inline void wrmsr(uint32_t msr, uint64_t Value)
{
uint32_t Low = (uint32_t)Value, High = (uint32_t)(Value >> 32);
asmv("wrmsr"
:
: "c"(msr), "a"(Low), "d"(High)
: "memory");
}
#endif #endif
} }
} }

View File

@ -174,14 +174,6 @@ namespace CPU
return (CR4){.raw = Result}; return (CR4){.raw = Result};
} }
nsa static inline CR8 readcr8()
{
uint32_t Result = 0;
asmv("mov %%cr8, %[Result]"
: [Result] "=q"(Result));
return (CR8){.raw = Result};
}
nsa static inline void writecr0(CR0 ControlRegister) nsa static inline void writecr0(CR0 ControlRegister)
{ {
asmv("mov %[ControlRegister], %%cr0" asmv("mov %[ControlRegister], %%cr0"
@ -213,14 +205,6 @@ namespace CPU
: [ControlRegister] "q"(ControlRegister.raw) : [ControlRegister] "q"(ControlRegister.raw)
: "memory"); : "memory");
} }
nsa static inline void writecr8(CR8 ControlRegister)
{
asmv("mov %[ControlRegister], %%cr8"
:
: [ControlRegister] "q"(ControlRegister.raw)
: "memory");
}
#endif #endif
} }
} }

View File

@ -1,426 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_CPU_x32_MSR_H__
#define __FENNIX_KERNEL_CPU_x32_MSR_H__
#include <types.h>
namespace CPU
{
namespace x32
{
enum MSRID
{
MSR_MONITOR_FILTER_SIZE = 0x6,
MSR_TIME_STAMP_COUNTER = 0x10,
MSR_PLATFORM_ID = 0x17,
MSR_APIC_BASE = 0x1B,
MSR_FEATURE_CONTROL = 0x3A,
MSR_TSC_ADJUST = 0x3B,
MSR_SPEC_CTRL = 0x48,
MSR_PRED_CMD = 0x49,
MSR_BIOS_UPDT_TRIG = 0x79,
MSR_BIOS_SIGN_ID = 0x8B,
MSR_SGXLEPUBKEYHASH0 = 0x8C,
MSR_SGXLEPUBKEYHASH1 = 0x8D,
MSR_SGXLEPUBKEYHASH2 = 0x8E,
MSR_SGXLEPUBKEYHASH3 = 0x8F,
MSR_SMM_MONITOR_CTL = 0x9B,
MSR_SMBASE = 0x9E,
MSR_PMC0 = 0xC1,
MSR_PMC1 = 0xC2,
MSR_PMC2 = 0xC3,
MSR_PMC3 = 0xC4,
MSR_PMC4 = 0xC5,
MSR_PMC5 = 0xC6,
MSR_PMC6 = 0xC7,
MSR_PMC7 = 0xC8,
MSR_UMWAIT_CONTROL = 0xE1,
MSR_MPERF = 0xE7,
MSR_APERF = 0xE8,
MSR_MTRRCAP = 0xFE,
MSR_ARCH_CAPABILITIES = 0x10A,
MSR_FLUSH_CMD = 0x10B,
MSR_SYSENTER_CS = 0x17A,
MSR_SYSENTER_ESP = 0x175,
MSR_SYSENTER_EIP = 0x176,
MSR_MCG_CAP = 0x179,
MSR_MCG_STATUS = 0x17A,
MSR_MCG_CTL = 0x17B,
MSR_PERFEVTSEL0 = 0x186,
MSR_PERFEVTSEL1 = 0x187,
MSR_PERFEVTSEL2 = 0x188,
MSR_PERFEVTSEL3 = 0x189,
MSR_PERF_STATUS = 0x198,
MSR_PERF_CTL = 0x199,
MSR_CLOCK_MODULATION = 0x19A,
MSR_THERM_INTERRUPT = 0x19B,
MSR_THERM_STATUS = 0x19C,
MSR_MISC_ENABLE = 0x1A0,
MSR_ENERGY_PERF_BIAS = 0x1B0,
MSR_PACKAGE_THERM_STATUS = 0x1B1,
MSR_PACKAGE_THERM_INTERRUPT = 0x1B2,
MSR_DEBUGCTL = 0x1D9,
MSR_SMRR_PHYSBASE = 0x1F2,
MSR_SMRR_PHYSMASK = 0x1F3,
MSR_PLATFORM_DCA_CAP = 0x1F8,
MSR_CPU_DCA_CAP = 0x1F9,
MSR_DCA_0_CAP = 0x1FA,
MSR_MTRR_PHYSBASE0 = 0x200,
MSR_MTRR_PHYSMASK0 = 0x201,
MSR_MTRR_PHYSBASE1 = 0x202,
MSR_MTRR_PHYSMASK1 = 0x203,
MSR_MTRR_PHYSBASE2 = 0x204,
MSR_MTRR_PHYSMASK2 = 0x205,
MSR_MTRR_PHYSBASE3 = 0x206,
MSR_MTRR_PHYSMASK3 = 0x207,
MSR_MTRR_PHYSBASE4 = 0x208,
MSR_MTRR_PHYSMASK4 = 0x209,
MSR_MTRR_PHYSBASE5 = 0x20A,
MSR_MTRR_PHYSMASK5 = 0x20B,
MSR_MTRR_PHYSBASE6 = 0x20C,
MSR_MTRR_PHYSMASK6 = 0x20D,
MSR_MTRR_PHYSBASE7 = 0x20E,
MSR_MTRR_PHYSMASK7 = 0x20F,
MSR_MTRR_PHYSBASE8 = 0x210,
MSR_MTRR_PHYSMASK8 = 0x211,
MSR_MTRR_PHYSBASE9 = 0x212,
MSR_MTRR_PHYSMASK9 = 0x213,
MSR_MTRR_FIX64K_00000 = 0x250,
MSR_MTRR_FIX16K_80000 = 0x258,
MSR_MTRR_FIX16K_A0000 = 0x259,
MSR_MTRR_FIX4K_C0000 = 0x268,
MSR_MTRR_FIX4K_C8000 = 0x269,
MSR_MTRR_FIX4K_D0000 = 0x26A,
MSR_MTRR_FIX4K_D8000 = 0x26B,
MSR_MTRR_FIX4K_E0000 = 0x26C,
MSR_MTRR_FIX4K_E8000 = 0x26D,
MSR_MTRR_FIX4K_F0000 = 0x26E,
MSR_MTRR_FIX4K_F8000 = 0x26F,
MSR_PAT = 0x277,
MSR_MC0_CTL2 = 0x280,
MSR_MC1_CTL2 = 0x281,
MSR_MC2_CTL2 = 0x282,
MSR_MC3_CTL2 = 0x283,
MSR_MC4_CTL2 = 0x284,
MSR_MC5_CTL2 = 0x285,
MSR_MC6_CTL2 = 0x286,
MSR_MC7_CTL2 = 0x287,
MSR_MC8_CTL2 = 0x288,
MSR_MC9_CTL2 = 0x289,
MSR_MC10_CTL2 = 0x28A,
MSR_MC11_CTL2 = 0x28B,
MSR_MC12_CTL2 = 0x28C,
MSR_MC13_CTL2 = 0x28D,
MSR_MC14_CTL2 = 0x28E,
MSR_MC15_CTL2 = 0x28F,
MSR_MC16_CTL2 = 0x290,
MSR_MC17_CTL2 = 0x291,
MSR_MC18_CTL2 = 0x292,
MSR_MC19_CTL2 = 0x293,
MSR_MC20_CTL2 = 0x294,
MSR_MC21_CTL2 = 0x295,
MSR_MC22_CTL2 = 0x296,
MSR_MC23_CTL2 = 0x297,
MSR_MC24_CTL2 = 0x298,
MSR_MC25_CTL2 = 0x299,
MSR_MC26_CTL2 = 0x29A,
MSR_MC27_CTL2 = 0x29B,
MSR_MC28_CTL2 = 0x29C,
MSR_MC29_CTL2 = 0x29D,
MSR_MC30_CTL2 = 0x29E,
MSR_MC31_CTL2 = 0x29F,
MSR_MTRR_DEF_TYPE = 0x2FF,
MSR_FIXED_CTR0 = 0x309,
MSR_FIXED_CTR1 = 0x30A,
MSR_FIXED_CTR2 = 0x30B,
MSR_PERF_CAPABILITIES = 0x345,
MSR_FIXED_CTR_CTRL = 0x38D,
MSR_PERF_GLOBAL_STATUS = 0x38E,
MSR_PERF_GLOBAL_CTRL = 0x38F,
MSR_PERF_GLOBAL_STATUS_RESET = 0x390,
MSR_PERF_GLOBAL_STATUS_SET = 0x391,
MSR_PERF_GLOBAL_INUSE = 0x392,
MSR_PEBS_ENABLE = 0x3F1,
MSR_MC0_CTL = 0x400,
MSR_MC0_STATUS = 0x401,
MSR_MC0_ADDR = 0x402,
MSR_MC0_MISC = 0x403,
MSR_MC1_CTL = 0x404,
MSR_MC1_STATUS = 0x405,
MSR_MC1_ADDR = 0x406,
MSR_MC1_MISC = 0x407,
MSR_MC2_CTL = 0x408,
MSR_MC2_STATUS = 0x409,
MSR_MC2_ADDR = 0x40A,
MSR_MC2_MISC = 0x40B,
MSR_MC3_CTL = 0x40C,
MSR_MC3_STATUS = 0x40D,
MSR_MC3_ADDR = 0x40E,
MSR_MC3_MISC = 0x40F,
MSR_MC4_CTL = 0x410,
MSR_MC4_STATUS = 0x411,
MSR_MC4_ADDR = 0x412,
MSR_MC4_MISC = 0x413,
MSR_MC5_CTL = 0x414,
MSR_MC5_STATUS = 0x415,
MSR_MC5_ADDR = 0x416,
MSR_MC5_MISC = 0x417,
MSR_MC6_CTL = 0x418,
MSR_MC6_STATUS = 0x419,
MSR_MC6_ADDR = 0x41A,
MSR_MC6_MISC = 0x41B,
MSR_MC7_CTL = 0x41C,
MSR_MC7_STATUS = 0x41D,
MSR_MC7_ADDR = 0x41E,
MSR_MC7_MISC = 0x41F,
MSR_MC8_CTL = 0x420,
MSR_MC8_STATUS = 0x421,
MSR_MC8_ADDR = 0x422,
MSR_MC8_MISC = 0x423,
MSR_MC9_CTL = 0x424,
MSR_MC9_STATUS = 0x425,
MSR_MC9_ADDR = 0x426,
MSR_MC9_MISC = 0x427,
MSR_MC10_CTL = 0x428,
MSR_MC10_STATUS = 0x429,
MSR_MC10_ADDR = 0x42A,
MSR_MC10_MISC = 0x42B,
MSR_MC11_CTL = 0x42C,
MSR_MC11_STATUS = 0x42D,
MSR_MC11_ADDR = 0x42E,
MSR_MC11_MISC = 0x42F,
MSR_MC12_CTL = 0x430,
MSR_MC12_STATUS = 0x431,
MSR_MC12_ADDR = 0x432,
MSR_MC12_MISC = 0x433,
MSR_MC13_CTL = 0x434,
MSR_MC13_STATUS = 0x435,
MSR_MC13_ADDR = 0x436,
MSR_MC13_MISC = 0x437,
MSR_MC14_CTL = 0x438,
MSR_MC14_STATUS = 0x439,
MSR_MC14_ADDR = 0x43A,
MSR_MC14_MISC = 0x43B,
MSR_MC15_CTL = 0x43C,
MSR_MC15_STATUS = 0x43D,
MSR_MC15_ADDR = 0x43E,
MSR_MC15_MISC = 0x43F,
MSR_MC16_CTL = 0x440,
MSR_MC16_STATUS = 0x441,
MSR_MC16_ADDR = 0x442,
MSR_MC16_MISC = 0x443,
MSR_MC17_CTL = 0x444,
MSR_MC17_STATUS = 0x445,
MSR_MC17_ADDR = 0x446,
MSR_MC17_MISC = 0x447,
MSR_MC18_CTL = 0x448,
MSR_MC18_STATUS = 0x449,
MSR_MC18_ADDR = 0x44A,
MSR_MC18_MISC = 0x44B,
MSR_MC19_CTL = 0x44C,
MSR_MC19_STATUS = 0x44D,
MSR_MC19_ADDR = 0x44E,
MSR_MC19_MISC = 0x44F,
MSR_MC20_CTL = 0x450,
MSR_MC20_STATUS = 0x451,
MSR_MC20_ADDR = 0x452,
MSR_MC20_MISC = 0x453,
MSR_MC21_CTL = 0x454,
MSR_MC21_STATUS = 0x455,
MSR_MC21_ADDR = 0x456,
MSR_MC21_MISC = 0x457,
MSR_MC22_CTL = 0x458,
MSR_MC22_STATUS = 0x459,
MSR_MC22_ADDR = 0x45A,
MSR_MC22_MISC = 0x45B,
MSR_MC23_CTL = 0x45C,
MSR_MC23_STATUS = 0x45D,
MSR_MC23_ADDR = 0x45E,
MSR_MC23_MISC = 0x45F,
MSR_MC24_CTL = 0x460,
MSR_MC24_STATUS = 0x461,
MSR_MC24_ADDR = 0x462,
MSR_MC24_MISC = 0x463,
MSR_MC25_CTL = 0x464,
MSR_MC25_STATUS = 0x465,
MSR_MC25_ADDR = 0x466,
MSR_MC25_MISC = 0x467,
MSR_MC26_CTL = 0x468,
MSR_MC26_STATUS = 0x469,
MSR_MC26_ADDR = 0x46A,
MSR_MC26_MISC = 0x46B,
MSR_MC27_CTL = 0x46C,
MSR_MC27_STATUS = 0x46D,
MSR_MC27_ADDR = 0x46E,
MSR_MC27_MISC = 0x46F,
MSR_MC28_CTL = 0x470,
MSR_MC28_STATUS = 0x471,
MSR_MC28_ADDR = 0x472,
MSR_MC28_MISC = 0x473,
MSR_VMX_BASIC = 0x480,
MSR_VMX_PINBASED_CTLS = 0x481,
MSR_VMX_PROCBASED_CTLS = 0x482,
MSR_VMX_EXIT_CTLS = 0x483,
MSR_VMX_ENTRY_CTLS = 0x484,
MSR_VMX_MISC = 0x485,
MSR_VMX_CR0_FIXED0 = 0x486,
MSR_VMX_CR0_FIXED1 = 0x487,
MSR_VMX_CR4_FIXED0 = 0x488,
MSR_VMX_CR4_FIXED1 = 0x489,
MSR_VMX_VMCS_ENUM = 0x48A,
MSR_VMX_PROCBASED_CTLS2 = 0x48B,
MSR_VMX_EPT_VPID_CAP = 0x48C,
MSR_VMX_TRUE_PINBASED_CTLS = 0x48D,
MSR_VMX_TRUE_PROCBASED_CTLS = 0x48E,
MSR_VMX_TRUE_EXIT_CTLS = 0x48F,
MSR_VMX_TRUE_ENTRY_CTLS = 0x490,
MSR_VMX_VMFUNC = 0x491,
MSR_A_PMC0 = 0x4C1,
MSR_A_PMC1 = 0x4C2,
MSR_A_PMC2 = 0x4C3,
MSR_A_PMC3 = 0x4C4,
MSR_A_PMC4 = 0x4C5,
MSR_A_PMC5 = 0x4C6,
MSR_A_PMC6 = 0x4C7,
MSR_A_PMC7 = 0x4C8,
MSR_MCG_EXT_CTL = 0x4D0,
MSR_SGX_SVN_STATUS = 0x500,
MSR_RTIT_OUTPUT_BASE = 0x560,
MSR_RTIT_OUTPUT_MASK_PTRS = 0x561,
MSR_RTIT_CTL = 0x570,
MSR_RTIT_STATUS = 0x571,
MSR_RTIT_CR3_MATCH = 0x572,
MSR_RTIT_ADDR0_A = 0x580,
MSR_RTIT_ADDR0_B = 0x581,
MSR_RTIT_ADDR1_A = 0x582,
MSR_RTIT_ADDR1_B = 0x583,
MSR_RTIT_ADDR2_A = 0x584,
MSR_RTIT_ADDR2_B = 0x585,
MSR_RTIT_ADDR3_A = 0x586,
MSR_RTIT_ADDR3_B = 0x587,
MSR_DS_AREA = 0x600,
MSR_TSC_DEADLINE = 0x6E0,
MSR_PM_ENABLE = 0x770,
MSR_HWP_CAPABILITIES = 0x771,
MSR_HWP_REQUEST_PKG = 0x772,
MSR_HWP_INTERRUPT = 0x773,
MSR_HWP_REQUEST = 0x774,
MSR_HWP_STATUS = 0x777,
MSR_X2APIC_APICID = 0x802,
MSR_X2APIC_VERSION = 0x803,
MSR_X2APIC_TPR = 0x808,
MSR_X2APIC_PPR = 0x80A,
MSR_X2APIC_EOI = 0x80B,
MSR_X2APIC_LDR = 0x80D,
MSR_X2APIC_SIVR = 0x80F,
MSR_X2APIC_ISR0 = 0x810,
MSR_X2APIC_ISR1 = 0x811,
MSR_X2APIC_ISR2 = 0x812,
MSR_X2APIC_ISR3 = 0x813,
MSR_X2APIC_ISR4 = 0x814,
MSR_X2APIC_ISR5 = 0x815,
MSR_X2APIC_ISR6 = 0x816,
MSR_X2APIC_ISR7 = 0x817,
MSR_X2APIC_TMR0 = 0x818,
MSR_X2APIC_TMR1 = 0x819,
MSR_X2APIC_TMR2 = 0x81A,
MSR_X2APIC_TMR3 = 0x81B,
MSR_X2APIC_TMR4 = 0x81C,
MSR_X2APIC_TMR5 = 0x81D,
MSR_X2APIC_TMR6 = 0x81E,
MSR_X2APIC_TMR7 = 0x81F,
MSR_X2APIC_IRR0 = 0x820,
MSR_X2APIC_IRR1 = 0x821,
MSR_X2APIC_IRR2 = 0x822,
MSR_X2APIC_IRR3 = 0x823,
MSR_X2APIC_IRR4 = 0x824,
MSR_X2APIC_IRR5 = 0x825,
MSR_X2APIC_IRR6 = 0x826,
MSR_X2APIC_IRR7 = 0x827,
MSR_X2APIC_ESR = 0x828,
MSR_X2APIC_LVT_CMCI = 0x82F,
MSR_X2APIC_ICR = 0x830,
MSR_X2APIC_LVT_TIMER = 0x832,
MSR_X2APIC_LVT_THERMAL = 0x833,
MSR_X2APIC_LVT_PMI = 0x834,
MSR_X2APIC_LVT_LINT0 = 0x835,
MSR_X2APIC_LVT_LINT1 = 0x836,
MSR_X2APIC_LVT_ERROR = 0x837,
MSR_X2APIC_INIT_COUNT = 0x838,
MSR_X2APIC_CUR_COUNT = 0x839,
MSR_X2APIC_DIV_CONF = 0x83E,
MSR_X2APIC_SELF_IPI = 0x83F,
MSR_DEBUG_INTERFACE = 0xC80,
MSR_L3_QOS_CFG = 0xC81,
MSR_L2_QOS_CFG = 0xC82,
MSR_QM_EVTSEL = 0xC8D,
MSR_QM_CTR = 0xC8E,
MSR_PQR_ASSOC = 0xC8F,
MSR_L3_MASK_0 = 0xC90,
MSR_L2_MASK_0 = 0xD10,
MSR_BNDCFGS = 0xD90,
MSR_XSS = 0xDA0,
MSR_PKG_HDC_CTL = 0xDB0,
MSR_PM_CTL1 = 0xDB1,
MSR_THREAD_STALL = 0xDB2,
/** @brief Extended Feature Enable Register (0xc0000080) */
MSR_EFER = 0xC0000080,
/** @brief legacy SYSCALL (0xC0000081) */
MSR_STAR = 0xC0000081,
/** @brief 64bit SYSCALL (0xC0000082) */
MSR_LSTAR = 0xC0000082,
/** @brief compatibility mode SYSCALL (0xC0000083) */
MSR_CSTAR = 0xC0000083,
/** @brief EFLAGS mask for syscall (0xC0000084) */
MSR_SYSCALL_MASK = 0xC0000084,
/** @brief 64bit FS base (0xC0000100) */
MSR_FS_BASE = 0xC0000100,
/** @brief 64bit GS base (0xC0000101) */
MSR_GS_BASE = 0xC0000101,
/** @brief SwapGS GS shadow (0xC0000102) */
MSR_SHADOW_GS_BASE = 0xC0000102,
/** @brief Auxiliary TSC (0xC0000103) */
MSR_TSC_AUX = 0xC0000103,
MSR_CR_PAT = 0x00000277,
};
#if defined(__i386__)
nsa static inline uint64_t rdmsr(uint32_t msr)
{
uint32_t Low, High;
asmv("rdmsr"
: "=a"(Low), "=d"(High)
: "c"(msr)
: "memory");
return ((uint64_t)Low) | (((uint64_t)High) << 32);
}
nsa static inline void wrmsr(uint32_t msr, uint64_t Value)
{
uint32_t Low = (uint32_t)Value, High = (uint32_t)(Value >> 32);
asmv("wrmsr"
:
: "c"(msr), "a"(Low), "d"(High)
: "memory");
}
#endif
}
}
#endif // !__FENNIX_KERNEL_CPU_x32_MSR_H__

View File

@ -146,10 +146,10 @@ static_assert(sizeof(blkcnt_t) == 8, "blkcnt_t must be 64 bits");
#else #else
static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits"); static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits");
static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits"); static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits");
static_assert(sizeof(mode_t) == 2, "mode_t must be 16 bits"); static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits");
static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits"); static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits");
static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits"); static_assert(sizeof(uid_t) == 4, "uid_t must be 32 bits");
static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits"); static_assert(sizeof(gid_t) == 4, "gid_t must be 32 bits");
static_assert(sizeof(off_t) == 4, "off_t must be 32 bits"); static_assert(sizeof(off_t) == 4, "off_t must be 32 bits");
static_assert(sizeof(time_t) == 4, "time_t must be 32 bits"); static_assert(sizeof(time_t) == 4, "time_t must be 32 bits");
static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits"); static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits");

View File

@ -33,10 +33,16 @@
static inline scarg syscall0(scarg syscall) static inline scarg syscall0(scarg syscall)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall) : "a"(syscall)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -52,10 +58,16 @@ static inline scarg syscall0(scarg syscall)
static inline scarg syscall1(scarg syscall, scarg arg1) static inline scarg syscall1(scarg syscall, scarg arg1)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1) : "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -72,10 +84,16 @@ static inline scarg syscall1(scarg syscall, scarg arg1)
static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2) static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2) : "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -93,10 +111,16 @@ static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3) static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -115,11 +139,17 @@ static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4) static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4; register scarg r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -139,12 +169,18 @@ static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5) static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4; register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5; register scarg r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -165,6 +201,7 @@ static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6) static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4; register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5; register scarg r8 __asm__("r8") = arg5;
register scarg r9 __asm__("r9") = arg6; register scarg r9 __asm__("r9") = arg6;
@ -172,6 +209,11 @@ static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }

View File

@ -61,7 +61,7 @@ namespace Memory
* @param Flag Flag to check * @param Flag Flag to check
* @return true if page has the specified flag, false otherwise. * @return true if page has the specified flag, false otherwise.
*/ */
bool Check(void *VirtualAddress, PTFlag Flag = PTFlag::P); bool Check(void *VirtualAddress, PTFlag Flag = PTFlag::P, MapType Type = MapType::FourKiB);
/** /**
* @brief Check if the region has the specified flag. * @brief Check if the region has the specified flag.

View File

@ -249,7 +249,7 @@ namespace Tasking
#else #else
CPU::x32::FXState fx; CPU::x32::FXState fx;
CPU::x32::SchedulerFrame tf; CPU::x32::SchedulerFrame tf;
uintptr_t GSBase, FSBase; uintptr_t GSBase, FSBase, ShadowGSBase;
#endif #endif
sigset_t SignalMask; sigset_t SignalMask;
int Compatibility; int Compatibility;
@ -354,8 +354,8 @@ namespace Tasking
int AddSignal(signal_t sig, union sigval val = {0}, pid_t tid = -1); int AddSignal(signal_t sig, union sigval val = {0}, pid_t tid = -1);
int RemoveSignal(signal_t sig); int RemoveSignal(signal_t sig);
bool HandleSignal(CPU::SchedulerFrame *tf, void *thread); arch bool HandleSignal(CPU::SchedulerFrame *tf, void *thread);
void RestoreHandleSignal(SyscallsFrame *tf, void *thread); arch void RestoreHandleSignal(SyscallsFrame *tf, void *thread);
int SetAction(signal_t sig, const SignalAction *act); int SetAction(signal_t sig, const SignalAction *act);
int GetAction(signal_t sig, SignalAction *act); int GetAction(signal_t sig, SignalAction *act);

View File

@ -355,11 +355,10 @@ namespace Tasking
ThreadSignal Signals; ThreadSignal Signals;
/* CPU state */ /* CPU state */
CPU::SchedulerFrame Registers{};
#if defined(__amd64__) #if defined(__amd64__)
CPU::x64::SchedulerFrame Registers{};
uintptr_t ShadowGSBase, GSBase, FSBase; uintptr_t ShadowGSBase, GSBase, FSBase;
#elif defined(__i386__) #elif defined(__i386__)
CPU::x32::SchedulerFrame Registers{};
uintptr_t ShadowGSBase, GSBase, FSBase; uintptr_t ShadowGSBase, GSBase, FSBase;
#elif defined(__aarch64__) #elif defined(__aarch64__)
uintptr_t Registers; // TODO uintptr_t Registers; // TODO

View File

@ -20,6 +20,14 @@
#include <stdbool.h> #include <stdbool.h>
/**
* It doesn't do anything.
*
* Used to specify a function that is dependent on the architecture.
* It's architecture specific variant is defined in arch/<arch>/...
*/
#define arch
#ifdef __cplusplus #ifdef __cplusplus
#define EXTERNC extern "C" #define EXTERNC extern "C"
#define START_EXTERNC \ #define START_EXTERNC \
@ -166,17 +174,17 @@ typedef int32_t pid_t;
#elif defined(__i386__) #elif defined(__i386__)
typedef int32_t off_t; typedef int32_t off_t;
typedef long long off64_t; typedef long long off64_t;
typedef __INT32_TYPE__ mode_t; typedef uint32_t mode_t;
typedef int32_t dev_t; typedef int32_t dev_t;
typedef int32_t ino64_t; typedef int32_t ino64_t;
typedef int32_t ino_t; typedef int32_t ino_t;
typedef unsigned int nlink_t; typedef uint32_t nlink_t;
typedef int blksize_t; typedef int blksize_t;
typedef int32_t blkcnt_t; typedef int32_t blkcnt_t;
typedef int32_t blkcnt64_t; typedef int32_t blkcnt64_t;
typedef int32_t time_t; typedef int32_t time_t;
typedef unsigned uid_t; typedef uint32_t uid_t;
typedef unsigned gid_t; typedef uint32_t gid_t;
typedef long clock_t; typedef long clock_t;
typedef int pid_t; typedef int pid_t;
#endif #endif

View File

@ -54,6 +54,7 @@ EXTERNC void *memset_sse2(void *dest, int c, size_t n)
for (; i + 64 <= n; i += 64) for (; i + 64 <= n; i += 64)
{ {
#if defined(__amd64__)
asmv("movd %0, %%xmm0\n" asmv("movd %0, %%xmm0\n"
"movdqa %%xmm0, (%1)\n" "movdqa %%xmm0, (%1)\n"
"movdqa %%xmm0, 16(%1)\n" "movdqa %%xmm0, 16(%1)\n"
@ -62,6 +63,9 @@ EXTERNC void *memset_sse2(void *dest, int c, size_t n)
: :
: "r"(c), "r"(((size_t)dest) + i) : "r"(c), "r"(((size_t)dest) + i)
: "xmm0"); : "xmm0");
#else
#warning "memset_sse2 not implemented for other arch"
#endif
} }
asmv("rep stosb\n" ::"a"((size_t)(c)), asmv("rep stosb\n" ::"a"((size_t)(c)),

View File

@ -627,9 +627,15 @@ void SetSigActToNative(const k_sigaction *linux, SignalAction *native)
native->Flags = linux->flags; native->Flags = linux->flags;
native->Restorer = linux->restorer; native->Restorer = linux->restorer;
#if defined(__amd64__)
unsigned long mask = ((unsigned long)linux->mask[1] << 32) | linux->mask[0]; unsigned long mask = ((unsigned long)linux->mask[1] << 32) | linux->mask[0];
native->Mask = std::bitset<64>(ConvertMaskToNative(mask)); native->Mask = std::bitset<64>(ConvertMaskToNative(mask));
debug("m0:%#lx m1:%#lx | n:%#lx", linux->mask[0], linux->mask[1], native->Mask); debug("m0:%#lx m1:%#lx | n:%#lx", linux->mask[0], linux->mask[1], native->Mask);
#elif defined(__i386__)
#warning "SetSigActToNative not implemented for i386"
#elif defined(__aarch64__)
#warning "SetSigActToNative not implemented for aarch64"
#endif
} }
void SetSigActToLinux(const SignalAction *native, k_sigaction *linux) void SetSigActToLinux(const SignalAction *native, k_sigaction *linux)
@ -638,12 +644,18 @@ void SetSigActToLinux(const SignalAction *native, k_sigaction *linux)
linux->flags = native->Flags; linux->flags = native->Flags;
linux->restorer = native->Restorer; linux->restorer = native->Restorer;
#if defined(__amd64__)
unsigned long mask = native->Mask.to_ulong(); unsigned long mask = native->Mask.to_ulong();
mask = ConvertMaskToLinux(mask); mask = ConvertMaskToLinux(mask);
linux->mask[0] = mask & 0xFFFFFFFF; linux->mask[0] = mask & 0xFFFFFFFF;
linux->mask[1] = (uint32_t)((mask >> 32) & 0xFFFFFFFF); linux->mask[1] = (uint32_t)((mask >> 32) & 0xFFFFFFFF);
debug("m0:%#lx m1:%#lx | n:%#lx", linux->mask[0], linux->mask[1], native->Mask); debug("m0:%#lx m1:%#lx | n:%#lx", linux->mask[0], linux->mask[1], native->Mask);
#elif defined(__i386__)
#warning "SetSigActToLinux not implemented for i386"
#elif defined(__aarch64__)
#warning "SetSigActToLinux not implemented for aarch64"
#endif
} }
struct kstat KStatToStat(struct linux_kstat linux_stat) struct kstat KStatToStat(struct linux_kstat linux_stat)
@ -2501,41 +2513,31 @@ static int linux_arch_prctl(SysFrm *, int code, unsigned long addr)
{ {
case linux_ARCH_SET_GS: case linux_ARCH_SET_GS:
{ {
#if defined(__amd64__) #if defined(__amd64__) || defined(__i386__)
CPU::x64::wrmsr(CPU::x64::MSRID::MSR_GS_BASE, addr); CPU::x86::wrmsr(CPU::x86::MSRID::MSR_GS_BASE, addr);
#elif defined(__i386__)
CPU::x32::wrmsr(CPU::x32::MSRID::MSR_GS_BASE, addr);
#endif #endif
return 0; return 0;
} }
case linux_ARCH_SET_FS: case linux_ARCH_SET_FS:
{ {
#if defined(__amd64__) #if defined(__amd64__) || defined(__i386__)
CPU::x64::wrmsr(CPU::x64::MSRID::MSR_FS_BASE, addr); CPU::x86::wrmsr(CPU::x86::MSRID::MSR_FS_BASE, addr);
#elif defined(__i386__)
CPU::x32::wrmsr(CPU::x32::MSRID::MSR_FS_BASE, addr);
#endif #endif
return 0; return 0;
} }
case linux_ARCH_GET_FS: case linux_ARCH_GET_FS:
{ {
#if defined(__amd64__) #if defined(__amd64__) || defined(__i386__)
*r_cst(uint64_t *, addr) = *r_cst(uint64_t *, addr) =
CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); CPU::x86::rdmsr(CPU::x86::MSRID::MSR_FS_BASE);
#elif defined(__i386__)
*r_cst(uint64_t *, addr) =
CPU::x32::rdmsr(CPU::x32::MSRID::MSR_FS_BASE);
#endif #endif
return 0; return 0;
} }
case linux_ARCH_GET_GS: case linux_ARCH_GET_GS:
{ {
#if defined(__amd64__) #if defined(__amd64__) || defined(__i386__)
*r_cst(uint64_t *, addr) = *r_cst(uint64_t *, addr) =
CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); CPU::x86::rdmsr(CPU::x86::MSRID::MSR_GS_BASE);
#elif defined(__i386__)
*r_cst(uint64_t *, addr) =
CPU::x32::rdmsr(CPU::x32::MSRID::MSR_GS_BASE);
#endif #endif
return 0; return 0;
} }
@ -2899,13 +2901,17 @@ __no_sanitize("undefined") static ssize_t linux_getdents64(SysFrm *,
if (pDirp == nullptr) if (pDirp == nullptr)
return -linux_EFAULT; return -linux_EFAULT;
/* Sanity checks */ /* Sanity checks */
#ifdef __LP64__
static_assert(sizeof(kdirent) == sizeof(linux_dirent64)); static_assert(sizeof(kdirent) == sizeof(linux_dirent64));
static_assert(offsetof(kdirent, d_ino) == offsetof(linux_dirent64, d_ino)); static_assert(offsetof(kdirent, d_ino) == offsetof(linux_dirent64, d_ino));
static_assert(offsetof(kdirent, d_off) == offsetof(linux_dirent64, d_off)); static_assert(offsetof(kdirent, d_off) == offsetof(linux_dirent64, d_off));
static_assert(offsetof(kdirent, d_reclen) == offsetof(linux_dirent64, d_reclen)); static_assert(offsetof(kdirent, d_reclen) == offsetof(linux_dirent64, d_reclen));
static_assert(offsetof(kdirent, d_type) == offsetof(linux_dirent64, d_type)); static_assert(offsetof(kdirent, d_type) == offsetof(linux_dirent64, d_type));
static_assert(offsetof(kdirent, d_name) == offsetof(linux_dirent64, d_name)); static_assert(offsetof(kdirent, d_name) == offsetof(linux_dirent64, d_name));
#else
#warning "Not implemented for 32-bit"
#endif
/* The structs are the same, no need for conversion. */ /* The structs are the same, no need for conversion. */
ssize_t ret = fildes.Node->ReadDir((struct kdirent *)pDirp, count, fildes.Offset, ssize_t ret = fildes.Node->ReadDir((struct kdirent *)pDirp, count, fildes.Offset,
@ -4290,14 +4296,14 @@ uintptr_t HandleLinuxSyscalls(SyscallsFrame *Frame)
debug("< [%ld:\"%s\"] = %ld", Frame->ax, Syscall.Name, sc_ret); debug("< [%ld:\"%s\"] = %ld", Frame->ax, Syscall.Name, sc_ret);
return sc_ret; return sc_ret;
#elif defined(__i386__) #elif defined(__i386__)
if (Frame->eax > sizeof(LinuxSyscallsTableI386) / sizeof(SyscallData)) if (Frame->ax > sizeof(LinuxSyscallsTableI386) / sizeof(SyscallData))
{ {
fixme("Syscall %d not implemented", fixme("Syscall %d not implemented",
Frame->eax); Frame->ax);
return -linux_ENOSYS; return -linux_ENOSYS;
} }
SyscallData Syscall = LinuxSyscallsTableI386[Frame->eax]; SyscallData Syscall = LinuxSyscallsTableI386[Frame->ax];
long (*call)(SysFrm *, long, ...) = r_cst(long (*)(SysFrm *, long, ...), long (*call)(SysFrm *, long, ...) = r_cst(long (*)(SysFrm *, long, ...),
Syscall.Handler); Syscall.Handler);
@ -4305,20 +4311,20 @@ uintptr_t HandleLinuxSyscalls(SyscallsFrame *Frame)
if (unlikely(!call)) if (unlikely(!call))
{ {
fixme("Syscall %s(%d) not implemented", fixme("Syscall %s(%d) not implemented",
Syscall.Name, Frame->eax); Syscall.Name, Frame->ax);
return -linux_ENOSYS; return -linux_ENOSYS;
} }
debug("> [%d:\"%s\"]( %#lx %#lx %#lx %#lx %#lx %#lx )", debug("> [%d:\"%s\"]( %#lx %#lx %#lx %#lx %#lx %#lx )",
Frame->eax, Syscall.Name, Frame->ax, Syscall.Name,
Frame->ebx, Frame->ecx, Frame->edx, Frame->bx, Frame->cx, Frame->dx,
Frame->esi, Frame->edi, Frame->ebp); Frame->si, Frame->di, Frame->bp);
int sc_ret = call(Frame, int sc_ret = call(Frame,
Frame->ebx, Frame->ecx, Frame->edx, Frame->bx, Frame->cx, Frame->dx,
Frame->esi, Frame->edi, Frame->ebp); Frame->si, Frame->di, Frame->bp);
debug("< [%d:\"%s\"] = %d", Frame->eax, Syscall.Name, sc_ret); debug("< [%d:\"%s\"] = %d", Frame->ax, Syscall.Name, sc_ret);
return sc_ret; return sc_ret;
#elif defined(__aarch64__) #elif defined(__aarch64__)
return -linux_ENOSYS; return -linux_ENOSYS;

View File

@ -255,19 +255,15 @@ static int sys_prctl(SysFrm *Frame, prctl_options_t option, unsigned long arg1,
if (arg == nullptr) if (arg == nullptr)
return -EFAULT; return -EFAULT;
#if defined(__amd64__) #if defined(__amd64__) || defined(__i386__)
*r_cst(uintptr_t *, arg) = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); *r_cst(uintptr_t *, arg) = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_GS_BASE);
#elif defined(__i386__)
*r_cst(uintptr_t *, arg) = CPU::x32::rdmsr(CPU::x32::MSRID::MSR_GS_BASE);
#endif #endif
return 0; return 0;
} }
case __SYS_SET_GS: case __SYS_SET_GS:
{ {
#if defined(__amd64__) #if defined(__amd64__) || defined(__i386__)
CPU::x64::wrmsr(CPU::x64::MSRID::MSR_GS_BASE, arg1); CPU::x86::wrmsr(CPU::x86::MSRID::MSR_GS_BASE, arg1);
#elif defined(__i386__)
CPU::x32::wrmsr(CPU::x32::MSRID::MSR_GS_BASE, arg1);
#endif #endif
return 0; return 0;
} }
@ -277,19 +273,15 @@ static int sys_prctl(SysFrm *Frame, prctl_options_t option, unsigned long arg1,
if (arg == nullptr) if (arg == nullptr)
return -EFAULT; return -EFAULT;
#if defined(__amd64__) #if defined(__amd64__) || defined(__i386__)
*r_cst(uintptr_t *, arg) = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); *r_cst(uintptr_t *, arg) = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_FS_BASE);
#elif defined(__i386__)
*r_cst(uintptr_t *, arg) = CPU::x32::rdmsr(CPU::x32::MSRID::MSR_FS_BASE);
#endif #endif
return 0; return 0;
} }
case __SYS_SET_FS: case __SYS_SET_FS:
{ {
#if defined(__amd64__) #if defined(__amd64__) || defined(__i386__)
CPU::x64::wrmsr(CPU::x64::MSRID::MSR_FS_BASE, arg1); CPU::x86::wrmsr(CPU::x86::MSRID::MSR_FS_BASE, arg1);
#elif defined(__i386__)
CPU::x32::wrmsr(CPU::x32::MSRID::MSR_FS_BASE, arg1);
#endif #endif
return 0; return 0;
} }

View File

@ -195,7 +195,7 @@ namespace Tasking::Scheduler
void Custom::StartScheduler() void Custom::StartScheduler()
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__)
if (Interrupts::apicTimer[0]) if (Interrupts::apicTimer[0])
{ {
((APIC::Timer *)Interrupts::apicTimer[0])->OneShot(CPU::x86::IRQ16, 100); ((APIC::Timer *)Interrupts::apicTimer[0])->OneShot(CPU::x86::IRQ16, 100);
@ -587,15 +587,11 @@ namespace Tasking::Scheduler
else else
{ {
CurrentCPU->CurrentThread->Registers = *Frame; CurrentCPU->CurrentThread->Registers = *Frame;
CPU::x64::fxsave(&CurrentCPU->CurrentThread->FPU); #if defined(__amd64__) || defined(__i386__)
#ifdef __amd64__ CPU::x86::fxsave(&CurrentCPU->CurrentThread->FPU);
CurrentCPU->CurrentThread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSR_SHADOW_GS_BASE); CurrentCPU->CurrentThread->ShadowGSBase = CPU::x86::rdmsr(CPU::x86::MSR_SHADOW_GS_BASE);
CurrentCPU->CurrentThread->GSBase = CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE); CurrentCPU->CurrentThread->GSBase = CPU::x86::rdmsr(CPU::x86::MSR_GS_BASE);
CurrentCPU->CurrentThread->FSBase = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE); CurrentCPU->CurrentThread->FSBase = CPU::x86::rdmsr(CPU::x86::MSR_FS_BASE);
#else
CurrentCPU->CurrentThread->ShadowGSBase = uintptr_t(CPU::x32::rdmsr(CPU::x32::MSR_SHADOW_GS_BASE));
CurrentCPU->CurrentThread->GSBase = uintptr_t(CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE));
CurrentCPU->CurrentThread->FSBase = uintptr_t(CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE));
#endif #endif
if (CurrentCPU->CurrentProcess->State.load() == TaskState::Running) if (CurrentCPU->CurrentProcess->State.load() == TaskState::Running)
@ -681,18 +677,12 @@ namespace Tasking::Scheduler
*Frame = CurrentCPU->CurrentThread->Registers; *Frame = CurrentCPU->CurrentThread->Registers;
#ifdef __amd64__ #if defined(__amd64__) || defined(__i386__)
GlobalDescriptorTable::SetKernelStack((void *)((uintptr_t)CurrentCPU->CurrentThread->Stack->GetStackTop())); GlobalDescriptorTable::SetKernelStack((void *)((uintptr_t)CurrentCPU->CurrentThread->Stack->GetStackTop()));
CPU::x64::fxrstor(&CurrentCPU->CurrentThread->FPU); CPU::x86::fxrstor(&CurrentCPU->CurrentThread->FPU);
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->ShadowGSBase); CPU::x86::wrmsr(CPU::x86::MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->ShadowGSBase);
CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, CurrentCPU->CurrentThread->GSBase); CPU::x86::wrmsr(CPU::x86::MSR_GS_BASE, CurrentCPU->CurrentThread->GSBase);
CPU::x64::wrmsr(CPU::x64::MSR_FS_BASE, CurrentCPU->CurrentThread->FSBase); CPU::x86::wrmsr(CPU::x86::MSR_FS_BASE, CurrentCPU->CurrentThread->FSBase);
#else
GlobalDescriptorTable::SetKernelStack((void *)((uintptr_t)CurrentCPU->CurrentThread->Stack->GetStackTop()));
CPU::x32::fxrstor(&CurrentCPU->CurrentThread->FPU);
CPU::x32::wrmsr(CPU::x32::MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->ShadowGSBase);
CPU::x32::wrmsr(CPU::x32::MSR_GS_BASE, CurrentCPU->CurrentThread->GSBase);
CPU::x32::wrmsr(CPU::x32::MSR_FS_BASE, CurrentCPU->CurrentThread->FSBase);
#endif #endif
CurrentCPU->CurrentProcess->Signals.HandleSignal(Frame, CurrentCPU->CurrentThread.load()); CurrentCPU->CurrentProcess->Signals.HandleSignal(Frame, CurrentCPU->CurrentThread.load());

View File

@ -20,13 +20,6 @@
#include <task.hpp> #include <task.hpp>
#include <errno.h> #include <errno.h>
#if defined(__amd64__)
#include "../arch/amd64/cpu/gdt.hpp"
#elif defined(__i386__)
#include "../arch/i386/cpu/gdt.hpp"
#elif defined(__aarch64__)
#endif
#include "../kernel.h" #include "../kernel.h"
#ifdef DEBUG #ifdef DEBUG
@ -344,149 +337,6 @@ namespace Tasking
return {}; return {};
} }
bool Signal::HandleSignal(CPU::SchedulerFrame *tf, void *thread)
{
/* We don't want to do this in kernel mode */
if (tf->cs != GDT_USER_CODE)
return false;
if (Queue.empty())
return false;
debug("We have %d signals to handle", Queue.size());
SmartLock(SignalLock);
SignalInfo sigI = GetAvailableSignal(thread);
if (sigI.sig == SIGNULL)
return false;
uintptr_t _p_rsp = ((PCB *)ctx)->PageTable->Get(tf->rsp);
uint64_t paRsp = _p_rsp;
paRsp &= ~0xF; /* Align */
paRsp -= 128; /* Red zone */
/* Calculate the virtual rsp */
uintptr_t _v_rsp = tf->rsp;
_v_rsp &= ~0xF; /* Align */
_v_rsp -= 128; /* Red zone */
uint64_t *vRsp = (uint64_t *)(_v_rsp - sizeof(StackInfo));
vRsp--; /* Alignment */
vRsp--; /* Handler Address */
assert(!((uintptr_t)vRsp & 0xF));
/* Add the stack info */
StackInfo si{};
CPU::x64::fxsave(&si.fx);
si.tf = *tf;
si.GSBase = CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE);
si.FSBase = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE);
si.ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSR_SHADOW_GS_BASE);
si.SignalMask = ((TCB *)thread)->Signals.Mask.to_ulong();
si.Compatibility = ((PCB *)ctx)->Info.Compatibility;
debug("gs: %#lx fs: %#lx shadow: %#lx",
si.GSBase, si.FSBase, si.ShadowGSBase);
/* Copy the stack info */
uint64_t *pRsp = (uint64_t *)(paRsp - sizeof(StackInfo));
memcpy(pRsp, &si, sizeof(StackInfo));
/* Set the handler address */
pRsp--; /* Alignment */
pRsp--;
*pRsp = uint64_t(sa[sigI.sig].sa_handler.Handler);
assert(!((uintptr_t)pRsp & 0xF));
int cSig = LinuxSig() ? ConvertSignalToLinux((signal_t)sigI.sig) : sigI.sig;
#ifdef DEBUG
DumpData("Stack Data", (void *)pRsp,
paRsp - uint64_t(pRsp));
debug("initial stack tf->rsp: %#lx after: %#lx",
tf->rsp, uint64_t(vRsp));
debug("sig: %d -> %d", sigI.sig, cSig);
#endif
tf->rsp = uint64_t(vRsp);
tf->rip = uint64_t(TrampAddr);
/* void func(int signo); */
/* void func(int signo, siginfo_t *info, void *context); */
tf->rdi = cSig;
if (sa[sigI.sig].Flags & SA_SIGINFO)
{
fixme("SA_SIGINFO not implemented");
siginfo_t *info = 0;
void *context = 0;
tf->rsi = uint64_t(info);
tf->rdx = uint64_t(context);
tf->rcx = 0;
tf->r8 = 0;
tf->r9 = 0;
}
else
{
tf->rsi = 0;
tf->rdx = 0;
tf->rcx = 0;
tf->r8 = 0;
tf->r9 = 0;
}
((TCB *)thread)->Signals.Mask = sa[sigI.sig].Mask;
assert(TrampAddr != nullptr);
return true;
}
void Signal::RestoreHandleSignal(SyscallsFrame *sf, void *thread)
{
debug("Restoring signal handler");
SmartLock(SignalLock);
gsTCB *gs = (gsTCB *)CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE);
uint64_t *sp = (uint64_t *)((PCB *)ctx)->PageTable->Get(gs->TempStack);
sp++; /* Alignment */
sp++; /* Handler Address */
assert(!((uintptr_t)sp & 0xF));
StackInfo *si = (StackInfo *)sp;
assert(si != nullptr);
sf->r15 = si->tf.r15;
sf->r14 = si->tf.r14;
sf->r13 = si->tf.r13;
sf->r12 = si->tf.r12;
sf->r11 = si->tf.r11;
sf->r10 = si->tf.r10;
sf->r9 = si->tf.r9;
sf->r8 = si->tf.r8;
sf->bp = si->tf.rbp;
sf->di = si->tf.rdi;
sf->si = si->tf.rsi;
sf->dx = si->tf.rdx;
sf->cx = si->tf.rcx;
sf->bx = si->tf.rbx;
sf->ax = si->tf.rax;
sf->Flags = si->tf.rflags.raw;
sf->ReturnAddress = si->tf.rip;
gs->TempStack = (void *)si->tf.rsp;
((TCB *)thread)->Signals.Mask = si->SignalMask;
CPU::x64::fxrstor(&si->fx);
CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, si->ShadowGSBase);
CPU::x64::wrmsr(CPU::x64::MSR_FS_BASE, si->FSBase);
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, si->GSBase);
debug("gs: %#lx fs: %#lx shadow: %#lx",
si->GSBase, si->FSBase, si->ShadowGSBase);
// ((PCB *)ctx)->GetContext()->Yield();
// __builtin_unreachable();
/* Return because we will restore at sysretq */
}
int Signal::SetAction(signal_t sig, const SignalAction *act) int Signal::SetAction(signal_t sig, const SignalAction *act)
{ {
SmartLock(SignalLock); SmartLock(SignalLock);

View File

@ -222,12 +222,12 @@ namespace Tasking
TCB *Task::CreateThread(PCB *Parent, IP EntryPoint, TCB *Task::CreateThread(PCB *Parent, IP EntryPoint,
const char **argv, const char **envp, const char **argv, const char **envp,
const std::vector<AuxiliaryVector> &auxv, const std::vector<AuxiliaryVector> &auxv,
TaskArchitecture arch, TaskCompatibility Compatibility, TaskArchitecture _arch, TaskCompatibility Compatibility,
bool ThreadNotReady) bool ThreadNotReady)
{ {
SmartLock(TaskingLock); SmartLock(TaskingLock);
return new TCB(this, Parent, EntryPoint, return new TCB(this, Parent, EntryPoint,
argv, envp, auxv, arch, argv, envp, auxv, _arch,
Compatibility, ThreadNotReady); Compatibility, ThreadNotReady);
} }

View File

@ -485,9 +485,9 @@ namespace Tasking
#if defined(__amd64__) #if defined(__amd64__)
this->ShadowGSBase = this->ShadowGSBase =
CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE); CPU::x86::rdmsr(CPU::x86::MSRID::MSR_SHADOW_GS_BASE);
this->GSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); this->GSBase = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_GS_BASE);
this->FSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); this->FSBase = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_FS_BASE);
this->Registers.cs = GDT_KERNEL_CODE; this->Registers.cs = GDT_KERNEL_CODE;
this->Registers.ss = GDT_KERNEL_DATA; this->Registers.ss = GDT_KERNEL_DATA;
this->Registers.rflags.AlwaysOne = 1; this->Registers.rflags.AlwaysOne = 1;
@ -498,7 +498,7 @@ namespace Tasking
POKE(uintptr_t, this->Registers.rsp) = (uintptr_t)ThreadDoExit; POKE(uintptr_t, this->Registers.rsp) = (uintptr_t)ThreadDoExit;
#elif defined(__i386__) #elif defined(__i386__)
this->Registers.cs = GDT_KERNEL_CODE; this->Registers.cs = GDT_KERNEL_CODE;
this->Registers.r3_ss = GDT_KERNEL_DATA; this->Registers.ss = GDT_KERNEL_DATA;
this->Registers.eflags.AlwaysOne = 1; this->Registers.eflags.AlwaysOne = 1;
this->Registers.eflags.IF = 1; this->Registers.eflags.IF = 1;
this->Registers.eflags.ID = 1; this->Registers.eflags.ID = 1;
@ -520,7 +520,13 @@ namespace Tasking
this->ctx->va.MapTo(gst, this->Parent->PageTable); this->ctx->va.MapTo(gst, this->Parent->PageTable);
gsTCB *gsT = (gsTCB *)gst.PhysicalAddress; gsTCB *gsT = (gsTCB *)gst.PhysicalAddress;
#ifdef DEBUG #ifdef DEBUG
#if defined(__amd64__)
gsT->__stub = 0xFFFFFFFFFFFFFFFF; gsT->__stub = 0xFFFFFFFFFFFFFFFF;
#elif defined(__i386__)
gsT->__stub = 0xFFFFFFFF;
#elif defined(__aarch64__)
gsT->__stub = 0xFFFFFFFFFFFFFFFF;
#endif
#endif #endif
gsT->ScPages = TO_PAGES(STACK_SIZE); gsT->ScPages = TO_PAGES(STACK_SIZE);
@ -552,7 +558,7 @@ namespace Tasking
this->SetupUserStack_x86_64(argv, envp, auxv, Compatibility); this->SetupUserStack_x86_64(argv, envp, auxv, Compatibility);
#elif defined(__i386__) #elif defined(__i386__)
this->Registers.cs = GDT_USER_CODE; this->Registers.cs = GDT_USER_CODE;
this->Registers.r3_ss = GDT_USER_DATA; this->Registers.ss = GDT_USER_DATA;
this->Registers.eflags.AlwaysOne = 1; this->Registers.eflags.AlwaysOne = 1;
this->Registers.eflags.IF = 1; this->Registers.eflags.IF = 1;
this->Registers.eflags.ID = 1; this->Registers.eflags.ID = 1;
@ -562,9 +568,9 @@ namespace Tasking
is exited or we are going to get is exited or we are going to get
an exception. */ an exception. */
this->SetupUserStack_x86_32(argv, envp, auxv); this->SetupUserStack_x86_32(argv, envp, auxv, Compatibility);
#elif defined(__aarch64__) #elif defined(__aarch64__)
this->SetupUserStack_aarch64(argv, envp, auxv); this->SetupUserStack_aarch64(argv, envp, auxv, Compatibility);
#endif #endif
#ifdef DEBUG_TASKING #ifdef DEBUG_TASKING
DumpData(this->Name, this->Stack, STACK_SIZE); DumpData(this->Name, this->Stack, STACK_SIZE);

View File

@ -121,9 +121,6 @@ namespace KernelConsole
switch (Request) switch (Request)
{ {
case 0xffffffff80045430: /* FIXME: ???? */
debug("???");
[[fallthrough]];
case TIOCGPTN: case TIOCGPTN:
{ {
fixme("stub ioctl TIOCGPTN"); fixme("stub ioctl TIOCGPTN");

View File

@ -54,6 +54,11 @@ Make sure to read and comply with these licenses before using or redistributing
- **License:** Unlicense and 0BSD - **License:** Unlicense and 0BSD
- **Location(s):** [Userspace/libc/interpreter/nanoprintf.h](Userspace/libc/interpreter/nanoprintf.h) - **Location(s):** [Userspace/libc/interpreter/nanoprintf.h](Userspace/libc/interpreter/nanoprintf.h)
## arith64.c
- **License:** Unlicense
- **Location(s):** [Userspace/libc/src/arith64.c](Userspace/libc/src/arith64.c)
--- ---
Please refer to the respective license files for the full text of each license. Please refer to the respective license files for the full text of each license.

View File

@ -14,7 +14,7 @@ export LDFLAGS := --sysroot=$(WORKSPACE_DIR)/out/ \
export CFLAGS := \ export CFLAGS := \
--sysroot=$(WORKSPACE_DIR)/out/ \ --sysroot=$(WORKSPACE_DIR)/out/ \
-I$(WORKSPACE_DIR)/out/include \ -I$(WORKSPACE_DIR)/out/include \
-DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
else # DEBUG else # DEBUG

View File

@ -92,10 +92,12 @@ typedef struct
static __inline long __musl_syscall1(long n, long a1) static __inline long __musl_syscall1(long n, long a1)
{ {
unsigned long ret; unsigned long ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(n), "D"(a1) : "a"(n), "D"(a1)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#endif
return ret; return ret;
} }

View File

@ -33,10 +33,16 @@
static inline scarg syscall0(scarg syscall) static inline scarg syscall0(scarg syscall)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall) : "a"(syscall)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -52,10 +58,16 @@ static inline scarg syscall0(scarg syscall)
static inline scarg syscall1(scarg syscall, scarg arg1) static inline scarg syscall1(scarg syscall, scarg arg1)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1) : "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -72,10 +84,16 @@ static inline scarg syscall1(scarg syscall, scarg arg1)
static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2) static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2) : "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -93,10 +111,16 @@ static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3) static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -115,11 +139,17 @@ static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4) static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4; register scarg r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -139,12 +169,18 @@ static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5) static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4; register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5; register scarg r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall" __asm__ __volatile__("syscall"
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }
@ -165,6 +201,7 @@ static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6) static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6)
{ {
scarg ret; scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4; register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5; register scarg r8 __asm__("r8") = arg5;
register scarg r9 __asm__("r9") = arg6; register scarg r9 __asm__("r9") = arg6;
@ -172,6 +209,11 @@ static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3,
: "=a"(ret) : "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
#elif defined(__i386__)
#warning "i386 syscall wrapper not implemented"
#else
#error "Unsupported architecture"
#endif
return ret; return ret;
} }

View File

@ -14,7 +14,7 @@ OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CFLAGS := -fvisibility=hidden -fPIC -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"' CFLAGS := -fvisibility=hidden -fPIC -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1) ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
endif endif
build: $(OBJECT_NAME) build: $(OBJECT_NAME)

View File

@ -124,6 +124,7 @@ ElfInfo *SearchLib(char *Path)
__attribute__((naked, used, no_stack_protector)) void _dl_runtime_resolve() __attribute__((naked, used, no_stack_protector)) void _dl_runtime_resolve()
{ {
#if defined(__amd64__)
__asm__( __asm__(
"pop %r11\n" /* Pop lazy resolve arguments */ "pop %r11\n" /* Pop lazy resolve arguments */
"pop %r10\n" "pop %r10\n"
@ -148,6 +149,11 @@ __attribute__((naked, used, no_stack_protector)) void _dl_runtime_resolve()
"pop %rdi\n" "pop %rdi\n"
"jmp *%r11\n"); /* Jump to the return value */ "jmp *%r11\n"); /* Jump to the return value */
#elif defined(__i386__)
#warning "i386 _dl_runtime_resolve not implemented"
#else
#error "Unsupported architecture"
#endif
} }
int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated); int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated);
@ -561,7 +567,7 @@ int CheckElfEhdr(Elf_Ehdr *ehdr, char *Path)
if (ehdr->e_ident[EI_CLASS] != elfClass) if (ehdr->e_ident[EI_CLASS] != elfClass)
{ {
printf("dl: %s is not a %s-bit ELF file\n", printf("dl: %s is not a %s-bit ELF file\n",
Path, __LP64__ ? "64" : "32"); Path, elfClass == ELFCLASS64 ? "64" : "32");
return -EINVAL; return -EINVAL;
} }
@ -804,6 +810,7 @@ int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated)
addAddend = 1; addAddend = 1;
break; break;
} }
#if __LP64__
case R_DTPMOD64: case R_DTPMOD64:
{ {
printf("dl: i don't know what to do with DTPMOD64\n"); printf("dl: i don't know what to do with DTPMOD64\n");
@ -822,6 +829,7 @@ int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated)
reloc = symAddress + Rela->r_addend; reloc = symAddress + Rela->r_addend;
break; break;
} }
#endif // __LP64__
default: default:
{ {
printf("dl: Unsupported relocation type %d\n", relType); printf("dl: Unsupported relocation type %d\n", relType);

View File

@ -99,6 +99,7 @@ void __fini_print_buffer();
__attribute__((naked, used, no_stack_protector)) void _start() __attribute__((naked, used, no_stack_protector)) void _start()
{ {
#if defined(__amd64__)
__asm__( __asm__(
"xorq %rbp, %rbp\n" /* Clear rbp */ "xorq %rbp, %rbp\n" /* Clear rbp */
@ -125,14 +126,21 @@ __attribute__((naked, used, no_stack_protector)) void _start()
"call main\n" /* Call _dl_main */ "call main\n" /* Call _dl_main */
"movl %eax, %edi\n" /* Move return value to edi */ "movl %eax, %edi\n" /* Move return value to edi */
"call _exit\n"); /* Call _exit */ "call _exit\n"); /* Call _exit */
#elif defined(__i386__)
#warning "i386 _start not implemented"
#else
#error "Unsupported architecture"
#endif
} }
__attribute__((no_stack_protector)) _Noreturn void _exit(int status) __attribute__((no_stack_protector)) _Noreturn void _exit(int status)
{ {
__fini_print_buffer(); __fini_print_buffer();
call_exit(status); call_exit(status);
/* At this point, the program *SHOULD* have exited. */ /* At this point, the program *SHOULD* have exited. */
#if defined(__amd64__) || defined(__i386__)
__asm__("ud2\n"); __asm__("ud2\n");
#endif
__builtin_unreachable(); __builtin_unreachable();
} }

View File

@ -39,6 +39,7 @@ void __crt_fini_array(void)
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start() __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{ {
#if defined(__amd64__)
asm("movq $0, %rbp\n" asm("movq $0, %rbp\n"
"pushq %rbp\n" "pushq %rbp\n"
"pushq %rbp\n" "pushq %rbp\n"
@ -65,6 +66,11 @@ __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
"movl %eax, %edi\n" "movl %eax, %edi\n"
"call _exit\n"); "call _exit\n");
#elif defined(__i386__)
#warning "i386 _start not implemented"
#else
#error "Unsupported architecture"
#endif
} }
/* These are declared in GNU ld */ /* These are declared in GNU ld */

View File

@ -39,6 +39,7 @@ void __crt_fini_array(void)
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start() __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{ {
#if defined(__amd64__)
asm("movq $0, %rbp\n" asm("movq $0, %rbp\n"
"pushq %rbp\n" "pushq %rbp\n"
"pushq %rbp\n" "pushq %rbp\n"
@ -65,6 +66,11 @@ __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
"movl %eax, %edi\n" "movl %eax, %edi\n"
"call _exit\n"); "call _exit\n");
#elif defined(__i386__)
#warning "i386 _start not implemented"
#else
#error "Unsupported architecture"
#endif
} }
/* These are declared in GNU ld */ /* These are declared in GNU ld */

View File

@ -15,7 +15,7 @@ OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CFLAGS := -fvisibility=hidden -fPIC -I../include -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"' CFLAGS := -fvisibility=hidden -fPIC -I../include -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1) ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
endif endif
build: $(DYNAMIC_NAME) $(STATIC_NAME) build: $(DYNAMIC_NAME) $(STATIC_NAME)

View File

@ -0,0 +1,290 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#if defined(__amd64__) || defined(__i386__)
// GCC 32/64-bit integer arithmetic support for 32-bit systems that can't link
// to libgcc.
// Function prototypes and descriptions are taken from
// https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html.
// This file may be #include'd by another file, so we try not to pollute the
// namespace and we don't import any headers.
// All functions must be resolvable by the linker and therefore can't be inline
// or static, even if they're #included into the file where they'll be used.
// For best performance we try to avoid branching. This makes the code a little
// weird in places.
// See https://github.com/glitchub/arith64 for more information.
// This software is released as-is into the public domain, as described at
// https://unlicense.org. Do whatever you like with it.
#define arith64_u64 unsigned long long int
#define arith64_s64 signed long long int
#define arith64_u32 unsigned int
#define arith64_s32 int
typedef union
{
arith64_u64 u64;
arith64_s64 s64;
struct
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
arith64_u32 hi; arith64_u32 lo;
#else
arith64_u32 lo; arith64_u32 hi;
#endif
} u32;
struct
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
arith64_s32 hi; arith64_s32 lo;
#else
arith64_s32 lo; arith64_s32 hi;
#endif
} s32;
} arith64_word;
// extract hi and lo 32-bit words from 64-bit value
#define arith64_hi(n) (arith64_word){.u64=n}.u32.hi
#define arith64_lo(n) (arith64_word){.u64=n}.u32.lo
// Negate a if b is negative, via invert and increment.
#define arith64_neg(a, b) (((a) ^ ((((arith64_s64)(b)) >= 0) - 1)) + (((arith64_s64)(b)) < 0))
#define arith64_abs(a) arith64_neg(a, a)
// Return the absolute value of a.
// Note LLINT_MIN cannot be negated.
arith64_s64 __absvdi2(arith64_s64 a)
{
return arith64_abs(a);
}
// Return the result of shifting a left by b bits.
arith64_s64 __ashldi3(arith64_s64 a, int b)
{
arith64_word w = {.s64 = a};
b &= 63;
if (b >= 32)
{
w.u32.hi = w.u32.lo << (b - 32);
w.u32.lo = 0;
} else if (b)
{
w.u32.hi = (w.u32.lo >> (32 - b)) | (w.u32.hi << b);
w.u32.lo <<= b;
}
return w.s64;
}
// Return the result of arithmetically shifting a right by b bits.
arith64_s64 __ashrdi3(arith64_s64 a, int b)
{
arith64_word w = {.s64 = a};
b &= 63;
if (b >= 32)
{
w.s32.lo = w.s32.hi >> (b - 32);
w.s32.hi >>= 31; // 0xFFFFFFFF or 0
} else if (b)
{
w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
w.s32.hi >>= b;
}
return w.s64;
}
// These functions return the number of leading 0-bits in a, starting at the
// most significant bit position. If a is zero, the result is undefined.
int __clzsi2(arith64_u32 a)
{
int b, n = 0;
b = !(a & 0xffff0000) << 4; n += b; a <<= b;
b = !(a & 0xff000000) << 3; n += b; a <<= b;
b = !(a & 0xf0000000) << 2; n += b; a <<= b;
b = !(a & 0xc0000000) << 1; n += b; a <<= b;
return n + !(a & 0x80000000);
}
int __clzdi2(arith64_u64 a)
{
int b, n = 0;
b = !(a & 0xffffffff00000000ULL) << 5; n += b; a <<= b;
b = !(a & 0xffff000000000000ULL) << 4; n += b; a <<= b;
b = !(a & 0xff00000000000000ULL) << 3; n += b; a <<= b;
b = !(a & 0xf000000000000000ULL) << 2; n += b; a <<= b;
b = !(a & 0xc000000000000000ULL) << 1; n += b; a <<= b;
return n + !(a & 0x8000000000000000ULL);
}
// These functions return the number of trailing 0-bits in a, starting at the
// least significant bit position. If a is zero, the result is undefined.
int __ctzsi2(arith64_u32 a)
{
int b, n = 0;
b = !(a & 0x0000ffff) << 4; n += b; a >>= b;
b = !(a & 0x000000ff) << 3; n += b; a >>= b;
b = !(a & 0x0000000f) << 2; n += b; a >>= b;
b = !(a & 0x00000003) << 1; n += b; a >>= b;
return n + !(a & 0x00000001);
}
int __ctzdi2(arith64_u64 a)
{
int b, n = 0;
b = !(a & 0x00000000ffffffffULL) << 5; n += b; a >>= b;
b = !(a & 0x000000000000ffffULL) << 4; n += b; a >>= b;
b = !(a & 0x00000000000000ffULL) << 3; n += b; a >>= b;
b = !(a & 0x000000000000000fULL) << 2; n += b; a >>= b;
b = !(a & 0x0000000000000003ULL) << 1; n += b; a >>= b;
return n + !(a & 0x0000000000000001ULL);
}
// Calculate both the quotient and remainder of the unsigned division of a by
// b. The return value is the quotient, and the remainder is placed in variable
// pointed to by c (if it's not NULL).
arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c)
{
if (b > a) // divisor > numerator?
{
if (c) *c = a; // remainder = numerator
return 0; // quotient = 0
}
if (!arith64_hi(b)) // divisor is 32-bit
{
if (b == 0) // divide by 0
{
volatile char x = 0; x = 1 / x; // force an exception
}
if (b == 1) // divide by 1
{
if (c) *c = 0; // remainder = 0
return a; // quotient = numerator
}
if (!arith64_hi(a)) // numerator is also 32-bit
{
if (c) // use generic 32-bit operators
*c = arith64_lo(a) % arith64_lo(b);
return arith64_lo(a) / arith64_lo(b);
}
}
// let's do long division
char bits = __clzdi2(b) - __clzdi2(a) + 1; // number of bits to iterate (a and b are non-zero)
arith64_u64 rem = a >> bits; // init remainder
a <<= 64 - bits; // shift numerator to the high bit
arith64_u64 wrap = 0; // start with wrap = 0
while (bits-- > 0) // for each bit
{
rem = (rem << 1) | (a >> 63); // shift numerator MSB to remainder LSB
a = (a << 1) | (wrap & 1); // shift out the numerator, shift in wrap
wrap = ((arith64_s64)(b - rem - 1) >> 63); // wrap = (b > rem) ? 0 : 0xffffffffffffffff (via sign extension)
rem -= b & wrap; // if (wrap) rem -= b
}
if (c) *c = rem; // maybe set remainder
return (a << 1) | (wrap & 1); // return the quotient
}
// Return the quotient of the signed division of a by b.
arith64_s64 __divdi3(arith64_s64 a, arith64_s64 b)
{
arith64_u64 q = __divmoddi4(arith64_abs(a), arith64_abs(b), (void *)0);
return arith64_neg(q, a^b); // negate q if a and b signs are different
}
// Return the index of the least significant 1-bit in a, or the value zero if a
// is zero. The least significant bit is index one.
int __ffsdi2(arith64_u64 a)
{
return a ? __ctzdi2(a) + 1 : 0;
}
// Return the result of logically shifting a right by b bits.
arith64_u64 __lshrdi3(arith64_u64 a, int b)
{
arith64_word w = {.u64 = a};
b &= 63;
if (b >= 32)
{
w.u32.lo = w.u32.hi >> (b - 32);
w.u32.hi = 0;
} else if (b)
{
w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
w.u32.hi >>= b;
}
return w.u64;
}
// Return the remainder of the signed division of a by b.
arith64_s64 __moddi3(arith64_s64 a, arith64_s64 b)
{
arith64_u64 r;
__divmoddi4(arith64_abs(a), arith64_abs(b), &r);
return arith64_neg(r, a); // negate remainder if numerator is negative
}
// Return the number of bits set in a.
int __popcountsi2(arith64_u32 a)
{
// collect sums into two low bytes
a = a - ((a >> 1) & 0x55555555);
a = ((a >> 2) & 0x33333333) + (a & 0x33333333);
a = (a + (a >> 4)) & 0x0F0F0F0F;
a = (a + (a >> 16));
// add the bytes, return bottom 6 bits
return (a + (a >> 8)) & 63;
}
// Return the number of bits set in a.
int __popcountdi2(arith64_u64 a)
{
// collect sums into two low bytes
a = a - ((a >> 1) & 0x5555555555555555ULL);
a = ((a >> 2) & 0x3333333333333333ULL) + (a & 0x3333333333333333ULL);
a = (a + (a >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
a = (a + (a >> 32));
a = (a + (a >> 16));
// add the bytes, return bottom 7 bits
return (a + (a >> 8)) & 127;
}
// Return the quotient of the unsigned division of a by b.
arith64_u64 __udivdi3(arith64_u64 a, arith64_u64 b)
{
return __divmoddi4(a, b, (void *)0);
}
// Return the remainder of the unsigned division of a by b.
arith64_u64 __umoddi3(arith64_u64 a, arith64_u64 b)
{
arith64_u64 r;
__divmoddi4(a, b, &r);
return r;
}
#endif

View File

@ -114,6 +114,7 @@ void __crt_fini_array(void)
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start() __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{ {
#if defined(__amd64__)
asm("movq $0, %rbp\n" asm("movq $0, %rbp\n"
"pushq %rbp\n" "pushq %rbp\n"
"pushq %rbp\n" "pushq %rbp\n"
@ -140,6 +141,11 @@ __attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
"movl %eax, %edi\n" "movl %eax, %edi\n"
"call _exit\n"); "call _exit\n");
#elif defined(__i386__)
#warning "i386 _start not implemented"
#else
#warning "unknown architecture"
#endif
} }
int main(int argc, char *argv[], char *envp[]) int main(int argc, char *argv[], char *envp[])

View File

@ -6,7 +6,7 @@ DEBUG = 1
OSNAME = Fennix OSNAME = Fennix
# OS architecture, check AVAILABLE_ARCHS for available options. # OS architecture, check AVAILABLE_ARCHS for available options.
OSARCH = i386 OSARCH = amd64
# Kernel version. # Kernel version.
KERNEL_VERSION = dev KERNEL_VERSION = dev