modules
This commit is contained in:
@@ -5,3 +5,4 @@ build/
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
__pycache__/
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
mainmenu "Zinnia Kernel Configuration"
|
||||
|
||||
source "dev/Kconfig"
|
||||
|
||||
config KERNEL_FLAVOR
|
||||
string "Kernel flavor name"
|
||||
default "vanilla"
|
||||
|
||||
source "arch/$(ARCH)/Kconfig"
|
||||
source "core/Kconfig"
|
||||
source "dev/Kconfig"
|
||||
|
||||
@@ -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,7 +1,6 @@
|
||||
kernel_c_args += [
|
||||
'-mgeneral-regs-only',
|
||||
'-mno-red-zone',
|
||||
'-mcmodel=kernel',
|
||||
'-masm=intel',
|
||||
]
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <zinnia/percpu.h>
|
||||
#include <zinnia/print.h>
|
||||
#include <config.h>
|
||||
#include <stddef.h>
|
||||
#include <x86_64/apic.h>
|
||||
#include <x86_64/asm.h>
|
||||
@@ -119,7 +120,9 @@ static void setup_cpu(struct percpu* cpu) {
|
||||
|
||||
void arch_percpu_init() {
|
||||
hpet_init();
|
||||
#if CONFIG_TSC
|
||||
tsc_init();
|
||||
#endif
|
||||
|
||||
// Init the BSP.
|
||||
setup_cpu(&percpu_bsp);
|
||||
|
||||
+3
-3
@@ -94,9 +94,9 @@ void task_entry_thunk() {
|
||||
asm volatile(
|
||||
"mov rdi, rbx\n"
|
||||
"mov rsi, r12\n"
|
||||
"jmp %c0"
|
||||
"jmp %0"
|
||||
:
|
||||
: "i"(task_entry)
|
||||
: "r"(task_entry)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
@@ -173,7 +173,7 @@ bool arch_sched_preempt_enable() {
|
||||
void arch_sched_jump_to_context(struct arch_context* context) {
|
||||
asm volatile(
|
||||
"mov rsp, rdi\n"
|
||||
"jmp %c0\n" ::"i"(interrupt_return)
|
||||
"jmp %0\n" ::"r"(interrupt_return)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -11,9 +11,9 @@
|
||||
[[__init, __naked, __used]]
|
||||
void _start() {
|
||||
asm volatile(
|
||||
"lea rsp, [rip + %0]\n"
|
||||
"mov rsp, %0\n"
|
||||
"jmp %1"
|
||||
:
|
||||
: "i"(__ld_stack_top), "r"(kernel_entry)
|
||||
: "r"(__ld_stack_top), "r"(kernel_entry)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ void arch_syscall_stub() {
|
||||
" push r15\n"
|
||||
" xor rbp, rbp\n"
|
||||
" mov rdi, rsp\n" // SysV ABI first argument.
|
||||
" call %c4\n" // Call syscall handler.
|
||||
" call %4\n" // Call syscall handler.
|
||||
" cli\n"
|
||||
" pop r15\n"
|
||||
" pop r14\n"
|
||||
@@ -66,6 +66,6 @@ void arch_syscall_stub() {
|
||||
"i"(offsetof(struct percpu, kernel_stack)), // 1
|
||||
"i"(offsetof(struct gdt, user_code64) | CPL_USER), // 2
|
||||
"i"(offsetof(struct gdt, user_data) | CPL_USER), // 3
|
||||
"i"(syscall_dispatch) // 4
|
||||
"r"(syscall_dispatch) // 4
|
||||
);
|
||||
}
|
||||
|
||||
+52
-53
@@ -1,6 +1,14 @@
|
||||
#include <zinnia/compiler.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_end();
|
||||
extern void x86_64_read_fault();
|
||||
@@ -11,37 +19,34 @@ static const struct usercopy_region read_region = {
|
||||
.fault_ip = x86_64_read_fault,
|
||||
};
|
||||
|
||||
[[__naked]]
|
||||
bool arch_usercopy_read(void* dst, const __user void* src, size_t len, struct usercopy_region** region) {
|
||||
asm volatile(
|
||||
"stac\n"
|
||||
// Setup regs for `rep movsb`.
|
||||
"xchg rcx, rdx\n"
|
||||
"mov rax, [rip + %0]\n"
|
||||
"xchg [rdx], rax\n"
|
||||
" xchg rcx, rdx\n"
|
||||
" mov rax, [rip + %0]\n"
|
||||
" xchg [rdx], rax\n"
|
||||
|
||||
".global x86_64_read_start\n"
|
||||
"x86_64_read_start:\n"
|
||||
"rep movsb\n"
|
||||
" x86_64_read_start:\n"
|
||||
" rep movsb\n"
|
||||
|
||||
".global x86_64_read_end\n"
|
||||
"x86_64_read_end:\n"
|
||||
"xor rax, rax\n"
|
||||
"xchg [rdx], rax\n"
|
||||
"mov rax, 1\n"
|
||||
"clac\n"
|
||||
"ret\n"
|
||||
" xor rax, rax\n"
|
||||
" xchg [rdx], rax\n"
|
||||
" mov rax, 1\n"
|
||||
" ret\n"
|
||||
|
||||
".global x86_64_read_fault\n"
|
||||
"x86_64_read_fault:\n"
|
||||
"xor rax, rax\n"
|
||||
"xchg [rdx], rax\n"
|
||||
"clac\n"
|
||||
"ret\n"
|
||||
" xor rax, rax\n"
|
||||
" xchg [rdx], rax\n"
|
||||
" ret\n"
|
||||
:
|
||||
: "i"(&read_region)
|
||||
: "memory"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
extern void x86_64_write_start();
|
||||
@@ -54,37 +59,34 @@ static const struct usercopy_region write_region = {
|
||||
.fault_ip = x86_64_write_fault,
|
||||
};
|
||||
|
||||
[[__naked]]
|
||||
bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct usercopy_region** region) {
|
||||
asm volatile(
|
||||
"stac\n"
|
||||
// Setup regs for `rep movsb`.
|
||||
"xchg rcx, rdx\n"
|
||||
"mov rax, [rip + %0]\n"
|
||||
"mov [rdx], rax\n"
|
||||
" xchg rcx, rdx\n"
|
||||
" mov rax, [rip + %0]\n"
|
||||
" mov [rdx], rax\n"
|
||||
|
||||
".global x86_64_write_start\n"
|
||||
"x86_64_write_start:\n"
|
||||
"rep movsb\n"
|
||||
" x86_64_write_start:\n"
|
||||
" rep movsb\n"
|
||||
|
||||
".global x86_64_write_end\n"
|
||||
"x86_64_write_end:\n"
|
||||
"xor rax, rax\n"
|
||||
"xchg [rdx], rax\n"
|
||||
"mov rax, 1\n"
|
||||
"clac\n"
|
||||
"ret\n"
|
||||
" x86_64_write_end:\n"
|
||||
" xor rax, rax\n"
|
||||
" xchg [rdx], rax\n"
|
||||
" mov rax, 1\n"
|
||||
" ret\n"
|
||||
|
||||
".global x86_64_write_fault\n"
|
||||
"x86_64_write_fault:\n"
|
||||
"xor rax, rax\n"
|
||||
"xchg [rdx], rax\n"
|
||||
"clac\n"
|
||||
"ret\n"
|
||||
" xor rax, rax\n"
|
||||
" xchg [rdx], rax\n"
|
||||
" ret\n"
|
||||
:
|
||||
: "i"(&write_region)
|
||||
: "memory"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
extern void x86_64_strlen_start();
|
||||
@@ -100,36 +102,33 @@ static const struct usercopy_region strlen_region = {
|
||||
[[__naked]]
|
||||
bool arch_usercopy_strlen(const __user char* str, size_t max, size_t* len, struct usercopy_region** region) {
|
||||
asm volatile(
|
||||
"stac\n"
|
||||
"mov rax, [rip + %0]\n"
|
||||
"xchg [rcx], rax\n"
|
||||
" mov rax, [rip + %0]\n"
|
||||
" xchg [rcx], rax\n"
|
||||
|
||||
".global x86_64_strlen_start\n"
|
||||
"x86_64_strlen_start:\n"
|
||||
"xor r8, r8\n"
|
||||
" x86_64_strlen_start:\n"
|
||||
" xor r8, r8\n"
|
||||
".Lloop:\n"
|
||||
"cmp byte ptr [rdi + r8], 0\n"
|
||||
"je .Lleave\n"
|
||||
"inc r8\n"
|
||||
"cmp rsi, r8\n"
|
||||
"jne .Lloop\n"
|
||||
" cmp byte ptr [rdi + r8], 0\n"
|
||||
" je .Lleave\n"
|
||||
" inc r8\n"
|
||||
" cmp rsi, r8\n"
|
||||
" jne .Lloop\n"
|
||||
".Lleave:\n"
|
||||
"mov [rdx], r8\n"
|
||||
" mov [rdx], r8\n"
|
||||
|
||||
".global x86_64_strlen_end\n"
|
||||
"x86_64_strlen_end:\n"
|
||||
"xor rax, rax\n"
|
||||
"xchg [rcx], rax\n"
|
||||
"mov rax, 1\n"
|
||||
"clac\n"
|
||||
"ret\n"
|
||||
" xor rax, rax\n"
|
||||
" xchg [rcx], rax\n"
|
||||
" mov rax, 1\n"
|
||||
" ret\n"
|
||||
|
||||
".global x86_64_strlen_fault\n"
|
||||
"x86_64_strlen_fault:\n"
|
||||
"xor rax, rax\n"
|
||||
"xchg [rcx], rax\n"
|
||||
"clac\n"
|
||||
"ret\n"
|
||||
" xor rax, rax\n"
|
||||
" xchg [rcx], rax\n"
|
||||
" ret\n"
|
||||
:
|
||||
: "i"(&strlen_region)
|
||||
: "memory"
|
||||
|
||||
+8
-6
@@ -54,27 +54,29 @@ SECTIONS
|
||||
|
||||
.dynsym : {
|
||||
__ld_dynsym_start = .;
|
||||
*(.dynsym)
|
||||
KEEP(*(.dynsym*))
|
||||
__ld_dynsym_end = .;
|
||||
} :data
|
||||
|
||||
.dynstr : {
|
||||
__ld_dynstr_start = .;
|
||||
*(.dynstr)
|
||||
KEEP(*(.dynstr*))
|
||||
__ld_dynstr_end = .;
|
||||
} :data
|
||||
|
||||
.dynamic : {
|
||||
*(.dynamic)
|
||||
*(.dynamic*)
|
||||
} :data :dynamic
|
||||
|
||||
.bss : {
|
||||
.bss ALIGN(CONSTANT(MAXPAGESIZE)) (NOLOAD) : {
|
||||
*(.*bss .*bss.*)
|
||||
*(COMMON)
|
||||
|
||||
/* Small stack to bootstrap the allocator */
|
||||
. = ALIGN(16);
|
||||
__ld_stack_bottom = .;
|
||||
. += 0x2000;
|
||||
__ld_stack_top = .;
|
||||
*(.*bss .*bss.*)
|
||||
*(COMMON)
|
||||
} :data
|
||||
|
||||
/* Per-CPU data block. MUST always come last. */
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
menu "Memory Management options"
|
||||
|
||||
config HAVE_MMU
|
||||
bool
|
||||
config HAVE_MMU_GENERIC
|
||||
bool
|
||||
|
||||
endmenu
|
||||
@@ -1,7 +1,6 @@
|
||||
kernel_sources += files(
|
||||
'fault.c',
|
||||
'init.c',
|
||||
'pmap.c',
|
||||
'pmm.c',
|
||||
'slab.c',
|
||||
'usercopy.c',
|
||||
@@ -9,3 +8,9 @@ kernel_sources += files(
|
||||
'vma.c',
|
||||
'vmo.c',
|
||||
)
|
||||
|
||||
if kconfig.get('CONFIG_HAVE_MMU', 'n') == 'y'
|
||||
kernel_sources += files(
|
||||
'pmap.c',
|
||||
)
|
||||
endif
|
||||
|
||||
@@ -3,8 +3,12 @@
|
||||
#include <zinnia/pmap.h>
|
||||
#include <zinnia/spin.h>
|
||||
#include <zinnia/vma.h>
|
||||
#include <config.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) {
|
||||
flags &= ~ALLOC_NOZERO;
|
||||
|
||||
|
||||
+12
-3
@@ -3,13 +3,22 @@
|
||||
#include <arch/usercopy.h>
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
kernel_sources += files(
|
||||
'core.c',
|
||||
'sched_dumb.c',
|
||||
)
|
||||
|
||||
if kconfig.get('CONFIG_SCHED_DUMB', 'n') == 'y'
|
||||
kernel_sources += files('sched_dumb.c')
|
||||
endif
|
||||
|
||||
@@ -12,4 +12,7 @@ config ACPI
|
||||
help
|
||||
Adds support for ACPI firmware, tables and devices.
|
||||
|
||||
source "dev/block/Kconfig"
|
||||
source "dev/pci/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
menu "Block device drivers"
|
||||
|
||||
source "dev/block/nvme/Kconfig"
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,3 @@
|
||||
if kconfig.get('CONFIG_NVME_CORE', 'n') != 'n'
|
||||
subdir('nvme')
|
||||
endif
|
||||
@@ -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
|
||||
@@ -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);
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
+5
-2
@@ -1,9 +1,12 @@
|
||||
subdir('common')
|
||||
subdir('block')
|
||||
|
||||
if cfg.get('CONFIG_ACPI', 0) == 1
|
||||
if kconfig.get('CONFIG_ACPI', 'n') == 'y'
|
||||
subdir('acpi')
|
||||
endif
|
||||
|
||||
if cfg.get('CONFIG_DT', 0) == 1
|
||||
if kconfig.get('CONFIG_DT', 'n') == 'y'
|
||||
subdir('dt')
|
||||
endif
|
||||
|
||||
module_lds = meson.current_source_dir() / 'module.ld'
|
||||
|
||||
+101
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
menu "PCI bus drivers"
|
||||
|
||||
config PCI
|
||||
bool "PCI core drivers"
|
||||
default y
|
||||
|
||||
endmenu
|
||||
@@ -2,6 +2,5 @@
|
||||
|
||||
#include <zinnia/errno.h>
|
||||
#include <stdint.h>
|
||||
#include <uapi/archctl.h>
|
||||
|
||||
errno_t arch_archctl(uintptr_t op, uintptr_t value);
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/elf.h>
|
||||
// TODO: Ensure bits are defining values right.
|
||||
|
||||
@@ -57,10 +57,10 @@ struct cmdline_option {
|
||||
};
|
||||
union {
|
||||
const char** str_limit;
|
||||
struct cmdline_option_limit_int {
|
||||
struct cmdline_limit_int {
|
||||
intptr_t min, max;
|
||||
}* intptr_limit;
|
||||
struct cmdline_option_limit_uint {
|
||||
struct cmdline_limit_uint {
|
||||
uintptr_t min, max;
|
||||
}* uintptr_limit;
|
||||
void* limit;
|
||||
@@ -69,14 +69,3 @@ struct cmdline_option {
|
||||
|
||||
// Parses the command line and invokes all options.
|
||||
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
|
||||
)
|
||||
);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#define __likely(x) __builtin_expect(!!(x), 1)
|
||||
#define __unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define __always_inline gnu::always_inline
|
||||
#define __visibility gnu::visibility
|
||||
|
||||
// Only clang has these hints, GCC will throw a warning here.
|
||||
// They also don't support the C23 attribute format.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <zinnia/module.h>
|
||||
|
||||
struct device {
|
||||
const char* name;
|
||||
struct module* owner;
|
||||
};
|
||||
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <zinnia/compiler.h>
|
||||
#include <zinnia/types.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define __init __used, __section(".init.text"), __cold
|
||||
#define __initdata __used, __section(".init.data")
|
||||
@@ -28,7 +28,9 @@ struct boot_info {
|
||||
phys_t rsdp;
|
||||
};
|
||||
|
||||
[[__visibility("hidden")]]
|
||||
extern uint8_t __ld_stack_top[];
|
||||
[[__visibility("hidden")]]
|
||||
extern uint8_t __ld_stack_bottom[];
|
||||
|
||||
extern phys_t rsdp_addr;
|
||||
|
||||
@@ -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
|
||||
@@ -9,7 +9,25 @@
|
||||
|
||||
ASSERT_TYPE(struct arch_percpu); // bits/percpu.h
|
||||
|
||||
/*
|
||||
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.
|
||||
struct percpu {
|
||||
|
||||
@@ -19,7 +19,7 @@ errno_t vma_new(struct vma** out);
|
||||
void vma_free(struct vma* v);
|
||||
|
||||
errno_t vma_map(
|
||||
struct vma* vm,
|
||||
struct vma* vma,
|
||||
struct vmo* vmo,
|
||||
uintptr_t addr,
|
||||
size_t len,
|
||||
|
||||
+64
-20
@@ -38,57 +38,58 @@ add_project_arguments(
|
||||
'-fno-stack-protector',
|
||||
'-ffunction-sections',
|
||||
'-fdata-sections',
|
||||
'-ffreestanding',
|
||||
'-nostdinc', # We provide our own headers.
|
||||
'-fno-stack-protector',
|
||||
language: 'c',
|
||||
)
|
||||
|
||||
add_project_link_arguments(
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-znoexecstack',
|
||||
'-Wl,--gc-sections',
|
||||
'-Wl,--build-id=none',
|
||||
language: 'c',
|
||||
)
|
||||
|
||||
common_includes = include_directories('include')
|
||||
common_includes = [
|
||||
include_directories('include'),
|
||||
include_directories('arch' / target_machine.cpu_family() / 'include'),
|
||||
]
|
||||
|
||||
cfg = configuration_data()
|
||||
cfg.set_quoted('ZINNIA_VERSION', meson.project_version())
|
||||
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_LINKER_ID', c_compiler.get_linker_id())
|
||||
|
||||
#
|
||||
# Parse kernel config
|
||||
kv = import('keyval')
|
||||
kconfig = kv.load(get_option('config_path'))
|
||||
foreach k, v : kconfig
|
||||
if v == 'y'
|
||||
cfg.set10(k, true)
|
||||
elif v == 'n'
|
||||
cfg.set10(k, false)
|
||||
else
|
||||
cfg.set(k, v)
|
||||
endif
|
||||
endforeach
|
||||
|
||||
kernel_c_args = [
|
||||
'-ffreestanding',
|
||||
'-nostdinc', # We provide our own headers.
|
||||
'-fno-stack-protector',
|
||||
'-fno-pie',
|
||||
]
|
||||
kernel_c_args = []
|
||||
|
||||
kernel_lds = meson.current_source_dir() / 'boot' / 'kernel.ld'
|
||||
|
||||
kernel_link_args = [
|
||||
'-ffreestanding',
|
||||
'-nostdlib',
|
||||
'-static',
|
||||
'-lgcc',
|
||||
'-static-libgcc',
|
||||
'-T' + kernel_lds,
|
||||
'-Wl,--export-dynamic',
|
||||
]
|
||||
|
||||
kernel_includes = [
|
||||
include_directories('arch' / target_machine.cpu_family() / 'include'),
|
||||
]
|
||||
|
||||
kernel_includes = []
|
||||
kernel_sources = []
|
||||
modules = {}
|
||||
|
||||
# Goes first so we can add arch-specific flags to drivers.
|
||||
subdir('arch' / target_machine.cpu_family())
|
||||
@@ -104,18 +105,61 @@ configure_file(
|
||||
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(
|
||||
'zinnia',
|
||||
include_directories: [
|
||||
common_includes,
|
||||
kernel_includes,
|
||||
],
|
||||
c_args: kernel_c_args,
|
||||
c_args: ['-DIN_KERNEL', kernel_c_args],
|
||||
link_args: kernel_link_args,
|
||||
link_depends: kernel_lds,
|
||||
sources: [
|
||||
kernel_sources,
|
||||
],
|
||||
sources: kernel_sources,
|
||||
install: true,
|
||||
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')
|
||||
|
||||
Executable
+37
@@ -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}")
|
||||
Reference in New Issue
Block a user