From 2bb997597e0335f0e56cf039ee0da20f071f80d9 Mon Sep 17 00:00:00 2001 From: EnderIce2 Date: Tue, 7 Jan 2025 17:49:37 +0200 Subject: [PATCH] refactor: Fix build on i386 Signed-off-by: EnderIce2 --- Drivers/include/fs.h | 8 +- Drivers/include/io.h | 30 +- Drivers/include/syscalls.h | 42 ++ Drivers/include/types.h | 2 +- Drivers/misc/vmware/main.c | 19 + Kernel/Makefile | 2 +- Kernel/arch/aarch64/core/panic/ui.cpp | 46 ++ Kernel/arch/amd64/core/panic/ui.cpp | 134 ++++++ Kernel/arch/amd64/cpu/smp.cpp | 4 +- Kernel/arch/amd64/memory/vmm.cpp | 2 +- Kernel/arch/amd64/syscalls.cpp | 8 +- Kernel/arch/amd64/tasking/signal.cpp | 172 +++++++ Kernel/arch/i386/core/panic/ui.cpp | 131 ++++++ Kernel/arch/i386/cpu/smp.cpp | 2 +- Kernel/arch/i386/memory/vmm.cpp | 32 +- Kernel/arch/i386/tasking/signal.cpp | 160 +++++++ Kernel/arch/i386/tasking/signal_trampoline.s | 38 ++ Kernel/core/cpu.cpp | 4 +- Kernel/core/driver/driver.cpp | 4 +- Kernel/core/interrupts_manager.cpp | 24 +- .../heap_allocators/rpmalloc/rpmalloc.c | 2 + Kernel/core/memory/page_table.cpp | 2 +- Kernel/core/memory/vma.cpp | 2 + Kernel/core/panic/handler.cpp | 2 +- Kernel/core/panic/kbd/xhci.cpp | 6 +- Kernel/core/panic/ui.cpp | 110 +---- Kernel/include/cpu.hpp | 176 +++++--- Kernel/include/cpu/x86/{x64 => }/msr.hpp | 43 +- Kernel/include/cpu/x86/x32/cr.hpp | 16 - Kernel/include/cpu/x86/x32/msr.hpp | 426 ------------------ Kernel/include/interface/fs.h | 8 +- Kernel/include/interface/syscalls.h | 42 ++ Kernel/include/memory/virtual.hpp | 2 +- Kernel/include/signal.hpp | 6 +- Kernel/include/task.hpp | 3 +- Kernel/include/types.h | 16 +- Kernel/library/simd_memset.cpp | 4 + Kernel/subsystem/linux/syscall.cpp | 64 +-- Kernel/syscalls/native.cpp | 24 +- Kernel/tasking/scheduler/custom.cpp | 32 +- Kernel/tasking/signal.cpp | 150 ------ Kernel/tasking/task.cpp | 4 +- Kernel/tasking/thread.cpp | 20 +- Kernel/tty/vt.cpp | 3 - LICENSES.md | 5 + Userspace/Makefile | 2 +- Userspace/apps/test/utest/userspace_test.c | 2 + Userspace/libc/include/fennix/syscalls.h | 42 ++ Userspace/libc/interpreter/Makefile | 2 +- Userspace/libc/interpreter/load.c | 10 +- Userspace/libc/interpreter/start.c | 10 +- Userspace/libc/runtime/Scrt1.c | 6 + Userspace/libc/runtime/crt1.c | 6 + Userspace/libc/src/Makefile | 2 +- Userspace/libc/src/arith64.c | 290 ++++++++++++ Userspace/libc/src/main.c | 6 + config.mk | 2 +- 57 files changed, 1489 insertions(+), 923 deletions(-) create mode 100644 Kernel/arch/aarch64/core/panic/ui.cpp create mode 100644 Kernel/arch/amd64/core/panic/ui.cpp create mode 100644 Kernel/arch/amd64/tasking/signal.cpp create mode 100644 Kernel/arch/i386/core/panic/ui.cpp create mode 100644 Kernel/arch/i386/tasking/signal.cpp create mode 100644 Kernel/arch/i386/tasking/signal_trampoline.s rename Kernel/include/cpu/x86/{x64 => }/msr.hpp (91%) delete mode 100644 Kernel/include/cpu/x86/x32/msr.hpp create mode 100644 Userspace/libc/src/arith64.c diff --git a/Drivers/include/fs.h b/Drivers/include/fs.h index 27718cd7..23e19f14 100644 --- a/Drivers/include/fs.h +++ b/Drivers/include/fs.h @@ -146,10 +146,10 @@ static_assert(sizeof(blkcnt_t) == 8, "blkcnt_t must be 64 bits"); #else 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(mode_t) == 2, "mode_t must be 16 bits"); -static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits"); -static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits"); -static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits"); +static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits"); +static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits"); +static_assert(sizeof(uid_t) == 4, "uid_t must be 32 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(time_t) == 4, "time_t must be 32 bits"); static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits"); diff --git a/Drivers/include/io.h b/Drivers/include/io.h index cb1d9d98..4e0e3374 100644 --- a/Drivers/include/io.h +++ b/Drivers/include/io.h @@ -75,7 +75,7 @@ extern "C" : "dN"(Port), "a"(Data)); } - static inline uint8_t mmioin8(uint64_t Address) + static inline uint8_t mmioin8(uintptr_t Address) { __asm__ volatile("" :: : "memory"); @@ -85,7 +85,7 @@ extern "C" return Result; } - static inline uint16_t mmioin16(uint64_t Address) + static inline uint16_t mmioin16(uintptr_t Address) { __asm__ volatile("" :: : "memory"); @@ -95,7 +95,7 @@ extern "C" return Result; } - static inline uint32_t mmioin32(uint64_t Address) + static inline uint32_t mmioin32(uintptr_t Address) { __asm__ volatile("" :: : "memory"); @@ -105,17 +105,17 @@ extern "C" return Result; } - static inline uint64_t mmioin64(uint64_t Address) + static inline uintptr_t mmioin64(uintptr_t Address) { __asm__ volatile("" :: : "memory"); - uint64_t Result = *(volatile uint64_t *)Address; + uintptr_t Result = *(volatile uintptr_t *)Address; __asm__ volatile("" :: : "memory"); return Result; } - static inline void mmioout8(uint64_t Address, uint8_t Data) + static inline void mmioout8(uintptr_t Address, uint8_t Data) { __asm__ volatile("" :: : "memory"); @@ -124,7 +124,7 @@ extern "C" : "memory"); } - static inline void mmioout16(uint64_t Address, uint16_t Data) + static inline void mmioout16(uintptr_t Address, uint16_t Data) { __asm__ volatile("" :: : "memory"); @@ -133,7 +133,7 @@ extern "C" : "memory"); } - static inline void mmioout32(uint64_t Address, uint32_t Data) + static inline void mmioout32(uintptr_t Address, uint32_t Data) { __asm__ volatile("" :: : "memory"); @@ -142,11 +142,11 @@ extern "C" : "memory"); } - static inline void mmioout64(uint64_t Address, uint64_t Data) + static inline void mmioout64(uintptr_t Address, uintptr_t Data) { __asm__ volatile("" :: : "memory"); - *(volatile uint64_t *)Address = Data; + *(volatile uintptr_t *)Address = Data; __asm__ volatile("" :: : "memory"); } @@ -175,10 +175,10 @@ extern "C" : "memory"); } - static inline void mmoutq(void *Address, uint64_t Value) + static inline void mmoutq(void *Address, uintptr_t Value) { __asm__ volatile("mov %1, %0" - : "=m"((*(uint64_t *)(Address))) + : "=m"((*(uintptr_t *)(Address))) : "r"(Value) : "memory"); } @@ -213,12 +213,12 @@ extern "C" 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" : "=r"(Result) - : "m"((*(uint64_t *)(Address))) + : "m"((*(uintptr_t *)(Address))) : "memory"); return Result; } diff --git a/Drivers/include/syscalls.h b/Drivers/include/syscalls.h index bde19d03..d0cab647 100644 --- a/Drivers/include/syscalls.h +++ b/Drivers/include/syscalls.h @@ -33,10 +33,16 @@ static inline scarg syscall0(scarg syscall) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif return ret; } @@ -52,10 +58,16 @@ static inline scarg syscall0(scarg syscall) static inline scarg syscall1(scarg syscall, scarg arg1) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif return ret; } @@ -72,10 +84,16 @@ static inline scarg syscall1(scarg syscall, scarg arg1) static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) register scarg r10 __asm__("r10") = arg4; __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) register scarg r10 __asm__("r10") = arg4; register scarg r8 __asm__("r8") = arg5; __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) register scarg r10 __asm__("r10") = arg4; register scarg r8 __asm__("r8") = arg5; 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"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif return ret; } diff --git a/Drivers/include/types.h b/Drivers/include/types.h index 03fee4a2..e4547dbb 100644 --- a/Drivers/include/types.h +++ b/Drivers/include/types.h @@ -71,7 +71,7 @@ typedef uint32_t uid_t; typedef uint32_t gid_t; typedef int64_t clock_t; typedef int32_t pid_t; -#elif defined(__LP32__) +#else typedef int32_t off_t; typedef long long off64_t; typedef __INT32_TYPE__ mode_t; diff --git a/Drivers/misc/vmware/main.c b/Drivers/misc/vmware/main.c index d4ea5f64..4519c7cf 100644 --- a/Drivers/misc/vmware/main.c +++ b/Drivers/misc/vmware/main.c @@ -107,6 +107,8 @@ typedef struct #define MESSAGE_RECV_PAYLOAD ToMsg(MSG_RECVPAYLOAD) #define MESSAGE_RECV_STATUS ToMsg(MSG_RECVSTATUS) +#if defined(__amd64__) + #define VM_PORT(cmd, in_ebx, isi, idi, \ flags, magic, \ ax, bx, cx, dx, si, di) \ @@ -169,6 +171,23 @@ typedef struct "D"(idi), \ "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: - use vmcall or vmmcall instead of "out" and "in" if available */ diff --git a/Kernel/Makefile b/Kernel/Makefile index 2f3455bf..32e26276 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -32,7 +32,7 @@ WARNCFLAG = -Wall -Wextra \ -Wfloat-equal -Wpointer-arith -Wcast-align \ -Wredundant-decls -Winit-self -Wswitch-default \ -Wstrict-overflow=5 -Wno-error=cpp -Werror \ - -Wno-unused-parameter + -Wno-unused-parameter -Wno-error=format CFLAG_STACK_PROTECTOR := -fstack-protector-all diff --git a/Kernel/arch/aarch64/core/panic/ui.cpp b/Kernel/arch/aarch64/core/panic/ui.cpp new file mode 100644 index 00000000..eeae5743 --- /dev/null +++ b/Kernel/arch/aarch64/core/panic/ui.cpp @@ -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 . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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"); +} diff --git a/Kernel/arch/amd64/core/panic/ui.cpp b/Kernel/arch/amd64/core/panic/ui.cpp new file mode 100644 index 00000000..1c3895d2 --- /dev/null +++ b/Kernel/arch/amd64/core/panic/ui.cpp @@ -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 . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/Kernel/arch/amd64/cpu/smp.cpp b/Kernel/arch/amd64/cpu/smp.cpp index d4c765a4..428d66c2 100644 --- a/Kernel/arch/amd64/cpu/smp.cpp +++ b/Kernel/arch/amd64/cpu/smp.cpp @@ -61,7 +61,7 @@ nsa CPUData *GetCurrentCPU() Memory::SwapPT(KernelPageTable, thisPageTable); if (apic->x2APIC) - CoreID = int(CPU::x64::rdmsr(CPU::x64::MSR_X2APIC_APICID)); + CoreID = int(CPU::x86::rdmsr(CPU::x86::MSR_X2APIC_APICID)); else CoreID = apic->Read(APIC::APIC_ID) >> 24; } @@ -151,7 +151,7 @@ namespace SMP debug("Initializing CPU %d", lapic->APICId); uint8_t APIC_ID = 0; 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 APIC_ID = uint8_t(apic->Read(APIC::APIC_ID) >> 24); diff --git a/Kernel/arch/amd64/memory/vmm.cpp b/Kernel/arch/amd64/memory/vmm.cpp index c8d64158..b0113e53 100644 --- a/Kernel/arch/amd64/memory/vmm.cpp +++ b/Kernel/arch/amd64/memory/vmm.cpp @@ -22,7 +22,7 @@ namespace Memory { - bool Virtual::Check(void *VirtualAddress, PTFlag Flag) + bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type) { uintptr_t Address = (uintptr_t)VirtualAddress; Address &= 0xFFFFFFFFFFFFF000; diff --git a/Kernel/arch/amd64/syscalls.cpp b/Kernel/arch/amd64/syscalls.cpp index 4e750521..d2751d97 100644 --- a/Kernel/arch/amd64/syscalls.cpp +++ b/Kernel/arch/amd64/syscalls.cpp @@ -92,8 +92,8 @@ extern "C" __naked __used __no_stack_protector __aligned(16) void SystemCallHand void InitializeSystemCalls() { - wrmsr(MSR_EFER, rdmsr(MSR_EFER) | 1); - wrmsr(MSR_STAR, ((uint64_t)(GDT_KERNEL_CODE) << 32) | ((uint64_t)(GDT_KERNEL_DATA | 3) << 48)); - wrmsr(MSR_LSTAR, (uint64_t)SystemCallHandlerStub); - wrmsr(MSR_SYSCALL_MASK, (uint64_t)(1 << 9)); + CPU::x86::wrmsr(CPU::x86::MSR_EFER, CPU::x86::rdmsr(CPU::x86::MSR_EFER) | 1); + CPU::x86::wrmsr(CPU::x86::MSR_STAR, ((uint64_t)(GDT_KERNEL_CODE) << 32) | ((uint64_t)(GDT_KERNEL_DATA | 3) << 48)); + CPU::x86::wrmsr(CPU::x86::MSR_LSTAR, (uint64_t)SystemCallHandlerStub); + CPU::x86::wrmsr(CPU::x86::MSR_SYSCALL_MASK, (uint64_t)(1 << 9)); } diff --git a/Kernel/arch/amd64/tasking/signal.cpp b/Kernel/arch/amd64/tasking/signal.cpp new file mode 100644 index 00000000..912fbd2a --- /dev/null +++ b/Kernel/arch/amd64/tasking/signal.cpp @@ -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 . +*/ + +#include +#include +#include +#include + +#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 */ + } +} diff --git a/Kernel/arch/i386/core/panic/ui.cpp b/Kernel/arch/i386/core/panic/ui.cpp new file mode 100644 index 00000000..defa3c6e --- /dev/null +++ b/Kernel/arch/i386/core/panic/ui.cpp @@ -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 . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/Kernel/arch/i386/cpu/smp.cpp b/Kernel/arch/i386/cpu/smp.cpp index cf5dccd3..b678c0db 100644 --- a/Kernel/arch/i386/cpu/smp.cpp +++ b/Kernel/arch/i386/cpu/smp.cpp @@ -55,7 +55,7 @@ nsa CPUData *GetCurrentCPU() if (CPUEnabled.load(std::memory_order_acquire) == true) { if (apic->x2APIC) - CoreID = int(CPU::x32::rdmsr(CPU::x32::MSR_X2APIC_APICID)); + CoreID = int(CPU::x86::rdmsr(CPU::x86::MSR_X2APIC_APICID)); else CoreID = apic->Read(APIC::APIC_ID) >> 24; } diff --git a/Kernel/arch/i386/memory/vmm.cpp b/Kernel/arch/i386/memory/vmm.cpp index ec7a5bd7..a16eb084 100644 --- a/Kernel/arch/i386/memory/vmm.cpp +++ b/Kernel/arch/i386/memory/vmm.cpp @@ -29,7 +29,7 @@ namespace Memory Address &= 0xFFFFF000; PageMapIndexer Index = PageMapIndexer(Address); - PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; + PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex]; PageTableEntryPtr *PTE = nullptr; if ((PDE->raw & Flag) > 0) @@ -54,7 +54,7 @@ namespace Memory Address &= 0xFFFFF000; PageMapIndexer Index = PageMapIndexer(Address); - PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; + PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex]; PageTableEntryPtr *PTE = nullptr; if (PDE->Present) @@ -80,7 +80,7 @@ namespace Memory PageMapIndexer Index = PageMapIndexer(Address); - PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; + PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex]; PageTableEntryPtr *PTE = nullptr; if (PDE->Present) @@ -104,7 +104,7 @@ namespace Memory Address &= 0xFFFFF000; PageMapIndexer Index = PageMapIndexer(Address); - PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; + PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex]; if (PDE->Present) return PDE; return nullptr; @@ -116,7 +116,7 @@ namespace Memory Address &= 0xFFFFF000; PageMapIndexer Index = PageMapIndexer(Address); - PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; + PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex]; if (!PDE->Present) return nullptr; @@ -130,7 +130,7 @@ namespace Memory void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type) { SmartLock(this->MemoryLock); - if (unlikely(!this->Table)) + if (unlikely(!this->pTable)) { error("No page table"); 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 uint64_t DirectoryFlags = Flags & 0x3F; - PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; + PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex]; if (Type == MapType::FourMiB) { PDE->raw |= (uintptr_t)Flags; @@ -191,14 +191,14 @@ namespace Memory void Virtual::Unmap(void *VirtualAddress, MapType Type) { SmartLock(this->MemoryLock); - if (!this->Table) + if (!this->pTable) { error("No page table"); return; } PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress); - PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; + PageDirectoryEntry *PDE = &this->pTable->Entries[Index.PDEIndex]; if (!PDE->Present) { warn("Page %#lx not present", PDE->GetAddress()); @@ -223,4 +223,18 @@ namespace Memory PTEPtr->Entries[Index.PTEIndex] = PTE; 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); + } } diff --git a/Kernel/arch/i386/tasking/signal.cpp b/Kernel/arch/i386/tasking/signal.cpp new file mode 100644 index 00000000..ff5492f4 --- /dev/null +++ b/Kernel/arch/i386/tasking/signal.cpp @@ -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 . +*/ + +#include +#include +#include +#include + +#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 */ + } +} diff --git a/Kernel/arch/i386/tasking/signal_trampoline.s b/Kernel/arch/i386/tasking/signal_trampoline.s new file mode 100644 index 00000000..08a6e2f0 --- /dev/null +++ b/Kernel/arch/i386/tasking/signal_trampoline.s @@ -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 . +*/ + +.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: diff --git a/Kernel/core/cpu.cpp b/Kernel/core/cpu.cpp index 3d507af5..2bc4f120 100644 --- a/Kernel/core/cpu.cpp +++ b/Kernel/core/cpu.cpp @@ -313,7 +313,7 @@ namespace CPU CoreData->Data.FPU.mxcsr = 0b0001111110000000; CoreData->Data.FPU.mxcsrmask = 0b1111111110111111; CoreData->Data.FPU.fcw = 0b0000001100111111; - fxrstor(&CoreData->Data.FPU); + CPU::x86::fxrstor(&CoreData->Data.FPU); SSEEnableAfter = true; } @@ -378,7 +378,7 @@ namespace CPU debug("Updated CR4."); 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++) trace("Features for BSP initialized."); if (SSEEnableAfter) diff --git a/Kernel/core/driver/driver.cpp b/Kernel/core/driver/driver.cpp index cda5fea6..e75f28ef 100644 --- a/Kernel/core/driver/driver.cpp +++ b/Kernel/core/driver/driver.cpp @@ -245,8 +245,8 @@ namespace Driver debug("Driver %s has entry point %#lx and base %#lx", File->Name.c_str(), Drv.EntryPoint, Drv.BaseAddress); - Elf64_Shdr sht_strtab{}; - Elf64_Shdr sht_symtab{}; + Elf_Shdr sht_strtab{}; + Elf_Shdr sht_symtab{}; Elf_Shdr shstrtab{}; Elf_Shdr shdr{}; __DriverInfo driverInfo{}; diff --git a/Kernel/core/interrupts_manager.cpp b/Kernel/core/interrupts_manager.cpp index 15f05f19..d25e7f98 100644 --- a/Kernel/core/interrupts_manager.cpp +++ b/Kernel/core/interrupts_manager.cpp @@ -114,13 +114,13 @@ namespace Interrupts void Initialize(int Core) { -#if defined(__amd64__) +#if defined(__amd64__) || defined(__i386__) GlobalDescriptorTable::Init(Core); InterruptDescriptorTable::Init(Core); CPUData *CoreData = GetCPU(Core); CoreData->Checksum = CPU_DATA_CHECKSUM; - CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, (uint64_t)CoreData); - CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData); + CPU::x86::wrmsr(CPU::x86::MSR_GS_BASE, (uint64_t)CoreData); + CPU::x86::wrmsr(CPU::x86::MSR_SHADOW_GS_BASE, (uint64_t)CoreData); CoreData->ID = Core; CoreData->IsActive = true; 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)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE); 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__) warn("aarch64 is not supported yet"); #endif diff --git a/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c b/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c index 11e6b0f2..e155c96f 100644 --- a/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c +++ b/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c @@ -551,7 +551,9 @@ struct heap_t }; /* Keep in sync with heap_t inside rpmalloc_compat.cpp */ +#ifndef __i386__ static_assert(sizeof(heap_t) == 56408, "heap_t size mismatch"); +#endif // __i386__ // Size class for defining a block size bucket struct size_class_t diff --git a/Kernel/core/memory/page_table.cpp b/Kernel/core/memory/page_table.cpp index 36620601..d4ab3d7f 100644 --- a/Kernel/core/memory/page_table.cpp +++ b/Kernel/core/memory/page_table.cpp @@ -73,7 +73,7 @@ namespace Memory } } #else -#error "PageTable::Fork() not implemented for other architectures" +#warning "PageTable::Fork() not implemented for other architectures" #endif debug("Forked page table %#lx to %#lx", this, NewTable); diff --git a/Kernel/core/memory/vma.cpp b/Kernel/core/memory/vma.cpp index 03074b73..87dc9494 100644 --- a/Kernel/core/memory/vma.cpp +++ b/Kernel/core/memory/vma.cpp @@ -236,7 +236,9 @@ namespace Memory assert(pte->Present == true); pte->ReadWrite = sr.Write; pte->UserSupervisor = sr.Read; +#if defined(__amd64__) pte->ExecuteDisable = sr.Exec; +#endif pte->CopyOnWrite = false; debug("PFA %#lx is CoW (pt %#lx, flags %#lx)", diff --git a/Kernel/core/panic/handler.cpp b/Kernel/core/panic/handler.cpp index 5ca3f022..788dab10 100644 --- a/Kernel/core/panic/handler.cpp +++ b/Kernel/core/panic/handler.cpp @@ -100,7 +100,7 @@ nsa void HaltAllCores() if (SMP::CPUCores <= 1) return; -#if defined(__amd64__) || defined(__i386__) +#if defined(__amd64__) if (Interrupts::apic[0] == nullptr) return; diff --git a/Kernel/core/panic/kbd/xhci.cpp b/Kernel/core/panic/kbd/xhci.cpp index 36bd8506..7e8177cd 100644 --- a/Kernel/core/panic/kbd/xhci.cpp +++ b/Kernel/core/panic/kbd/xhci.cpp @@ -140,9 +140,9 @@ nsa CrashXHCIKeyboardDriver::CrashXHCIKeyboardDriver(PCIDevice xhci) 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) - baseAddress |= (uintptr_t)BAR[1] << 32; + baseAddress |= (uint64_t)BAR[1] << 32; if (baseAddress & 0x1) baseAddress &= 0xFFFFFFFFFFFFFFFC; @@ -158,7 +158,7 @@ nsa CrashXHCIKeyboardDriver::CrashXHCIKeyboardDriver(PCIDevice xhci) runtime = (XHCIruntime *)(baseAddress + (caps->RTSOFF & ~0x1F)); doorbell = (XHCIdoorbell *)(baseAddress + (caps->DBOFF & ~0x3)); 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); #pragma GCC diagnostic push diff --git a/Kernel/core/panic/ui.cpp b/Kernel/core/panic/ui.cpp index 73b95fc7..af37abd6 100644 --- a/Kernel/core/panic/ui.cpp +++ b/Kernel/core/panic/ui.cpp @@ -95,17 +95,6 @@ x86ExceptionName x86Exceptions[] = { /*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; char __modSym[20]; @@ -139,9 +128,19 @@ nsa const char *ExGetKSymbolByAddress(uintptr_t Address) nsa const char *ExGetKSymbol(CPU::ExceptionFrame *Frame) { +#if defined(__amd64__) if (Frame->rip < (uintptr_t)&_kernel_start && Frame->rip > (uintptr_t)&_kernel_end) return ""; +#elif defined(__i386__) + if (Frame->eip < (uintptr_t)&_kernel_start && + Frame->eip > (uintptr_t)&_kernel_end) + return ""; +#elif defined(__aarch64__) + if (Frame->pc < (uintptr_t)&_kernel_start && + Frame->pc > (uintptr_t)&_kernel_end) + return ""; +#endif #if defined(__amd64__) return ExGetKSymbolByAddress(Frame->rip); @@ -338,94 +337,7 @@ nsa void DisplayMainScreen(CPU::ExceptionFrame *Frame) ExPrint("\nUse command 'diag' to create a diagnostic report.\n"); } -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); -} +arch void DisplayDetailsScreen(CPU::ExceptionFrame *Frame); nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame) { diff --git a/Kernel/include/cpu.hpp b/Kernel/include/cpu.hpp index 15167679..490ab86a 100644 --- a/Kernel/include/cpu.hpp +++ b/Kernel/include/cpu.hpp @@ -23,13 +23,13 @@ #include #include #include -#include #include -#include #include #include #include +#include #include +#include #include /** @@ -211,6 +211,41 @@ namespace CPU /** @brief Get CPU counter value. */ 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 { /** @@ -294,24 +329,83 @@ namespace CPU struct TrapFrame { - uint32_t edi; // Destination index for string operations - uint32_t esi; // Source index for string operations - uint32_t ebp; // Base Pointer (meant for stack frames) - uint32_t esp; // Stack Pointer - uint32_t ebx; // Base - uint32_t edx; // Data (commonly extends the A register) - uint32_t ecx; // Counter - uint32_t eax; // Accumulator + uint32_t edi; /* Destination index for string operations */ + uint32_t esi; /* Source index for string operations */ + uint32_t ebp; /* Base Pointer (meant for stack frames) */ + uint32_t ebx; /* Base */ + uint32_t edx; /* Data (commonly extends the A register) */ + uint32_t ecx; /* Counter */ + uint32_t eax; /* Accumulator */ - uint32_t InterruptNumber; // Interrupt Number - uint32_t ErrorCode; // Error code + 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 eip; /* Instruction Pointer */ + uint32_t cs; /* Code Segment */ + EFLAGS eflags; /* Register Flags */ + uint32_t esp; /* Stack Pointer */ + uint32_t ss; /* Stack Segment */ + }; - uint32_t r3_esp; // Stack Pointer - uint32_t r3_ss; // Stack Segment + struct SchedulerFrame + { + 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 @@ -319,27 +413,27 @@ namespace CPU struct { /** @brief Breakpoint #0 Condition Detected */ - uint64_t B0 : 1; + uint32_t B0 : 1; /** @brief Breakpoint #1 Condition Detected */ - uint64_t B1 : 1; + uint32_t B1 : 1; /** @brief Breakpoint #2 Condition Detected */ - uint64_t B2 : 1; + uint32_t B2 : 1; /** @brief Breakpoint #3 Condition Detected */ - uint64_t B3 : 1; + uint32_t B3 : 1; /** @brief Reserved */ - uint64_t Reserved0 : 8; + uint32_t Reserved0 : 8; /** @brief Reserved */ - uint64_t Reserved1 : 1; + uint32_t Reserved1 : 1; /** @brief Breakpoint Debug Access Detected */ - uint64_t BD : 1; + uint32_t BD : 1; /** @brief Breakpoint Single Step */ - uint64_t BS : 1; + uint32_t BS : 1; /** @brief Breakpoint Task Switch */ - uint64_t BT : 1; + uint32_t BT : 1; /** @brief Reserved */ - uint64_t Reserved2 : 15; + uint32_t Reserved2 : 15; }; - uint64_t raw; + uint32_t raw; } DR6; typedef union DR7 @@ -978,32 +1072,6 @@ namespace CPU cpuid(0x0, &eax, &ebx, &ecx, &edx); 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 diff --git a/Kernel/include/cpu/x86/x64/msr.hpp b/Kernel/include/cpu/x86/msr.hpp similarity index 91% rename from Kernel/include/cpu/x86/x64/msr.hpp rename to Kernel/include/cpu/x86/msr.hpp index 8b54418f..3390bcd1 100644 --- a/Kernel/include/cpu/x86/x64/msr.hpp +++ b/Kernel/include/cpu/x86/msr.hpp @@ -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 - 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 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. + 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 . + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . */ #ifndef __FENNIX_KERNEL_CPU_x64_MSR_H__ @@ -22,7 +22,7 @@ namespace CPU { - namespace x64 + namespace x86 { enum MSRID { @@ -420,6 +420,25 @@ namespace CPU : "c"(msr), "a"(Low), "d"(High) : "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 } } diff --git a/Kernel/include/cpu/x86/x32/cr.hpp b/Kernel/include/cpu/x86/x32/cr.hpp index d650c5e9..98b87b5d 100644 --- a/Kernel/include/cpu/x86/x32/cr.hpp +++ b/Kernel/include/cpu/x86/x32/cr.hpp @@ -174,14 +174,6 @@ namespace CPU 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) { asmv("mov %[ControlRegister], %%cr0" @@ -213,14 +205,6 @@ namespace CPU : [ControlRegister] "q"(ControlRegister.raw) : "memory"); } - - nsa static inline void writecr8(CR8 ControlRegister) - { - asmv("mov %[ControlRegister], %%cr8" - : - : [ControlRegister] "q"(ControlRegister.raw) - : "memory"); - } #endif } } diff --git a/Kernel/include/cpu/x86/x32/msr.hpp b/Kernel/include/cpu/x86/x32/msr.hpp deleted file mode 100644 index 42244b88..00000000 --- a/Kernel/include/cpu/x86/x32/msr.hpp +++ /dev/null @@ -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 . -*/ - -#ifndef __FENNIX_KERNEL_CPU_x32_MSR_H__ -#define __FENNIX_KERNEL_CPU_x32_MSR_H__ - -#include - -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__ diff --git a/Kernel/include/interface/fs.h b/Kernel/include/interface/fs.h index 27718cd7..23e19f14 100644 --- a/Kernel/include/interface/fs.h +++ b/Kernel/include/interface/fs.h @@ -146,10 +146,10 @@ static_assert(sizeof(blkcnt_t) == 8, "blkcnt_t must be 64 bits"); #else 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(mode_t) == 2, "mode_t must be 16 bits"); -static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits"); -static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits"); -static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits"); +static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits"); +static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits"); +static_assert(sizeof(uid_t) == 4, "uid_t must be 32 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(time_t) == 4, "time_t must be 32 bits"); static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits"); diff --git a/Kernel/include/interface/syscalls.h b/Kernel/include/interface/syscalls.h index bde19d03..d0cab647 100644 --- a/Kernel/include/interface/syscalls.h +++ b/Kernel/include/interface/syscalls.h @@ -33,10 +33,16 @@ static inline scarg syscall0(scarg syscall) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif return ret; } @@ -52,10 +58,16 @@ static inline scarg syscall0(scarg syscall) static inline scarg syscall1(scarg syscall, scarg arg1) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif return ret; } @@ -72,10 +84,16 @@ static inline scarg syscall1(scarg syscall, scarg arg1) static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) register scarg r10 __asm__("r10") = arg4; __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) register scarg r10 __asm__("r10") = arg4; register scarg r8 __asm__("r8") = arg5; __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) register scarg r10 __asm__("r10") = arg4; register scarg r8 __asm__("r8") = arg5; 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"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif return ret; } diff --git a/Kernel/include/memory/virtual.hpp b/Kernel/include/memory/virtual.hpp index aa336421..4afc5d65 100644 --- a/Kernel/include/memory/virtual.hpp +++ b/Kernel/include/memory/virtual.hpp @@ -61,7 +61,7 @@ namespace Memory * @param Flag Flag to check * @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. diff --git a/Kernel/include/signal.hpp b/Kernel/include/signal.hpp index bbafb57d..3b338452 100644 --- a/Kernel/include/signal.hpp +++ b/Kernel/include/signal.hpp @@ -249,7 +249,7 @@ namespace Tasking #else CPU::x32::FXState fx; CPU::x32::SchedulerFrame tf; - uintptr_t GSBase, FSBase; + uintptr_t GSBase, FSBase, ShadowGSBase; #endif sigset_t SignalMask; int Compatibility; @@ -354,8 +354,8 @@ namespace Tasking int AddSignal(signal_t sig, union sigval val = {0}, pid_t tid = -1); int RemoveSignal(signal_t sig); - bool HandleSignal(CPU::SchedulerFrame *tf, void *thread); - void RestoreHandleSignal(SyscallsFrame *tf, void *thread); + arch bool HandleSignal(CPU::SchedulerFrame *tf, void *thread); + arch void RestoreHandleSignal(SyscallsFrame *tf, void *thread); int SetAction(signal_t sig, const SignalAction *act); int GetAction(signal_t sig, SignalAction *act); diff --git a/Kernel/include/task.hpp b/Kernel/include/task.hpp index eb3cc68d..cf3ab26e 100644 --- a/Kernel/include/task.hpp +++ b/Kernel/include/task.hpp @@ -355,11 +355,10 @@ namespace Tasking ThreadSignal Signals; /* CPU state */ + CPU::SchedulerFrame Registers{}; #if defined(__amd64__) - CPU::x64::SchedulerFrame Registers{}; uintptr_t ShadowGSBase, GSBase, FSBase; #elif defined(__i386__) - CPU::x32::SchedulerFrame Registers{}; uintptr_t ShadowGSBase, GSBase, FSBase; #elif defined(__aarch64__) uintptr_t Registers; // TODO diff --git a/Kernel/include/types.h b/Kernel/include/types.h index 2438007c..5b782c42 100644 --- a/Kernel/include/types.h +++ b/Kernel/include/types.h @@ -20,6 +20,14 @@ #include +/** + * 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//... + */ +#define arch + #ifdef __cplusplus #define EXTERNC extern "C" #define START_EXTERNC \ @@ -166,17 +174,17 @@ typedef int32_t pid_t; #elif defined(__i386__) typedef int32_t off_t; typedef long long off64_t; -typedef __INT32_TYPE__ mode_t; +typedef uint32_t mode_t; typedef int32_t dev_t; typedef int32_t ino64_t; typedef int32_t ino_t; -typedef unsigned int nlink_t; +typedef uint32_t nlink_t; typedef int blksize_t; typedef int32_t blkcnt_t; typedef int32_t blkcnt64_t; typedef int32_t time_t; -typedef unsigned uid_t; -typedef unsigned gid_t; +typedef uint32_t uid_t; +typedef uint32_t gid_t; typedef long clock_t; typedef int pid_t; #endif diff --git a/Kernel/library/simd_memset.cpp b/Kernel/library/simd_memset.cpp index a5647aad..acb3fdde 100644 --- a/Kernel/library/simd_memset.cpp +++ b/Kernel/library/simd_memset.cpp @@ -54,6 +54,7 @@ EXTERNC void *memset_sse2(void *dest, int c, size_t n) for (; i + 64 <= n; i += 64) { +#if defined(__amd64__) asmv("movd %0, %%xmm0\n" "movdqa %%xmm0, (%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) : "xmm0"); +#else +#warning "memset_sse2 not implemented for other arch" +#endif } asmv("rep stosb\n" ::"a"((size_t)(c)), diff --git a/Kernel/subsystem/linux/syscall.cpp b/Kernel/subsystem/linux/syscall.cpp index 031d6b14..60c970ff 100644 --- a/Kernel/subsystem/linux/syscall.cpp +++ b/Kernel/subsystem/linux/syscall.cpp @@ -627,9 +627,15 @@ void SetSigActToNative(const k_sigaction *linux, SignalAction *native) native->Flags = linux->flags; native->Restorer = linux->restorer; +#if defined(__amd64__) unsigned long mask = ((unsigned long)linux->mask[1] << 32) | linux->mask[0]; native->Mask = std::bitset<64>(ConvertMaskToNative(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) @@ -638,12 +644,18 @@ void SetSigActToLinux(const SignalAction *native, k_sigaction *linux) linux->flags = native->Flags; linux->restorer = native->Restorer; +#if defined(__amd64__) unsigned long mask = native->Mask.to_ulong(); mask = ConvertMaskToLinux(mask); linux->mask[0] = mask & 0xFFFFFFFF; linux->mask[1] = (uint32_t)((mask >> 32) & 0xFFFFFFFF); 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) @@ -2501,41 +2513,31 @@ static int linux_arch_prctl(SysFrm *, int code, unsigned long addr) { case linux_ARCH_SET_GS: { -#if defined(__amd64__) - CPU::x64::wrmsr(CPU::x64::MSRID::MSR_GS_BASE, addr); -#elif defined(__i386__) - CPU::x32::wrmsr(CPU::x32::MSRID::MSR_GS_BASE, addr); +#if defined(__amd64__) || defined(__i386__) + CPU::x86::wrmsr(CPU::x86::MSRID::MSR_GS_BASE, addr); #endif return 0; } case linux_ARCH_SET_FS: { -#if defined(__amd64__) - CPU::x64::wrmsr(CPU::x64::MSRID::MSR_FS_BASE, addr); -#elif defined(__i386__) - CPU::x32::wrmsr(CPU::x32::MSRID::MSR_FS_BASE, addr); +#if defined(__amd64__) || defined(__i386__) + CPU::x86::wrmsr(CPU::x86::MSRID::MSR_FS_BASE, addr); #endif return 0; } case linux_ARCH_GET_FS: { -#if defined(__amd64__) +#if defined(__amd64__) || defined(__i386__) *r_cst(uint64_t *, addr) = - CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); -#elif defined(__i386__) - *r_cst(uint64_t *, addr) = - CPU::x32::rdmsr(CPU::x32::MSRID::MSR_FS_BASE); + CPU::x86::rdmsr(CPU::x86::MSRID::MSR_FS_BASE); #endif return 0; } case linux_ARCH_GET_GS: { -#if defined(__amd64__) +#if defined(__amd64__) || defined(__i386__) *r_cst(uint64_t *, addr) = - CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); -#elif defined(__i386__) - *r_cst(uint64_t *, addr) = - CPU::x32::rdmsr(CPU::x32::MSRID::MSR_GS_BASE); + CPU::x86::rdmsr(CPU::x86::MSRID::MSR_GS_BASE); #endif return 0; } @@ -2899,13 +2901,17 @@ __no_sanitize("undefined") static ssize_t linux_getdents64(SysFrm *, if (pDirp == nullptr) return -linux_EFAULT; - /* Sanity checks */ +/* Sanity checks */ +#ifdef __LP64__ static_assert(sizeof(kdirent) == sizeof(linux_dirent64)); 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_reclen) == offsetof(linux_dirent64, d_reclen)); static_assert(offsetof(kdirent, d_type) == offsetof(linux_dirent64, d_type)); 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. */ 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); return sc_ret; #elif defined(__i386__) - if (Frame->eax > sizeof(LinuxSyscallsTableI386) / sizeof(SyscallData)) + if (Frame->ax > sizeof(LinuxSyscallsTableI386) / sizeof(SyscallData)) { fixme("Syscall %d not implemented", - Frame->eax); + Frame->ax); return -linux_ENOSYS; } - SyscallData Syscall = LinuxSyscallsTableI386[Frame->eax]; + SyscallData Syscall = LinuxSyscallsTableI386[Frame->ax]; long (*call)(SysFrm *, long, ...) = r_cst(long (*)(SysFrm *, long, ...), Syscall.Handler); @@ -4305,20 +4311,20 @@ uintptr_t HandleLinuxSyscalls(SyscallsFrame *Frame) if (unlikely(!call)) { fixme("Syscall %s(%d) not implemented", - Syscall.Name, Frame->eax); + Syscall.Name, Frame->ax); return -linux_ENOSYS; } debug("> [%d:\"%s\"]( %#lx %#lx %#lx %#lx %#lx %#lx )", - Frame->eax, Syscall.Name, - Frame->ebx, Frame->ecx, Frame->edx, - Frame->esi, Frame->edi, Frame->ebp); + Frame->ax, Syscall.Name, + Frame->bx, Frame->cx, Frame->dx, + Frame->si, Frame->di, Frame->bp); int sc_ret = call(Frame, - Frame->ebx, Frame->ecx, Frame->edx, - Frame->esi, Frame->edi, Frame->ebp); + Frame->bx, Frame->cx, Frame->dx, + 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; #elif defined(__aarch64__) return -linux_ENOSYS; diff --git a/Kernel/syscalls/native.cpp b/Kernel/syscalls/native.cpp index 9a8649c8..abdf91e3 100644 --- a/Kernel/syscalls/native.cpp +++ b/Kernel/syscalls/native.cpp @@ -255,19 +255,15 @@ static int sys_prctl(SysFrm *Frame, prctl_options_t option, unsigned long arg1, if (arg == nullptr) return -EFAULT; -#if defined(__amd64__) - *r_cst(uintptr_t *, arg) = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); -#elif defined(__i386__) - *r_cst(uintptr_t *, arg) = CPU::x32::rdmsr(CPU::x32::MSRID::MSR_GS_BASE); +#if defined(__amd64__) || defined(__i386__) + *r_cst(uintptr_t *, arg) = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_GS_BASE); #endif return 0; } case __SYS_SET_GS: { -#if defined(__amd64__) - CPU::x64::wrmsr(CPU::x64::MSRID::MSR_GS_BASE, arg1); -#elif defined(__i386__) - CPU::x32::wrmsr(CPU::x32::MSRID::MSR_GS_BASE, arg1); +#if defined(__amd64__) || defined(__i386__) + CPU::x86::wrmsr(CPU::x86::MSRID::MSR_GS_BASE, arg1); #endif return 0; } @@ -277,19 +273,15 @@ static int sys_prctl(SysFrm *Frame, prctl_options_t option, unsigned long arg1, if (arg == nullptr) return -EFAULT; -#if defined(__amd64__) - *r_cst(uintptr_t *, arg) = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); -#elif defined(__i386__) - *r_cst(uintptr_t *, arg) = CPU::x32::rdmsr(CPU::x32::MSRID::MSR_FS_BASE); +#if defined(__amd64__) || defined(__i386__) + *r_cst(uintptr_t *, arg) = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_FS_BASE); #endif return 0; } case __SYS_SET_FS: { -#if defined(__amd64__) - CPU::x64::wrmsr(CPU::x64::MSRID::MSR_FS_BASE, arg1); -#elif defined(__i386__) - CPU::x32::wrmsr(CPU::x32::MSRID::MSR_FS_BASE, arg1); +#if defined(__amd64__) || defined(__i386__) + CPU::x86::wrmsr(CPU::x86::MSRID::MSR_FS_BASE, arg1); #endif return 0; } diff --git a/Kernel/tasking/scheduler/custom.cpp b/Kernel/tasking/scheduler/custom.cpp index 4558f1b9..3153923c 100644 --- a/Kernel/tasking/scheduler/custom.cpp +++ b/Kernel/tasking/scheduler/custom.cpp @@ -195,7 +195,7 @@ namespace Tasking::Scheduler void Custom::StartScheduler() { -#if defined(__amd64__) || defined(__i386__) +#if defined(__amd64__) if (Interrupts::apicTimer[0]) { ((APIC::Timer *)Interrupts::apicTimer[0])->OneShot(CPU::x86::IRQ16, 100); @@ -587,15 +587,11 @@ namespace Tasking::Scheduler else { CurrentCPU->CurrentThread->Registers = *Frame; - CPU::x64::fxsave(&CurrentCPU->CurrentThread->FPU); -#ifdef __amd64__ - CurrentCPU->CurrentThread->ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSR_SHADOW_GS_BASE); - CurrentCPU->CurrentThread->GSBase = CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE); - CurrentCPU->CurrentThread->FSBase = CPU::x64::rdmsr(CPU::x64::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)); +#if defined(__amd64__) || defined(__i386__) + CPU::x86::fxsave(&CurrentCPU->CurrentThread->FPU); + CurrentCPU->CurrentThread->ShadowGSBase = CPU::x86::rdmsr(CPU::x86::MSR_SHADOW_GS_BASE); + CurrentCPU->CurrentThread->GSBase = CPU::x86::rdmsr(CPU::x86::MSR_GS_BASE); + CurrentCPU->CurrentThread->FSBase = CPU::x86::rdmsr(CPU::x86::MSR_FS_BASE); #endif if (CurrentCPU->CurrentProcess->State.load() == TaskState::Running) @@ -681,18 +677,12 @@ namespace Tasking::Scheduler *Frame = CurrentCPU->CurrentThread->Registers; -#ifdef __amd64__ +#if defined(__amd64__) || defined(__i386__) GlobalDescriptorTable::SetKernelStack((void *)((uintptr_t)CurrentCPU->CurrentThread->Stack->GetStackTop())); - CPU::x64::fxrstor(&CurrentCPU->CurrentThread->FPU); - CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->ShadowGSBase); - CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, CurrentCPU->CurrentThread->GSBase); - CPU::x64::wrmsr(CPU::x64::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); + CPU::x86::fxrstor(&CurrentCPU->CurrentThread->FPU); + CPU::x86::wrmsr(CPU::x86::MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->ShadowGSBase); + CPU::x86::wrmsr(CPU::x86::MSR_GS_BASE, CurrentCPU->CurrentThread->GSBase); + CPU::x86::wrmsr(CPU::x86::MSR_FS_BASE, CurrentCPU->CurrentThread->FSBase); #endif CurrentCPU->CurrentProcess->Signals.HandleSignal(Frame, CurrentCPU->CurrentThread.load()); diff --git a/Kernel/tasking/signal.cpp b/Kernel/tasking/signal.cpp index 488b5fa8..765bee9c 100644 --- a/Kernel/tasking/signal.cpp +++ b/Kernel/tasking/signal.cpp @@ -20,13 +20,6 @@ #include #include -#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" #ifdef DEBUG @@ -344,149 +337,6 @@ namespace Tasking 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) { SmartLock(SignalLock); diff --git a/Kernel/tasking/task.cpp b/Kernel/tasking/task.cpp index 0f42053b..6b051ed3 100644 --- a/Kernel/tasking/task.cpp +++ b/Kernel/tasking/task.cpp @@ -222,12 +222,12 @@ namespace Tasking TCB *Task::CreateThread(PCB *Parent, IP EntryPoint, const char **argv, const char **envp, const std::vector &auxv, - TaskArchitecture arch, TaskCompatibility Compatibility, + TaskArchitecture _arch, TaskCompatibility Compatibility, bool ThreadNotReady) { SmartLock(TaskingLock); return new TCB(this, Parent, EntryPoint, - argv, envp, auxv, arch, + argv, envp, auxv, _arch, Compatibility, ThreadNotReady); } diff --git a/Kernel/tasking/thread.cpp b/Kernel/tasking/thread.cpp index 374d0b1e..d15a9421 100644 --- a/Kernel/tasking/thread.cpp +++ b/Kernel/tasking/thread.cpp @@ -485,9 +485,9 @@ namespace Tasking #if defined(__amd64__) this->ShadowGSBase = - CPU::x64::rdmsr(CPU::x64::MSRID::MSR_SHADOW_GS_BASE); - this->GSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_GS_BASE); - this->FSBase = CPU::x64::rdmsr(CPU::x64::MSRID::MSR_FS_BASE); + CPU::x86::rdmsr(CPU::x86::MSRID::MSR_SHADOW_GS_BASE); + this->GSBase = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_GS_BASE); + this->FSBase = CPU::x86::rdmsr(CPU::x86::MSRID::MSR_FS_BASE); this->Registers.cs = GDT_KERNEL_CODE; this->Registers.ss = GDT_KERNEL_DATA; this->Registers.rflags.AlwaysOne = 1; @@ -498,7 +498,7 @@ namespace Tasking POKE(uintptr_t, this->Registers.rsp) = (uintptr_t)ThreadDoExit; #elif defined(__i386__) 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.IF = 1; this->Registers.eflags.ID = 1; @@ -520,7 +520,13 @@ namespace Tasking this->ctx->va.MapTo(gst, this->Parent->PageTable); gsTCB *gsT = (gsTCB *)gst.PhysicalAddress; #ifdef DEBUG +#if defined(__amd64__) gsT->__stub = 0xFFFFFFFFFFFFFFFF; +#elif defined(__i386__) + gsT->__stub = 0xFFFFFFFF; +#elif defined(__aarch64__) + gsT->__stub = 0xFFFFFFFFFFFFFFFF; +#endif #endif gsT->ScPages = TO_PAGES(STACK_SIZE); @@ -552,7 +558,7 @@ namespace Tasking this->SetupUserStack_x86_64(argv, envp, auxv, Compatibility); #elif defined(__i386__) 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.IF = 1; this->Registers.eflags.ID = 1; @@ -562,9 +568,9 @@ namespace Tasking is exited or we are going to get an exception. */ - this->SetupUserStack_x86_32(argv, envp, auxv); + this->SetupUserStack_x86_32(argv, envp, auxv, Compatibility); #elif defined(__aarch64__) - this->SetupUserStack_aarch64(argv, envp, auxv); + this->SetupUserStack_aarch64(argv, envp, auxv, Compatibility); #endif #ifdef DEBUG_TASKING DumpData(this->Name, this->Stack, STACK_SIZE); diff --git a/Kernel/tty/vt.cpp b/Kernel/tty/vt.cpp index ded1eed1..15db878c 100644 --- a/Kernel/tty/vt.cpp +++ b/Kernel/tty/vt.cpp @@ -121,9 +121,6 @@ namespace KernelConsole switch (Request) { - case 0xffffffff80045430: /* FIXME: ???? */ - debug("???"); - [[fallthrough]]; case TIOCGPTN: { fixme("stub ioctl TIOCGPTN"); diff --git a/LICENSES.md b/LICENSES.md index 621bdaf2..4208f37b 100644 --- a/LICENSES.md +++ b/LICENSES.md @@ -54,6 +54,11 @@ Make sure to read and comply with these licenses before using or redistributing - **License:** Unlicense and 0BSD - **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. diff --git a/Userspace/Makefile b/Userspace/Makefile index 1c4dccfd..1b5d48a4 100644 --- a/Userspace/Makefile +++ b/Userspace/Makefile @@ -14,7 +14,7 @@ export LDFLAGS := --sysroot=$(WORKSPACE_DIR)/out/ \ export CFLAGS := \ --sysroot=$(WORKSPACE_DIR)/out/ \ -I$(WORKSPACE_DIR)/out/include \ - -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm + -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always else # DEBUG diff --git a/Userspace/apps/test/utest/userspace_test.c b/Userspace/apps/test/utest/userspace_test.c index efae0af1..e99e366a 100644 --- a/Userspace/apps/test/utest/userspace_test.c +++ b/Userspace/apps/test/utest/userspace_test.c @@ -92,10 +92,12 @@ typedef struct static __inline long __musl_syscall1(long n, long a1) { unsigned long ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); +#endif return ret; } diff --git a/Userspace/libc/include/fennix/syscalls.h b/Userspace/libc/include/fennix/syscalls.h index bde19d03..d0cab647 100644 --- a/Userspace/libc/include/fennix/syscalls.h +++ b/Userspace/libc/include/fennix/syscalls.h @@ -33,10 +33,16 @@ static inline scarg syscall0(scarg syscall) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif return ret; } @@ -52,10 +58,16 @@ static inline scarg syscall0(scarg syscall) static inline scarg syscall1(scarg syscall, scarg arg1) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif return ret; } @@ -72,10 +84,16 @@ static inline scarg syscall1(scarg syscall, scarg arg1) static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) register scarg r10 __asm__("r10") = arg4; __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) register scarg r10 __asm__("r10") = arg4; register scarg r8 __asm__("r8") = arg5; __asm__ __volatile__("syscall" : "=a"(ret) : "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif 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) { scarg ret; +#if defined(__amd64__) register scarg r10 __asm__("r10") = arg4; register scarg r8 __asm__("r8") = arg5; 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"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); +#elif defined(__i386__) +#warning "i386 syscall wrapper not implemented" +#else +#error "Unsupported architecture" +#endif return ret; } diff --git a/Userspace/libc/interpreter/Makefile b/Userspace/libc/interpreter/Makefile index d68811a5..27713cc1 100644 --- a/Userspace/libc/interpreter/Makefile +++ b/Userspace/libc/interpreter/Makefile @@ -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)"' ifeq ($(DEBUG), 1) - CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm + CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always endif build: $(OBJECT_NAME) diff --git a/Userspace/libc/interpreter/load.c b/Userspace/libc/interpreter/load.c index 4670a75d..ce8e7dd8 100644 --- a/Userspace/libc/interpreter/load.c +++ b/Userspace/libc/interpreter/load.c @@ -124,6 +124,7 @@ ElfInfo *SearchLib(char *Path) __attribute__((naked, used, no_stack_protector)) void _dl_runtime_resolve() { +#if defined(__amd64__) __asm__( "pop %r11\n" /* Pop lazy resolve arguments */ "pop %r10\n" @@ -148,6 +149,11 @@ __attribute__((naked, used, no_stack_protector)) void _dl_runtime_resolve() "pop %rdi\n" "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); @@ -561,7 +567,7 @@ int CheckElfEhdr(Elf_Ehdr *ehdr, char *Path) if (ehdr->e_ident[EI_CLASS] != elfClass) { printf("dl: %s is not a %s-bit ELF file\n", - Path, __LP64__ ? "64" : "32"); + Path, elfClass == ELFCLASS64 ? "64" : "32"); return -EINVAL; } @@ -804,6 +810,7 @@ int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated) addAddend = 1; break; } +#if __LP64__ case R_DTPMOD64: { 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; break; } +#endif // __LP64__ default: { printf("dl: Unsupported relocation type %d\n", relType); diff --git a/Userspace/libc/interpreter/start.c b/Userspace/libc/interpreter/start.c index 4b695a61..f2b44cb2 100644 --- a/Userspace/libc/interpreter/start.c +++ b/Userspace/libc/interpreter/start.c @@ -99,6 +99,7 @@ void __fini_print_buffer(); __attribute__((naked, used, no_stack_protector)) void _start() { +#if defined(__amd64__) __asm__( "xorq %rbp, %rbp\n" /* Clear rbp */ @@ -125,14 +126,21 @@ __attribute__((naked, used, no_stack_protector)) void _start() "call main\n" /* Call _dl_main */ "movl %eax, %edi\n" /* Move return value to edi */ "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) { __fini_print_buffer(); 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"); +#endif __builtin_unreachable(); } diff --git a/Userspace/libc/runtime/Scrt1.c b/Userspace/libc/runtime/Scrt1.c index 671767b1..20837a53 100644 --- a/Userspace/libc/runtime/Scrt1.c +++ b/Userspace/libc/runtime/Scrt1.c @@ -39,6 +39,7 @@ void __crt_fini_array(void) __attribute__((naked, used, no_stack_protector, section(".text"))) void _start() { +#if defined(__amd64__) asm("movq $0, %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" "call _exit\n"); +#elif defined(__i386__) +#warning "i386 _start not implemented" +#else +#error "Unsupported architecture" +#endif } /* These are declared in GNU ld */ diff --git a/Userspace/libc/runtime/crt1.c b/Userspace/libc/runtime/crt1.c index 671767b1..20837a53 100644 --- a/Userspace/libc/runtime/crt1.c +++ b/Userspace/libc/runtime/crt1.c @@ -39,6 +39,7 @@ void __crt_fini_array(void) __attribute__((naked, used, no_stack_protector, section(".text"))) void _start() { +#if defined(__amd64__) asm("movq $0, %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" "call _exit\n"); +#elif defined(__i386__) +#warning "i386 _start not implemented" +#else +#error "Unsupported architecture" +#endif } /* These are declared in GNU ld */ diff --git a/Userspace/libc/src/Makefile b/Userspace/libc/src/Makefile index 9ce59780..fca5c2bd 100644 --- a/Userspace/libc/src/Makefile +++ b/Userspace/libc/src/Makefile @@ -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)"' ifeq ($(DEBUG), 1) - CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm + CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always endif build: $(DYNAMIC_NAME) $(STATIC_NAME) diff --git a/Userspace/libc/src/arith64.c b/Userspace/libc/src/arith64.c new file mode 100644 index 00000000..1a7ff727 --- /dev/null +++ b/Userspace/libc/src/arith64.c @@ -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 . +*/ + +#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 diff --git a/Userspace/libc/src/main.c b/Userspace/libc/src/main.c index 47d12bd0..591f0fba 100644 --- a/Userspace/libc/src/main.c +++ b/Userspace/libc/src/main.c @@ -114,6 +114,7 @@ void __crt_fini_array(void) __attribute__((naked, used, no_stack_protector, section(".text"))) void _start() { +#if defined(__amd64__) asm("movq $0, %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" "call _exit\n"); +#elif defined(__i386__) +#warning "i386 _start not implemented" +#else +#warning "unknown architecture" +#endif } int main(int argc, char *argv[], char *envp[]) diff --git a/config.mk b/config.mk index 1e697c58..3bf48d6f 100644 --- a/config.mk +++ b/config.mk @@ -6,7 +6,7 @@ DEBUG = 1 OSNAME = Fennix # OS architecture, check AVAILABLE_ARCHS for available options. -OSARCH = i386 +OSARCH = amd64 # Kernel version. KERNEL_VERSION = dev