From 39b2af76260904b87d9e7dd6f4007be608c8a11e Mon Sep 17 00:00:00 2001 From: karina Date: Sun, 3 May 2026 21:57:20 +0400 Subject: [PATCH] wip: IPC and Runtime --- .gitignore | 1 + Kernel/Include/Arch/CPU.h | 18 ++++-- Kernel/Include/Arch/IO.h | 2 +- Kernel/Include/OS/IPC.h | 7 +++ Kernel/Include/OS/Modules.h | 3 +- Kernel/Include/OS/Scheduler.h | 34 ++++++++++-- Kernel/Include/OS/Syscall.h | 10 ++++ Kernel/Source/Arch/Exceptions.c | 12 ++-- Kernel/Source/KernelMain.c | 3 +- Kernel/Source/OS/IPC.c | 46 ++++++++++++++++ Kernel/Source/OS/Modules.c | 6 +- Kernel/Source/OS/Scheduler.c | 28 ++++++++++ Kernel/Source/OS/Syscall.c | 25 +++++++++ Runtime/Common/aarch64.cmake | 4 ++ Runtime/Common/ksOS_SDK.cmake | 29 ++++++++++ Runtime/System/Init/CMakeLists.txt | 34 +----------- Runtime/System/Init/Source/main.c | 10 ++-- Runtime/System/Test/CMakeLists.txt | 19 +++++++ Runtime/System/Test/Source/main.c | 9 +++ Runtime/System/libksOS/CMakeLists.txt | 17 ++++++ Runtime/System/libksOS/Include/ksOS/Syscall.h | 55 +++++++++++++++++++ Runtime/System/libksOS/Include/ksOS/Types.h | 33 +++++++++++ Runtime/System/libksOS/Source/Syscall.c | 2 + .../Source/entry.S => libksOS/Source/crt0.S} | 5 -- Runtime/justfile | 25 +++++++++ 25 files changed, 371 insertions(+), 66 deletions(-) create mode 100644 Kernel/Include/OS/IPC.h create mode 100644 Kernel/Include/OS/Syscall.h create mode 100644 Kernel/Source/OS/IPC.c create mode 100644 Kernel/Source/OS/Syscall.c create mode 100644 Runtime/Common/ksOS_SDK.cmake create mode 100644 Runtime/System/Test/CMakeLists.txt create mode 100644 Runtime/System/Test/Source/main.c create mode 100644 Runtime/System/libksOS/CMakeLists.txt create mode 100644 Runtime/System/libksOS/Include/ksOS/Syscall.h create mode 100644 Runtime/System/libksOS/Include/ksOS/Types.h create mode 100644 Runtime/System/libksOS/Source/Syscall.c rename Runtime/System/{Init/Source/entry.S => libksOS/Source/crt0.S} (75%) diff --git a/.gitignore b/.gitignore index 1eac00a..289894b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ compile_commands.json ide-swift-toolchain.txt .cache .zed +Runtime/.clangd diff --git a/Kernel/Include/Arch/CPU.h b/Kernel/Include/Arch/CPU.h index 7c38579..c63716c 100644 --- a/Kernel/Include/Arch/CPU.h +++ b/Kernel/Include/Arch/CPU.h @@ -2,6 +2,7 @@ // Copyright (c) 2026 0xKSor #pragma once +#include "Arch/Exceptions.h" #include static inline void CPUYield() { @@ -63,7 +64,7 @@ static inline void CPUEnableMMU(Address l0PhysicalAddress) { // MAIR_EL1 (Memory Attribute Indirection Register) // kPTENormalMem is index 0 and kPTEDeviceMem is index 1 // 0xFF = Normal, 0x00 = Device - UInt64 mair = (0xFFULL << 0) | (0x00ULL << 8); + UInt64 mair = (0xFFULL << 0) | (0x00ULL << 8); // TCR_EL1 (Translation Control Register) // configures the mmu for 4kb pages and 48bit virtual addresses @@ -82,11 +83,11 @@ static inline void CPUEnableMMU(Address l0PhysicalAddress) { "msr tcr_el1, %1\n" "msr ttbr0_el1, %2\n" // set userspace root "msr ttbr1_el1, %2\n" // set kernelspace root - "tlbi vmalle1is\n" + "tlbi vmalle1is\n" "isb\n" // Instruction Synchronization Barrier :: "r"(mair), "r"(tcr), "r"(l0PhysicalAddress) : "memory" ); - + // turn on the MMU in SCTLR_EL1 (System Control Register) // Bit 0 = M (MMU Enable), Bit 2 = C (Data Cache Enable), Bit 12 = I (Instruction Cache Enable) UInt64 sctlr; @@ -111,4 +112,13 @@ static inline void CPUSwitchAddressSpace(Address l0Physical) { ); } -#define CPUException(number) __asm__ volatile ("svc %0" :: "i" (number) : "memory") \ No newline at end of file +static inline void CPUCopyIPCRegisters(ExceptionsContext* source, ExceptionsContext* destination) { + destination->x2 = source->x2; + destination->x3 = source->x3; + destination->x4 = source->x4; + destination->x5 = source->x5; + destination->x6 = source->x6; + destination->x7 = source->x7; +} + +#define CPUException(number) __asm__ volatile ("svc %0" :: "i" (number) : "memory") diff --git a/Kernel/Include/Arch/IO.h b/Kernel/Include/Arch/IO.h index 8f52f35..afe92ba 100644 --- a/Kernel/Include/Arch/IO.h +++ b/Kernel/Include/Arch/IO.h @@ -14,4 +14,4 @@ static inline UInt32 IOAddressRead32(Address address) { UInt32 value = *(volatile UInt32*)address; __asm__ volatile ("dsb ld" ::: "memory"); // wait till my read is finished physically return value; -} \ No newline at end of file +} diff --git a/Kernel/Include/OS/IPC.h b/Kernel/Include/OS/IPC.h new file mode 100644 index 0000000..f569976 --- /dev/null +++ b/Kernel/Include/OS/IPC.h @@ -0,0 +1,7 @@ +#pragma once +#include "Arch/Exceptions.h" +#include +#include + +UInt64 IPCSend(OSTask* sender, UInt64 handleID, UInt64 data); +void IPCReceive(ExceptionsContext* receiverFrame); diff --git a/Kernel/Include/OS/Modules.h b/Kernel/Include/OS/Modules.h index 4aca698..ff0f998 100644 --- a/Kernel/Include/OS/Modules.h +++ b/Kernel/Include/OS/Modules.h @@ -1,5 +1,6 @@ #pragma once #include #include "../Common/bootinfo.h" +#include -void ModuleLoad(BootModule* module); +OSTask* ModuleLoad(BootModule* module); diff --git a/Kernel/Include/OS/Scheduler.h b/Kernel/Include/OS/Scheduler.h index c2dce53..674e686 100644 --- a/Kernel/Include/OS/Scheduler.h +++ b/Kernel/Include/OS/Scheduler.h @@ -4,12 +4,31 @@ #pragma once #include +typedef enum { + kOSHandleTypeNone = 0, + kOSHandleTypeTask +} OSHandleType; + +typedef struct { + OSHandleType type; + Pointer object; +} OSHandle; + +enum { + kOSSchedulerTaskStackSize = 16 * 1024, + kOSSchedulerExceptionNumber = 0xF0F0, + kOSMaxHandlesPerProcess = 256, +}; + typedef enum OSTaskState { OSTaskStateDead, OSTaskStateRunning, OSTaskStateReady, OSTaskStateBlocked, OSTaskStateSleeping, + + OSTaskStateBlockedReceive, + OSTaskStateBlockedSend, } OSTaskState; typedef struct OSProcess { @@ -20,11 +39,12 @@ typedef struct OSProcess { Address heapCurrent; struct OSProcess* parent; ASCII name[32]; + + OSHandle handles[kOSMaxHandlesPerProcess]; } OSProcess; typedef struct OSTask { Address stackPointer; - struct OSTask* next; UInt32 id; UInt32 sleepTicks; OSTaskState state; @@ -32,12 +52,10 @@ typedef struct OSTask { Pointer kernelStackBase; OSProcess* process; Int32 waitingForProcessId; -} OSTask; -enum { - kOSSchedulerTaskStackSize = 16 * 1024, - kOSSchedulerExceptionNumber = 0xF0F0 -}; + struct OSTask* next; + struct OSTask* senderWaiting; +} OSTask; extern UInt32 gOSSchedulerNextProcessID; @@ -46,3 +64,7 @@ OSTask* SchedulerSpawn(void(*entryPoint)(), OSProcess* owner, Boolean isUser, Ad Address SchedulerNext(Address stackPointer); void SchedulerYield(UInt64 ticks); UInt64 SchedulerGetNextProcessID(); +void SchedulerBlockCurrentTask(UInt32 newState); +OSTask* SchedulerGetCurrentTask(); +Int32 SchedulerProcessAllocateHandle(OSProcess* process, OSHandleType type, Pointer object); +Pointer SchedulerProcessGetHandle(OSProcess* process, UInt32 handleId, OSHandleType expectedType); diff --git a/Kernel/Include/OS/Syscall.h b/Kernel/Include/OS/Syscall.h new file mode 100644 index 0000000..9c7b76f --- /dev/null +++ b/Kernel/Include/OS/Syscall.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include + +enum Syscalls { + kSyscallSend, + kSyscallReceive, +}; + +Address SyscallDispatch(ExceptionsContext* frame); diff --git a/Kernel/Source/Arch/Exceptions.c b/Kernel/Source/Arch/Exceptions.c index 9433402..707dca6 100644 --- a/Kernel/Source/Arch/Exceptions.c +++ b/Kernel/Source/Arch/Exceptions.c @@ -5,6 +5,7 @@ #include #include #include +#include Address ExceptionsHandler(ExceptionsContext* frame, ExceptionsType type) { if (type == ExceptionsIRQEl1h || type == ExceptionsIRQEl064) return GICDispatch(frame, type); @@ -13,14 +14,9 @@ Address ExceptionsHandler(ExceptionsContext* frame, ExceptionsType type) { UInt32 class = (esr >> 26) & 0x3F; UInt32 syndrome = esr & 0x1FFFFFF; - if (class == 0x11 || class == 0x15) { - if (syndrome == kOSSchedulerExceptionNumber) { - return SchedulerNext((Address)frame); - } - } - - if (class == 0x15 && syndrome == 0) { - OSPanic("Hi from userspace!!"); + if (class == 0x15) { + if (syndrome == kOSSchedulerExceptionNumber) return SchedulerNext((Address)frame); + if (syndrome == 0) return SyscallDispatch(frame); } } OSPanicException(frame); diff --git a/Kernel/Source/KernelMain.c b/Kernel/Source/KernelMain.c index e017abd..924fab6 100644 --- a/Kernel/Source/KernelMain.c +++ b/Kernel/Source/KernelMain.c @@ -40,8 +40,7 @@ void KernelMain(Bootinfo* bootinfo) { SchedulerInitialize(); for (UInt32 i = 0; i < bootinfo->moduleCount; i++) { - ModuleLoad(&bootinfo->modules[i]); // TODO: make some sort of priority of loading modules - // like init first then uart then fb ... + ModuleLoad(&bootinfo->modules[i]); // TODO: priority } OSLog("Kernel initialized.\n"); diff --git a/Kernel/Source/OS/IPC.c b/Kernel/Source/OS/IPC.c new file mode 100644 index 0000000..98e1cc5 --- /dev/null +++ b/Kernel/Source/OS/IPC.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +UInt64 IPCSend(OSTask* sender, UInt64 handleID, UInt64 data) { + if (handleID == 0) return -1; + OSProcess* currentProcess = sender->process; + OSTask* targetTask = (OSTask*)SchedulerProcessGetHandle(currentProcess, handleID, kOSHandleTypeTask); + if (!targetTask) return -1; + + if (targetTask->state == OSTaskStateBlockedReceive) { + ExceptionsContext* receiverContext = (ExceptionsContext*)targetTask->stackPointer; + receiverContext->x1 = data; + receiverContext->x0 = currentProcess->id; + + targetTask->state = OSTaskStateRunning; + return 0; + } + + if (targetTask->senderWaiting != nullptr) return -2; + + targetTask->senderWaiting = sender; + + SchedulerBlockCurrentTask(OSTaskStateBlockedSend); + return 0; +} + +void IPCReceive(ExceptionsContext* receiverFrame) { + OSTask* receiver = SchedulerGetCurrentTask(); + + if (receiver->senderWaiting != nullptr) { + OSTask* sender = receiver->senderWaiting; + + ExceptionsContext* senderContext = (ExceptionsContext*)sender->stackPointer; + + receiverFrame->x1 = senderContext->x1; // Data + receiverFrame->x0 = sender->process->id; // Sender ID + + receiver->senderWaiting = nullptr; + sender->state = OSTaskStateRunning; + return; + } + + SchedulerBlockCurrentTask(OSTaskStateBlockedReceive); +} diff --git a/Kernel/Source/OS/Modules.c b/Kernel/Source/OS/Modules.c index 3adbb36..2cf1ef1 100644 --- a/Kernel/Source/OS/Modules.c +++ b/Kernel/Source/OS/Modules.c @@ -7,7 +7,7 @@ #include #include "../Common/bootinfo.h" -void ModuleLoad(BootModule* module) { +OSTask* ModuleLoad(BootModule* module) { OSProcess* userProc = HeapAllocate(sizeof(OSProcess)); MemorySet(userProc, 0, sizeof(OSProcess)); userProc->id = SchedulerGetNextProcessID(); @@ -56,8 +56,8 @@ void ModuleLoad(BootModule* module) { if ((Address)userEntryPoint == 0x0) { OSLog("Skipping module %s: entry point is 0x0.\n", module->name); - return; + return nullptr; } - SchedulerSpawn(userEntryPoint, userProc, true, userStackVirt + kVMPageSize); + return SchedulerSpawn(userEntryPoint, userProc, true, userStackVirt + kVMPageSize); } diff --git a/Kernel/Source/OS/Scheduler.c b/Kernel/Source/OS/Scheduler.c index 0bbbe3d..60300d1 100644 --- a/Kernel/Source/OS/Scheduler.c +++ b/Kernel/Source/OS/Scheduler.c @@ -69,6 +69,7 @@ OSTask* SchedulerSpawn(void(*entryPoint)(), OSProcess* owner, Boolean isUser, Ad task->waitingForProcessId = -1; task->next = gOSSchedulerCurrentTask->next; + task->senderWaiting = nullptr; gOSSchedulerCurrentTask->next = task; return task; @@ -126,3 +127,30 @@ void SchedulerYield(UInt64 ticks) { UInt64 SchedulerGetNextProcessID() { return gOSSchedulerNextProcessID++; } + +void SchedulerBlockCurrentTask(UInt32 newState) { + gOSSchedulerCurrentTask->state = newState; + CPUException(kOSSchedulerExceptionNumber); +} + +OSTask* SchedulerGetCurrentTask() { + return gOSSchedulerCurrentTask; +} + +Int32 SchedulerProcessAllocateHandle(OSProcess* process, OSHandleType type, Pointer object) { + for (Int32 i = 1; i < kOSMaxHandlesPerProcess; i++) { + if (process->handles[i].type == kOSHandleTypeNone) { + process->handles[i].type = type; + process->handles[i].object = object; + return i; + } + } + return -1; +} + +Pointer SchedulerProcessGetHandle(OSProcess* process, UInt32 handleId, OSHandleType expectedType) { + if (handleId == 0 || handleId >= kOSMaxHandlesPerProcess) return nullptr; + OSHandle* handle = &process->handles[handleId]; + if (handle->type != expectedType) return nullptr; + return handle->object; +} diff --git a/Kernel/Source/OS/Syscall.c b/Kernel/Source/OS/Syscall.c new file mode 100644 index 0000000..bea454a --- /dev/null +++ b/Kernel/Source/OS/Syscall.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include + +Address SyscallDispatch(ExceptionsContext* frame) { + UInt64 syscallNumber = frame->x8; + OSTask* current = SchedulerGetCurrentTask(); + + switch (syscallNumber) { + case kSyscallSend: + frame->x0 = IPCSend(current, frame->x0, frame->x1); + break; + case kSyscallReceive: + IPCReceive(frame); + break; + default: + frame->x0 = -1; + break; + } + + if (current->state != OSTaskStateRunning) return SchedulerNext((Address)frame); + return (Address)frame; +} diff --git a/Runtime/Common/aarch64.cmake b/Runtime/Common/aarch64.cmake index 2a5ab03..73bafbb 100644 --- a/Runtime/Common/aarch64.cmake +++ b/Runtime/Common/aarch64.cmake @@ -56,3 +56,7 @@ find_program(LLVM_OBJCOPY NAMES llvm-objcopy objcopy /opt/homebrew/bin REQUIRED ) + +set(CMAKE_C_FLAGS_INIT "-ffreestanding -mgeneral-regs-only -std=c23") + +set(CMAKE_EXE_LINKER_FLAGS_INIT "-nostdlib -static -no-pie -z max-page-size=0x1000 --no-dynamic-linker -T ${CMAKE_CURRENT_LIST_DIR}/linker.ld -Ttext=0x400000") diff --git a/Runtime/Common/ksOS_SDK.cmake b/Runtime/Common/ksOS_SDK.cmake new file mode 100644 index 0000000..1264f3f --- /dev/null +++ b/Runtime/Common/ksOS_SDK.cmake @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (c) 2026 0xKSor + +set(KSOS_SYSROOT_SRC "${CMAKE_CURRENT_LIST_DIR}/..") +set(BUILD_DIR $ENV{BUILD_DIR}) +if(NOT BUILD_DIR) + set(BUILD_DIR "${CMAKE_CURRENT_LIST_DIR}/../../.build") +endif() + +set(KSOS_LIB_DIR "${BUILD_DIR}/Runtime/System/libksOS") + +function(add_ksos_executable TARGET_NAME) + add_executable(${TARGET_NAME} + "${KSOS_SYSROOT_SRC}/System/libksOS/Source/crt0.S" + ${ARGN} + ) + + target_include_directories(${TARGET_NAME} PRIVATE + "${KSOS_SYSROOT_SRC}/System/libksOS/Include" + ) + + target_link_directories(${TARGET_NAME} PRIVATE + "${KSOS_LIB_DIR}" + ) + + target_link_libraries(${TARGET_NAME} PRIVATE + ksOS + ) +endfunction() diff --git a/Runtime/System/Init/CMakeLists.txt b/Runtime/System/Init/CMakeLists.txt index a610e36..3c88da6 100644 --- a/Runtime/System/Init/CMakeLists.txt +++ b/Runtime/System/Init/CMakeLists.txt @@ -4,44 +4,16 @@ cmake_minimum_required(VERSION 3.20) project(ksOS_init LANGUAGES C ASM) +include("${CMAKE_CURRENT_SOURCE_DIR}/../../Common/ksOS_SDK.cmake") file(GLOB_RECURSE INIT_SOURCES CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Source/*.S ${CMAKE_CURRENT_SOURCE_DIR}/Source/*.c ) -add_executable(init ${INIT_SOURCES}) +add_ksos_executable(Init ${INIT_SOURCES}) -target_include_directories(init PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/Source - ${CMAKE_CURRENT_SOURCE_DIR}/../../Common -) - -target_compile_options(init PRIVATE - $<$: - -std=c23 - -fno-stack-protector - -fno-builtin - -Wall - -Wextra - > - -ffreestanding - -g - -mgeneral-regs-only -) - -target_link_options(init PRIVATE - -nostdlib - -static - -no-pie - -T "${CMAKE_CURRENT_SOURCE_DIR}/../../Common/linker.ld" - -Ttext=0x400000 - -e _start - -z max-page-size=0x1000 - --no-dynamic-linker -) - -set_target_properties(init PROPERTIES +set_target_properties(Init PROPERTIES OUTPUT_NAME "Init" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) diff --git a/Runtime/System/Init/Source/main.c b/Runtime/System/Init/Source/main.c index fa9b93e..e3116fe 100644 --- a/Runtime/System/Init/Source/main.c +++ b/Runtime/System/Init/Source/main.c @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (c) 2026 0xKSor -void main(void) { - __asm__ volatile( - "svc #0\n" - "b .\n" - ); +#include + +int main(void) { + SysSend(1, 0xa0a0a0a0a); + while (1) {} } diff --git a/Runtime/System/Test/CMakeLists.txt b/Runtime/System/Test/CMakeLists.txt new file mode 100644 index 0000000..fe7c119 --- /dev/null +++ b/Runtime/System/Test/CMakeLists.txt @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (c) 2026 0xKSor + +cmake_minimum_required(VERSION 3.20) +project(ksOS_test LANGUAGES C ASM) + +include("${CMAKE_CURRENT_SOURCE_DIR}/../../Common/ksOS_SDK.cmake") + +file(GLOB_RECURSE INIT_SOURCES CMAKE_CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/Source/*.S + ${CMAKE_CURRENT_SOURCE_DIR}/Source/*.c +) + +add_ksos_executable(Init ${INIT_SOURCES}) + +set_target_properties(Init PROPERTIES + OUTPUT_NAME "Test" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" +) diff --git a/Runtime/System/Test/Source/main.c b/Runtime/System/Test/Source/main.c new file mode 100644 index 0000000..48861c3 --- /dev/null +++ b/Runtime/System/Test/Source/main.c @@ -0,0 +1,9 @@ +#include + + +int main() { + IPCMessage message = SysRecive(); + if (message.data == 0xa0a0a0a0a) { + Sys228(); + } +} diff --git a/Runtime/System/libksOS/CMakeLists.txt b/Runtime/System/libksOS/CMakeLists.txt new file mode 100644 index 0000000..9fdf08c --- /dev/null +++ b/Runtime/System/libksOS/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-3.0-or-later +cmake_minimum_required(VERSION 3.20) +project(libksOS LANGUAGES C ASM) + +file(GLOB_RECURSE LIB_SOURCES CMAKE_CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/*.c +) + +add_library(ksOS STATIC ${LIB_SOURCES}) + +target_include_directories(ksOS PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/Include +) + +target_compile_options(ksOS PRIVATE + -std=c23 -fno-stack-protector -fno-builtin -Wall -Wextra +) diff --git a/Runtime/System/libksOS/Include/ksOS/Syscall.h b/Runtime/System/libksOS/Include/ksOS/Syscall.h new file mode 100644 index 0000000..84cbcbb --- /dev/null +++ b/Runtime/System/libksOS/Include/ksOS/Syscall.h @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKSor + +#pragma once +#include + +enum { + kSyscallSend = 1, + kSyscallReceive, +}; + +typedef struct IPCMessage { + UInt64 senderID; + UInt64 data; +} IPCMessage; + +static inline UInt64 SysSend(UInt64 handleID, UInt64 data) { + register UInt64 x8 __asm__("x8") = kSyscallSend; + register UInt64 x0 __asm__("x0") = handleID; + register UInt64 x1 __asm__("x1") = data; + + __asm__ volatile( + "svc #0\n" + : "+r" (x0) + : "r" (x1), "r" (x8) + : "memory", "cc" + ); + return x0; +} + +static inline IPCMessage SysRecive(void) { + register UInt64 x8 __asm__("x8") = kSyscallReceive; + register UInt64 x0 __asm__("x0"); + register UInt64 x1 __asm__("x1"); + + __asm__ volatile( + "svc #0\n" + : "=r" (x0), "=r" (x1) + : "r" (x8) + : "memory", "cc" + ); + + struct IPCMessage msg = { x0, x1 }; + return msg; +} + +static inline void Sys228(void) { + register UInt64 x8 __asm__("x8") = 228; + __asm__ volatile( + "svc #0\n" + : + : "r" (x8) + : "memory", "cc" + ); +} diff --git a/Runtime/System/libksOS/Include/ksOS/Types.h b/Runtime/System/libksOS/Include/ksOS/Types.h new file mode 100644 index 0000000..28d1bcf --- /dev/null +++ b/Runtime/System/libksOS/Include/ksOS/Types.h @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKSor + +#pragma once + +#if defined(NDEBUG) || defined(__OPTIMIZE__) + #define IS_RELEASE 1 +#else + #define IS_RELEASE 0 +#endif + +typedef unsigned char UInt8; +typedef unsigned short UInt16; +typedef unsigned int UInt32; +typedef unsigned long long UInt64; +typedef unsigned long long UInt; + +typedef void* Pointer; +typedef UInt Address; +typedef UInt32 Address32; +typedef UInt8* BytePointer; +typedef UInt8* MemoryPointer; + +typedef signed char Int8; +typedef signed short Int16; +typedef signed int Int32; +typedef signed long long Int64; +typedef int Int; + +typedef UInt64 Size; +typedef char ASCII; + +typedef _Bool Boolean; diff --git a/Runtime/System/libksOS/Source/Syscall.c b/Runtime/System/libksOS/Source/Syscall.c new file mode 100644 index 0000000..15e21be --- /dev/null +++ b/Runtime/System/libksOS/Source/Syscall.c @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2026 0xKSor diff --git a/Runtime/System/Init/Source/entry.S b/Runtime/System/libksOS/Source/crt0.S similarity index 75% rename from Runtime/System/Init/Source/entry.S rename to Runtime/System/libksOS/Source/crt0.S index 67c5a32..d1d5f08 100644 --- a/Runtime/System/Init/Source/entry.S +++ b/Runtime/System/libksOS/Source/crt0.S @@ -4,14 +4,9 @@ .section .text.entry, "ax" .global _start _start: - // Set up stack pointer (8KB stack) adrp x0, stack_top add sp, x0, :lo12:stack_top - - // Jump to C main bl main - - // If main returns, loop forever b . .section .bss, "aw", @nobits diff --git a/Runtime/justfile b/Runtime/justfile index 9fdcc82..95420b3 100644 --- a/Runtime/justfile +++ b/Runtime/justfile @@ -95,8 +95,22 @@ _default: exit 0 fi + # libksOS MUST be built first โ€” everyone depends on it for dir in "${projects[@]}"; do name=$(basename "${dir}") + if [ "${name}" = "libksOS" ]; then + echo "" + echo " ๐Ÿ“ฆ ${CATEGORY}/${name}" + just --quiet _build_cmake "${dir}" "${CATEGORY}/${name}" + break + fi + done + + for dir in "${projects[@]}"; do + name=$(basename "${dir}") + if [ "${name}" = "libksOS" ]; then + continue + fi echo "" echo " ๐Ÿ“ฆ ${CATEGORY}/${name}" @@ -111,6 +125,7 @@ _default: @build: @echo "๐Ÿ› ๏ธ Building Runtime..." + @just --quiet clangd @mkdir -p {{ RUNTIME_BUILD_DIR }}/System @mkdir -p {{ RUNTIME_BUILD_DIR }}/Apps @just --quiet _discover_and_build System @@ -122,3 +137,13 @@ _default: @rm -rf {{ TEMP_DIR }}/Runtime @rm -rf {{ RUNTIME_BUILD_DIR }} @echo "๐Ÿงน Runtime cleaned" + +@clangd: + #!/usr/bin/env bash + set -e + RUNTIME_DIR="{{ justfile_directory() }}" + INCLUDE_DIR="${RUNTIME_DIR}/System/libksOS/Include" + + printf 'CompileFlags:\n Add:\n - -xc\n - --target=aarch64-none-elf\n - -ffreestanding\n - -I%s\n' "${INCLUDE_DIR}" > "${RUNTIME_DIR}/.clangd" + + echo "โœ… Generated ${RUNTIME_DIR}/.clangd"