Feat: userspace !!!!
This commit is contained in:
commit
1d80b23b7e
|
@ -5,6 +5,11 @@ class Builder:
|
|||
def __init__(self, args: cli.Args, arch: str = "x86_64"):
|
||||
self.__registry = model.Registry.use(args)
|
||||
self.__kernel_scope = builder.TargetScope(
|
||||
self.__registry,
|
||||
self.__registry.lookup(f"kernel-{arch}", model.Target),
|
||||
)
|
||||
|
||||
self.__user_scope = builder.TargetScope(
|
||||
self.__registry,
|
||||
self.__registry.lookup(f"navy-{arch}", model.Target),
|
||||
)
|
||||
|
@ -14,6 +19,16 @@ class Builder:
|
|||
product = builder.build(self.__kernel_scope, core_component)[0]
|
||||
return Path(product.path).absolute()
|
||||
|
||||
def build_modules(self) -> list[Path]:
|
||||
modules = dict(filter(lambda x: type(x[1]) is model.Component and \
|
||||
x[1].type == model.Kind.EXE and x[0] != "core", self.__registry.manifests.items()))
|
||||
|
||||
products = []
|
||||
for component in modules.values():
|
||||
products.append(Path(builder.build(self.__user_scope, component)[0].path).absolute())
|
||||
|
||||
return products
|
||||
|
||||
@property
|
||||
def arch(self) -> str:
|
||||
return self.__kernel_scope.target.id.split("-")[1]
|
|
@ -1,4 +1,5 @@
|
|||
from cutekit import cli, model
|
||||
from cutekit import cli, model, shell
|
||||
from pathlib import Path
|
||||
|
||||
from . import build
|
||||
from . import image
|
||||
|
@ -13,11 +14,14 @@ def _(args: cli.Args):
|
|||
def _(args: cli.Args):
|
||||
qemu.Qemu(
|
||||
image.Image(
|
||||
build.Builder(args)
|
||||
)
|
||||
build.Builder(args),
|
||||
),
|
||||
no_display=args.consumeOpt("no-display"),
|
||||
soft_dbg=args.consumeOpt("soft-dbg")
|
||||
).run()
|
||||
|
||||
|
||||
@cli.command("B", "navy/build", "Build Navy")
|
||||
def _(args: cli.Args):
|
||||
build.Builder(args).build_core()
|
||||
build.Builder(args).build_core()
|
||||
build.Builder(args).build_modules()
|
||||
|
|
|
@ -25,14 +25,20 @@ class Image:
|
|||
boot_dir = self.path / "boot"
|
||||
boot_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
bin_dir = self.path / "bin"
|
||||
bin_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
return {
|
||||
"efi_boot": efi_boot,
|
||||
"boot_dir": boot_dir,
|
||||
"bin_dir": bin_dir,
|
||||
}
|
||||
|
||||
|
||||
def efi_x86_64(self):
|
||||
kernel_path = self.builder.build_core()
|
||||
modules = self.builder.build_modules()
|
||||
|
||||
paths = self.__efi_common()
|
||||
|
||||
cfg = [
|
||||
|
@ -43,6 +49,14 @@ class Image:
|
|||
"KERNEL_PATH=boot:///boot/kernel.elf",
|
||||
]
|
||||
|
||||
for mod in modules:
|
||||
name = mod.name.split(".")[0]
|
||||
cfg.append(f"MODULE_PATH=boot:///bin/{name}")
|
||||
shell.cp(
|
||||
str(mod),
|
||||
str(paths["bin_dir"] / name)
|
||||
)
|
||||
|
||||
shell.wget(
|
||||
"https://github.com/limine-bootloader/limine/raw/v6.x-branch-binary/BOOTX64.EFI",
|
||||
str(paths["efi_boot"] / "BOOTX64.EFI"),
|
||||
|
|
|
@ -5,8 +5,8 @@ from cutekit import shell
|
|||
from .image import Image
|
||||
|
||||
class Qemu:
|
||||
def __init__(self, img: Image, no_reboot: bool = True, nographics: bool = False,
|
||||
no_shutdown: bool = True, efi: bool = True, memory: str = "4G", debug: bool = False):
|
||||
def __init__(self, img: Image, no_reboot: bool = True, no_display: bool = False,
|
||||
no_shutdown: bool = True, efi: bool = True, memory: str = "4G", debug: bool = False, soft_dbg: bool = False):
|
||||
self.__img = img
|
||||
self.__binary = None
|
||||
self.__efi = efi
|
||||
|
@ -26,12 +26,15 @@ class Qemu:
|
|||
if no_shutdown:
|
||||
self.__args.append("-no-shutdown")
|
||||
|
||||
if nographics:
|
||||
self.__args.append("-nographic")
|
||||
if no_display:
|
||||
self.__args += ["-display", "none"]
|
||||
|
||||
if self.iskvmAvailable():
|
||||
self.__args += ["-enable-kvm", "-cpu", "host"]
|
||||
|
||||
if soft_dbg:
|
||||
self.__args += ["-d", "int"]
|
||||
|
||||
try:
|
||||
getattr(self, f"arch_{img.builder.arch}")()
|
||||
except AttributeError:
|
||||
|
|
99
meta/targets/kernel-x86_64.json
Normal file
99
meta/targets/kernel-x86_64.json
Normal file
|
@ -0,0 +1,99 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.target.v1",
|
||||
"id": "kernel-x86_64",
|
||||
"type": "target",
|
||||
"props": {
|
||||
"toolchain": "clang",
|
||||
"arch": "x86_64",
|
||||
"bits": "64",
|
||||
"sys": "kernel",
|
||||
"loader": "limine",
|
||||
"abi": "sysv",
|
||||
"encoding": "utf8",
|
||||
"freestanding": true,
|
||||
"host": false
|
||||
},
|
||||
"tools": {
|
||||
"cc": {
|
||||
"cmd": [
|
||||
"@latest",
|
||||
"clang"
|
||||
],
|
||||
"args": [
|
||||
"-target",
|
||||
"x86_64-none-elf",
|
||||
"-ffreestanding",
|
||||
"-fno-stack-protector",
|
||||
"-mno-80387",
|
||||
"-mno-mmx",
|
||||
"-mno-3dnow",
|
||||
"-mno-sse",
|
||||
"-mno-sse2",
|
||||
"-mno-red-zone",
|
||||
"-mcmodel=kernel",
|
||||
"-Dauto=__auto_type",
|
||||
"-g"
|
||||
]
|
||||
},
|
||||
"cxx": {
|
||||
"cmd": [
|
||||
"@latest",
|
||||
"clang++"
|
||||
],
|
||||
"args": [
|
||||
"-target",
|
||||
"x86_64-none-elf",
|
||||
"-ffreestanding",
|
||||
"-fno-stack-protector",
|
||||
"-mno-80387",
|
||||
"-mno-mmx",
|
||||
"-mno-3dnow",
|
||||
"-mno-sse",
|
||||
"-mno-sse2",
|
||||
"-mno-red-zone",
|
||||
"-mcmodel=kernel"
|
||||
]
|
||||
},
|
||||
"ld": {
|
||||
"cmd": [
|
||||
"@latest",
|
||||
"ld.lld"
|
||||
],
|
||||
"args": [
|
||||
"-m",
|
||||
"elf_x86_64",
|
||||
"-T",
|
||||
[
|
||||
"@abspath",
|
||||
"kernel-x86_64.ld"
|
||||
],
|
||||
"-z",
|
||||
"max-page-size=0x1000"
|
||||
],
|
||||
"files": [
|
||||
"meta/targets/kernel-x86_64.ld"
|
||||
]
|
||||
},
|
||||
"ar": {
|
||||
"cmd": [
|
||||
"@latest",
|
||||
"llvm-ar"
|
||||
],
|
||||
"args": [
|
||||
"rcs"
|
||||
]
|
||||
},
|
||||
"as": {
|
||||
"cmd": [
|
||||
"@latest",
|
||||
"clang"
|
||||
],
|
||||
"args": [
|
||||
"-target",
|
||||
"x86_64-none-elf",
|
||||
"-c",
|
||||
"-g"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
67
meta/targets/kernel-x86_64.ld
Normal file
67
meta/targets/kernel-x86_64.ld
Normal file
|
@ -0,0 +1,67 @@
|
|||
/* Tell the linker that we want an x86_64 ELF64 output file */
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
|
||||
/* We want the symbol _start to be our entry point */
|
||||
ENTRY(_start)
|
||||
|
||||
/* Define the program headers we want so the bootloader gives us the right */
|
||||
/* MMU permissions */
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
|
||||
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
|
||||
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
|
||||
/* and because that is what the Limine spec mandates. */
|
||||
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||
/* that is the beginning of the region. */
|
||||
. = 0xffffffff80000000;
|
||||
|
||||
text_start_addr = .;
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
|
||||
text_end_addr = .;
|
||||
|
||||
/* Move to the next memory page for .rodata */
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
|
||||
rodata_start_addr = .;
|
||||
|
||||
PROVIDE(symbol_table = 1);
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
rodata_end_addr = .;
|
||||
|
||||
/* Move to the next memory page for .data */
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
|
||||
data_start_addr = .;
|
||||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
|
||||
.bss : {
|
||||
*(COMMON)
|
||||
*(.bss .bss.*)
|
||||
} :data
|
||||
|
||||
data_end_addr = .;
|
||||
|
||||
/* Discard .note.* and .eh_frame since they may cause issues on some hosts. */
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
*(.note .note.*)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.target.v1",
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"id": "navy-x86_64",
|
||||
"type": "target",
|
||||
"props": {
|
||||
|
@ -7,10 +7,9 @@
|
|||
"arch": "x86_64",
|
||||
"bits": "64",
|
||||
"sys": "navy",
|
||||
"loader": "limine",
|
||||
"abi": "sysv",
|
||||
"encoding": "utf8",
|
||||
"freestanding": true,
|
||||
"freestanding": false,
|
||||
"host": false
|
||||
},
|
||||
"tools": {
|
||||
|
@ -23,15 +22,11 @@
|
|||
"-target",
|
||||
"x86_64-none-elf",
|
||||
"-ffreestanding",
|
||||
"-fno-stack-protector",
|
||||
"-mno-80387",
|
||||
"-mno-mmx",
|
||||
"-mno-3dnow",
|
||||
"-mno-sse",
|
||||
"-mno-sse2",
|
||||
"-mno-red-zone",
|
||||
"-mcmodel=kernel",
|
||||
"-Dauto=__auto_type"
|
||||
"-mno-sse2"
|
||||
]
|
||||
},
|
||||
"cxx": {
|
||||
|
@ -43,14 +38,11 @@
|
|||
"-target",
|
||||
"x86_64-none-elf",
|
||||
"-ffreestanding",
|
||||
"-fno-stack-protector",
|
||||
"-mno-80387",
|
||||
"-mno-mmx",
|
||||
"-mno-3dnow",
|
||||
"-mno-sse",
|
||||
"-mno-sse2",
|
||||
"-mno-red-zone",
|
||||
"-mcmodel=kernel"
|
||||
"-mno-sse2"
|
||||
]
|
||||
},
|
||||
"ld": {
|
||||
|
@ -64,13 +56,10 @@
|
|||
"-T",
|
||||
[
|
||||
"@abspath",
|
||||
"kernel-x86_64.ld"
|
||||
"navy-x86_64.ld"
|
||||
],
|
||||
"-z",
|
||||
"max-page-size=0x1000"
|
||||
],
|
||||
"files": [
|
||||
"meta/targets/kernel-x86_64.ld"
|
||||
]
|
||||
},
|
||||
"ar": {
|
||||
|
@ -83,15 +72,11 @@
|
|||
]
|
||||
},
|
||||
"as": {
|
||||
"cmd": [
|
||||
"@latest",
|
||||
"clang"
|
||||
],
|
||||
"cmd": "clang",
|
||||
"args": [
|
||||
"-target",
|
||||
"x86_64-none-elf",
|
||||
"-c",
|
||||
"-g"
|
||||
"-c"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,67 +1,27 @@
|
|||
/* Tell the linker that we want an x86_64 ELF64 output file */
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
|
||||
/* We want the symbol _start to be our entry point */
|
||||
ENTRY(_start)
|
||||
|
||||
/* Define the program headers we want so the bootloader gives us the right */
|
||||
/* MMU permissions */
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
|
||||
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
|
||||
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
|
||||
/* and because that is what the Limine spec mandates. */
|
||||
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||
/* that is the beginning of the region. */
|
||||
. = 0xffffffff80000000;
|
||||
. = 4M;
|
||||
|
||||
text_start_addr = .;
|
||||
.text : ALIGN(4K)
|
||||
{
|
||||
*(.text)
|
||||
}
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
.rodata : ALIGN(4K)
|
||||
{
|
||||
*(.rodata)
|
||||
}
|
||||
|
||||
text_end_addr = .;
|
||||
.data : ALIGN(4K)
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
|
||||
/* Move to the next memory page for .rodata */
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
|
||||
rodata_start_addr = .;
|
||||
|
||||
PROVIDE(symbol_table = 1);
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
rodata_end_addr = .;
|
||||
|
||||
/* Move to the next memory page for .data */
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
|
||||
data_start_addr = .;
|
||||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
|
||||
.bss : {
|
||||
.bss : ALIGN(4K)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss .bss.*)
|
||||
} :data
|
||||
|
||||
data_end_addr = .;
|
||||
|
||||
/* Discard .note.* and .eh_frame since they may cause issues on some hosts. */
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
*(.note .note.*)
|
||||
*(.bss)
|
||||
}
|
||||
}
|
|
@ -1,8 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <io/stream.h>
|
||||
#include <navy/api.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __ck_arch_x86_64__
|
||||
# include <x86_64/acpi.h>
|
||||
# include <x86_64/ctx.h>
|
||||
# include <x86_64/regs.h>
|
||||
#endif
|
||||
|
||||
Res hal_setup(void);
|
||||
|
||||
/* --- Structs ------------------------------------------------------------ */
|
||||
|
@ -45,11 +52,24 @@ Res hal_space_map(HalPage *space, uintptr_t virt, uintptr_t phys, size_t len, ui
|
|||
|
||||
void hal_space_apply(HalPage *space);
|
||||
|
||||
Res hal_space_create(HalPage **self);
|
||||
|
||||
/* --- Arch Specific ------------------------------------------------------- */
|
||||
|
||||
#ifdef __ck_arch_x86_64__
|
||||
# include <x86_64/acpi.h>
|
||||
|
||||
Rsdp *hal_acpi_rsdp(void);
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct _HalContext HalContext;
|
||||
|
||||
Res hal_context_create(void);
|
||||
|
||||
Res hal_context_start(HalContext *self, uintptr_t ip, uintptr_t sp, SysArgs args);
|
||||
|
||||
void hal_context_destroy(HalContext *self);
|
||||
|
||||
void hal_context_save(HalContext *self, HalRegs *regs);
|
||||
|
||||
void hal_context_restore(HalContext *self, HalRegs *regs);
|
||||
|
||||
void hal_regs_dump(HalRegs const *regs);
|
68
src/kernel/archs/x86_64/ctx.c
Normal file
68
src/kernel/archs/x86_64/ctx.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include <dbg/log.h>
|
||||
#include <hal.h>
|
||||
#include <kmalloc/kmalloc.h>
|
||||
#include <navy/api.h>
|
||||
|
||||
#include "x86_64/ctx.h"
|
||||
|
||||
#include "../../core/pmm.h"
|
||||
#include "cpu.h"
|
||||
#include "gdt.h"
|
||||
#include "simd.h"
|
||||
#include "syscall.h"
|
||||
|
||||
Res hal_context_create(void)
|
||||
{
|
||||
Alloc alloc = kmalloc_acquire();
|
||||
|
||||
HalContext *self = (HalContext *)try$(alloc.calloc(1, sizeof(HalContext) + simd_context_size()));
|
||||
simd_context_init(self);
|
||||
return uok$((uintptr_t)self);
|
||||
}
|
||||
|
||||
void hal_context_destroy(HalContext *self)
|
||||
{
|
||||
Alloc alloc = kmalloc_acquire();
|
||||
alloc.free(self);
|
||||
}
|
||||
|
||||
Res hal_context_start(HalContext *self, uintptr_t ip, uintptr_t sp, SysArgs args)
|
||||
{
|
||||
self->regs.rip = ip;
|
||||
self->regs.rflags = RFLAGS_INTERRUPT_ENABLE | RFLAGS_RESERVED1;
|
||||
|
||||
self->regs.rdi = args.arg1;
|
||||
self->regs.rsi = args.arg2;
|
||||
self->regs.rdx = args.arg3;
|
||||
self->regs.rcx = args.arg4;
|
||||
self->regs.r8 = args.arg5;
|
||||
|
||||
self->regs.cs = (GDT_USER_CODE * 8) | 3;
|
||||
self->regs.ss = (GDT_USER_DATA * 8) | 3;
|
||||
self->regs.rsp = sp + STACK_SIZE;
|
||||
self->regs.rbp = sp;
|
||||
|
||||
PmmObj kStackObj = pmm_alloc(align_up$(STACK_SIZE, PMM_PAGE_SIZE) / PMM_PAGE_SIZE);
|
||||
if (kStackObj.base == 0)
|
||||
{
|
||||
return err$(RES_NOMEM);
|
||||
}
|
||||
|
||||
self->syscall_kernel_stack = hal_mmap_l2h(kStackObj.base) + KERNEL_STACK_SIZE;
|
||||
memset((void *)self->syscall_kernel_stack, 0, KERNEL_STACK_SIZE);
|
||||
|
||||
return ok$();
|
||||
}
|
||||
|
||||
void hal_context_save(HalContext *self, HalRegs *regs)
|
||||
{
|
||||
simd_context_save(self->simd);
|
||||
self->regs = *regs;
|
||||
}
|
||||
|
||||
void hal_context_restore(HalContext *self, HalRegs *regs)
|
||||
{
|
||||
*regs = self->regs;
|
||||
simd_context_load(self->simd);
|
||||
syscall_set_gs((uintptr_t)self);
|
||||
}
|
18
src/kernel/archs/x86_64/ctx.h
Normal file
18
src/kernel/archs/x86_64/ctx.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "regs.h"
|
||||
|
||||
#define STACK_SIZE (kib$(4))
|
||||
#define KERNEL_STACK_SIZE (0x1000)
|
||||
#define USER_STACK_BASE (0xff0000000)
|
||||
|
||||
struct _HalContext
|
||||
{
|
||||
uintptr_t syscall_kernel_stack;
|
||||
uintptr_t syscall_user_stack;
|
||||
|
||||
struct _HalRegs regs;
|
||||
_Alignas(64) uint8_t simd[];
|
||||
};
|
|
@ -1,11 +1,14 @@
|
|||
#include <dbg/log.h>
|
||||
#include <hal.h>
|
||||
#include <kmalloc/kmalloc.h>
|
||||
#include <string.h>
|
||||
#include <sync/spinlock.h>
|
||||
|
||||
#include "ctx.h"
|
||||
#include "gdt.h"
|
||||
|
||||
static Gdt gdt = {0};
|
||||
static Tss tss = {0};
|
||||
|
||||
static Spinlock lock = SPINLOCK_INIT;
|
||||
|
||||
|
@ -78,4 +81,18 @@ void gdt_init(void)
|
|||
|
||||
tss_flush();
|
||||
log$("TSS loaded");
|
||||
}
|
||||
|
||||
Res gdt_init_tss(void)
|
||||
{
|
||||
Alloc heap = kmalloc_acquire();
|
||||
tss.ist[1] = (uintptr_t)(try$(heap.malloc(KERNEL_STACK_SIZE)) + KERNEL_STACK_SIZE);
|
||||
tss.ist[0] = (uintptr_t)(try$(heap.malloc(KERNEL_STACK_SIZE)) + KERNEL_STACK_SIZE);
|
||||
tss.rsp[0] = (uintptr_t)(try$(heap.malloc(KERNEL_STACK_SIZE)) + KERNEL_STACK_SIZE);
|
||||
|
||||
log$("TSS initialized");
|
||||
gdt_load_tss(&tss);
|
||||
tss_flush();
|
||||
|
||||
return ok$();
|
||||
}
|
|
@ -85,6 +85,7 @@ typedef struct [[gnu::packed]]
|
|||
|
||||
void gdt_init(void);
|
||||
void gdt_load_tss(Tss *self);
|
||||
Res gdt_init_tss(void);
|
||||
uintptr_t gdt_descriptor(void);
|
||||
|
||||
extern void gdt_flush(uintptr_t);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include <hal.h>
|
||||
#include <sync/spinlock.h>
|
||||
|
||||
#include "../core/pre-sched.h"
|
||||
#include "apic.h"
|
||||
#include "asm.h"
|
||||
#include "regs.h"
|
||||
|
||||
|
@ -68,6 +70,7 @@ static void dump_backtrace(uintptr_t rbp)
|
|||
static void kpanic(HalRegs const regs[static 1])
|
||||
{
|
||||
spinlock_acquire(&lock);
|
||||
|
||||
uint64_t cr0, cr2, cr3, cr4;
|
||||
|
||||
asm_read_cr(0, cr0);
|
||||
|
@ -107,6 +110,11 @@ uintptr_t interrupt_handler(uintptr_t rsp)
|
|||
hal_pause();
|
||||
}
|
||||
}
|
||||
else if (regs->intno == IRQ0)
|
||||
{
|
||||
switch_to_scheduler(regs);
|
||||
}
|
||||
|
||||
lapic_eoi();
|
||||
return rsp;
|
||||
}
|
|
@ -110,4 +110,31 @@ __interrupts_vector:
|
|||
|
||||
idt_flush:
|
||||
lidt (%rdi)
|
||||
ret
|
||||
ret
|
||||
|
||||
.extern syscall_handler
|
||||
.globl syscall_handle
|
||||
|
||||
syscall_handle:
|
||||
swapgs
|
||||
mov %rsp, %gs:0x8
|
||||
mov %gs:0x0, %rsp
|
||||
|
||||
pushq $0x1b
|
||||
pushq %gs:0x8
|
||||
push %r11
|
||||
pushq $0x23
|
||||
push %rcx
|
||||
|
||||
cld
|
||||
__pusha
|
||||
|
||||
mov %rsp, %rdi
|
||||
movl $0, %ebp
|
||||
call syscall_handler
|
||||
|
||||
__popa
|
||||
|
||||
mov %gs:0x8, %rsp
|
||||
swapgs
|
||||
sysretq
|
|
@ -5,12 +5,17 @@
|
|||
"enableIf": {
|
||||
"arch": [
|
||||
"x86_64"
|
||||
],
|
||||
"sys": [
|
||||
"kernel"
|
||||
]
|
||||
},
|
||||
"provides": [
|
||||
"arch"
|
||||
],
|
||||
"requires": [
|
||||
"io",
|
||||
"stdc-shim",
|
||||
"dbg"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -2,13 +2,14 @@
|
|||
#include <io/stream.h>
|
||||
#include <res.h>
|
||||
|
||||
#include "apic.h"
|
||||
#include "e9.h"
|
||||
#include "gdt.h"
|
||||
#include "hpet.h"
|
||||
#include "idt.h"
|
||||
#include "paging.h"
|
||||
#include "hpet.h"
|
||||
#include "apic.h"
|
||||
#include "simd.h"
|
||||
#include "syscall.h"
|
||||
|
||||
Stream hal_dbg_stream(void)
|
||||
{
|
||||
|
@ -22,6 +23,8 @@ Res hal_setup(void)
|
|||
gdt_init();
|
||||
idt_init();
|
||||
try$(paging_init());
|
||||
try$(gdt_init_tss());
|
||||
syscall_init();
|
||||
acpi_init();
|
||||
try$(hpet_init());
|
||||
try$(apic_init());
|
||||
|
|
|
@ -68,8 +68,8 @@ static Res paging_get_pml_alloc(uintptr_t *pml, size_t index, bool alloc)
|
|||
else if (alloc)
|
||||
{
|
||||
PmmObj obj = pmm_alloc(1);
|
||||
memset((void *)obj.base, 0, obj.len);
|
||||
uintptr_t ptr_hddm = hal_mmap_l2h(obj.base);
|
||||
memset((void *)ptr_hddm, 0, obj.len);
|
||||
|
||||
pml[index] = obj.base | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER;
|
||||
|
||||
|
@ -158,11 +158,11 @@ Res paging_init(void)
|
|||
return err$(RES_NOMEM);
|
||||
}
|
||||
|
||||
memset((void *)obj.base, 0, obj.len);
|
||||
|
||||
log$("PML4: 0x%p", obj.base);
|
||||
pml4 = (uintptr_t *)hal_mmap_l2h((uintptr_t)obj.base);
|
||||
|
||||
memset((void *)pml4, 0, obj.len);
|
||||
|
||||
if (cpuid_has_1gb_pages())
|
||||
{
|
||||
log$("1GB pages are supported");
|
||||
|
@ -220,14 +220,14 @@ Res hal_space_create(HalPage **self)
|
|||
{
|
||||
|
||||
PmmObj obj = pmm_alloc(1);
|
||||
memset((void *)obj.base, 0, obj.len);
|
||||
uintptr_t *space = (uintptr_t *)hal_mmap_l2h(obj.base);
|
||||
memset((void *)space, 0, obj.len);
|
||||
|
||||
if (obj.base == 0)
|
||||
{
|
||||
return err$(RES_NOMEM);
|
||||
}
|
||||
|
||||
uintptr_t *space = (uintptr_t *)hal_mmap_l2h(obj.base);
|
||||
memset((void *)space, 0, PMM_PAGE_SIZE);
|
||||
|
||||
for (size_t i = 255; i < 512; i++)
|
||||
|
|
25
src/kernel/archs/x86_64/regs.c
Normal file
25
src/kernel/archs/x86_64/regs.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include <dbg/log.h>
|
||||
#include <hal.h>
|
||||
|
||||
#include "asm.h"
|
||||
|
||||
void hal_regs_dump(HalRegs const *regs)
|
||||
{
|
||||
uint64_t cr0, cr2, cr3, cr4;
|
||||
|
||||
asm_read_cr(0, cr0);
|
||||
asm_read_cr(2, cr2);
|
||||
asm_read_cr(3, cr3);
|
||||
asm_read_cr(4, cr4);
|
||||
|
||||
log$("=== Registers Dump ============================================");
|
||||
log$("interrupt: %x, err: %x", regs->intno, regs->err);
|
||||
log$("RAX %p RBX %p RCX %p RDX %p", regs->rax, regs->rbx, regs->rcx, regs->rdx);
|
||||
log$("RSI %p RDI %p RBP %p RSP %p", regs->rsi, regs->rdi, regs->rbp, regs->rsp);
|
||||
log$("R8 %p R9 %p R10 %p R11 %p", regs->r8, regs->r9, regs->r10, regs->r11);
|
||||
log$("R12 %p R13 %p R14 %p R15 %p", regs->r12, regs->r13, regs->r14, regs->r15);
|
||||
log$("CR0 %p CR2 %p CR3 %p CR4 %p", cr0, cr2, cr3, cr4);
|
||||
log$("CS %p SS %p FLG %p", regs->cs, regs->ss, regs->rflags);
|
||||
log$("RIP \033[7m%p\033[0m", regs->rip);
|
||||
log$("==============================================================");
|
||||
}
|
25
src/kernel/archs/x86_64/syscall.c
Normal file
25
src/kernel/archs/x86_64/syscall.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include <dbg/log.h>
|
||||
#include <hal.h>
|
||||
|
||||
#include "asm.h"
|
||||
#include "gdt.h"
|
||||
#include "syscall.h"
|
||||
|
||||
void syscall_init(void)
|
||||
{
|
||||
asm_write_msr(MSR_EFER, asm_read_msr(MSR_EFER) | 1);
|
||||
asm_write_msr(MSR_STAR, ((uint64_t)(GDT_KERNEL_CODE * 8) << STAR_KCODE_OFFSET) | ((uint64_t)(((GDT_USER_DATA - 1) * 8) | 3) << STAR_UCODE_OFFSET));
|
||||
asm_write_msr(MSR_LSTAR, (uint64_t)syscall_handle);
|
||||
asm_write_msr(MSR_SYSCALL_FLAG_MASK, 0xfffffffe);
|
||||
}
|
||||
|
||||
void syscall_set_gs(uintptr_t addr)
|
||||
{
|
||||
asm_write_msr(MSR_GS_BASE, addr);
|
||||
asm_write_msr(MSR_KERN_GS_BASE, addr);
|
||||
}
|
||||
|
||||
int64_t syscall_handler(HalRegs *regs)
|
||||
{
|
||||
return _syscall_handler(regs->rax, (SysArgs){regs->rdi, regs->rsi, regs->rdx, regs->r8, regs->r9, regs->r10}).type;
|
||||
}
|
9
src/kernel/archs/x86_64/syscall.h
Normal file
9
src/kernel/archs/x86_64/syscall.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void syscall_handle(void);
|
||||
|
||||
void syscall_set_gs(uintptr_t addr);
|
||||
|
||||
void syscall_init(void);
|
|
@ -2,11 +2,33 @@
|
|||
#include <hal.h>
|
||||
|
||||
#include "pmm.h"
|
||||
#include "pre-sched.h"
|
||||
|
||||
_Noreturn int _start()
|
||||
{
|
||||
pmm_init();
|
||||
hal_setup();
|
||||
Res pmm = pmm_init();
|
||||
if (pmm.type != RES_OK)
|
||||
{
|
||||
error$("%s at %s (%s:%d) - Couldn't initialize PMM",
|
||||
res_to_str(pmm), pmm.loc.func, pmm.loc.file, pmm.loc.line);
|
||||
hal_panic();
|
||||
}
|
||||
|
||||
Res hal = hal_setup();
|
||||
if (hal.type != RES_OK)
|
||||
{
|
||||
error$("%s at %s (%s:%d) - Couldn't initialize HAL",
|
||||
res_to_str(hal), hal.loc.func, hal.loc.file, hal.loc.line);
|
||||
hal_panic();
|
||||
}
|
||||
|
||||
Res sched = load_scheduler();
|
||||
if (sched.type != RES_OK)
|
||||
{
|
||||
error$("%s at %s (%s:%d) - Couldn't initialize scheduler",
|
||||
res_to_str(sched), sched.loc.func, sched.loc.file, sched.loc.line);
|
||||
hal_panic();
|
||||
}
|
||||
|
||||
for (;;)
|
||||
;
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
"arch",
|
||||
"dbg",
|
||||
"stdc-shim",
|
||||
"loader"
|
||||
"loader",
|
||||
"kmalloc"
|
||||
],
|
||||
"tools": {
|
||||
"cc": {
|
||||
|
|
99
src/kernel/core/pre-sched.c
Normal file
99
src/kernel/core/pre-sched.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
#include <dbg/log.h>
|
||||
#include <loader.h>
|
||||
#include <specs/elf.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hal.h"
|
||||
#include "pmm.h"
|
||||
#include "pre-sched.h"
|
||||
|
||||
#ifdef __ck_bits_64__
|
||||
# define Elf_Ehdr Elf64_Ehdr
|
||||
# define ELFCLASS ELFCLASS64
|
||||
# define Elf_Phdr Elf64_Phdr
|
||||
#else
|
||||
# define Elf_Ehdr Elf32_Ehdr
|
||||
# define ELFCLASS ELFCLASS32
|
||||
# define Elf_Phdr Elf32_Phdr
|
||||
#endif
|
||||
|
||||
static HalPage *sched_vspace;
|
||||
static HalContext *sched_ctx;
|
||||
|
||||
static HalContext *kernel_ctx;
|
||||
static bool need_switch = false;
|
||||
|
||||
Res load_scheduler(void)
|
||||
{
|
||||
Module sched = loader_get_module("/bin/sched");
|
||||
if (sched.len == 0)
|
||||
{
|
||||
return err$(RES_NOENT);
|
||||
}
|
||||
|
||||
try$(hal_space_create(&sched_vspace));
|
||||
|
||||
Elf_Ehdr *hdr = (Elf_Ehdr *)sched.base;
|
||||
if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0)
|
||||
{
|
||||
return err$(RES_INVAL);
|
||||
}
|
||||
|
||||
if (hdr->e_ident[EI_CLASS] != ELFCLASS)
|
||||
{
|
||||
return err$(RES_INVAL);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < hdr->e_phnum; i++)
|
||||
{
|
||||
Elf_Phdr *phdr = (Elf_Phdr *)(sched.base + hdr->e_phoff + i * hdr->e_phentsize);
|
||||
|
||||
if (phdr->p_type == PT_LOAD)
|
||||
{
|
||||
log$("Mapping scheduler segment 0x%x -> 0x%x (len: %x)",
|
||||
phdr->p_vaddr, phdr->p_vaddr + phdr->p_memsz, phdr->p_memsz);
|
||||
|
||||
PmmObj paddr = pmm_alloc(align_up$(phdr->p_memsz, PMM_PAGE_SIZE));
|
||||
if (paddr.len == 0)
|
||||
{
|
||||
return err$(RES_NOMEM);
|
||||
}
|
||||
|
||||
log$("Scheduler segment mapped to 0x%x", paddr.base);
|
||||
try$(hal_space_map(sched_vspace, phdr->p_vaddr, paddr.base, align_up$(phdr->p_memsz, PMM_PAGE_SIZE), HAL_MEM_READ | HAL_MEM_WRITE | HAL_MEM_USER | HAL_MEM_EXEC));
|
||||
|
||||
memcpy((void *)hal_mmap_l2h(paddr.base), (void *)sched.base + phdr->p_offset, phdr->p_filesz);
|
||||
memset((void *)hal_mmap_l2h(paddr.base + phdr->p_filesz), 0, phdr->p_memsz - phdr->p_filesz);
|
||||
}
|
||||
}
|
||||
|
||||
sched_ctx = (HalContext *)try$(hal_context_create());
|
||||
kernel_ctx = (HalContext *)try$(hal_context_create());
|
||||
|
||||
PmmObj sched_stack_obj = pmm_alloc(align_up$(STACK_SIZE, PMM_PAGE_SIZE) / PMM_PAGE_SIZE);
|
||||
if (sched_stack_obj.len == 0)
|
||||
{
|
||||
return err$(RES_NOMEM);
|
||||
}
|
||||
|
||||
hal_space_map(sched_vspace, USER_STACK_BASE, sched_stack_obj.base, STACK_SIZE, HAL_MEM_READ | HAL_MEM_WRITE | HAL_MEM_USER);
|
||||
hal_context_start(sched_ctx, hdr->e_entry, USER_STACK_BASE, (SysArgs){0, 0, 0, 0, 0, 0});
|
||||
need_switch = true;
|
||||
|
||||
return ok$();
|
||||
}
|
||||
|
||||
void switch_to_scheduler(HalRegs *regs)
|
||||
{
|
||||
if (need_switch)
|
||||
{
|
||||
hal_context_save(kernel_ctx, regs);
|
||||
|
||||
hal_space_apply((HalPage *)sched_vspace);
|
||||
hal_context_restore(sched_ctx, regs);
|
||||
|
||||
need_switch = false;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
8
src/kernel/core/pre-sched.h
Normal file
8
src/kernel/core/pre-sched.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <hal.h>
|
||||
#include <res.h>
|
||||
|
||||
Res load_scheduler(void);
|
||||
|
||||
void switch_to_scheduler(HalRegs *regs);
|
26
src/kernel/core/syscall_handler.c
Normal file
26
src/kernel/core/syscall_handler.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include <dbg/log.h>
|
||||
#include <navy/api.h>
|
||||
#include <res.h>
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
typedef Res Handler(SysArg arg1, SysArg arg2, SysArg arg3, SysArg arg4, SysArg arg5, SysArg arg6);
|
||||
|
||||
static Res _sys_log(char const *s, size_t len)
|
||||
{
|
||||
return hal_dbg_stream().write(len, s);
|
||||
}
|
||||
|
||||
static Handler *handlers[__SYSCALL_LENGTH] = {
|
||||
[SYS_LOG] = (Handler *)_sys_log,
|
||||
};
|
||||
|
||||
Res _syscall_handler(Syscalls no, SysArgs args)
|
||||
{
|
||||
if (no >= __SYSCALL_LENGTH)
|
||||
{
|
||||
return err$(RES_BADSYSCALL);
|
||||
}
|
||||
|
||||
return handlers[no](args.arg1, args.arg2, args.arg3, args.arg4, args.arg5, args.arg6);
|
||||
}
|
|
@ -1,28 +1,11 @@
|
|||
#include <dbg/log.h>
|
||||
#include <fmt/fmt.h>
|
||||
#include <hal.h>
|
||||
#include <stdarg.h>
|
||||
#include <sync/spinlock.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
static Spinlock _lock = SPINLOCK_INIT;
|
||||
|
||||
static char const *level_names[LOG_EVENT_LENGTH] = {
|
||||
[LOG_NONE] = "",
|
||||
[LOG_INFO] = "INFO",
|
||||
[LOG_WARN] = "WARN",
|
||||
[LOG_ERROR] = "ERROR",
|
||||
[LOG_CRIT] = "CRITIC",
|
||||
};
|
||||
|
||||
static char const *level_colors[LOG_EVENT_LENGTH] = {
|
||||
[LOG_NONE] = "",
|
||||
[LOG_INFO] = "\e[1;34m",
|
||||
[LOG_WARN] = "\e[1;33m",
|
||||
[LOG_ERROR] = "\e[1;31m",
|
||||
[LOG_CRIT] = "\e[1;35m",
|
||||
};
|
||||
|
||||
void _log(LogEvent event, Loc loc, char const *format, ...)
|
||||
{
|
||||
spinlock_acquire(&_lock);
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"type": "lib",
|
||||
"id": "dbg",
|
||||
"id": "dbg-kernel",
|
||||
"enableIf": {
|
||||
"freestanding": [
|
||||
true
|
||||
"sys": [
|
||||
"kernel"
|
||||
]
|
||||
},
|
||||
"provides": [
|
||||
"dbg"
|
||||
],
|
||||
"requires": [
|
||||
"sync",
|
||||
"fmt"
|
||||
|
|
13
src/kernel/klibs/kmalloc/manifest.json
Normal file
13
src/kernel/klibs/kmalloc/manifest.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"type": "lib",
|
||||
"id": "kmalloc",
|
||||
"requires": [
|
||||
"libheap"
|
||||
],
|
||||
"enableIf": {
|
||||
"sys": [
|
||||
"kernel"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
#include <dbg/log.h>
|
||||
#include <hal.h>
|
||||
#include <loader.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "limine.h"
|
||||
#include "loader.h"
|
||||
|
||||
static Mmap mmap = {0};
|
||||
|
||||
|
@ -33,10 +34,10 @@ static volatile struct limine_rsdp_request rsdp_req = {
|
|||
.response = NULL,
|
||||
};
|
||||
|
||||
static volatile struct limine_smp_request smp_req = {
|
||||
.id = LIMINE_SMP_REQUEST,
|
||||
volatile struct limine_module_request module_request = {
|
||||
.id = LIMINE_MODULE_REQUEST,
|
||||
.response = 0,
|
||||
.revision = 0,
|
||||
.response = NULL,
|
||||
};
|
||||
|
||||
/* --- Loader functions ---------------------------------------------------- */
|
||||
|
@ -172,27 +173,27 @@ Rsdp *hal_acpi_rsdp(void)
|
|||
return (Rsdp *)rsdp_req.response->address;
|
||||
}
|
||||
|
||||
size_t cpu_count(void)
|
||||
Module loader_get_module(char const *path)
|
||||
{
|
||||
if (smp_req.response == NULL)
|
||||
if (module_request.response == NULL)
|
||||
{
|
||||
error$("Couldn't retrieve SMP info from Limine");
|
||||
hal_panic();
|
||||
return (Module){0};
|
||||
}
|
||||
|
||||
return smp_req.response->cpu_count;
|
||||
}
|
||||
|
||||
void hal_smp_boot(void (*entry)(void))
|
||||
{
|
||||
if (smp_req.response == NULL)
|
||||
for (size_t i = 0; i < module_request.response->module_count; i++)
|
||||
{
|
||||
error$("Couldn't retrieve SMP info from Limine");
|
||||
hal_panic();
|
||||
if (memcmp(path, module_request.response->modules[i]->path, strlen(path)) == 0)
|
||||
{
|
||||
Module mod = {
|
||||
.base = (uintptr_t)module_request.response->modules[i]->address,
|
||||
.len = module_request.response->modules[i]->size,
|
||||
};
|
||||
|
||||
memcpy(mod.name, module_request.response->modules[i]->path, strlen(path));
|
||||
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < smp_req.response->cpu_count; i++)
|
||||
{
|
||||
smp_req.response->cpus[i]->goto_address = (limine_goto_address)entry;
|
||||
}
|
||||
return (Module){0};
|
||||
}
|
|
@ -8,9 +8,16 @@
|
|||
],
|
||||
"arch": [
|
||||
"x86_64"
|
||||
],
|
||||
"sys": [
|
||||
"kernel"
|
||||
]
|
||||
},
|
||||
"provides": [
|
||||
"loader"
|
||||
],
|
||||
"requires": [
|
||||
"stdc-shim",
|
||||
"dbg"
|
||||
]
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <res.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -37,6 +38,17 @@ typedef struct
|
|||
|
||||
Mmap loader_get_mmap(void);
|
||||
|
||||
/* --- Modules -------------------------------------------------------------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uintptr_t base;
|
||||
size_t len;
|
||||
char name[64];
|
||||
} Module;
|
||||
|
||||
Module loader_get_module(char const *path);
|
||||
|
||||
/* --- Misc ---------------------------------------------------------------- */
|
||||
|
||||
KernelMmap loader_get_kernel_mmap(void);
|
|
@ -1,13 +1,16 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"type": "lib",
|
||||
"id": "stdc-shim",
|
||||
"id": "stdc-shim-kernel",
|
||||
"props": {
|
||||
"cpp-root-include": true
|
||||
},
|
||||
"enableIf": {
|
||||
"freestanding": [
|
||||
true
|
||||
"sys": [
|
||||
"kernel"
|
||||
]
|
||||
}
|
||||
},
|
||||
"provides": [
|
||||
"stdc-shim"
|
||||
]
|
||||
}
|
|
@ -3,8 +3,8 @@
|
|||
"type": "lib",
|
||||
"id": "sync",
|
||||
"enableIf": {
|
||||
"freestanding": [
|
||||
true
|
||||
"sys": [
|
||||
"kernel"
|
||||
]
|
||||
}
|
||||
}
|
39
src/libs/dbg/log.c
Normal file
39
src/libs/dbg/log.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include <fmt/fmt.h>
|
||||
#include <navy/api.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
/* --- Define sys_log as a stream ------------------------------------------- */
|
||||
|
||||
static Res stream_write(size_t n, char const buf[static n])
|
||||
{
|
||||
try$(sys_log(buf, n));
|
||||
return uok$(n);
|
||||
}
|
||||
|
||||
static Stream _stream = {
|
||||
.write = stream_write,
|
||||
};
|
||||
|
||||
/* --- Define log functions -------------------------------------------------- */
|
||||
|
||||
void _log(LogEvent event, Loc loc, char const *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
if (event != LOG_NONE)
|
||||
{
|
||||
fmt(_stream, "%s%s\e[0m %s:%d ", level_colors[event], level_names[event], loc.file, loc.line);
|
||||
}
|
||||
|
||||
vfmt(_stream, format, args);
|
||||
|
||||
if (event != LOG_NONE)
|
||||
{
|
||||
_stream.write(1, "\n");
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
|
@ -21,4 +21,20 @@ typedef enum
|
|||
#define critical$(...) _log(LOG_CRIT, loc$(), __VA_ARGS__)
|
||||
#define print$(...) _log(LOG_NONE, (Loc){}, __VA_ARGS__)
|
||||
|
||||
static char const *level_names[LOG_EVENT_LENGTH] = {
|
||||
[LOG_NONE] = "",
|
||||
[LOG_INFO] = "INFO",
|
||||
[LOG_WARN] = "WARN",
|
||||
[LOG_ERROR] = "ERROR",
|
||||
[LOG_CRIT] = "CRITIC",
|
||||
};
|
||||
|
||||
static char const *level_colors[LOG_EVENT_LENGTH] = {
|
||||
[LOG_NONE] = "",
|
||||
[LOG_INFO] = "\e[1;34m",
|
||||
[LOG_WARN] = "\e[1;33m",
|
||||
[LOG_ERROR] = "\e[1;31m",
|
||||
[LOG_CRIT] = "\e[1;35m",
|
||||
};
|
||||
|
||||
void _log(LogEvent event, Loc loc, char const *format, ...);
|
18
src/libs/dbg/manifest.json
Normal file
18
src/libs/dbg/manifest.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"type": "lib",
|
||||
"id": "dbg-user",
|
||||
"enableIf": {
|
||||
"sys": [
|
||||
"navy"
|
||||
]
|
||||
},
|
||||
"provides": [
|
||||
"dbg"
|
||||
],
|
||||
"requires": [
|
||||
"fmt",
|
||||
"stdc-shim",
|
||||
"io"
|
||||
]
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"type": "lib",
|
||||
"id": "fmt"
|
||||
"id": "fmt",
|
||||
"requires": [
|
||||
"stdc-shim"
|
||||
]
|
||||
}
|
65
src/libs/navy/api.h
Normal file
65
src/libs/navy/api.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
#pragma once
|
||||
|
||||
#include <res.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* --- Types --------------------------------------------------------------- */
|
||||
|
||||
typedef uintptr_t SysArg;
|
||||
|
||||
typedef enum : size_t
|
||||
{
|
||||
SYS_LOG,
|
||||
|
||||
__SYSCALL_LENGTH
|
||||
} Syscalls;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysArg arg1;
|
||||
SysArg arg2;
|
||||
SysArg arg3;
|
||||
SysArg arg4;
|
||||
SysArg arg5;
|
||||
SysArg arg6;
|
||||
} SysArgs;
|
||||
|
||||
/* --- Syscall ------------------------------------------------------------- */
|
||||
|
||||
#ifdef __ck_arch_x86_64__
|
||||
|
||||
static inline Res __syscall_impl(Syscalls s, SysArg arg1, SysArg arg2, SysArg arg3, SysArg arg4, SysArg arg5, SysArg arg6)
|
||||
{
|
||||
enum res_type res;
|
||||
|
||||
// s : rax, arg1 : rdi, arg2 : rsi, arg3 : rdx, arg4 : r10, arg5 : r8, arg6 : r9
|
||||
__asm__ volatile(
|
||||
"syscall"
|
||||
: "=a"(res)
|
||||
: "a"(s), "D"(arg1), "S"(arg2), "d"(arg3), "r"(arg4), "r"(arg5), "r"(arg6)
|
||||
: "rcx", "r11", "memory");
|
||||
|
||||
return (Res){
|
||||
.type = res,
|
||||
.uvalue = 0,
|
||||
.loc = loc$(),
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
# error "Unsupported architecture"
|
||||
#endif
|
||||
|
||||
#define __syscall(id, a1, a2, a3, a4, a5, a6, ...) __syscall_impl(id, a1, a2, a3, a4, a5, a6)
|
||||
|
||||
#define syscall(...) __syscall(__VA_ARGS__, 0, 0, 0, 0, 0, 0)
|
||||
|
||||
Res _syscall_handler(Syscalls no, SysArgs args);
|
||||
|
||||
/* --- Syscalls ------------------------------------------------------------- */
|
||||
|
||||
static inline Res sys_log(char const *str, size_t len)
|
||||
{
|
||||
return syscall(SYS_LOG, (SysArg)str, (SysArg)len);
|
||||
}
|
|
@ -10,7 +10,8 @@
|
|||
F(RES_INVAL) \
|
||||
F(RES_NOMEM) \
|
||||
F(RES_BADALIGN) \
|
||||
F(RES_NOENT)
|
||||
F(RES_NOENT) \
|
||||
F(RES_BADSYSCALL)
|
||||
|
||||
enum res_type
|
||||
{
|
||||
|
|
2719
src/libs/specs/elf.h
Normal file
2719
src/libs/specs/elf.h
Normal file
File diff suppressed because it is too large
Load diff
16
src/libs/stdc-shim/manifest.json
Normal file
16
src/libs/stdc-shim/manifest.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"type": "lib",
|
||||
"id": "stdc-shim-user",
|
||||
"props": {
|
||||
"cpp-root-include": true
|
||||
},
|
||||
"enableIf": {
|
||||
"sys": [
|
||||
"navy"
|
||||
]
|
||||
},
|
||||
"provides": [
|
||||
"stdc-shim"
|
||||
]
|
||||
}
|
9
src/libs/stdc-shim/string.c
Normal file
9
src/libs/stdc-shim/string.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include "string.h"
|
||||
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; s[i] != '\0'; i++)
|
||||
;
|
||||
return i;
|
||||
}
|
13
src/libs/stdc-shim/string.h
Normal file
13
src/libs/stdc-shim/string.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* @brief The strlen function computes the length of the string pointed to by s.
|
||||
* @cite ISO/IEC 9899:2023 - 7.26.6.4 The strlen function
|
||||
*
|
||||
* @arg s - pointer to the string to be examined
|
||||
* @return - the number of characters that precede the terminating null character
|
||||
**/
|
||||
|
||||
size_t strlen(const char *s);
|
8
src/srvs/sched/main.c
Normal file
8
src/srvs/sched/main.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <dbg/log.h>
|
||||
|
||||
_Noreturn int _start()
|
||||
{
|
||||
log$("Hello, world!");
|
||||
for (;;)
|
||||
;
|
||||
}
|
13
src/srvs/sched/manifest.json
Normal file
13
src/srvs/sched/manifest.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"type": "exe",
|
||||
"id": "sched",
|
||||
"requires": [
|
||||
"dbg"
|
||||
],
|
||||
"enableIf": {
|
||||
"sys": [
|
||||
"navy"
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue