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"):
|
def __init__(self, args: cli.Args, arch: str = "x86_64"):
|
||||||
self.__registry = model.Registry.use(args)
|
self.__registry = model.Registry.use(args)
|
||||||
self.__kernel_scope = builder.TargetScope(
|
self.__kernel_scope = builder.TargetScope(
|
||||||
|
self.__registry,
|
||||||
|
self.__registry.lookup(f"kernel-{arch}", model.Target),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.__user_scope = builder.TargetScope(
|
||||||
self.__registry,
|
self.__registry,
|
||||||
self.__registry.lookup(f"navy-{arch}", model.Target),
|
self.__registry.lookup(f"navy-{arch}", model.Target),
|
||||||
)
|
)
|
||||||
|
@ -14,6 +19,16 @@ class Builder:
|
||||||
product = builder.build(self.__kernel_scope, core_component)[0]
|
product = builder.build(self.__kernel_scope, core_component)[0]
|
||||||
return Path(product.path).absolute()
|
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
|
@property
|
||||||
def arch(self) -> str:
|
def arch(self) -> str:
|
||||||
return self.__kernel_scope.target.id.split("-")[1]
|
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 build
|
||||||
from . import image
|
from . import image
|
||||||
|
@ -13,11 +14,14 @@ def _(args: cli.Args):
|
||||||
def _(args: cli.Args):
|
def _(args: cli.Args):
|
||||||
qemu.Qemu(
|
qemu.Qemu(
|
||||||
image.Image(
|
image.Image(
|
||||||
build.Builder(args)
|
build.Builder(args),
|
||||||
)
|
),
|
||||||
|
no_display=args.consumeOpt("no-display"),
|
||||||
|
soft_dbg=args.consumeOpt("soft-dbg")
|
||||||
).run()
|
).run()
|
||||||
|
|
||||||
|
|
||||||
@cli.command("B", "navy/build", "Build Navy")
|
@cli.command("B", "navy/build", "Build Navy")
|
||||||
def _(args: cli.Args):
|
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 = self.path / "boot"
|
||||||
boot_dir.mkdir(parents=True, exist_ok=True)
|
boot_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
bin_dir = self.path / "bin"
|
||||||
|
bin_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"efi_boot": efi_boot,
|
"efi_boot": efi_boot,
|
||||||
"boot_dir": boot_dir,
|
"boot_dir": boot_dir,
|
||||||
|
"bin_dir": bin_dir,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def efi_x86_64(self):
|
def efi_x86_64(self):
|
||||||
kernel_path = self.builder.build_core()
|
kernel_path = self.builder.build_core()
|
||||||
|
modules = self.builder.build_modules()
|
||||||
|
|
||||||
paths = self.__efi_common()
|
paths = self.__efi_common()
|
||||||
|
|
||||||
cfg = [
|
cfg = [
|
||||||
|
@ -43,6 +49,14 @@ class Image:
|
||||||
"KERNEL_PATH=boot:///boot/kernel.elf",
|
"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(
|
shell.wget(
|
||||||
"https://github.com/limine-bootloader/limine/raw/v6.x-branch-binary/BOOTX64.EFI",
|
"https://github.com/limine-bootloader/limine/raw/v6.x-branch-binary/BOOTX64.EFI",
|
||||||
str(paths["efi_boot"] / "BOOTX64.EFI"),
|
str(paths["efi_boot"] / "BOOTX64.EFI"),
|
||||||
|
|
|
@ -5,8 +5,8 @@ from cutekit import shell
|
||||||
from .image import Image
|
from .image import Image
|
||||||
|
|
||||||
class Qemu:
|
class Qemu:
|
||||||
def __init__(self, img: Image, no_reboot: bool = True, nographics: 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):
|
no_shutdown: bool = True, efi: bool = True, memory: str = "4G", debug: bool = False, soft_dbg: bool = False):
|
||||||
self.__img = img
|
self.__img = img
|
||||||
self.__binary = None
|
self.__binary = None
|
||||||
self.__efi = efi
|
self.__efi = efi
|
||||||
|
@ -26,12 +26,15 @@ class Qemu:
|
||||||
if no_shutdown:
|
if no_shutdown:
|
||||||
self.__args.append("-no-shutdown")
|
self.__args.append("-no-shutdown")
|
||||||
|
|
||||||
if nographics:
|
if no_display:
|
||||||
self.__args.append("-nographic")
|
self.__args += ["-display", "none"]
|
||||||
|
|
||||||
if self.iskvmAvailable():
|
if self.iskvmAvailable():
|
||||||
self.__args += ["-enable-kvm", "-cpu", "host"]
|
self.__args += ["-enable-kvm", "-cpu", "host"]
|
||||||
|
|
||||||
|
if soft_dbg:
|
||||||
|
self.__args += ["-d", "int"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
getattr(self, f"arch_{img.builder.arch}")()
|
getattr(self, f"arch_{img.builder.arch}")()
|
||||||
except AttributeError:
|
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",
|
"id": "navy-x86_64",
|
||||||
"type": "target",
|
"type": "target",
|
||||||
"props": {
|
"props": {
|
||||||
|
@ -7,10 +7,9 @@
|
||||||
"arch": "x86_64",
|
"arch": "x86_64",
|
||||||
"bits": "64",
|
"bits": "64",
|
||||||
"sys": "navy",
|
"sys": "navy",
|
||||||
"loader": "limine",
|
|
||||||
"abi": "sysv",
|
"abi": "sysv",
|
||||||
"encoding": "utf8",
|
"encoding": "utf8",
|
||||||
"freestanding": true,
|
"freestanding": false,
|
||||||
"host": false
|
"host": false
|
||||||
},
|
},
|
||||||
"tools": {
|
"tools": {
|
||||||
|
@ -23,15 +22,11 @@
|
||||||
"-target",
|
"-target",
|
||||||
"x86_64-none-elf",
|
"x86_64-none-elf",
|
||||||
"-ffreestanding",
|
"-ffreestanding",
|
||||||
"-fno-stack-protector",
|
|
||||||
"-mno-80387",
|
"-mno-80387",
|
||||||
"-mno-mmx",
|
"-mno-mmx",
|
||||||
"-mno-3dnow",
|
"-mno-3dnow",
|
||||||
"-mno-sse",
|
"-mno-sse",
|
||||||
"-mno-sse2",
|
"-mno-sse2"
|
||||||
"-mno-red-zone",
|
|
||||||
"-mcmodel=kernel",
|
|
||||||
"-Dauto=__auto_type"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"cxx": {
|
"cxx": {
|
||||||
|
@ -43,14 +38,11 @@
|
||||||
"-target",
|
"-target",
|
||||||
"x86_64-none-elf",
|
"x86_64-none-elf",
|
||||||
"-ffreestanding",
|
"-ffreestanding",
|
||||||
"-fno-stack-protector",
|
|
||||||
"-mno-80387",
|
"-mno-80387",
|
||||||
"-mno-mmx",
|
"-mno-mmx",
|
||||||
"-mno-3dnow",
|
"-mno-3dnow",
|
||||||
"-mno-sse",
|
"-mno-sse",
|
||||||
"-mno-sse2",
|
"-mno-sse2"
|
||||||
"-mno-red-zone",
|
|
||||||
"-mcmodel=kernel"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ld": {
|
"ld": {
|
||||||
|
@ -64,13 +56,10 @@
|
||||||
"-T",
|
"-T",
|
||||||
[
|
[
|
||||||
"@abspath",
|
"@abspath",
|
||||||
"kernel-x86_64.ld"
|
"navy-x86_64.ld"
|
||||||
],
|
],
|
||||||
"-z",
|
"-z",
|
||||||
"max-page-size=0x1000"
|
"max-page-size=0x1000"
|
||||||
],
|
|
||||||
"files": [
|
|
||||||
"meta/targets/kernel-x86_64.ld"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ar": {
|
"ar": {
|
||||||
|
@ -83,15 +72,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"as": {
|
"as": {
|
||||||
"cmd": [
|
"cmd": "clang",
|
||||||
"@latest",
|
|
||||||
"clang"
|
|
||||||
],
|
|
||||||
"args": [
|
"args": [
|
||||||
"-target",
|
"-target",
|
||||||
"x86_64-none-elf",
|
"x86_64-none-elf",
|
||||||
"-c",
|
"-c"
|
||||||
"-g"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
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
|
SECTIONS
|
||||||
{
|
{
|
||||||
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
|
. = 4M;
|
||||||
/* 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 : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
.text : {
|
.rodata : ALIGN(4K)
|
||||||
*(.text .text.*)
|
{
|
||||||
} :text
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
text_end_addr = .;
|
.data : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
/* Move to the next memory page for .rodata */
|
.bss : ALIGN(4K)
|
||||||
. += 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)
|
*(COMMON)
|
||||||
*(.bss .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,8 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <io/stream.h>
|
#include <io/stream.h>
|
||||||
|
#include <navy/api.h>
|
||||||
#include <stdint.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);
|
Res hal_setup(void);
|
||||||
|
|
||||||
/* --- Structs ------------------------------------------------------------ */
|
/* --- 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);
|
void hal_space_apply(HalPage *space);
|
||||||
|
|
||||||
|
Res hal_space_create(HalPage **self);
|
||||||
|
|
||||||
/* --- Arch Specific ------------------------------------------------------- */
|
/* --- Arch Specific ------------------------------------------------------- */
|
||||||
|
|
||||||
#ifdef __ck_arch_x86_64__
|
#ifdef __ck_arch_x86_64__
|
||||||
# include <x86_64/acpi.h>
|
|
||||||
|
|
||||||
Rsdp *hal_acpi_rsdp(void);
|
Rsdp *hal_acpi_rsdp(void);
|
||||||
|
|
||||||
#endif
|
#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 <dbg/log.h>
|
||||||
#include <hal.h>
|
#include <hal.h>
|
||||||
|
#include <kmalloc/kmalloc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sync/spinlock.h>
|
#include <sync/spinlock.h>
|
||||||
|
|
||||||
|
#include "ctx.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
|
|
||||||
static Gdt gdt = {0};
|
static Gdt gdt = {0};
|
||||||
|
static Tss tss = {0};
|
||||||
|
|
||||||
static Spinlock lock = SPINLOCK_INIT;
|
static Spinlock lock = SPINLOCK_INIT;
|
||||||
|
|
||||||
|
@ -79,3 +82,17 @@ void gdt_init(void)
|
||||||
tss_flush();
|
tss_flush();
|
||||||
log$("TSS loaded");
|
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_init(void);
|
||||||
void gdt_load_tss(Tss *self);
|
void gdt_load_tss(Tss *self);
|
||||||
|
Res gdt_init_tss(void);
|
||||||
uintptr_t gdt_descriptor(void);
|
uintptr_t gdt_descriptor(void);
|
||||||
|
|
||||||
extern void gdt_flush(uintptr_t);
|
extern void gdt_flush(uintptr_t);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include <hal.h>
|
#include <hal.h>
|
||||||
#include <sync/spinlock.h>
|
#include <sync/spinlock.h>
|
||||||
|
|
||||||
|
#include "../core/pre-sched.h"
|
||||||
|
#include "apic.h"
|
||||||
#include "asm.h"
|
#include "asm.h"
|
||||||
#include "regs.h"
|
#include "regs.h"
|
||||||
|
|
||||||
|
@ -68,6 +70,7 @@ static void dump_backtrace(uintptr_t rbp)
|
||||||
static void kpanic(HalRegs const regs[static 1])
|
static void kpanic(HalRegs const regs[static 1])
|
||||||
{
|
{
|
||||||
spinlock_acquire(&lock);
|
spinlock_acquire(&lock);
|
||||||
|
|
||||||
uint64_t cr0, cr2, cr3, cr4;
|
uint64_t cr0, cr2, cr3, cr4;
|
||||||
|
|
||||||
asm_read_cr(0, cr0);
|
asm_read_cr(0, cr0);
|
||||||
|
@ -107,6 +110,11 @@ uintptr_t interrupt_handler(uintptr_t rsp)
|
||||||
hal_pause();
|
hal_pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (regs->intno == IRQ0)
|
||||||
|
{
|
||||||
|
switch_to_scheduler(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
lapic_eoi();
|
||||||
return rsp;
|
return rsp;
|
||||||
}
|
}
|
|
@ -111,3 +111,30 @@ __interrupts_vector:
|
||||||
idt_flush:
|
idt_flush:
|
||||||
lidt (%rdi)
|
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": {
|
"enableIf": {
|
||||||
"arch": [
|
"arch": [
|
||||||
"x86_64"
|
"x86_64"
|
||||||
|
],
|
||||||
|
"sys": [
|
||||||
|
"kernel"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"provides": [
|
"provides": [
|
||||||
"arch"
|
"arch"
|
||||||
],
|
],
|
||||||
"requires": [
|
"requires": [
|
||||||
|
"io",
|
||||||
|
"stdc-shim",
|
||||||
"dbg"
|
"dbg"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -2,13 +2,14 @@
|
||||||
#include <io/stream.h>
|
#include <io/stream.h>
|
||||||
#include <res.h>
|
#include <res.h>
|
||||||
|
|
||||||
|
#include "apic.h"
|
||||||
#include "e9.h"
|
#include "e9.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
|
#include "hpet.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "paging.h"
|
#include "paging.h"
|
||||||
#include "hpet.h"
|
|
||||||
#include "apic.h"
|
|
||||||
#include "simd.h"
|
#include "simd.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
Stream hal_dbg_stream(void)
|
Stream hal_dbg_stream(void)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +23,8 @@ Res hal_setup(void)
|
||||||
gdt_init();
|
gdt_init();
|
||||||
idt_init();
|
idt_init();
|
||||||
try$(paging_init());
|
try$(paging_init());
|
||||||
|
try$(gdt_init_tss());
|
||||||
|
syscall_init();
|
||||||
acpi_init();
|
acpi_init();
|
||||||
try$(hpet_init());
|
try$(hpet_init());
|
||||||
try$(apic_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)
|
else if (alloc)
|
||||||
{
|
{
|
||||||
PmmObj obj = pmm_alloc(1);
|
PmmObj obj = pmm_alloc(1);
|
||||||
memset((void *)obj.base, 0, obj.len);
|
|
||||||
uintptr_t ptr_hddm = hal_mmap_l2h(obj.base);
|
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;
|
pml[index] = obj.base | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER;
|
||||||
|
|
||||||
|
@ -158,11 +158,11 @@ Res paging_init(void)
|
||||||
return err$(RES_NOMEM);
|
return err$(RES_NOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset((void *)obj.base, 0, obj.len);
|
|
||||||
|
|
||||||
log$("PML4: 0x%p", obj.base);
|
log$("PML4: 0x%p", obj.base);
|
||||||
pml4 = (uintptr_t *)hal_mmap_l2h((uintptr_t)obj.base);
|
pml4 = (uintptr_t *)hal_mmap_l2h((uintptr_t)obj.base);
|
||||||
|
|
||||||
|
memset((void *)pml4, 0, obj.len);
|
||||||
|
|
||||||
if (cpuid_has_1gb_pages())
|
if (cpuid_has_1gb_pages())
|
||||||
{
|
{
|
||||||
log$("1GB pages are supported");
|
log$("1GB pages are supported");
|
||||||
|
@ -220,14 +220,14 @@ Res hal_space_create(HalPage **self)
|
||||||
{
|
{
|
||||||
|
|
||||||
PmmObj obj = pmm_alloc(1);
|
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)
|
if (obj.base == 0)
|
||||||
{
|
{
|
||||||
return err$(RES_NOMEM);
|
return err$(RES_NOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t *space = (uintptr_t *)hal_mmap_l2h(obj.base);
|
|
||||||
memset((void *)space, 0, PMM_PAGE_SIZE);
|
memset((void *)space, 0, PMM_PAGE_SIZE);
|
||||||
|
|
||||||
for (size_t i = 255; i < 512; i++)
|
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 <hal.h>
|
||||||
|
|
||||||
#include "pmm.h"
|
#include "pmm.h"
|
||||||
|
#include "pre-sched.h"
|
||||||
|
|
||||||
_Noreturn int _start()
|
_Noreturn int _start()
|
||||||
{
|
{
|
||||||
pmm_init();
|
Res pmm = pmm_init();
|
||||||
hal_setup();
|
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 (;;)
|
for (;;)
|
||||||
;
|
;
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
"arch",
|
"arch",
|
||||||
"dbg",
|
"dbg",
|
||||||
"stdc-shim",
|
"stdc-shim",
|
||||||
"loader"
|
"loader",
|
||||||
|
"kmalloc"
|
||||||
],
|
],
|
||||||
"tools": {
|
"tools": {
|
||||||
"cc": {
|
"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 <fmt/fmt.h>
|
||||||
#include <hal.h>
|
#include <hal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <sync/spinlock.h>
|
#include <sync/spinlock.h>
|
||||||
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
static Spinlock _lock = SPINLOCK_INIT;
|
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, ...)
|
void _log(LogEvent event, Loc loc, char const *format, ...)
|
||||||
{
|
{
|
||||||
spinlock_acquire(&_lock);
|
spinlock_acquire(&_lock);
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||||
"type": "lib",
|
"type": "lib",
|
||||||
"id": "dbg",
|
"id": "dbg-kernel",
|
||||||
"enableIf": {
|
"enableIf": {
|
||||||
"freestanding": [
|
"sys": [
|
||||||
true
|
"kernel"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"provides": [
|
||||||
|
"dbg"
|
||||||
|
],
|
||||||
"requires": [
|
"requires": [
|
||||||
"sync",
|
"sync",
|
||||||
"fmt"
|
"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 <dbg/log.h>
|
||||||
#include <hal.h>
|
#include <hal.h>
|
||||||
|
#include <loader.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "limine.h"
|
#include "limine.h"
|
||||||
#include "loader.h"
|
|
||||||
|
|
||||||
static Mmap mmap = {0};
|
static Mmap mmap = {0};
|
||||||
|
|
||||||
|
@ -33,10 +34,10 @@ static volatile struct limine_rsdp_request rsdp_req = {
|
||||||
.response = NULL,
|
.response = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static volatile struct limine_smp_request smp_req = {
|
volatile struct limine_module_request module_request = {
|
||||||
.id = LIMINE_SMP_REQUEST,
|
.id = LIMINE_MODULE_REQUEST,
|
||||||
|
.response = 0,
|
||||||
.revision = 0,
|
.revision = 0,
|
||||||
.response = NULL,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* --- Loader functions ---------------------------------------------------- */
|
/* --- Loader functions ---------------------------------------------------- */
|
||||||
|
@ -172,27 +173,27 @@ Rsdp *hal_acpi_rsdp(void)
|
||||||
return (Rsdp *)rsdp_req.response->address;
|
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");
|
return (Module){0};
|
||||||
hal_panic();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return smp_req.response->cpu_count;
|
for (size_t i = 0; i < module_request.response->module_count; i++)
|
||||||
}
|
{
|
||||||
|
if (memcmp(path, module_request.response->modules[i]->path, strlen(path)) == 0)
|
||||||
void hal_smp_boot(void (*entry)(void))
|
{
|
||||||
{
|
Module mod = {
|
||||||
if (smp_req.response == NULL)
|
.base = (uintptr_t)module_request.response->modules[i]->address,
|
||||||
{
|
.len = module_request.response->modules[i]->size,
|
||||||
error$("Couldn't retrieve SMP info from Limine");
|
};
|
||||||
hal_panic();
|
|
||||||
}
|
memcpy(mod.name, module_request.response->modules[i]->path, strlen(path));
|
||||||
|
|
||||||
for (size_t i = 0; i < smp_req.response->cpu_count; i++)
|
return mod;
|
||||||
{
|
}
|
||||||
smp_req.response->cpus[i]->goto_address = (limine_goto_address)entry;
|
}
|
||||||
}
|
|
||||||
|
return (Module){0};
|
||||||
}
|
}
|
|
@ -8,9 +8,16 @@
|
||||||
],
|
],
|
||||||
"arch": [
|
"arch": [
|
||||||
"x86_64"
|
"x86_64"
|
||||||
|
],
|
||||||
|
"sys": [
|
||||||
|
"kernel"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"provides": [
|
"provides": [
|
||||||
"loader"
|
"loader"
|
||||||
|
],
|
||||||
|
"requires": [
|
||||||
|
"stdc-shim",
|
||||||
|
"dbg"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <res.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -37,6 +38,17 @@ typedef struct
|
||||||
|
|
||||||
Mmap loader_get_mmap(void);
|
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 ---------------------------------------------------------------- */
|
/* --- Misc ---------------------------------------------------------------- */
|
||||||
|
|
||||||
KernelMmap loader_get_kernel_mmap(void);
|
KernelMmap loader_get_kernel_mmap(void);
|
|
@ -1,13 +1,16 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||||
"type": "lib",
|
"type": "lib",
|
||||||
"id": "stdc-shim",
|
"id": "stdc-shim-kernel",
|
||||||
"props": {
|
"props": {
|
||||||
"cpp-root-include": true
|
"cpp-root-include": true
|
||||||
},
|
},
|
||||||
"enableIf": {
|
"enableIf": {
|
||||||
"freestanding": [
|
"sys": [
|
||||||
true
|
"kernel"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"provides": [
|
||||||
|
"stdc-shim"
|
||||||
]
|
]
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -3,8 +3,8 @@
|
||||||
"type": "lib",
|
"type": "lib",
|
||||||
"id": "sync",
|
"id": "sync",
|
||||||
"enableIf": {
|
"enableIf": {
|
||||||
"freestanding": [
|
"sys": [
|
||||||
true
|
"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 critical$(...) _log(LOG_CRIT, loc$(), __VA_ARGS__)
|
||||||
#define print$(...) _log(LOG_NONE, (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, ...);
|
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",
|
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||||
"type": "lib",
|
"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_INVAL) \
|
||||||
F(RES_NOMEM) \
|
F(RES_NOMEM) \
|
||||||
F(RES_BADALIGN) \
|
F(RES_BADALIGN) \
|
||||||
F(RES_NOENT)
|
F(RES_NOENT) \
|
||||||
|
F(RES_BADSYSCALL)
|
||||||
|
|
||||||
enum res_type
|
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