mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-01 18:39:16 +00:00
refactor: Fix build on i386
Some checks failed
CodeQL Advanced / Analyze (${{ matrix.language }}) (manual, c-cpp) (push) Has been cancelled
Deploy Documentation / Deploy Documentation to GitHub Pages (push) Has been cancelled
Build OS / Build Cross-Compiler & Toolchain (push) Has been cancelled
Build OS / Build amd64 (push) Has been cancelled
Build OS / Build i386 (push) Has been cancelled
Build OS / Build aarch64 (push) Has been cancelled
Some checks failed
CodeQL Advanced / Analyze (${{ matrix.language }}) (manual, c-cpp) (push) Has been cancelled
Deploy Documentation / Deploy Documentation to GitHub Pages (push) Has been cancelled
Build OS / Build Cross-Compiler & Toolchain (push) Has been cancelled
Build OS / Build amd64 (push) Has been cancelled
Build OS / Build i386 (push) Has been cancelled
Build OS / Build aarch64 (push) Has been cancelled
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
46
Kernel/arch/aarch64/core/panic/ui.cpp
Normal file
46
Kernel/arch/aarch64/core/panic/ui.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <display.hpp>
|
||||
#include <bitmap.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
#include <rand.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(__amd64__)
|
||||
#include "../../arch/amd64/cpu/gdt.hpp"
|
||||
#include "../arch/amd64/cpu/apic.hpp"
|
||||
#elif defined(__i386__)
|
||||
#include "../../arch/i386/cpu/gdt.hpp"
|
||||
#include "../arch/i386/cpu/apic.hpp"
|
||||
#elif defined(__aarch64__)
|
||||
#endif
|
||||
|
||||
#include "../../../../kernel.h"
|
||||
|
||||
extern void ExPrint(const char *Format, ...);
|
||||
|
||||
arch nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
ExPrint("\nException Frame:\n");
|
||||
}
|
134
Kernel/arch/amd64/core/panic/ui.cpp
Normal file
134
Kernel/arch/amd64/core/panic/ui.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <display.hpp>
|
||||
#include <bitmap.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
#include <rand.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#include "../../cpu/gdt.hpp"
|
||||
#include "../../cpu/apic.hpp"
|
||||
#include "../../../../kernel.h"
|
||||
|
||||
extern void ExPrint(const char *Format, ...);
|
||||
|
||||
static const char *x86PageFaultDescriptions[9] = {
|
||||
"Supervisor tried to read a non-present page entry\n",
|
||||
"Supervisor tried to read a page and caused a protection fault\n",
|
||||
"Supervisor tried to write to a non-present page entry\n",
|
||||
"Supervisor tried to write a page and caused a protection fault\n",
|
||||
"User tried to read a non-present page entry\n",
|
||||
"User tried to read a page and caused a protection fault\n",
|
||||
"User tried to write to a non-present page entry\n",
|
||||
"User tried to write a page and caused a protection fault\n",
|
||||
"One or more page directory entries contain reserved bits which are set to 1.\n"};
|
||||
|
||||
arch nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
ExPrint("\nException Frame:\n");
|
||||
ExPrint(" General Purpose Registers:\n");
|
||||
ExPrint(" RAX: %#lx RBX: %#lx RCX: %#lx RDX: %#lx\n",
|
||||
Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
|
||||
ExPrint(" RSI: %#lx RDI: %#lx R8: %#lx R9: %#lx\n",
|
||||
Frame->rsi, Frame->rdi, Frame->r8, Frame->r9);
|
||||
ExPrint(" R10: %#lx R11: %#lx R12: %#lx R13: %#lx\n",
|
||||
Frame->r10, Frame->r11, Frame->r12, Frame->r13);
|
||||
ExPrint(" R14: %#lx R15: %#lx\n", Frame->r14, Frame->r15);
|
||||
|
||||
ExPrint(" Control Registers:\n");
|
||||
ExPrint(" CR0: %#lx CR2: %#lx CR3: %#lx CR4: %#lx\n",
|
||||
Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4);
|
||||
ExPrint(" CR8: %#lx\n", Frame->cr8);
|
||||
|
||||
ExPrint(" Segment Registers:\n");
|
||||
ExPrint(" CS: %#lx SS: %#lx DS: %#lx ES: %#lx FS: %#lx GS: %#lx\n",
|
||||
Frame->cs, Frame->ss, Frame->ds, Frame->es, Frame->fs, Frame->gs);
|
||||
|
||||
ExPrint(" Debug Registers:\n");
|
||||
ExPrint(" DR0: %#lx DR1: %#lx DR2: %#lx DR3: %#lx\n",
|
||||
Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3);
|
||||
ExPrint(" DR6: %#lx DR7: %#lx\n", Frame->dr6, Frame->dr7);
|
||||
|
||||
ExPrint(" Other:\n");
|
||||
ExPrint(" INT: %#lx ERR: %#lx RIP: %#lx RFLAGS: %#lx\n",
|
||||
Frame->InterruptNumber, Frame->ErrorCode,
|
||||
Frame->rip, Frame->rflags.raw);
|
||||
ExPrint(" RSP: %#lx RBP: %#lx\n",
|
||||
Frame->rsp, Frame->rbp);
|
||||
|
||||
ExPrint("Exception Details:\n");
|
||||
switch (Frame->InterruptNumber)
|
||||
{
|
||||
case CPU::x86::PageFault:
|
||||
{
|
||||
CPU::x64::PageFaultErrorCode pfCode = {.raw = (uint32_t)Frame->ErrorCode};
|
||||
ExPrint("PFEC: P:%d W:%d U:%d R:%d I:%d PK:%d SS:%d SGX:%d\n",
|
||||
pfCode.P, pfCode.W, pfCode.U, pfCode.R,
|
||||
pfCode.I, pfCode.PK, pfCode.SS, pfCode.SGX);
|
||||
|
||||
{
|
||||
Memory::Virtual vmm((Memory::PageTable *)Frame->cr3);
|
||||
if (vmm.GetMapType((void *)Frame->cr2) != Memory::Virtual::FourKiB)
|
||||
ExPrint("Can't display page %#lx\n", Frame->cr2);
|
||||
else
|
||||
{
|
||||
Memory::PageTableEntry *pte = vmm.GetPTE((void *)Frame->cr2);
|
||||
ExPrint("Page %#lx: P:%d W:%d U:%d G:%d CoW:%d KRsv:%d NX:%d\n",
|
||||
ALIGN_DOWN(Frame->cr2, 0x1000), pte->Present, pte->ReadWrite,
|
||||
pte->UserSupervisor, pte->Global, pte->CopyOnWrite,
|
||||
pte->KernelReserve, pte->ExecuteDisable);
|
||||
}
|
||||
}
|
||||
|
||||
ExPrint("%s", x86PageFaultDescriptions[Frame->ErrorCode & 0b111]);
|
||||
if (Frame->ErrorCode & 0x8)
|
||||
ExPrint("%s", x86PageFaultDescriptions[8]);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::StackSegmentFault:
|
||||
case CPU::x86::GeneralProtectionFault:
|
||||
{
|
||||
CPU::x64::SelectorErrorCode sCode = {.raw = Frame->ErrorCode};
|
||||
ExPrint("Kernel performed an illegal operation.\n");
|
||||
ExPrint("External: %d\n", sCode.External);
|
||||
ExPrint("Table: %d\n", sCode.Table);
|
||||
ExPrint("Index: %#x\n", sCode.Idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ExPrint("No additional information available for this exception.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!TaskManager)
|
||||
return;
|
||||
|
||||
CPUData *core = GetCurrentCPU();
|
||||
Tasking::PCB *proc = core->CurrentProcess.load();
|
||||
Tasking::TCB *thread = core->CurrentThread.load();
|
||||
ExPrint("Exception in %s process %s(%d) thread %s(%d)\n",
|
||||
proc->Security.ExecutionMode == Tasking::User ? "user" : "kernel",
|
||||
proc->Name, proc->ID,
|
||||
thread->Name, thread->ID);
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
172
Kernel/arch/amd64/tasking/signal.cpp
Normal file
172
Kernel/arch/amd64/tasking/signal.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <signal.hpp>
|
||||
#include <dumper.hpp>
|
||||
#include <task.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../cpu/gdt.hpp"
|
||||
|
||||
/* subsystem/linux/syscall.cpp */
|
||||
extern int ConvertSignalToLinux(signal_t sig);
|
||||
|
||||
namespace Tasking
|
||||
{
|
||||
bool Signal::HandleSignal(CPU::SchedulerFrame *tf, void *thread)
|
||||
{
|
||||
/* We don't want to do this in kernel mode */
|
||||
if (tf->cs != GDT_USER_CODE)
|
||||
return false;
|
||||
|
||||
if (Queue.empty())
|
||||
return false;
|
||||
|
||||
debug("We have %d signals to handle", Queue.size());
|
||||
|
||||
SmartLock(SignalLock);
|
||||
SignalInfo sigI = GetAvailableSignal(thread);
|
||||
if (sigI.sig == SIGNULL)
|
||||
return false;
|
||||
|
||||
uintptr_t _p_rsp = ((PCB *)ctx)->PageTable->Get(tf->rsp);
|
||||
uint64_t paRsp = _p_rsp;
|
||||
paRsp &= ~0xF; /* Align */
|
||||
paRsp -= 128; /* Red zone */
|
||||
|
||||
/* Calculate the virtual rsp */
|
||||
uintptr_t _v_rsp = tf->rsp;
|
||||
_v_rsp &= ~0xF; /* Align */
|
||||
_v_rsp -= 128; /* Red zone */
|
||||
uint64_t *vRsp = (uint64_t *)(_v_rsp - sizeof(StackInfo));
|
||||
vRsp--; /* Alignment */
|
||||
vRsp--; /* Handler Address */
|
||||
assert(!((uintptr_t)vRsp & 0xF));
|
||||
|
||||
/* Add the stack info */
|
||||
StackInfo si{};
|
||||
CPU::x86::fxsave(&si.fx);
|
||||
si.tf = *tf;
|
||||
si.GSBase = CPU::x86::rdmsr(CPU::x86::MSR_GS_BASE);
|
||||
si.FSBase = CPU::x86::rdmsr(CPU::x86::MSR_FS_BASE);
|
||||
si.ShadowGSBase = CPU::x86::rdmsr(CPU::x86::MSR_SHADOW_GS_BASE);
|
||||
si.SignalMask = ((TCB *)thread)->Signals.Mask.to_ulong();
|
||||
si.Compatibility = ((PCB *)ctx)->Info.Compatibility;
|
||||
|
||||
debug("gs: %#lx fs: %#lx shadow: %#lx",
|
||||
si.GSBase, si.FSBase, si.ShadowGSBase);
|
||||
|
||||
/* Copy the stack info */
|
||||
uint64_t *pRsp = (uint64_t *)(paRsp - sizeof(StackInfo));
|
||||
memcpy(pRsp, &si, sizeof(StackInfo));
|
||||
|
||||
/* Set the handler address */
|
||||
pRsp--; /* Alignment */
|
||||
pRsp--;
|
||||
*pRsp = uint64_t(sa[sigI.sig].sa_handler.Handler);
|
||||
|
||||
assert(!((uintptr_t)pRsp & 0xF));
|
||||
|
||||
int cSig = LinuxSig() ? ConvertSignalToLinux((signal_t)sigI.sig) : sigI.sig;
|
||||
|
||||
#ifdef DEBUG
|
||||
DumpData("Stack Data", (void *)pRsp,
|
||||
paRsp - uint64_t(pRsp));
|
||||
debug("initial stack tf->rsp: %#lx after: %#lx",
|
||||
tf->rsp, uint64_t(vRsp));
|
||||
debug("sig: %d -> %d", sigI.sig, cSig);
|
||||
#endif
|
||||
|
||||
tf->rsp = uint64_t(vRsp);
|
||||
tf->rip = uint64_t(TrampAddr);
|
||||
|
||||
/* void func(int signo); */
|
||||
/* void func(int signo, siginfo_t *info, void *context); */
|
||||
tf->rdi = cSig;
|
||||
if (sa[sigI.sig].Flags & SA_SIGINFO)
|
||||
{
|
||||
fixme("SA_SIGINFO not implemented");
|
||||
siginfo_t *info = 0;
|
||||
void *context = 0;
|
||||
tf->rsi = uint64_t(info);
|
||||
tf->rdx = uint64_t(context);
|
||||
tf->rcx = 0;
|
||||
tf->r8 = 0;
|
||||
tf->r9 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tf->rsi = 0;
|
||||
tf->rdx = 0;
|
||||
tf->rcx = 0;
|
||||
tf->r8 = 0;
|
||||
tf->r9 = 0;
|
||||
}
|
||||
|
||||
((TCB *)thread)->Signals.Mask = sa[sigI.sig].Mask;
|
||||
assert(TrampAddr != nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Signal::RestoreHandleSignal(SyscallsFrame *sf, void *thread)
|
||||
{
|
||||
debug("Restoring signal handler");
|
||||
SmartLock(SignalLock);
|
||||
|
||||
gsTCB *gs = (gsTCB *)CPU::x86::rdmsr(CPU::x86::MSR_GS_BASE);
|
||||
uint64_t *sp = (uint64_t *)((PCB *)ctx)->PageTable->Get(gs->TempStack);
|
||||
sp++; /* Alignment */
|
||||
sp++; /* Handler Address */
|
||||
|
||||
assert(!((uintptr_t)sp & 0xF));
|
||||
|
||||
StackInfo *si = (StackInfo *)sp;
|
||||
assert(si != nullptr);
|
||||
|
||||
sf->r15 = si->tf.r15;
|
||||
sf->r14 = si->tf.r14;
|
||||
sf->r13 = si->tf.r13;
|
||||
sf->r12 = si->tf.r12;
|
||||
sf->r11 = si->tf.r11;
|
||||
sf->r10 = si->tf.r10;
|
||||
sf->r9 = si->tf.r9;
|
||||
sf->r8 = si->tf.r8;
|
||||
sf->bp = si->tf.rbp;
|
||||
sf->di = si->tf.rdi;
|
||||
sf->si = si->tf.rsi;
|
||||
sf->dx = si->tf.rdx;
|
||||
sf->cx = si->tf.rcx;
|
||||
sf->bx = si->tf.rbx;
|
||||
sf->ax = si->tf.rax;
|
||||
sf->Flags = si->tf.rflags.raw;
|
||||
sf->ReturnAddress = si->tf.rip;
|
||||
gs->TempStack = (void *)si->tf.rsp;
|
||||
|
||||
((TCB *)thread)->Signals.Mask = si->SignalMask;
|
||||
|
||||
CPU::x86::fxrstor(&si->fx);
|
||||
CPU::x86::wrmsr(CPU::x86::MSR_GS_BASE, si->ShadowGSBase);
|
||||
CPU::x86::wrmsr(CPU::x86::MSR_FS_BASE, si->FSBase);
|
||||
CPU::x86::wrmsr(CPU::x86::MSR_SHADOW_GS_BASE, si->GSBase);
|
||||
debug("gs: %#lx fs: %#lx shadow: %#lx",
|
||||
si->GSBase, si->FSBase, si->ShadowGSBase);
|
||||
|
||||
// ((PCB *)ctx)->GetContext()->Yield();
|
||||
// __builtin_unreachable();
|
||||
/* Return because we will restore at sysretq */
|
||||
}
|
||||
}
|
131
Kernel/arch/i386/core/panic/ui.cpp
Normal file
131
Kernel/arch/i386/core/panic/ui.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <display.hpp>
|
||||
#include <bitmap.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
#include <rand.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#include "../../cpu/gdt.hpp"
|
||||
#include "../../cpu/apic.hpp"
|
||||
#include "../../../../kernel.h"
|
||||
|
||||
extern void ExPrint(const char *Format, ...);
|
||||
|
||||
static const char *x86PageFaultDescriptions[9] = {
|
||||
"Supervisor tried to read a non-present page entry\n",
|
||||
"Supervisor tried to read a page and caused a protection fault\n",
|
||||
"Supervisor tried to write to a non-present page entry\n",
|
||||
"Supervisor tried to write a page and caused a protection fault\n",
|
||||
"User tried to read a non-present page entry\n",
|
||||
"User tried to read a page and caused a protection fault\n",
|
||||
"User tried to write to a non-present page entry\n",
|
||||
"User tried to write a page and caused a protection fault\n",
|
||||
"One or more page directory entries contain reserved bits which are set to 1.\n"};
|
||||
|
||||
arch nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
ExPrint("\nException Frame:\n");
|
||||
ExPrint(" General Purpose Registers:\n");
|
||||
ExPrint(" EAX: %#lx EBX: %#lx ECX: %#lx EDX: %#lx\n",
|
||||
Frame->eax, Frame->ebx, Frame->ecx, Frame->edx);
|
||||
ExPrint(" ESI: %#lx EDI: %#lx\n",
|
||||
Frame->esi, Frame->edi);
|
||||
|
||||
ExPrint(" Control Registers:\n");
|
||||
ExPrint(" CR0: %#lx CR2: %#lx CR3: %#lx CR4: %#lx\n",
|
||||
Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4);
|
||||
ExPrint(" CR8: %#lx\n", Frame->cr8);
|
||||
|
||||
ExPrint(" Segment Registers:\n");
|
||||
ExPrint(" CS: %#lx SS: %#lx DS: %#lx ES: %#lx FS: %#lx GS: %#lx\n",
|
||||
Frame->cs, Frame->ss, Frame->ds, Frame->es, Frame->fs, Frame->gs);
|
||||
|
||||
ExPrint(" Debug Registers:\n");
|
||||
ExPrint(" DR0: %#lx DR1: %#lx DR2: %#lx DR3: %#lx\n",
|
||||
Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3);
|
||||
ExPrint(" DR6: %#lx DR7: %#lx\n", Frame->dr6, Frame->dr7);
|
||||
|
||||
ExPrint(" Other:\n");
|
||||
ExPrint(" INT: %#lx ERR: %#lx EIP: %#lx RFLAGS: %#lx\n",
|
||||
Frame->InterruptNumber, Frame->ErrorCode,
|
||||
Frame->eip, Frame->eflags.raw);
|
||||
ExPrint(" RSP: %#lx RBP: %#lx\n",
|
||||
Frame->esp, Frame->ebp);
|
||||
|
||||
ExPrint("Exception Details:\n");
|
||||
switch (Frame->InterruptNumber)
|
||||
{
|
||||
case CPU::x86::PageFault:
|
||||
{
|
||||
CPU::x64::PageFaultErrorCode pfCode = {.raw = (uint32_t)Frame->ErrorCode};
|
||||
ExPrint("PFEC: P:%d W:%d U:%d R:%d I:%d PK:%d SS:%d SGX:%d\n",
|
||||
pfCode.P, pfCode.W, pfCode.U, pfCode.R,
|
||||
pfCode.I, pfCode.PK, pfCode.SS, pfCode.SGX);
|
||||
|
||||
{
|
||||
Memory::Virtual vmm((Memory::PageTable *)Frame->cr3);
|
||||
if (vmm.GetMapType((void *)Frame->cr2) != Memory::Virtual::FourKiB)
|
||||
ExPrint("Can't display page %#lx\n", Frame->cr2);
|
||||
else
|
||||
{
|
||||
Memory::PageTableEntry *pte = vmm.GetPTE((void *)Frame->cr2);
|
||||
ExPrint("Page %#lx: P:%d W:%d U:%d G:%d CoW:%d KRsv:%d\n",
|
||||
ALIGN_DOWN(Frame->cr2, 0x1000), pte->Present, pte->ReadWrite,
|
||||
pte->UserSupervisor, pte->Global, pte->CopyOnWrite,
|
||||
pte->KernelReserve);
|
||||
}
|
||||
}
|
||||
|
||||
ExPrint("%s", x86PageFaultDescriptions[Frame->ErrorCode & 0b111]);
|
||||
if (Frame->ErrorCode & 0x8)
|
||||
ExPrint("%s", x86PageFaultDescriptions[8]);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::StackSegmentFault:
|
||||
case CPU::x86::GeneralProtectionFault:
|
||||
{
|
||||
CPU::x64::SelectorErrorCode sCode = {.raw = Frame->ErrorCode};
|
||||
ExPrint("Kernel performed an illegal operation.\n");
|
||||
ExPrint("External: %d\n", sCode.External);
|
||||
ExPrint("Table: %d\n", sCode.Table);
|
||||
ExPrint("Index: %#x\n", sCode.Idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ExPrint("No additional information available for this exception.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!TaskManager)
|
||||
return;
|
||||
|
||||
CPUData *core = GetCurrentCPU();
|
||||
Tasking::PCB *proc = core->CurrentProcess.load();
|
||||
Tasking::TCB *thread = core->CurrentThread.load();
|
||||
ExPrint("Exception in %s process %s(%d) thread %s(%d)\n",
|
||||
proc->Security.ExecutionMode == Tasking::User ? "user" : "kernel",
|
||||
proc->Name, proc->ID,
|
||||
thread->Name, thread->ID);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
160
Kernel/arch/i386/tasking/signal.cpp
Normal file
160
Kernel/arch/i386/tasking/signal.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <signal.hpp>
|
||||
#include <dumper.hpp>
|
||||
#include <task.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../cpu/gdt.hpp"
|
||||
|
||||
/* subsystem/linux/syscall.cpp */
|
||||
extern int ConvertSignalToLinux(signal_t sig);
|
||||
|
||||
namespace Tasking
|
||||
{
|
||||
bool Signal::HandleSignal(CPU::SchedulerFrame *tf, void *thread)
|
||||
{
|
||||
/* We don't want to do this in kernel mode */
|
||||
if (tf->cs != GDT_USER_CODE)
|
||||
return false;
|
||||
|
||||
if (Queue.empty())
|
||||
return false;
|
||||
|
||||
debug("We have %d signals to handle", Queue.size());
|
||||
|
||||
SmartLock(SignalLock);
|
||||
SignalInfo sigI = GetAvailableSignal(thread);
|
||||
if (sigI.sig == SIGNULL)
|
||||
return false;
|
||||
|
||||
uintptr_t _p_esp = ((PCB *)ctx)->PageTable->Get(tf->esp);
|
||||
uint64_t paEsp = _p_esp;
|
||||
paEsp &= ~0xF; /* Align */
|
||||
paEsp -= 128; /* Red zone */
|
||||
|
||||
/* Calculate the virtual rsp */
|
||||
uintptr_t _v_esp = tf->esp;
|
||||
_v_esp &= ~0xF; /* Align */
|
||||
_v_esp -= 128; /* Red zone */
|
||||
uint64_t *vEsp = (uint64_t *)(_v_esp - sizeof(StackInfo));
|
||||
vEsp--; /* Alignment */
|
||||
vEsp--; /* Handler Address */
|
||||
assert(!((uintptr_t)vEsp & 0xF));
|
||||
|
||||
/* Add the stack info */
|
||||
StackInfo si{};
|
||||
CPU::x86::fxsave(&si.fx);
|
||||
si.tf = *tf;
|
||||
si.GSBase = CPU::x86::rdmsr(CPU::x86::MSR_GS_BASE);
|
||||
si.FSBase = CPU::x86::rdmsr(CPU::x86::MSR_FS_BASE);
|
||||
si.ShadowGSBase = CPU::x86::rdmsr(CPU::x86::MSR_SHADOW_GS_BASE);
|
||||
si.SignalMask = ((TCB *)thread)->Signals.Mask.to_ulong();
|
||||
si.Compatibility = ((PCB *)ctx)->Info.Compatibility;
|
||||
|
||||
debug("gs: %#lx fs: %#lx shadow: %#lx",
|
||||
si.GSBase, si.FSBase, si.ShadowGSBase);
|
||||
|
||||
/* Copy the stack info */
|
||||
uint64_t *pEsp = (uint64_t *)(paEsp - sizeof(StackInfo));
|
||||
memcpy(pEsp, &si, sizeof(StackInfo));
|
||||
|
||||
/* Set the handler address */
|
||||
pEsp--; /* Alignment */
|
||||
pEsp--;
|
||||
*pEsp = uint64_t(sa[sigI.sig].sa_handler.Handler);
|
||||
|
||||
assert(!((uintptr_t)pEsp & 0xF));
|
||||
|
||||
int cSig = LinuxSig() ? ConvertSignalToLinux((signal_t)sigI.sig) : sigI.sig;
|
||||
|
||||
#ifdef DEBUG
|
||||
DumpData("Stack Data", (void *)pEsp,
|
||||
paEsp - uint64_t(pEsp));
|
||||
debug("initial stack tf->rsp: %#lx after: %#lx",
|
||||
tf->esp, uint64_t(vEsp));
|
||||
debug("sig: %d -> %d", sigI.sig, cSig);
|
||||
#endif
|
||||
|
||||
tf->esp = uint64_t(vEsp);
|
||||
tf->eip = uint64_t(TrampAddr);
|
||||
|
||||
/* void func(int signo); */
|
||||
/* void func(int signo, siginfo_t *info, void *context); */
|
||||
tf->edi = cSig;
|
||||
if (sa[sigI.sig].Flags & SA_SIGINFO)
|
||||
{
|
||||
fixme("SA_SIGINFO not implemented");
|
||||
siginfo_t *info = 0;
|
||||
void *context = 0;
|
||||
tf->eax = uint64_t(info);
|
||||
tf->edx = uint64_t(context);
|
||||
tf->ecx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tf->eax = 0;
|
||||
tf->edx = 0;
|
||||
tf->ecx = 0;
|
||||
}
|
||||
|
||||
((TCB *)thread)->Signals.Mask = sa[sigI.sig].Mask;
|
||||
assert(TrampAddr != nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Signal::RestoreHandleSignal(SyscallsFrame *sf, void *thread)
|
||||
{
|
||||
debug("Restoring signal handler");
|
||||
SmartLock(SignalLock);
|
||||
|
||||
gsTCB *gs = (gsTCB *)CPU::x86::rdmsr(CPU::x86::MSR_GS_BASE);
|
||||
uint64_t *sp = (uint64_t *)((PCB *)ctx)->PageTable->Get(gs->TempStack);
|
||||
sp++; /* Alignment */
|
||||
sp++; /* Handler Address */
|
||||
|
||||
assert(!((uintptr_t)sp & 0xF));
|
||||
|
||||
StackInfo *si = (StackInfo *)sp;
|
||||
assert(si != nullptr);
|
||||
|
||||
sf->bp = si->tf.ebp;
|
||||
sf->di = si->tf.edi;
|
||||
sf->si = si->tf.esi;
|
||||
sf->dx = si->tf.edx;
|
||||
sf->cx = si->tf.ecx;
|
||||
sf->bx = si->tf.ebx;
|
||||
sf->ax = si->tf.eax;
|
||||
sf->Flags = si->tf.eflags.raw;
|
||||
sf->ReturnAddress = si->tf.eip;
|
||||
gs->TempStack = (void *)si->tf.esp;
|
||||
|
||||
((TCB *)thread)->Signals.Mask = si->SignalMask;
|
||||
|
||||
CPU::x86::fxrstor(&si->fx);
|
||||
CPU::x86::wrmsr(CPU::x86::MSR_GS_BASE, si->ShadowGSBase);
|
||||
CPU::x86::wrmsr(CPU::x86::MSR_FS_BASE, si->FSBase);
|
||||
CPU::x86::wrmsr(CPU::x86::MSR_SHADOW_GS_BASE, si->GSBase);
|
||||
debug("gs: %#lx fs: %#lx shadow: %#lx",
|
||||
si->GSBase, si->FSBase, si->ShadowGSBase);
|
||||
|
||||
// ((PCB *)ctx)->GetContext()->Yield();
|
||||
// __builtin_unreachable();
|
||||
/* Return because we will restore at sysretq */
|
||||
}
|
||||
}
|
38
Kernel/arch/i386/tasking/signal_trampoline.s
Normal file
38
Kernel/arch/i386/tasking/signal_trampoline.s
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.code64
|
||||
|
||||
.global _sig_native_trampoline_start
|
||||
_sig_native_trampoline_start:
|
||||
int $0x3
|
||||
|
||||
.global _sig_native_trampoline_end
|
||||
_sig_native_trampoline_end:
|
||||
|
||||
.global _sig_linux_trampoline_start
|
||||
_sig_linux_trampoline_start:
|
||||
movq %rsp, %rbp
|
||||
movq (%rbp), %rax
|
||||
call *%rax
|
||||
mov %rbp, %rsp
|
||||
/* rt_sigreturn = 15 */
|
||||
movq $15, %rax
|
||||
syscall
|
||||
|
||||
.global _sig_linux_trampoline_end
|
||||
_sig_linux_trampoline_end:
|
Reference in New Issue
Block a user