This commit is contained in:
2026-09-20 05:27:41 +02:00
parent 831308b2ad
commit 77f228df11
38 changed files with 465 additions and 115 deletions
+1
View File
@@ -5,3 +5,4 @@ build/
*.o *.o
*.a *.a
*.so *.so
__pycache__/
+4 -2
View File
@@ -1,7 +1,9 @@
mainmenu "Zinnia Kernel Configuration" mainmenu "Zinnia Kernel Configuration"
source "dev/Kconfig"
config KERNEL_FLAVOR config KERNEL_FLAVOR
string "Kernel flavor name" string "Kernel flavor name"
default "vanilla" default "vanilla"
source "arch/$(ARCH)/Kconfig"
source "core/Kconfig"
source "dev/Kconfig"
+16
View File
@@ -0,0 +1,16 @@
menu "x86_64 Architecture options"
config X86_64
bool
default y
select ACPI
select HAVE_MMU
select HAVE_MMU_GENERIC
help
64-bit x86 CPU support for AMD and Intel CPUs.
config TSC
bool "Invariant Timestamp Counter support"
default y
endmenu
-1
View File
@@ -1,7 +1,6 @@
kernel_c_args += [ kernel_c_args += [
'-mgeneral-regs-only', '-mgeneral-regs-only',
'-mno-red-zone', '-mno-red-zone',
'-mcmodel=kernel',
'-masm=intel', '-masm=intel',
] ]
+3
View File
@@ -1,5 +1,6 @@
#include <zinnia/percpu.h> #include <zinnia/percpu.h>
#include <zinnia/print.h> #include <zinnia/print.h>
#include <config.h>
#include <stddef.h> #include <stddef.h>
#include <x86_64/apic.h> #include <x86_64/apic.h>
#include <x86_64/asm.h> #include <x86_64/asm.h>
@@ -119,7 +120,9 @@ static void setup_cpu(struct percpu* cpu) {
void arch_percpu_init() { void arch_percpu_init() {
hpet_init(); hpet_init();
#if CONFIG_TSC
tsc_init(); tsc_init();
#endif
// Init the BSP. // Init the BSP.
setup_cpu(&percpu_bsp); setup_cpu(&percpu_bsp);
+3 -3
View File
@@ -94,9 +94,9 @@ void task_entry_thunk() {
asm volatile( asm volatile(
"mov rdi, rbx\n" "mov rdi, rbx\n"
"mov rsi, r12\n" "mov rsi, r12\n"
"jmp %c0" "jmp %0"
: :
: "i"(task_entry) : "r"(task_entry)
: "memory" : "memory"
); );
} }
@@ -173,7 +173,7 @@ bool arch_sched_preempt_enable() {
void arch_sched_jump_to_context(struct arch_context* context) { void arch_sched_jump_to_context(struct arch_context* context) {
asm volatile( asm volatile(
"mov rsp, rdi\n" "mov rsp, rdi\n"
"jmp %c0\n" ::"i"(interrupt_return) "jmp %0\n" ::"r"(interrupt_return)
); );
} }
+2 -2
View File
@@ -11,9 +11,9 @@
[[__init, __naked, __used]] [[__init, __naked, __used]]
void _start() { void _start() {
asm volatile( asm volatile(
"lea rsp, [rip + %0]\n" "mov rsp, %0\n"
"jmp %1" "jmp %1"
: :
: "i"(__ld_stack_top), "r"(kernel_entry) : "r"(__ld_stack_top), "r"(kernel_entry)
); );
} }
+2 -2
View File
@@ -39,7 +39,7 @@ void arch_syscall_stub() {
" push r15\n" " push r15\n"
" xor rbp, rbp\n" " xor rbp, rbp\n"
" mov rdi, rsp\n" // SysV ABI first argument. " mov rdi, rsp\n" // SysV ABI first argument.
" call %c4\n" // Call syscall handler. " call %4\n" // Call syscall handler.
" cli\n" " cli\n"
" pop r15\n" " pop r15\n"
" pop r14\n" " pop r14\n"
@@ -66,6 +66,6 @@ void arch_syscall_stub() {
"i"(offsetof(struct percpu, kernel_stack)), // 1 "i"(offsetof(struct percpu, kernel_stack)), // 1
"i"(offsetof(struct gdt, user_code64) | CPL_USER), // 2 "i"(offsetof(struct gdt, user_code64) | CPL_USER), // 2
"i"(offsetof(struct gdt, user_data) | CPL_USER), // 3 "i"(offsetof(struct gdt, user_data) | CPL_USER), // 3
"i"(syscall_dispatch) // 4 "r"(syscall_dispatch) // 4
); );
} }
+52 -53
View File
@@ -1,6 +1,14 @@
#include <zinnia/compiler.h> #include <zinnia/compiler.h>
#include <arch/usercopy.h> #include <arch/usercopy.h>
void arch_usercopy_allow(bool state) {
if (state) {
asm volatile("stac" ::: "memory");
} else {
asm volatile("clac" ::: "memory");
}
}
extern void x86_64_read_start(); extern void x86_64_read_start();
extern void x86_64_read_end(); extern void x86_64_read_end();
extern void x86_64_read_fault(); extern void x86_64_read_fault();
@@ -11,37 +19,34 @@ static const struct usercopy_region read_region = {
.fault_ip = x86_64_read_fault, .fault_ip = x86_64_read_fault,
}; };
[[__naked]]
bool arch_usercopy_read(void* dst, const __user void* src, size_t len, struct usercopy_region** region) { bool arch_usercopy_read(void* dst, const __user void* src, size_t len, struct usercopy_region** region) {
asm volatile( asm volatile(
"stac\n"
// Setup regs for `rep movsb`. // Setup regs for `rep movsb`.
"xchg rcx, rdx\n" " xchg rcx, rdx\n"
"mov rax, [rip + %0]\n" " mov rax, [rip + %0]\n"
"xchg [rdx], rax\n" " xchg [rdx], rax\n"
".global x86_64_read_start\n" ".global x86_64_read_start\n"
"x86_64_read_start:\n" " x86_64_read_start:\n"
"rep movsb\n" " rep movsb\n"
".global x86_64_read_end\n" ".global x86_64_read_end\n"
"x86_64_read_end:\n" "x86_64_read_end:\n"
"xor rax, rax\n" " xor rax, rax\n"
"xchg [rdx], rax\n" " xchg [rdx], rax\n"
"mov rax, 1\n" " mov rax, 1\n"
"clac\n" " ret\n"
"ret\n"
".global x86_64_read_fault\n" ".global x86_64_read_fault\n"
"x86_64_read_fault:\n" "x86_64_read_fault:\n"
"xor rax, rax\n" " xor rax, rax\n"
"xchg [rdx], rax\n" " xchg [rdx], rax\n"
"clac\n" " ret\n"
"ret\n"
: :
: "i"(&read_region) : "i"(&read_region)
: "memory" : "memory"
); );
return false;
} }
extern void x86_64_write_start(); extern void x86_64_write_start();
@@ -54,37 +59,34 @@ static const struct usercopy_region write_region = {
.fault_ip = x86_64_write_fault, .fault_ip = x86_64_write_fault,
}; };
[[__naked]]
bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct usercopy_region** region) { bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct usercopy_region** region) {
asm volatile( asm volatile(
"stac\n"
// Setup regs for `rep movsb`. // Setup regs for `rep movsb`.
"xchg rcx, rdx\n" " xchg rcx, rdx\n"
"mov rax, [rip + %0]\n" " mov rax, [rip + %0]\n"
"mov [rdx], rax\n" " mov [rdx], rax\n"
".global x86_64_write_start\n" ".global x86_64_write_start\n"
"x86_64_write_start:\n" " x86_64_write_start:\n"
"rep movsb\n" " rep movsb\n"
".global x86_64_write_end\n" ".global x86_64_write_end\n"
"x86_64_write_end:\n" " x86_64_write_end:\n"
"xor rax, rax\n" " xor rax, rax\n"
"xchg [rdx], rax\n" " xchg [rdx], rax\n"
"mov rax, 1\n" " mov rax, 1\n"
"clac\n" " ret\n"
"ret\n"
".global x86_64_write_fault\n" ".global x86_64_write_fault\n"
"x86_64_write_fault:\n" "x86_64_write_fault:\n"
"xor rax, rax\n" " xor rax, rax\n"
"xchg [rdx], rax\n" " xchg [rdx], rax\n"
"clac\n" " ret\n"
"ret\n"
: :
: "i"(&write_region) : "i"(&write_region)
: "memory" : "memory"
); );
return false;
} }
extern void x86_64_strlen_start(); extern void x86_64_strlen_start();
@@ -100,36 +102,33 @@ static const struct usercopy_region strlen_region = {
[[__naked]] [[__naked]]
bool arch_usercopy_strlen(const __user char* str, size_t max, size_t* len, struct usercopy_region** region) { bool arch_usercopy_strlen(const __user char* str, size_t max, size_t* len, struct usercopy_region** region) {
asm volatile( asm volatile(
"stac\n" " mov rax, [rip + %0]\n"
"mov rax, [rip + %0]\n" " xchg [rcx], rax\n"
"xchg [rcx], rax\n"
".global x86_64_strlen_start\n" ".global x86_64_strlen_start\n"
"x86_64_strlen_start:\n" " x86_64_strlen_start:\n"
"xor r8, r8\n" " xor r8, r8\n"
".Lloop:\n" ".Lloop:\n"
"cmp byte ptr [rdi + r8], 0\n" " cmp byte ptr [rdi + r8], 0\n"
"je .Lleave\n" " je .Lleave\n"
"inc r8\n" " inc r8\n"
"cmp rsi, r8\n" " cmp rsi, r8\n"
"jne .Lloop\n" " jne .Lloop\n"
".Lleave:\n" ".Lleave:\n"
"mov [rdx], r8\n" " mov [rdx], r8\n"
".global x86_64_strlen_end\n" ".global x86_64_strlen_end\n"
"x86_64_strlen_end:\n" "x86_64_strlen_end:\n"
"xor rax, rax\n" " xor rax, rax\n"
"xchg [rcx], rax\n" " xchg [rcx], rax\n"
"mov rax, 1\n" " mov rax, 1\n"
"clac\n" " ret\n"
"ret\n"
".global x86_64_strlen_fault\n" ".global x86_64_strlen_fault\n"
"x86_64_strlen_fault:\n" "x86_64_strlen_fault:\n"
"xor rax, rax\n" " xor rax, rax\n"
"xchg [rcx], rax\n" " xchg [rcx], rax\n"
"clac\n" " ret\n"
"ret\n"
: :
: "i"(&strlen_region) : "i"(&strlen_region)
: "memory" : "memory"
+8 -6
View File
@@ -54,27 +54,29 @@ SECTIONS
.dynsym : { .dynsym : {
__ld_dynsym_start = .; __ld_dynsym_start = .;
*(.dynsym) KEEP(*(.dynsym*))
__ld_dynsym_end = .; __ld_dynsym_end = .;
} :data } :data
.dynstr : { .dynstr : {
__ld_dynstr_start = .; __ld_dynstr_start = .;
*(.dynstr) KEEP(*(.dynstr*))
__ld_dynstr_end = .; __ld_dynstr_end = .;
} :data } :data
.dynamic : { .dynamic : {
*(.dynamic) *(.dynamic*)
} :data :dynamic } :data :dynamic
.bss : { .bss ALIGN(CONSTANT(MAXPAGESIZE)) (NOLOAD) : {
*(.*bss .*bss.*)
*(COMMON)
/* Small stack to bootstrap the allocator */ /* Small stack to bootstrap the allocator */
. = ALIGN(16);
__ld_stack_bottom = .; __ld_stack_bottom = .;
. += 0x2000; . += 0x2000;
__ld_stack_top = .; __ld_stack_top = .;
*(.*bss .*bss.*)
*(COMMON)
} :data } :data
/* Per-CPU data block. MUST always come last. */ /* Per-CPU data block. MUST always come last. */
+18
View File
@@ -0,0 +1,18 @@
menu "Kernel Core options"
source "core/mem/Kconfig"
choice SCHED_ALG
prompt "Scheduler algorithm"
default SCHED_DUMB
help
The algorithm to use for scheduling.
config SCHED_DUMB
bool "Dumb Scheduler"
help
Very basic scheduler, without any priorities.
endchoice
endmenu
+8
View File
@@ -0,0 +1,8 @@
menu "Memory Management options"
config HAVE_MMU
bool
config HAVE_MMU_GENERIC
bool
endmenu
+6 -1
View File
@@ -1,7 +1,6 @@
kernel_sources += files( kernel_sources += files(
'fault.c', 'fault.c',
'init.c', 'init.c',
'pmap.c',
'pmm.c', 'pmm.c',
'slab.c', 'slab.c',
'usercopy.c', 'usercopy.c',
@@ -9,3 +8,9 @@ kernel_sources += files(
'vma.c', 'vma.c',
'vmo.c', 'vmo.c',
) )
if kconfig.get('CONFIG_HAVE_MMU', 'n') == 'y'
kernel_sources += files(
'pmap.c',
)
endif
+4
View File
@@ -3,8 +3,12 @@
#include <zinnia/pmap.h> #include <zinnia/pmap.h>
#include <zinnia/spin.h> #include <zinnia/spin.h>
#include <zinnia/vma.h> #include <zinnia/vma.h>
#include <config.h>
#include <string.h> #include <string.h>
// TODO: For now, we assume that we can do generic PTE lookups on every arch that has a MMU.
static_assert(CONFIG_HAVE_MMU_GENERIC);
errno_t pmap_new_kernel(struct pmap* pt, enum alloc_flags flags) { errno_t pmap_new_kernel(struct pmap* pt, enum alloc_flags flags) {
flags &= ~ALLOC_NOZERO; flags &= ~ALLOC_NOZERO;
+12 -3
View File
@@ -3,13 +3,22 @@
#include <arch/usercopy.h> #include <arch/usercopy.h>
bool usercopy_read(void* dst, const __user void* src, size_t len) { bool usercopy_read(void* dst, const __user void* src, size_t len) {
return arch_usercopy_read(dst, src, len, &percpu_get()->sched.current->usercopy_region); arch_usercopy_allow(true);
bool success = arch_usercopy_read(dst, src, len, &percpu_get()->sched.current->usercopy_region);
arch_usercopy_allow(false);
return success;
} }
bool usercopy_write(__user void* dst, const void* src, size_t len) { bool usercopy_write(__user void* dst, const void* src, size_t len) {
return arch_usercopy_write(dst, src, len, &percpu_get()->sched.current->usercopy_region); arch_usercopy_allow(true);
bool success = arch_usercopy_write(dst, src, len, &percpu_get()->sched.current->usercopy_region);
arch_usercopy_allow(false);
return success;
} }
bool usercopy_strlen(const __user char* str, size_t max, size_t* len) { bool usercopy_strlen(const __user char* str, size_t max, size_t* len) {
return arch_usercopy_strlen(str, max, len, &percpu_get()->sched.current->usercopy_region); arch_usercopy_allow(true);
bool success = arch_usercopy_strlen(str, max, len, &percpu_get()->sched.current->usercopy_region);
arch_usercopy_allow(false);
return success;
} }
+4 -1
View File
@@ -1,4 +1,7 @@
kernel_sources += files( kernel_sources += files(
'core.c', 'core.c',
'sched_dumb.c',
) )
if kconfig.get('CONFIG_SCHED_DUMB', 'n') == 'y'
kernel_sources += files('sched_dumb.c')
endif
+3
View File
@@ -12,4 +12,7 @@ config ACPI
help help
Adds support for ACPI firmware, tables and devices. Adds support for ACPI firmware, tables and devices.
source "dev/block/Kconfig"
source "dev/pci/Kconfig"
endmenu endmenu
+5
View File
@@ -0,0 +1,5 @@
menu "Block device drivers"
source "dev/block/nvme/Kconfig"
endmenu
+3
View File
@@ -0,0 +1,3 @@
if kconfig.get('CONFIG_NVME_CORE', 'n') != 'n'
subdir('nvme')
endif
+13
View File
@@ -0,0 +1,13 @@
menu "NVMe Support"
config NVME_CORE
bool
default y
config NVME_PCI
bool "NVMe via PCI transport"
default y
depends on PCI
depends on NVME_CORE
endmenu
+12
View File
@@ -0,0 +1,12 @@
#include <zinnia/cmdline.h>
#include <zinnia/module.h>
#include <zinnia/print.h>
void nvme_init(struct module* mod) {
log("Hello world from NVMe!\n");
}
void do_nvme(bool on) {}
CMDLINE_OPTION("nvme_on", "My description", do_nvme);
MODULE("NVME", "Marvin Friedrich", "ISC", "1.0", nvme_init);
+12
View File
@@ -0,0 +1,12 @@
nvme_sources = files('core.c')
if kconfig.get('CONFIG_NVME_PCI', 'n') == 'y'
nvme_sources += files('pci.c')
endif
modules += {
'nvme': {
'modular': true, #kconfig.get('CONFIG_NVME_CORE') == 'm',
'sources': nvme_sources,
},
}
View File
+1
View File
@@ -0,0 +1 @@
#pragma once
+5 -2
View File
@@ -1,9 +1,12 @@
subdir('common') subdir('common')
subdir('block')
if cfg.get('CONFIG_ACPI', 0) == 1 if kconfig.get('CONFIG_ACPI', 'n') == 'y'
subdir('acpi') subdir('acpi')
endif endif
if cfg.get('CONFIG_DT', 0) == 1 if kconfig.get('CONFIG_DT', 'n') == 'y'
subdir('dt') subdir('dt')
endif endif
module_lds = meson.current_source_dir() / 'module.ld'
+101
View File
@@ -0,0 +1,101 @@
/* Linker script for kernel modules */
ENTRY(__module_start)
PHDRS
{
text PT_LOAD FLAGS(5);
rodata PT_LOAD FLAGS(4);
data PT_LOAD FLAGS(6);
dynamic PT_DYNAMIC FLAGS(6);
modversion 0x60000001;
modauthor 0x60000002;
moddesc 0x60000003;
modlicense 0x60000004;
modcmdline 0x60000005;
}
SECTIONS
{
. = ALIGN(CONSTANT(MAXPAGESIZE));
/* Code */
.text : {
*(.init .init.*)
*(.text .text.*)
*(.fini .fini.*)
*(.plt .plt.*)
} :text
. = ALIGN(CONSTANT(MAXPAGESIZE));
/* Read-only data */
.rodata : {
*(.rodata .rodata.*)
*(.hash .hash.*)
*(.got .got.*)
*(.got.plt .got.plt.*)
} :rodata
.cmdline : {
KEEP(*(.cmdline))
} :rodata :modcmdline
.mod.version : {
KEEP(*(.mod.version))
} :rodata :modversion
.mod.author : {
KEEP(*(.mod.author))
} :rodata :modauthor
.mod.desc : {
KEEP(*(.mod.desc))
} :rodata :moddesc
.mod.license : {
KEEP(*(.mod.license))
} :rodata :modlicense
. = ALIGN(CONSTANT(MAXPAGESIZE));
/* Read-Write data */
.data : {
*(.data)
*(.data.*)
} :data
/* Zero-initialized memory */
.bss : {
*(.*bss .*bss.*)
*(COMMON)
} :data
.dynsym : {
*(.dynsym .dynsym.*)
} :data
.dynstr : {
*(.dynstr .dynstr.*)
} :data
.rela.dyn : {
*(.rela.dyn .rela.dyn.*)
} :data
/* Dynamic tags */
.dynamic : {
*(.dynamic)
} :data :dynamic
/DISCARD/ :
{
*(.comment*)
*(.eh_frame*)
*(.rel.eh_frame*)
*(.relr.dyn .relr.dyn.*)
*(.gcc_except_table*)
*(.note*)
*(.interp)
}
}
+7
View File
@@ -0,0 +1,7 @@
menu "PCI bus drivers"
config PCI
bool "PCI core drivers"
default y
endmenu
-1
View File
@@ -2,6 +2,5 @@
#include <zinnia/errno.h> #include <zinnia/errno.h>
#include <stdint.h> #include <stdint.h>
#include <uapi/archctl.h>
errno_t arch_archctl(uintptr_t op, uintptr_t value); errno_t arch_archctl(uintptr_t op, uintptr_t value);
+1 -1
View File
@@ -1,3 +1,3 @@
#pragma once #pragma once
#include <zinnia/elf.h> // TODO: Ensure bits are defining values right.
+2 -13
View File
@@ -57,10 +57,10 @@ struct cmdline_option {
}; };
union { union {
const char** str_limit; const char** str_limit;
struct cmdline_option_limit_int { struct cmdline_limit_int {
intptr_t min, max; intptr_t min, max;
}* intptr_limit; }* intptr_limit;
struct cmdline_option_limit_uint { struct cmdline_limit_uint {
uintptr_t min, max; uintptr_t min, max;
}* uintptr_limit; }* uintptr_limit;
void* limit; void* limit;
@@ -69,14 +69,3 @@ struct cmdline_option {
// Parses the command line and invokes all options. // Parses the command line and invokes all options.
void cmdline_parse(const char* cmdline); void cmdline_parse(const char* cmdline);
static_assert(
0 ==
_Generic(
(cmdline_parse),
void (*)(const char*): CMDLINE_STRING,
void (*)(bool): CMDLINE_BOOL,
void (*)(intptr_t): CMDLINE_INTPTR,
void (*)(uintptr_t): CMDLINE_UINTPTR
)
);
+1
View File
@@ -15,6 +15,7 @@
#define __likely(x) __builtin_expect(!!(x), 1) #define __likely(x) __builtin_expect(!!(x), 1)
#define __unlikely(x) __builtin_expect(!!(x), 0) #define __unlikely(x) __builtin_expect(!!(x), 0)
#define __always_inline gnu::always_inline #define __always_inline gnu::always_inline
#define __visibility gnu::visibility
// Only clang has these hints, GCC will throw a warning here. // Only clang has these hints, GCC will throw a warning here.
// They also don't support the C23 attribute format. // They also don't support the C23 attribute format.
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include <zinnia/module.h>
struct device {
const char* name;
struct module* owner;
};
+4 -2
View File
@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <stddef.h>
#include <stdint.h>
#include <zinnia/compiler.h> #include <zinnia/compiler.h>
#include <zinnia/types.h> #include <zinnia/types.h>
#include <zinnia/utils.h> #include <zinnia/utils.h>
#include <stddef.h>
#include <stdint.h>
#define __init __used, __section(".init.text"), __cold #define __init __used, __section(".init.text"), __cold
#define __initdata __used, __section(".init.data") #define __initdata __used, __section(".init.data")
@@ -28,7 +28,9 @@ struct boot_info {
phys_t rsdp; phys_t rsdp;
}; };
[[__visibility("hidden")]]
extern uint8_t __ld_stack_top[]; extern uint8_t __ld_stack_top[];
[[__visibility("hidden")]]
extern uint8_t __ld_stack_bottom[]; extern uint8_t __ld_stack_bottom[];
extern phys_t rsdp_addr; extern phys_t rsdp_addr;
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include <zinnia/compiler.h>
#include <zinnia/utils.h>
#include <stdint.h>
#define MODULE_PROPERTY(name, data) \
[[__used, __section(".mod." name)]] \
static const char UNIQUE_IDENT(_name)[] = data;
#define MODULE(desc, author, license, version, entry) \
void __module_start(struct module* _module) { \
entry(_module); \
} \
MODULE_PROPERTY("author", author); \
MODULE_PROPERTY("desc", desc); \
MODULE_PROPERTY("version", version); \
MODULE_PROPERTY("license", license);
struct module {
const char* name;
struct module* owner;
};
#define THIS_MODULE (struct module*)nullptr
+19 -1
View File
@@ -9,7 +9,25 @@
ASSERT_TYPE(struct arch_percpu); // bits/percpu.h ASSERT_TYPE(struct arch_percpu); // bits/percpu.h
#define __percpu __used, __section(".percpu") /*
On using per-CPU data
---------------------
Defining variables with `[[__percpu]]` will put them in a special section.
This section is unique for every CPU. To access the correct memory of the
caller's CPU, use `percpu_ref`.
# Example
[[__percpu]]
int my_cpu_data = 0;
int get_foo() {
return *percpu_ref(my_cpu_data);
}
*/
#define __percpu __used, __section(".percpu")
#define percpu_ref(x) ((typeof(&(x)))((void*)percpu_get() + ((void*)&(x) - (void*)&percpu_bsp)))
// CPU-relative information. // CPU-relative information.
struct percpu { struct percpu {
+1 -1
View File
@@ -19,7 +19,7 @@ errno_t vma_new(struct vma** out);
void vma_free(struct vma* v); void vma_free(struct vma* v);
errno_t vma_map( errno_t vma_map(
struct vma* vm, struct vma* vma,
struct vmo* vmo, struct vmo* vmo,
uintptr_t addr, uintptr_t addr,
size_t len, size_t len,
+64 -20
View File
@@ -38,57 +38,58 @@ add_project_arguments(
'-fno-stack-protector', '-fno-stack-protector',
'-ffunction-sections', '-ffunction-sections',
'-fdata-sections', '-fdata-sections',
'-ffreestanding',
'-nostdinc', # We provide our own headers.
'-fno-stack-protector',
language: 'c', language: 'c',
) )
add_project_link_arguments( add_project_link_arguments(
'-ffreestanding',
'-nostdlib',
'-znoexecstack', '-znoexecstack',
'-Wl,--gc-sections', '-Wl,--gc-sections',
'-Wl,--build-id=none', '-Wl,--build-id=none',
language: 'c', language: 'c',
) )
common_includes = include_directories('include') common_includes = [
include_directories('include'),
include_directories('arch' / target_machine.cpu_family() / 'include'),
]
cfg = configuration_data() cfg = configuration_data()
cfg.set_quoted('ZINNIA_VERSION', meson.project_version()) cfg.set_quoted('ZINNIA_VERSION', meson.project_version())
cfg.set_quoted('ZINNIA_ARCH', target_machine.cpu_family()) cfg.set_quoted('ZINNIA_ARCH', target_machine.cpu_family())
cfg.set_quoted('ZINNIA_COMPILER_ID', c_compiler.get_id() + ' ' + c_compiler.version()) cfg.set_quoted('ZINNIA_COMPILER_ID', c_compiler.get_id() + ' ' + c_compiler.version())
cfg.set_quoted('ZINNIA_LINKER_ID', c_compiler.get_linker_id()) cfg.set_quoted('ZINNIA_LINKER_ID', c_compiler.get_linker_id())
#
# Parse kernel config # Parse kernel config
kv = import('keyval') kv = import('keyval')
kconfig = kv.load(get_option('config_path')) kconfig = kv.load(get_option('config_path'))
foreach k, v : kconfig foreach k, v : kconfig
if v == 'y' if v == 'y'
cfg.set10(k, true) cfg.set10(k, true)
elif v == 'n'
cfg.set10(k, false)
else else
cfg.set(k, v) cfg.set(k, v)
endif endif
endforeach endforeach
kernel_c_args = [ kernel_c_args = []
'-ffreestanding',
'-nostdinc', # We provide our own headers.
'-fno-stack-protector',
'-fno-pie',
]
kernel_lds = meson.current_source_dir() / 'boot' / 'kernel.ld' kernel_lds = meson.current_source_dir() / 'boot' / 'kernel.ld'
kernel_link_args = [ kernel_link_args = [
'-ffreestanding',
'-nostdlib',
'-static',
'-lgcc', '-lgcc',
'-static-libgcc',
'-T' + kernel_lds, '-T' + kernel_lds,
'-Wl,--export-dynamic',
] ]
kernel_includes = [ kernel_includes = []
include_directories('arch' / target_machine.cpu_family() / 'include'),
]
kernel_sources = [] kernel_sources = []
modules = {}
# Goes first so we can add arch-specific flags to drivers. # Goes first so we can add arch-specific flags to drivers.
subdir('arch' / target_machine.cpu_family()) subdir('arch' / target_machine.cpu_family())
@@ -104,18 +105,61 @@ configure_file(
output: 'config.h', output: 'config.h',
) )
mod_summary = {}
foreach name, v : modules
is_modular = v.get('modular', false)
mod_sources = v.get('sources')
mod_c_args = v.get('c_args', [])
mod_link_args = v.get('link_args', [])
mod_includes = v.get('include_directories', [])
mod_link = v.get('link_with', [])
if is_modular
shared_library(
name,
sources: mod_sources,
c_args: ['-fPIC', '-fPIE', '-DIN_MODULE', mod_c_args],
link_args: [
'-T' + module_lds, mod_link_args,
],
link_depends: module_lds,
include_directories: [
common_includes,
kernel_includes, # We want this, actually
mod_includes,
],
name_prefix: '',
name_suffix: 'kso',
link_with: mod_link,
override_options: ['b_lundef=false'],
#link_depends: kernel.full_path(),
)
else
kernel_sources += mod_sources
kernel_c_args += mod_c_args
kernel_includes += mod_includes
kernel_link_args += mod_link_args
endif
mod_summary += {name: is_modular}
endforeach
# Kernel
executable( executable(
'zinnia', 'zinnia',
include_directories: [ include_directories: [
common_includes, common_includes,
kernel_includes, kernel_includes,
], ],
c_args: kernel_c_args, c_args: ['-DIN_KERNEL', kernel_c_args],
link_args: kernel_link_args, link_args: kernel_link_args,
link_depends: kernel_lds, link_depends: kernel_lds,
sources: [ sources: kernel_sources,
kernel_sources,
],
install: true, install: true,
install_dir: get_option('datadir') / 'zinnia', install_dir: get_option('datadir') / 'zinnia',
pie: true,
) )
# Print a summary
summary(mod_summary, section: 'Driver configuration')
summary(kconfig, bool_yn: true, section: 'Kernel configuration')
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env python3
# Small script to print all options available inside a built kernel.
# fmt: off
import sys
from elftools.elf.elffile import ELFFile
SIZEOF_PTR = 8
SIZEOF_STRUCT = 40
ENDIAN = "little"
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Provide a path to the kernel binary to use")
sys.exit(1)
with open(sys.argv[1], "rb") as elffile:
file = ELFFile(elffile)
version = "?"
author = "?"
desc = "?"
license = "?"
for segment in file.iter_segments():
match segment["p_type"]:
case 0x60000001: version = segment.data()[:-1].decode()
case 0x60000002: author = segment.data()[:-1].decode()
case 0x60000003: desc = segment.data()[:-1].decode()
case 0x60000004: license = segment.data()[:-1].decode()
print(f"Module info for \"{sys.argv[1]}\"")
print(f"Description:\t{desc}")
print(f"Version:\t{version}")
print(f"Author(s):\t{author}")
print(f"License:\t{license}")