From fbe9fbfbd1821b5008cb13a225e02fbb9c0e4b73 Mon Sep 17 00:00:00 2001 From: EnderIce2 Date: Fri, 10 Jan 2025 18:55:34 +0200 Subject: [PATCH] kernel: add arm architecture support Signed-off-by: EnderIce2 --- Kernel/.vscode/c_cpp_properties.json | 27 +++ Kernel/Makefile | 11 ++ Kernel/arch/arm/aeabi.c | 40 ++++ Kernel/arch/arm/bootstrap/boot.S | 18 ++ Kernel/arch/arm/core/panic/ui.cpp | 46 +++++ Kernel/arch/arm/cpu/smp.cpp | 59 ++++++ Kernel/arch/arm/entry.cpp | 27 +++ Kernel/arch/arm/include/.gitkeep | 0 Kernel/arch/arm/linker.ld | 89 +++++++++ Kernel/arch/arm/madt.cpp | 97 ++++++++++ Kernel/arch/arm/memory/vmm.cpp | 69 +++++++ Kernel/arch/arm/syscalls.cpp | 30 +++ Kernel/arch/arm/tasking/signal.cpp | 38 ++++ Kernel/arch/arm/tasking/signal_trampoline.s | 28 +++ .../heap_allocators/rpmalloc/rpmalloc.c | 12 +- Kernel/core/memory/reserve_essentials.cpp | 2 +- Kernel/core/panic/ui.cpp | 9 + Kernel/core/symbols.cpp | 4 +- Kernel/include/abi.h | 4 +- Kernel/include/convert.h | 4 +- Kernel/include/cpu.hpp | 75 ++++++++ Kernel/include/elf.h | 2 +- Kernel/include/memory/macro.hpp | 2 +- Kernel/include/syscalls.hpp | 8 + Kernel/include/task.hpp | 2 + Kernel/include/types.h | 2 +- Kernel/include_std/float.h | 4 + Kernel/include_std/functional | 4 + Kernel/include_std/new | 12 +- Kernel/library/convert.cpp | 2 +- Kernel/library/kexcept/cxxabi.cpp | 2 + Kernel/library/md5.c | 2 +- Kernel/library/std/new.cpp | 53 +++++- Kernel/subsystem/linux/include/defs.hpp | 20 +- Makefile | 18 +- Userspace/.vscode/c_cpp_properties.json | 21 +++ Userspace/libc/include/stdio.h | 2 +- Userspace/libc/include/stdlib.h | 2 +- Userspace/libc/include/sys/types.h | 2 +- Userspace/libc/interpreter/elf.h | 20 +- Userspace/libc/interpreter/start.c | 2 + Userspace/libc/runtime/Scrt1.c | 2 + Userspace/libc/runtime/crt1.c | 2 + Userspace/libc/src/softfloat.c | 173 ++++++++++++++++++ 44 files changed, 1019 insertions(+), 29 deletions(-) create mode 100644 Kernel/arch/arm/aeabi.c create mode 100644 Kernel/arch/arm/bootstrap/boot.S create mode 100644 Kernel/arch/arm/core/panic/ui.cpp create mode 100644 Kernel/arch/arm/cpu/smp.cpp create mode 100644 Kernel/arch/arm/entry.cpp create mode 100644 Kernel/arch/arm/include/.gitkeep create mode 100644 Kernel/arch/arm/linker.ld create mode 100644 Kernel/arch/arm/madt.cpp create mode 100644 Kernel/arch/arm/memory/vmm.cpp create mode 100644 Kernel/arch/arm/syscalls.cpp create mode 100644 Kernel/arch/arm/tasking/signal.cpp create mode 100644 Kernel/arch/arm/tasking/signal_trampoline.s diff --git a/Kernel/.vscode/c_cpp_properties.json b/Kernel/.vscode/c_cpp_properties.json index 8d3c3fd6..fb685623 100644 --- a/Kernel/.vscode/c_cpp_properties.json +++ b/Kernel/.vscode/c_cpp_properties.json @@ -137,6 +137,33 @@ "-nostdinc++" ] }, + { + "name": "Fennix Arm (Linux, GCC, debug)", + "includePath": [ + "${workspaceFolder}/include", + "${workspaceFolder}/include/**", + "${workspaceFolder}/include_std", + "${workspaceFolder}/include_std/**", + "${workspaceFolder}/arch/aarch64/include" + ], + "forcedInclude": [ + "${workspaceFolder}/.vscode/preinclude.h" + ], + "defines": [ + "DEBUG=\"1\"" + ], + "compilerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gcc", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "linux-gcc-arm", + "configurationProvider": "ms-vscode.makefile-tools", + "compilerArgs": [ + // VSCode flags + "-ffreestanding", + "-nostdinc", + "-nostdinc++" + ] + }, { "name": "Fennix Aarch64 (Linux, GCC, debug)", "includePath": [ diff --git a/Kernel/Makefile b/Kernel/Makefile index 65130491..76f49399 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -53,6 +53,10 @@ LDFLAGS += -Tarch/amd64/linker.ld else ifeq ($(OSARCH), i386) CFLAGS += -march=pentium -m32 -mno-red-zone LDFLAGS += -Tarch/i386/linker.ld +else ifeq ($(OSARCH), arm) +CFLAGS += -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 +LDFLAGS += -Tarch/arm/linker.ld +WARNCFLAG += -w else ifeq ($(OSARCH), aarch64) CFLAGS += -march=armv9.4-a -mtune=cortex-a72 -mlittle-endian -mcmodel=large LDFLAGS += -Tarch/aarch64/linker.ld @@ -67,6 +71,9 @@ ifeq ($(DEBUG), 1) ifeq ($(OSARCH), amd64) CFLAGS += -fverbose-asm endif # amd64 +ifeq ($(OSARCH), arm) + CFLAGS += -fstack-check -fverbose-asm +endif # arm ifeq ($(OSARCH), aarch64) CFLAGS += -fstack-check -fverbose-asm endif # aarch64 @@ -119,6 +126,8 @@ ifeq ($(OSARCH), amd64) $(__CONF_OBJCOPY) -O elf64-x86-64 -I binary $< $@ else ifeq ($(OSARCH), i386) $(__CONF_OBJCOPY) -O elf32-i386 -I binary $< $@ +else ifeq ($(OSARCH), arm) + $(__CONF_OBJCOPY) -O elf32-littlearm -I binary $< $@ else ifeq ($(OSARCH), aarch64) $(__CONF_OBJCOPY) -O elf64-littleaarch64 -I binary $< $@ endif @@ -129,6 +138,8 @@ ifeq ($(OSARCH), amd64) $(__CONF_OBJCOPY) -O elf64-x86-64 -I binary $< $@ else ifeq ($(OSARCH), i386) $(__CONF_OBJCOPY) -O elf32-i386 -I binary $< $@ +else ifeq ($(OSARCH), arm) + $(__CONF_OBJCOPY) -O elf32-littlearm -I binary $< $@ else ifeq ($(OSARCH), aarch64) $(__CONF_OBJCOPY) -O elf64-littlearch64 -I binary $< $@ endif diff --git a/Kernel/arch/arm/aeabi.c b/Kernel/arch/arm/aeabi.c new file mode 100644 index 00000000..c6410f19 --- /dev/null +++ b/Kernel/arch/arm/aeabi.c @@ -0,0 +1,40 @@ +/* + 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 . +*/ + +unsigned __aeabi_uidiv(unsigned a, unsigned b) { return a / b; } +unsigned __aeabi_idiv(unsigned a, unsigned b) { return a / b; } +unsigned __aeabi_l2d(unsigned a) { return a; } +unsigned __aeabi_d2lz(unsigned a) { return a; } + +unsigned __aeabi_ldivmod(unsigned a, unsigned b, unsigned *r) { *r = a % b; return a / b; } + +unsigned __aeabi_uldivmod(unsigned a, unsigned b, unsigned *r) { *r = a % b; return a / b; } + +unsigned __aeabi_uidivmod(unsigned a, unsigned b, unsigned *r) { *r = a % b; return a / b; } + + +unsigned __aeabi_idivmod(unsigned a, unsigned b, unsigned *r) { *r = a % b; return a / b; } + + +unsigned __aeabi_unwind_cpp_pr1(void) { return 0; } +unsigned __aeabi_atexit(void) { return 0; } +unsigned __cxa_end_cleanup(void) { return 0; } +unsigned __aeabi_unwind_cpp_pr0(void) { return 0; } + + + + diff --git a/Kernel/arch/arm/bootstrap/boot.S b/Kernel/arch/arm/bootstrap/boot.S new file mode 100644 index 00000000..956b21f1 --- /dev/null +++ b/Kernel/arch/arm/bootstrap/boot.S @@ -0,0 +1,18 @@ +/* Based on this tutorial: + https://github.com/s-matyukevich/raspberry-pi-os */ + +.section ".text.boot", "a" + +.extern _bss_start +.extern _bss_end + +.global _start +_start: + b CPU_Loop + +Halt: + wfe + b Halt + +CPU_Loop: + b CPU_Loop diff --git a/Kernel/arch/arm/core/panic/ui.cpp b/Kernel/arch/arm/core/panic/ui.cpp new file mode 100644 index 00000000..eeae5743 --- /dev/null +++ b/Kernel/arch/arm/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/arm/cpu/smp.cpp b/Kernel/arch/arm/cpu/smp.cpp new file mode 100644 index 00000000..7f6454dc --- /dev/null +++ b/Kernel/arch/arm/cpu/smp.cpp @@ -0,0 +1,59 @@ +/* + 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 "../../../kernel.h" + +volatile bool CPUEnabled = false; + +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +static __aligned(0x1000) CPUData CPUs[MAX_CPU] = {0}; + +CPUData *GetCPU(uint64_t id) { return &CPUs[id]; } + +CPUData *GetCurrentCPU() +{ + uint64_t ret = 0; + + if (!CPUs[ret].IsActive) + { + error("CPU %d is not active!", ret); + return &CPUs[0]; + } + + if (CPUs[ret].Checksum != CPU_DATA_CHECKSUM) + { + error("CPU %d data is corrupted!", ret); + return &CPUs[0]; + } + return &CPUs[ret]; +} + +namespace SMP +{ + int CPUCores = 0; + + void Initialize(void *madt) + { + fixme("SMP::Initialize() is not implemented!"); + } +} diff --git a/Kernel/arch/arm/entry.cpp b/Kernel/arch/arm/entry.cpp new file mode 100644 index 00000000..d0ec97cd --- /dev/null +++ b/Kernel/arch/arm/entry.cpp @@ -0,0 +1,27 @@ +/* + 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 + +EXTERNC void arm64Entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3) +{ + trace("Hello, World!"); + CPU::Halt(true); +} diff --git a/Kernel/arch/arm/include/.gitkeep b/Kernel/arch/arm/include/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Kernel/arch/arm/linker.ld b/Kernel/arch/arm/linker.ld new file mode 100644 index 00000000..23fb294a --- /dev/null +++ b/Kernel/arch/arm/linker.ld @@ -0,0 +1,89 @@ +/* + 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 . +*/ + +ENTRY(_start) + +SECTIONS +{ + _bootstrap_start = .; + .text.boot : + { + *(.text.boot) + . += CONSTANT(MAXPAGESIZE); + _bss_start = .; + *(.text.bss) + _bss_end = .; + } + _bootstrap_end = .; + + _kernel_start = .; + _kernel_text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text .text.*) + } + . = ALIGN(4096); + _kernel_text_end = .; + + _kernel_data_start = .; + .data : + { + *(.data .data.*) + } + . = ALIGN(4096); + _kernel_data_end = .; + + _kernel_rodata_start = .; + .rodata : + { + *(.rodata .rodata.*) + } + . = ALIGN(4096); + + .init_array : + { + PROVIDE_HIDDEN(__init_array_start = .); + KEEP(*(.init_array .ctors)) + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + PROVIDE_HIDDEN (__init_array_end = .); + } + + .fini_array : + { + PROVIDE_HIDDEN(__fini_array_start = .); + KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP(*(.fini_array .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + _kernel_rodata_end = .; + + _kernel_bss_start = .; + .bss : + { + *(.bss .bss.*) + } + . = ALIGN(4096); + _kernel_bss_end = .; + _kernel_end = .; + _bss_size = _kernel_end - _kernel_rodata_end; + + /DISCARD/ : + { + *(.comment*) + } +} diff --git a/Kernel/arch/arm/madt.cpp b/Kernel/arch/arm/madt.cpp new file mode 100644 index 00000000..eaf2b011 --- /dev/null +++ b/Kernel/arch/arm/madt.cpp @@ -0,0 +1,97 @@ +/* + 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 "acpi.hpp" + +#include +#include + +#include "../../kernel.h" + +namespace ACPI +{ + MADT::MADT(ACPI::MADTHeader *madt) + { + trace("Initializing MADT"); + if (!madt) + { + error("MADT is NULL"); + return; + } + + CPUCores = 0; + LAPICAddress = (LAPIC *)(uintptr_t)madt->LocalControllerAddress; + for (uint8_t *ptr = (uint8_t *)(madt->Entries); + (uintptr_t)(ptr) < (uintptr_t)(madt) + madt->Header.Length; + ptr += *(ptr + 1)) + { + switch (*(ptr)) + { + case 0: + { + if (ptr[4] & 1) + { + lapic.push_back((LocalAPIC *)ptr); + KPrint("Local APIC %d (APIC %d) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId); + CPUCores++; + } + break; + } + case 1: + { + ioapic.push_back((MADTIOApic *)ptr); + KPrint("I/O APIC %d (Address %#lx) found.", ioapic.back()->APICID, ioapic.back()->Address); + Memory::Virtual(KernelPageTable).Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped. + break; + } + case 2: + { + iso.push_back((MADTIso *)ptr); + KPrint("ISO (IRQ:%#lx, BUS:%#lx, GSI:%#lx, %s/%s) found.", + iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI, + iso.back()->Flags & 0x00000004 ? "Active High" : "Active Low", + iso.back()->Flags & 0x00000100 ? "Edge Triggered" : "Level Triggered"); + break; + } + case 4: + { + nmi.push_back((MADTNmi *)ptr); + KPrint("NMI %#lx (lint:%#lx) found.", nmi.back()->processor, nmi.back()->lint); + break; + } + case 5: + { + LAPICAddress = (LAPIC *)ptr; + KPrint("APIC found at %#lx", LAPICAddress); + break; + } + default: + { + KPrint("Unknown MADT entry %#lx", *(ptr)); + break; + } + } + Memory::Virtual(KernelPageTable).Map((void *)LAPICAddress, (void *)LAPICAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page? + } + CPUCores--; // We start at 0 (BSP) and end at 11 (APs), so we have 12 cores. + KPrint("Total CPU cores: %d", CPUCores + 1); + } + + MADT::~MADT() + { + } +} diff --git a/Kernel/arch/arm/memory/vmm.cpp b/Kernel/arch/arm/memory/vmm.cpp new file mode 100644 index 00000000..185a082f --- /dev/null +++ b/Kernel/arch/arm/memory/vmm.cpp @@ -0,0 +1,69 @@ +/* + 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 + +namespace Memory +{ + bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type) + { +#warning "arm not implemented" + return 0; + } + + void *Virtual::GetPhysical(void *VirtualAddress) + { +#warning "arm not implemented" + return nullptr; + } + + Virtual::MapType Virtual::GetMapType(void *VirtualAddress) + { +#warning "arm not implemented" + return MapType::NoMapType; + } + + PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type) + { +#warning "arm not implemented" + return nullptr; + } + + PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type) + { +#warning "arm not implemented" + return nullptr; + } + + void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type) + { +#warning "arm not implemented" + } + + void Virtual::Unmap(void *VirtualAddress, MapType Type) + { +#warning "arm not implemented" + } + + void Virtual::Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type) + { +#warning "arm not implemented" + } +} diff --git a/Kernel/arch/arm/syscalls.cpp b/Kernel/arch/arm/syscalls.cpp new file mode 100644 index 00000000..e3fe63d7 --- /dev/null +++ b/Kernel/arch/arm/syscalls.cpp @@ -0,0 +1,30 @@ +/* + 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 + +extern "C" __used __no_stack_protector void SystemCallHandlerStub() +{ +} + +extern "C" uint64_t SystemCallsHandler(SyscallsFrame *regs); + +void InitializeSystemCalls() +{ +} diff --git a/Kernel/arch/arm/tasking/signal.cpp b/Kernel/arch/arm/tasking/signal.cpp new file mode 100644 index 00000000..619bd798 --- /dev/null +++ b/Kernel/arch/arm/tasking/signal.cpp @@ -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 . +*/ + +#include +#include +#include +#include + +/* subsystem/linux/syscall.cpp */ +extern int ConvertSignalToLinux(signal_t sig); + +namespace Tasking +{ + bool Signal::HandleSignal(CPU::SchedulerFrame *tf, void *thread) + { +#warning "arm not implemented" + return false; + } + + void Signal::RestoreHandleSignal(SyscallsFrame *sf, void *thread) + { +#warning "arm not implemented" + } +} diff --git a/Kernel/arch/arm/tasking/signal_trampoline.s b/Kernel/arch/arm/tasking/signal_trampoline.s new file mode 100644 index 00000000..c23e2f51 --- /dev/null +++ b/Kernel/arch/arm/tasking/signal_trampoline.s @@ -0,0 +1,28 @@ +/* + 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 . +*/ + +.global _sig_native_trampoline_start +_sig_native_trampoline_start: + +.global _sig_native_trampoline_end +_sig_native_trampoline_end: + +.global _sig_linux_trampoline_start +_sig_linux_trampoline_start: + +.global _sig_linux_trampoline_end +_sig_linux_trampoline_end: diff --git a/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c b/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c index e155c96f..064b7c2f 100644 --- a/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c +++ b/Kernel/core/memory/heap_allocators/rpmalloc/rpmalloc.c @@ -551,9 +551,9 @@ struct heap_t }; /* Keep in sync with heap_t inside rpmalloc_compat.cpp */ -#ifndef __i386__ +#if !defined(__i386__) && !defined(__arm__) static_assert(sizeof(heap_t) == 56408, "heap_t size mismatch"); -#endif // __i386__ +#endif // __i386__ || __arm__ // Size class for defining a block size bucket struct size_class_t @@ -3105,7 +3105,11 @@ rpcalloc(size_t num, size_t size) { size_t total; #if ENABLE_VALIDATE_ARGS +#ifdef __arm__ + int err = __builtin_umull_overflow(num, size, (unsigned long *)&total); +#else int err = __builtin_umull_overflow(num, size, &total); +#endif assert(!err && (total < MAX_ALLOC_SIZE)); #else total = num * size; @@ -3150,7 +3154,11 @@ rpaligned_calloc(size_t alignment, size_t num, size_t size) { size_t total; #if ENABLE_VALIDATE_ARGS +#ifdef __arm__ + int err = __builtin_umull_overflow(num, size, (unsigned long *)&total); +#else int err = __builtin_umull_overflow(num, size, &total); +#endif assert(!err && (total < MAX_ALLOC_SIZE)); #else total = num * size; diff --git a/Kernel/core/memory/reserve_essentials.cpp b/Kernel/core/memory/reserve_essentials.cpp index 2c9b5b00..b1253b8e 100644 --- a/Kernel/core/memory/reserve_essentials.cpp +++ b/Kernel/core/memory/reserve_essentials.cpp @@ -93,7 +93,7 @@ namespace Memory #if defined(__amd64__) || defined(__aarch64__) Elf64_Xword SymbolSize = 0; Elf64_Xword StringSize = 0; -#elif defined(__i386__) +#elif defined(__i386__) || defined(__arm__) Elf32_Word SymbolSize = 0; Elf32_Word StringSize = 0; #endif diff --git a/Kernel/core/panic/ui.cpp b/Kernel/core/panic/ui.cpp index c9c81e82..c9cf6a13 100644 --- a/Kernel/core/panic/ui.cpp +++ b/Kernel/core/panic/ui.cpp @@ -304,12 +304,19 @@ nsa void DisplayMainScreen(CPU::ExceptionFrame *Frame) "stub", "stub", #warning "aarch64 not implemented" +#elif defined(__arm__) + "stub", + "stub", +#warning "arm not implemented" #endif #if defined(__amd64__) || defined(__i386__) Frame->InterruptNumber); #elif defined(__aarch64__) 0); #warning "aarch64 not implemented" +#elif defined(__arm__) + 0); +#warning "arm not implemented" #endif #if defined(__amd64__) || defined(__i386__) ExPrint("Cause: %s\n", x86Exceptions[Frame->InterruptNumber].Cause); @@ -320,6 +327,8 @@ nsa void DisplayMainScreen(CPU::ExceptionFrame *Frame) Frame->rip); #elif defined(__i386__) Frame->eip); +#elif defined(__arm__) +0); #elif defined(__aarch64__) 0); #warning "aarch64 not implemented" diff --git a/Kernel/core/symbols.cpp b/Kernel/core/symbols.cpp index 4af12849..8fb4d39a 100644 --- a/Kernel/core/symbols.cpp +++ b/Kernel/core/symbols.cpp @@ -104,7 +104,7 @@ namespace SymbolResolver #if defined(__amd64__) || defined(__aarch64__) Elf64_Xword SymbolSize = 0; // Elf64_Xword StringSize = 0; -#elif defined(__i386__) +#elif defined(__i386__) || defined(__arm__) Elf32_Word SymbolSize = 0; // Elf32_Word StringSize = 0; #endif @@ -220,7 +220,7 @@ namespace SymbolResolver #if defined(__amd64__) || defined(__aarch64__) Elf64_Ehdr *Header = (Elf64_Ehdr *)ImageAddress; -#elif defined(__i386__) +#elif defined(__i386__) || defined(__arm__) Elf32_Ehdr *Header = (Elf32_Ehdr *)ImageAddress; #endif if (Header->e_ident[0] != 0x7F && diff --git a/Kernel/include/abi.h b/Kernel/include/abi.h index 36fecc1c..2895af08 100644 --- a/Kernel/include/abi.h +++ b/Kernel/include/abi.h @@ -80,9 +80,11 @@ typedef struct #if defined(__amd64__) typedef Elf64_auxv_t Elf_auxv_t; #elif defined(__i386__) -typedef Elf64_auxv_t Elf_auxv_t; +typedef Elf32_auxv_t Elf_auxv_t; #elif defined(__aarch64__) typedef Elf64_auxv_t Elf_auxv_t; +#elif defined(__arm__) +typedef Elf32_auxv_t Elf_auxv_t; #endif typedef struct diff --git a/Kernel/include/convert.h b/Kernel/include/convert.h index b78891c4..9a8f71e2 100644 --- a/Kernel/include/convert.h +++ b/Kernel/include/convert.h @@ -90,8 +90,8 @@ extern "C" long unsigned strlen_sse4_1(const char s[]); long unsigned strlen_sse4_2(const char s[]); - long unsigned strlen(const char s[]); - int strncmp(const char *s1, const char *s2, unsigned long n); + size_t strlen(const char s[]); + int strncmp(const char *s1, const char *s2, size_t n); char *strcat_unsafe(char *destination, const char *source); char *strcpy_unsafe(char *destination, const char *source); char *strncpy(char *destination, const char *source, unsigned long num); diff --git a/Kernel/include/cpu.hpp b/Kernel/include/cpu.hpp index 0f53d505..38d699df 100644 --- a/Kernel/include/cpu.hpp +++ b/Kernel/include/cpu.hpp @@ -1072,6 +1072,72 @@ namespace CPU } } + namespace arm + { + struct TrapFrame + { + uint32_t R0; /* Register R0 (argument / scratch) */ + uint32_t R1; /* Register R1 (argument / scratch) */ + uint32_t R2; /* Register R2 (argument / scratch) */ + uint32_t R3; /* Register R3 (argument / scratch) */ + uint32_t R4; /* Register R4 (callee-saved) */ + uint32_t R5; /* Register R5 (callee-saved) */ + uint32_t R6; /* Register R6 (callee-saved) */ + uint32_t R7; /* Register R7 (callee-saved) */ + uint32_t R8; /* Register R8 (callee-saved) */ + uint32_t R9; /* Register R9 (platform-specific) */ + uint32_t R10; /* Register R10 (callee-saved) */ + uint32_t FP; /* Frame Pointer (R11) */ + uint32_t IP; /* Intra-Procedure Scratch (R12) */ + uint32_t SP; /* Stack Pointer (R13) */ + uint32_t LR; /* Link Register (R14) */ + uint32_t PC; /* Program Counter (R15) */ + uint32_t CPSR; /* Current Program Status Register */ + }; + + struct SchedulerFrame + { + uint32_t R0; /* Register R0 (argument / scratch) */ + uint32_t R1; /* Register R1 (argument / scratch) */ + uint32_t R2; /* Register R2 (argument / scratch) */ + uint32_t R3; /* Register R3 (argument / scratch) */ + uint32_t R4; /* Register R4 (callee-saved) */ + uint32_t R5; /* Register R5 (callee-saved) */ + uint32_t R6; /* Register R6 (callee-saved) */ + uint32_t R7; /* Register R7 (callee-saved) */ + uint32_t R8; /* Register R8 (callee-saved) */ + uint32_t R9; /* Register R9 (platform-specific) */ + uint32_t R10; /* Register R10 (callee-saved) */ + uint32_t FP; /* Frame Pointer (R11) */ + uint32_t IP; /* Intra-Procedure Scratch (R12) */ + uint32_t SP; /* Stack Pointer (R13) */ + uint32_t LR; /* Link Register (R14) */ + uint32_t PC; /* Program Counter (R15) */ + uint32_t CPSR; /* Current Program Status Register */ + }; + + struct ExceptionFrame + { + uint32_t R0; /* Register R0 (argument / scratch) */ + uint32_t R1; /* Register R1 (argument / scratch) */ + uint32_t R2; /* Register R2 (argument / scratch) */ + uint32_t R3; /* Register R3 (argument / scratch) */ + uint32_t R4; /* Register R4 (callee-saved) */ + uint32_t R5; /* Register R5 (callee-saved) */ + uint32_t R6; /* Register R6 (callee-saved) */ + uint32_t R7; /* Register R7 (callee-saved) */ + uint32_t R8; /* Register R8 (callee-saved) */ + uint32_t R9; /* Register R9 (platform-specific) */ + uint32_t R10; /* Register R10 (callee-saved) */ + uint32_t FP; /* Frame Pointer (R11) */ + uint32_t IP; /* Intra-Procedure Scratch (R12) */ + uint32_t SP; /* Stack Pointer (R13) */ + uint32_t LR; /* Link Register (R14) */ + uint32_t PC; /* Program Counter (R15) */ + uint32_t CPSR; /* Current Program Status Register */ + }; + } + namespace aarch64 { struct TrapFrame @@ -1123,6 +1189,15 @@ namespace CPU typedef x32::TrapFrame TrapFrame; typedef x32::SchedulerFrame SchedulerFrame; typedef x32::ExceptionFrame ExceptionFrame; +#elif defined(__arm__) + /** + * CPU trap frame for the current architecture + * + * @note This is for arm + */ + typedef arm::TrapFrame TrapFrame; + typedef arm::SchedulerFrame SchedulerFrame; + typedef arm::ExceptionFrame ExceptionFrame; #elif defined(__aarch64__) /** * CPU trap frame for the current architecture diff --git a/Kernel/include/elf.h b/Kernel/include/elf.h index d3de007f..b63f9dda 100644 --- a/Kernel/include/elf.h +++ b/Kernel/include/elf.h @@ -962,7 +962,7 @@ typedef Elf64_Rel Elf_Rel; typedef Elf64_Sym Elf_Sym; typedef Elf64_Dyn Elf_Dyn; typedef Elf64_Rela Elf_Rela; -#elif defined(__i386__) +#elif defined(__i386__) || defined(__arm__) typedef Elf32_Addr Elf_Addr; typedef Elf32_Half Elf_Half; typedef Elf32_Off Elf_Off; diff --git a/Kernel/include/memory/macro.hpp b/Kernel/include/memory/macro.hpp index e75beb83..3bd33600 100644 --- a/Kernel/include/memory/macro.hpp +++ b/Kernel/include/memory/macro.hpp @@ -59,7 +59,7 @@ #define USER_STACK_END 0xFFFFEFFF00000000 /* 256 MiB */ #define USER_STACK_BASE 0xFFFFEFFFFFFF0000 -#elif defined(__i386__) +#elif defined(__i386__) || defined(__arm__) #define KERNEL_VMA_OFFSET 0xC0000000 #define USER_ALLOC_BASE 0x80000000 diff --git a/Kernel/include/syscalls.hpp b/Kernel/include/syscalls.hpp index f0cd1d3b..45fcd777 100644 --- a/Kernel/include/syscalls.hpp +++ b/Kernel/include/syscalls.hpp @@ -67,6 +67,14 @@ typedef struct SyscallsFrame uint64_t ExceptionSyndromeRegister; uint64_t FaultAddressRegister; uint64_t SavedProgramStatusRegister; +#elif defined(__arm__) + uint32_t ReturnAddress; /* r0 */ + uint32_t x[14]; + uint32_t StackPointer; + uint32_t ExceptionLinkRegister; + uint32_t ExceptionSyndromeRegister; + uint32_t FaultAddressRegister; + uint32_t SavedProgramStatusRegister; #endif uintptr_t ReturnValue() const diff --git a/Kernel/include/task.hpp b/Kernel/include/task.hpp index 07b5545a..105b0a1e 100644 --- a/Kernel/include/task.hpp +++ b/Kernel/include/task.hpp @@ -553,6 +553,8 @@ namespace Tasking return x64; #elif defined(__i386__) return x32; +#elif defined(__arm__) + return ARM32; #elif defined(__aarch64__) return ARM64; #endif diff --git a/Kernel/include/types.h b/Kernel/include/types.h index 5b782c42..9714a7db 100644 --- a/Kernel/include/types.h +++ b/Kernel/include/types.h @@ -171,7 +171,7 @@ typedef uint32_t uid_t; typedef uint32_t gid_t; typedef int64_t clock_t; typedef int32_t pid_t; -#elif defined(__i386__) +#elif defined(__i386__) || defined(__arm__) typedef int32_t off_t; typedef long long off64_t; typedef uint32_t mode_t; diff --git a/Kernel/include_std/float.h b/Kernel/include_std/float.h index 369b7161..ee779857 100644 --- a/Kernel/include_std/float.h +++ b/Kernel/include_std/float.h @@ -27,6 +27,10 @@ #define DBL_MANT_DIG 24 #define DBL_MAX_10_EXP 38 #define DBL_MAX 3.4028234663852886e+38 +#elif __arm__ +#define DBL_MANT_DIG __DBL_MANT_DIG__ +#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__ +#define DBL_MAX __DBL_MAX__ #elif __aarch64__ #define DBL_MANT_DIG __DBL_MANT_DIG__ #define DBL_MAX_10_EXP __DBL_MAX_10_EXP__ diff --git a/Kernel/include_std/functional b/Kernel/include_std/functional index 97ac2bbf..e58d5588 100644 --- a/Kernel/include_std/functional +++ b/Kernel/include_std/functional @@ -45,6 +45,10 @@ namespace std static_assert(sizeof(uintptr_t) == sizeof(uint32_t)); const uint32_t FNV_OFFSET_BASIS = 2166136261u; const uint32_t FNV_PRIME = 16777619u; +#elif defined(__arm__) + static_assert(sizeof(uintptr_t) == sizeof(uint32_t)); + const uint32_t FNV_OFFSET_BASIS = 2166136261u; + const uint32_t FNV_PRIME = 16777619u; #elif defined(__aarch64__) static_assert(sizeof(uintptr_t) == sizeof(uint64_t)); const uint64_t FNV_OFFSET_BASIS = 14695981039346656037ull; diff --git a/Kernel/include_std/new b/Kernel/include_std/new index 7d90a8c9..ec7f2fdd 100644 --- a/Kernel/include_std/new +++ b/Kernel/include_std/new @@ -79,13 +79,13 @@ namespace std [[nodiscard]] void *operator new(std::size_t count); [[nodiscard]] void *operator new[](std::size_t count); -// [[nodiscard]] void *operator new(std::size_t count, std::align_val_t al); -// [[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al); +[[nodiscard]] void *operator new(std::size_t count, std::align_val_t al); +[[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al); -// [[nodiscard]] void *operator new(std::size_t count, const std::nothrow_t &tag) noexcept; -// [[nodiscard]] void *operator new[](std::size_t count, const std::nothrow_t &tag) noexcept; -// [[nodiscard]] void *operator new(std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept; -// [[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept; +[[nodiscard]] void *operator new(std::size_t count, const std::nothrow_t &tag) noexcept; +[[nodiscard]] void *operator new[](std::size_t count, const std::nothrow_t &tag) noexcept; +[[nodiscard]] void *operator new(std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept; +[[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept; [[nodiscard]] void *operator new(std::size_t count, void *ptr) noexcept; [[nodiscard]] void *operator new[](std::size_t count, void *ptr) noexcept; diff --git a/Kernel/library/convert.cpp b/Kernel/library/convert.cpp index 0810e8b6..c75fba0b 100644 --- a/Kernel/library/convert.cpp +++ b/Kernel/library/convert.cpp @@ -62,7 +62,7 @@ EXTERNC int strncmp(const char *s1, const char *s2, size_t n) return 0; } -EXTERNC long unsigned strlen(const char s[]) +EXTERNC size_t strlen(const char s[]) { if (Config.SIMD) { diff --git a/Kernel/library/kexcept/cxxabi.cpp b/Kernel/library/kexcept/cxxabi.cpp index 0f9b17f7..40d544d5 100644 --- a/Kernel/library/kexcept/cxxabi.cpp +++ b/Kernel/library/kexcept/cxxabi.cpp @@ -192,7 +192,9 @@ extern "C" __noreturn void __cxa_throw(void *thrown_object, Exception->terminateHandler = &terminate_header_stub; Exception->unwindHeader.exception_cleanup = &exception_cleanup_stub; INIT_EXCEPTION_CLASS(&Exception->unwindHeader.exception_class); +#ifndef __arm__ Exception->adjustedPtr = thrown_object; +#endif _Unwind_RaiseException(&Exception->unwindHeader); __cxa_begin_catch(&Exception->unwindHeader); diff --git a/Kernel/library/md5.c b/Kernel/library/md5.c index 45606595..466683de 100644 --- a/Kernel/library/md5.c +++ b/Kernel/library/md5.c @@ -134,7 +134,7 @@ void md5Finalize(MD5Context *ctx) (uint32_t)(ctx->input[(j * 4)]); } input[14] = (uint32_t)(ctx->size * 8); -#ifdef __i386__ +#if defined(__i386__) || defined(__arm__) input[15] = (uint32_t)((uint64_t)(((uint64_t)ctx->size >> 32) | ((uint64_t)ctx->size << 32)) >> 32); #else input[15] = (uint32_t)((ctx->size * 8) >> 32); diff --git a/Kernel/library/std/new.cpp b/Kernel/library/std/new.cpp index 4859ed05..aa3f97e9 100644 --- a/Kernel/library/std/new.cpp +++ b/Kernel/library/std/new.cpp @@ -42,8 +42,37 @@ void *operator new[](std::size_t count) throw std::bad_alloc{}; } -// void *operator new(std::size_t count, std::align_val_t al) -// void *operator new[](std::size_t count, std::align_val_t al) +void *operator new(std::size_t count, std::align_val_t al) +{ + if (count == 0) + ++count; + + std::size_t alignment = static_cast(al); + void *ptr = kmalloc(count + alignment - 1 + sizeof(void *)); + if (!ptr) + throw std::bad_alloc{}; + + void *aligned_ptr = reinterpret_cast( + (reinterpret_cast(ptr) + sizeof(void *) + alignment - 1) & ~(alignment - 1)); + reinterpret_cast(aligned_ptr)[-1] = ptr; + return aligned_ptr; +} + +void *operator new[](std::size_t count, std::align_val_t al) +{ + if (count == 0) + ++count; + + std::size_t alignment = static_cast(al); + void *ptr = kmalloc(count + alignment - 1 + sizeof(void *)); + if (!ptr) + throw std::bad_alloc{}; + + void *aligned_ptr = reinterpret_cast( + (reinterpret_cast(ptr) + sizeof(void *) + alignment - 1) & ~(alignment - 1)); + reinterpret_cast(aligned_ptr)[-1] = ptr; + return aligned_ptr; +} // void *operator new(std::size_t count, const std::nothrow_t &tag) // void *operator new[](std::size_t count, const std::nothrow_t &tag) @@ -62,8 +91,24 @@ void operator delete(void *ptr) noexcept { kfree(ptr); } void operator delete[](void *ptr) noexcept { kfree(ptr); } -// void operator delete(void *ptr, std::align_val_t al) noexcept -// void operator delete[](void *ptr, std::align_val_t al) noexcept +void operator delete(void *ptr, std::align_val_t al) noexcept +{ + if (!ptr) + return; + + void *original_ptr = reinterpret_cast(ptr)[-1]; + kfree(original_ptr); +} + +void operator delete[](void *ptr, std::align_val_t al) noexcept +{ + if (!ptr) + return; + + void *original_ptr = reinterpret_cast(ptr)[-1]; + kfree(original_ptr); +} + void operator delete(void *ptr, std::size_t) noexcept { kfree(ptr); } void operator delete[](void *ptr, std::size_t sz) noexcept { kfree(ptr); } diff --git a/Kernel/subsystem/linux/include/defs.hpp b/Kernel/subsystem/linux/include/defs.hpp index a70e4914..4ef82edd 100644 --- a/Kernel/subsystem/linux/include/defs.hpp +++ b/Kernel/subsystem/linux/include/defs.hpp @@ -334,6 +334,24 @@ struct linux_kstat __kernel_ulong_t st_ctime_nsec; #undef __unused __kernel_long_t __unused[3]; +#elif defined(__arm__) + __kernel_ulong_t st_dev; + __kernel_ulong_t st_ino; + __kernel_ulong_t st_nlink; + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad0; + __kernel_ulong_t st_rdev; + __kernel_long_t st_size; + __kernel_long_t st_blksize; + __kernel_long_t st_blocks; + __kernel_ulong_t st_atime; + __kernel_ulong_t st_atime_nsec; + __kernel_ulong_t st_mtime; + __kernel_ulong_t st_mtime_nsec; + __kernel_ulong_t st_ctime; + __kernel_ulong_t st_ctime_nsec; #else #error "Unsupported architecture" #endif @@ -371,7 +389,7 @@ struct __old_kernel_stat unsigned short st_uid; unsigned short st_gid; unsigned short st_rdev; -#ifdef __i386__ +#if defined(__i386__) || defined(__arm__) unsigned long st_size; unsigned long st_atime; unsigned long st_mtime; diff --git a/Makefile b/Makefile index 8508f6c0..97088452 100644 --- a/Makefile +++ b/Makefile @@ -66,6 +66,15 @@ QEMUFLAGS += -M q35 \ -device intel-hda \ -device ich9-intel-hda \ -acpitable file=tools/acpi/SSDT1.dat +else ifeq ($(OSARCH), arm) +QEMUFLAGS += -M raspi2b \ + -monitor pty \ + -cpu cortex-a15 \ + -serial file:serial.log \ + -serial file:COM2.dmp \ + -serial file:COM3.dmp \ + -serial stdio \ + -kernel $(OSNAME).img else ifeq ($(OSARCH), aarch64) QEMUFLAGS += -M raspi3b \ -monitor pty \ @@ -160,7 +169,7 @@ ifeq ($(BOOTLOADER), grub) cp tools/grub.cfg iso_tmp_data/boot/grub/ grub-mkrescue -o $(OSNAME).iso iso_tmp_data endif -ifeq ($(OSARCH), aarch64) +ifneq ($(filter aarch64 arm,$(OSARCH)),) $(__CONF_OBJCOPY) Kernel/fennix.elf -O binary $(OSNAME).img endif @@ -179,6 +188,10 @@ ifeq ($(OSARCH), i386) QEMU_SMP = -smp $(shell nproc) endif +ifeq ($(OSARCH), arm) +QEMU_SMP = -smp 4 +endif + ifeq ($(OSARCH), aarch64) QEMU_SMP = -smp 4 endif @@ -189,6 +202,9 @@ QEMUMEMORY = -m 4G else ifeq ($(OSARCH), i386) QEMUHWACCELERATION = -machine q35 -enable-kvm QEMUMEMORY = -m 4G +else ifeq ($(OSARCH), arm) +QEMUHWACCELERATION = +QEMUMEMORY = -m 1G else ifeq ($(OSARCH), aarch64) QEMUHWACCELERATION = QEMUMEMORY = -m 1G diff --git a/Userspace/.vscode/c_cpp_properties.json b/Userspace/.vscode/c_cpp_properties.json index 4c598532..a6c44b52 100644 --- a/Userspace/.vscode/c_cpp_properties.json +++ b/Userspace/.vscode/c_cpp_properties.json @@ -82,6 +82,27 @@ "-nostdinc++" ] }, + { + "name": "Fennix Arm (Linux, GCC, debug)", + "includePath": [ + "${workspaceFolder}/libc/include/**", + "${workspaceFolder}/libs/include/**" + ], + "defines": [ + "__debug_vscode__", + "DEBUG=\"1\"" + ], + "compilerPath": "${workspaceFolder}/../tools/cross/bin/arm-fennix-gcc", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "linux-gcc-arm", + "configurationProvider": "ms-vscode.makefile-tools", + "compilerArgs": [ + "-ffreestanding", + "-nostdinc", + "-nostdinc++" + ] + }, { "name": "Fennix Aarch64 (Linux, GCC, debug)", "includePath": [ diff --git a/Userspace/libc/include/stdio.h b/Userspace/libc/include/stdio.h index ae09002c..50ec245d 100644 --- a/Userspace/libc/include/stdio.h +++ b/Userspace/libc/include/stdio.h @@ -50,7 +50,7 @@ extern "C" #define P_tmpdir "/tmp/" typedef long fpos_t; - typedef unsigned long size_t; + typedef __SIZE_TYPE__ size_t; struct _IO_FILE { diff --git a/Userspace/libc/include/stdlib.h b/Userspace/libc/include/stdlib.h index a543744e..5191a601 100644 --- a/Userspace/libc/include/stdlib.h +++ b/Userspace/libc/include/stdlib.h @@ -46,7 +46,7 @@ extern "C" long rem; } ldiv_t; - typedef unsigned long size_t; + typedef __SIZE_TYPE__ size_t; // typedef __WCHAR_TYPE__ wchar_t; long a64l(const char *); diff --git a/Userspace/libc/include/sys/types.h b/Userspace/libc/include/sys/types.h index 61ebc2b3..0fa16811 100644 --- a/Userspace/libc/include/sys/types.h +++ b/Userspace/libc/include/sys/types.h @@ -108,7 +108,7 @@ extern "C" char __data; } pthread_barrier_t; - typedef unsigned long size_t; + typedef __SIZE_TYPE__ size_t; typedef long ssize_t; typedef long suseconds_t; diff --git a/Userspace/libc/interpreter/elf.h b/Userspace/libc/interpreter/elf.h index 5b0319b6..b4e4c4b8 100644 --- a/Userspace/libc/interpreter/elf.h +++ b/Userspace/libc/interpreter/elf.h @@ -189,6 +189,15 @@ enum RelocationTypes R_AARCH64_RELATIVE = 1027, R_AARCH64_TLS_DTPMOD64 = 1028, + R_ARM_NONE = 0, + R_ARM_COPY = 1024, + R_ARM_GLOB_DAT = 1025, + R_ARM_JUMP_SLOT = 1026, + R_ARM_RELATIVE = 1027, + R_ARM_TLS_DTPMOD32 = 1028, + R_ARM_TLS_DTPOFF32 = 1029, + R_ARM_TLS_TPOFF32 = 1030, + #if defined(__x86_64__) R_NONE = R_X86_64_NONE, R_COPY = R_X86_64_COPY, @@ -216,6 +225,15 @@ enum RelocationTypes R_DTPMOD64 = R_AARCH64_TLS_DTPMOD64, R_DTPOFF64 = R_AARCH64_NONE, R_TPOFF64 = R_AARCH64_NONE, +#elif defined(__arm__) + R_NONE = R_ARM_NONE, + R_COPY = R_ARM_COPY, + R_GLOB_DAT = R_ARM_GLOB_DAT, + R_JMP_SLOT = R_ARM_JUMP_SLOT, + R_RELATIVE = R_ARM_RELATIVE, + R_DTPMOD64 = R_ARM_TLS_DTPMOD32, + R_DTPOFF64 = R_ARM_TLS_DTPOFF32, + R_TPOFF64 = R_ARM_TLS_TPOFF32, #endif }; @@ -1002,7 +1020,7 @@ typedef Elf64_Rela Elf_Rela; #define ELF_ST_BIND(info) ELF64_ST_BIND(info) #define ELF_ST_TYPE(info) ELF64_ST_TYPE(info) #define ELF_ST_INFO(bind, type) ELF64_ST_INFO(bind, type) -#elif defined(__i386__) +#elif defined(__i386__) || defined(__arm__) typedef Elf32_Addr Elf_Addr; typedef Elf32_Half Elf_Half; typedef Elf32_Off Elf_Off; diff --git a/Userspace/libc/interpreter/start.c b/Userspace/libc/interpreter/start.c index 1bfc3c02..0a99e591 100644 --- a/Userspace/libc/interpreter/start.c +++ b/Userspace/libc/interpreter/start.c @@ -128,6 +128,8 @@ __attribute__((naked, used, no_stack_protector)) void _start() "call _exit\n"); /* Call _exit */ #elif defined(__i386__) #warning "i386 _start not implemented" +#elif defined(__arm__) +#warning "arm _start not implemented" #elif defined(__aarch64__) #warning "aarch64 _start not implemented" #else diff --git a/Userspace/libc/runtime/Scrt1.c b/Userspace/libc/runtime/Scrt1.c index 2e962f64..99cf28df 100644 --- a/Userspace/libc/runtime/Scrt1.c +++ b/Userspace/libc/runtime/Scrt1.c @@ -68,6 +68,8 @@ __attribute__((naked, used, no_stack_protector, section(".text"))) void _start() "call _exit\n"); #elif defined(__i386__) #warning "i386 _start not implemented" +#elif defined(__arm__) +#warning "arm _start not implemented" #elif defined(__aarch64__) #warning "aarch64 _start not implemented" #else diff --git a/Userspace/libc/runtime/crt1.c b/Userspace/libc/runtime/crt1.c index 2e962f64..99cf28df 100644 --- a/Userspace/libc/runtime/crt1.c +++ b/Userspace/libc/runtime/crt1.c @@ -68,6 +68,8 @@ __attribute__((naked, used, no_stack_protector, section(".text"))) void _start() "call _exit\n"); #elif defined(__i386__) #warning "i386 _start not implemented" +#elif defined(__arm__) +#warning "arm _start not implemented" #elif defined(__aarch64__) #warning "aarch64 _start not implemented" #else diff --git a/Userspace/libc/src/softfloat.c b/Userspace/libc/src/softfloat.c index a321b308..b36d7902 100644 --- a/Userspace/libc/src/softfloat.c +++ b/Userspace/libc/src/softfloat.c @@ -19,3 +19,176 @@ double __trunctfdf2(long double a) { return (double)a; } + +int __aeabi_dcmple(long double a, long double b) +{ + return a <= b; +} + +long long __aeabi_d2lz(double a) +{ + return (long long)a; +} + +int __aeabi_dcmplt(long double a, long double b) +{ + return a < b; +} + +typedef union +{ + double d; + struct + { + __UINT64_TYPE__ mantissa : 52; + __UINT64_TYPE__ exponent : 11; + __UINT64_TYPE__ sign : 1; + } parts; +} aeabi_double_t; + +aeabi_double_t __aeabi_ddiv(aeabi_double_t a, aeabi_double_t b) +{ + aeabi_double_t result; + result.d = a.d / b.d; + return result; +} + +aeabi_double_t __aeabi_dmul(aeabi_double_t a, aeabi_double_t b) +{ + aeabi_double_t result; + result.d = a.d * b.d; + return result; +} + +aeabi_double_t __aeabi_dadd(aeabi_double_t a, aeabi_double_t b) +{ + aeabi_double_t result; + result.d = a.d + b.d; + return result; +} + +int __aeabi_dcmpgt(aeabi_double_t a, aeabi_double_t b) +{ + return a.d > b.d; +} + +int __aeabi_dcmpge(aeabi_double_t a, aeabi_double_t b) +{ + return a.d >= b.d; +} + +aeabi_double_t __aeabi_dsub(aeabi_double_t a, aeabi_double_t b) +{ + aeabi_double_t result; + result.d = a.d - b.d; + return result; +} + +aeabi_double_t __aeabi_i2d(int a) +{ + aeabi_double_t result; + result.d = (double)a; + return result; +} + +aeabi_double_t __aeabi_l2d(long long a) +{ + aeabi_double_t result; + result.d = (double)a; + return result; +} + +int __aeabi_dcmpeq(aeabi_double_t a, aeabi_double_t b) +{ + return a.d == b.d; +} + +int __aeabi_d2iz(aeabi_double_t a) +{ + return (int)a.d; +} + +struct ldivmod_result +{ + long quot; + long rem; +}; + +struct ldivmod_result __aeabi_ldivmod(long numerator, long denominator) +{ + struct ldivmod_result result; + result.quot = numerator / denominator; + result.rem = numerator % denominator; + return result; +} + +signed __aeabi_idiv(signed numerator, signed denominator) +{ + return numerator / denominator; +} + +signed __aeabi_idivmod(signed numerator, signed denominator) +{ + signed quotient = numerator / denominator; + signed remainder = numerator % denominator; + return (quotient << 16) | remainder; +} + +unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator) +{ + return numerator / denominator; +} + +unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator) +{ + unsigned quotient = numerator / denominator; + unsigned remainder = numerator % denominator; + return (quotient << 16) | remainder; +} + +__UINT64_TYPE__ __udivmoddi4(__UINT64_TYPE__ numerator, __UINT64_TYPE__ denominator, __UINT64_TYPE__ *remainder) +{ + __UINT64_TYPE__ quotient = 0; + __UINT64_TYPE__ bit = 1; + + if (denominator == 0) + { + *remainder = numerator; + return ~0ULL; + } + + while (denominator < numerator && (denominator & (1ULL << 63)) == 0) + { + denominator <<= 1; + bit <<= 1; + } + + while (bit) + { + if (numerator >= denominator) + { + numerator -= denominator; + quotient |= bit; + } + denominator >>= 1; + bit >>= 1; + } + + if (remainder) + *remainder = numerator; + + return quotient; +} + +struct udivmod_result +{ + __UINT64_TYPE__ quot; + __UINT64_TYPE__ rem; +}; + +struct udivmod_result __aeabi_uldivmod(__UINT64_TYPE__ numerator, __UINT64_TYPE__ denominator) +{ + struct udivmod_result result; + result.quot = __udivmoddi4(numerator, denominator, &result.rem); + return result; +}