Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 39b2af7626 |
@@ -6,3 +6,4 @@ compile_commands.json
|
|||||||
ide-swift-toolchain.txt
|
ide-swift-toolchain.txt
|
||||||
.cache
|
.cache
|
||||||
.zed
|
.zed
|
||||||
|
Runtime/.clangd
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Copyright (c) 2026 0xKSor
|
// Copyright (c) 2026 0xKSor
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "Arch/Exceptions.h"
|
||||||
#include <Types.h>
|
#include <Types.h>
|
||||||
|
|
||||||
static inline void CPUYield() {
|
static inline void CPUYield() {
|
||||||
@@ -111,4 +112,13 @@ static inline void CPUSwitchAddressSpace(Address l0Physical) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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")
|
#define CPUException(number) __asm__ volatile ("svc %0" :: "i" (number) : "memory")
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Arch/Exceptions.h"
|
||||||
|
#include <Types.h>
|
||||||
|
#include <OS/Scheduler.h>
|
||||||
|
|
||||||
|
UInt64 IPCSend(OSTask* sender, UInt64 handleID, UInt64 data);
|
||||||
|
void IPCReceive(ExceptionsContext* receiverFrame);
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Types.h>
|
#include <Types.h>
|
||||||
#include "../Common/bootinfo.h"
|
#include "../Common/bootinfo.h"
|
||||||
|
#include <OS/Scheduler.h>
|
||||||
|
|
||||||
void ModuleLoad(BootModule* module);
|
OSTask* ModuleLoad(BootModule* module);
|
||||||
|
|||||||
@@ -4,12 +4,31 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Types.h>
|
#include <Types.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
kOSHandleTypeNone = 0,
|
||||||
|
kOSHandleTypeTask
|
||||||
|
} OSHandleType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
OSHandleType type;
|
||||||
|
Pointer object;
|
||||||
|
} OSHandle;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kOSSchedulerTaskStackSize = 16 * 1024,
|
||||||
|
kOSSchedulerExceptionNumber = 0xF0F0,
|
||||||
|
kOSMaxHandlesPerProcess = 256,
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum OSTaskState {
|
typedef enum OSTaskState {
|
||||||
OSTaskStateDead,
|
OSTaskStateDead,
|
||||||
OSTaskStateRunning,
|
OSTaskStateRunning,
|
||||||
OSTaskStateReady,
|
OSTaskStateReady,
|
||||||
OSTaskStateBlocked,
|
OSTaskStateBlocked,
|
||||||
OSTaskStateSleeping,
|
OSTaskStateSleeping,
|
||||||
|
|
||||||
|
OSTaskStateBlockedReceive,
|
||||||
|
OSTaskStateBlockedSend,
|
||||||
} OSTaskState;
|
} OSTaskState;
|
||||||
|
|
||||||
typedef struct OSProcess {
|
typedef struct OSProcess {
|
||||||
@@ -20,11 +39,12 @@ typedef struct OSProcess {
|
|||||||
Address heapCurrent;
|
Address heapCurrent;
|
||||||
struct OSProcess* parent;
|
struct OSProcess* parent;
|
||||||
ASCII name[32];
|
ASCII name[32];
|
||||||
|
|
||||||
|
OSHandle handles[kOSMaxHandlesPerProcess];
|
||||||
} OSProcess;
|
} OSProcess;
|
||||||
|
|
||||||
typedef struct OSTask {
|
typedef struct OSTask {
|
||||||
Address stackPointer;
|
Address stackPointer;
|
||||||
struct OSTask* next;
|
|
||||||
UInt32 id;
|
UInt32 id;
|
||||||
UInt32 sleepTicks;
|
UInt32 sleepTicks;
|
||||||
OSTaskState state;
|
OSTaskState state;
|
||||||
@@ -32,12 +52,10 @@ typedef struct OSTask {
|
|||||||
Pointer kernelStackBase;
|
Pointer kernelStackBase;
|
||||||
OSProcess* process;
|
OSProcess* process;
|
||||||
Int32 waitingForProcessId;
|
Int32 waitingForProcessId;
|
||||||
} OSTask;
|
|
||||||
|
|
||||||
enum {
|
struct OSTask* next;
|
||||||
kOSSchedulerTaskStackSize = 16 * 1024,
|
struct OSTask* senderWaiting;
|
||||||
kOSSchedulerExceptionNumber = 0xF0F0
|
} OSTask;
|
||||||
};
|
|
||||||
|
|
||||||
extern UInt32 gOSSchedulerNextProcessID;
|
extern UInt32 gOSSchedulerNextProcessID;
|
||||||
|
|
||||||
@@ -46,3 +64,7 @@ OSTask* SchedulerSpawn(void(*entryPoint)(), OSProcess* owner, Boolean isUser, Ad
|
|||||||
Address SchedulerNext(Address stackPointer);
|
Address SchedulerNext(Address stackPointer);
|
||||||
void SchedulerYield(UInt64 ticks);
|
void SchedulerYield(UInt64 ticks);
|
||||||
UInt64 SchedulerGetNextProcessID();
|
UInt64 SchedulerGetNextProcessID();
|
||||||
|
void SchedulerBlockCurrentTask(UInt32 newState);
|
||||||
|
OSTask* SchedulerGetCurrentTask();
|
||||||
|
Int32 SchedulerProcessAllocateHandle(OSProcess* process, OSHandleType type, Pointer object);
|
||||||
|
Pointer SchedulerProcessGetHandle(OSProcess* process, UInt32 handleId, OSHandleType expectedType);
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Types.h>
|
||||||
|
#include <Arch/Exceptions.h>
|
||||||
|
|
||||||
|
enum Syscalls {
|
||||||
|
kSyscallSend,
|
||||||
|
kSyscallReceive,
|
||||||
|
};
|
||||||
|
|
||||||
|
Address SyscallDispatch(ExceptionsContext* frame);
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <Arch/GIC.h>
|
#include <Arch/GIC.h>
|
||||||
#include <OS/Panic.h>
|
#include <OS/Panic.h>
|
||||||
#include <OS/Scheduler.h>
|
#include <OS/Scheduler.h>
|
||||||
|
#include <OS/Syscall.h>
|
||||||
|
|
||||||
Address ExceptionsHandler(ExceptionsContext* frame, ExceptionsType type) {
|
Address ExceptionsHandler(ExceptionsContext* frame, ExceptionsType type) {
|
||||||
if (type == ExceptionsIRQEl1h || type == ExceptionsIRQEl064) return GICDispatch(frame, 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 class = (esr >> 26) & 0x3F;
|
||||||
UInt32 syndrome = esr & 0x1FFFFFF;
|
UInt32 syndrome = esr & 0x1FFFFFF;
|
||||||
|
|
||||||
if (class == 0x11 || class == 0x15) {
|
if (class == 0x15) {
|
||||||
if (syndrome == kOSSchedulerExceptionNumber) {
|
if (syndrome == kOSSchedulerExceptionNumber) return SchedulerNext((Address)frame);
|
||||||
return SchedulerNext((Address)frame);
|
if (syndrome == 0) return SyscallDispatch(frame);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (class == 0x15 && syndrome == 0) {
|
|
||||||
OSPanic("Hi from userspace!!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OSPanicException(frame);
|
OSPanicException(frame);
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ void KernelMain(Bootinfo* bootinfo) {
|
|||||||
SchedulerInitialize();
|
SchedulerInitialize();
|
||||||
|
|
||||||
for (UInt32 i = 0; i < bootinfo->moduleCount; i++) {
|
for (UInt32 i = 0; i < bootinfo->moduleCount; i++) {
|
||||||
ModuleLoad(&bootinfo->modules[i]); // TODO: make some sort of priority of loading modules
|
ModuleLoad(&bootinfo->modules[i]); // TODO: priority
|
||||||
// like init first then uart then fb ...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OSLog("Kernel initialized.\n");
|
OSLog("Kernel initialized.\n");
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#include <OS/IPC.h>
|
||||||
|
#include <OS/Scheduler.h>
|
||||||
|
#include <Arch/CPU.h>
|
||||||
|
#include <Arch/Exceptions.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <Arch/CPU.h>
|
#include <Arch/CPU.h>
|
||||||
#include "../Common/bootinfo.h"
|
#include "../Common/bootinfo.h"
|
||||||
|
|
||||||
void ModuleLoad(BootModule* module) {
|
OSTask* ModuleLoad(BootModule* module) {
|
||||||
OSProcess* userProc = HeapAllocate(sizeof(OSProcess));
|
OSProcess* userProc = HeapAllocate(sizeof(OSProcess));
|
||||||
MemorySet(userProc, 0, sizeof(OSProcess));
|
MemorySet(userProc, 0, sizeof(OSProcess));
|
||||||
userProc->id = SchedulerGetNextProcessID();
|
userProc->id = SchedulerGetNextProcessID();
|
||||||
@@ -56,8 +56,8 @@ void ModuleLoad(BootModule* module) {
|
|||||||
|
|
||||||
if ((Address)userEntryPoint == 0x0) {
|
if ((Address)userEntryPoint == 0x0) {
|
||||||
OSLog("Skipping module %s: entry point is 0x0.\n", module->name);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ OSTask* SchedulerSpawn(void(*entryPoint)(), OSProcess* owner, Boolean isUser, Ad
|
|||||||
task->waitingForProcessId = -1;
|
task->waitingForProcessId = -1;
|
||||||
|
|
||||||
task->next = gOSSchedulerCurrentTask->next;
|
task->next = gOSSchedulerCurrentTask->next;
|
||||||
|
task->senderWaiting = nullptr;
|
||||||
gOSSchedulerCurrentTask->next = task;
|
gOSSchedulerCurrentTask->next = task;
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
@@ -126,3 +127,30 @@ void SchedulerYield(UInt64 ticks) {
|
|||||||
UInt64 SchedulerGetNextProcessID() {
|
UInt64 SchedulerGetNextProcessID() {
|
||||||
return gOSSchedulerNextProcessID++;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#include <OS/Syscall.h>
|
||||||
|
#include <OS/IPC.h>
|
||||||
|
#include <OS/Scheduler.h>
|
||||||
|
#include <OS/Panic.h>
|
||||||
|
#include <Arch/Exceptions.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -56,3 +56,7 @@ find_program(LLVM_OBJCOPY NAMES llvm-objcopy objcopy
|
|||||||
/opt/homebrew/bin
|
/opt/homebrew/bin
|
||||||
REQUIRED
|
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")
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -4,44 +4,16 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
project(ksOS_init LANGUAGES C ASM)
|
project(ksOS_init LANGUAGES C ASM)
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_SOURCE_DIR}/../../Common/ksOS_SDK.cmake")
|
||||||
|
|
||||||
file(GLOB_RECURSE INIT_SOURCES CMAKE_CONFIGURE_DEPENDS
|
file(GLOB_RECURSE INIT_SOURCES CMAKE_CONFIGURE_DEPENDS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Source/*.S
|
${CMAKE_CURRENT_SOURCE_DIR}/Source/*.S
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Source/*.c
|
${CMAKE_CURRENT_SOURCE_DIR}/Source/*.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(init ${INIT_SOURCES})
|
add_ksos_executable(Init ${INIT_SOURCES})
|
||||||
|
|
||||||
target_include_directories(init PRIVATE
|
set_target_properties(Init PROPERTIES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Source
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../Common
|
|
||||||
)
|
|
||||||
|
|
||||||
target_compile_options(init PRIVATE
|
|
||||||
$<$<COMPILE_LANGUAGE:C>:
|
|
||||||
-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
|
|
||||||
OUTPUT_NAME "Init"
|
OUTPUT_NAME "Init"
|
||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2026 0xKSor
|
// Copyright (c) 2026 0xKSor
|
||||||
|
|
||||||
void main(void) {
|
#include <ksOS/Syscall.h>
|
||||||
__asm__ volatile(
|
|
||||||
"svc #0\n"
|
int main(void) {
|
||||||
"b .\n"
|
SysSend(1, 0xa0a0a0a0a);
|
||||||
);
|
while (1) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}"
|
||||||
|
)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#include <ksOS/Syscall.h>
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
IPCMessage message = SysRecive();
|
||||||
|
if (message.data == 0xa0a0a0a0a) {
|
||||||
|
Sys228();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
)
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKSor
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <ksOS/Types.h>
|
||||||
|
|
||||||
|
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"
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKSor
|
||||||
@@ -4,14 +4,9 @@
|
|||||||
.section .text.entry, "ax"
|
.section .text.entry, "ax"
|
||||||
.global _start
|
.global _start
|
||||||
_start:
|
_start:
|
||||||
// Set up stack pointer (8KB stack)
|
|
||||||
adrp x0, stack_top
|
adrp x0, stack_top
|
||||||
add sp, x0, :lo12:stack_top
|
add sp, x0, :lo12:stack_top
|
||||||
|
|
||||||
// Jump to C main
|
|
||||||
bl main
|
bl main
|
||||||
|
|
||||||
// If main returns, loop forever
|
|
||||||
b .
|
b .
|
||||||
|
|
||||||
.section .bss, "aw", @nobits
|
.section .bss, "aw", @nobits
|
||||||
@@ -95,8 +95,22 @@ _default:
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# libksOS MUST be built first — everyone depends on it
|
||||||
for dir in "${projects[@]}"; do
|
for dir in "${projects[@]}"; do
|
||||||
name=$(basename "${dir}")
|
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 ""
|
||||||
echo " 📦 ${CATEGORY}/${name}"
|
echo " 📦 ${CATEGORY}/${name}"
|
||||||
|
|
||||||
@@ -111,6 +125,7 @@ _default:
|
|||||||
|
|
||||||
@build:
|
@build:
|
||||||
@echo "🛠️ Building Runtime..."
|
@echo "🛠️ Building Runtime..."
|
||||||
|
@just --quiet clangd
|
||||||
@mkdir -p {{ RUNTIME_BUILD_DIR }}/System
|
@mkdir -p {{ RUNTIME_BUILD_DIR }}/System
|
||||||
@mkdir -p {{ RUNTIME_BUILD_DIR }}/Apps
|
@mkdir -p {{ RUNTIME_BUILD_DIR }}/Apps
|
||||||
@just --quiet _discover_and_build System
|
@just --quiet _discover_and_build System
|
||||||
@@ -122,3 +137,13 @@ _default:
|
|||||||
@rm -rf {{ TEMP_DIR }}/Runtime
|
@rm -rf {{ TEMP_DIR }}/Runtime
|
||||||
@rm -rf {{ RUNTIME_BUILD_DIR }}
|
@rm -rf {{ RUNTIME_BUILD_DIR }}
|
||||||
@echo "🧹 Runtime cleaned"
|
@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"
|
||||||
|
|||||||
Reference in New Issue
Block a user