modules
This commit is contained in:
@@ -5,3 +5,4 @@ build/
|
|||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.so
|
*.so
|
||||||
|
__pycache__/
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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 += [
|
kernel_c_args += [
|
||||||
'-mgeneral-regs-only',
|
'-mgeneral-regs-only',
|
||||||
'-mno-red-zone',
|
'-mno-red-zone',
|
||||||
'-mcmodel=kernel',
|
|
||||||
'-masm=intel',
|
'-masm=intel',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-11
@@ -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,9 +19,9 @@ 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"
|
||||||
@@ -28,20 +36,17 @@ bool arch_usercopy_read(void* dst, const __user void* src, size_t len, struct us
|
|||||||
" 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,9 +59,9 @@ 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"
|
||||||
@@ -71,20 +76,17 @@ bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct u
|
|||||||
" 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,7 +102,6 @@ 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"
|
||||||
|
|
||||||
@@ -121,14 +122,12 @@ bool arch_usercopy_strlen(const __user char* str, size_t max, size_t* len, struc
|
|||||||
" 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)
|
||||||
|
|||||||
+8
-6
@@ -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. */
|
||||||
|
|||||||
@@ -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(
|
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
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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('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
@@ -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 <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
@@ -1,3 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <zinnia/elf.h>
|
// TODO: Ensure bits are defining values right.
|
||||||
|
|||||||
@@ -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
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <zinnia/module.h>
|
||||||
|
|
||||||
|
struct device {
|
||||||
|
const char* name;
|
||||||
|
struct module* owner;
|
||||||
|
};
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
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 __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 {
|
||||||
|
|||||||
@@ -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
@@ -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')
|
||||||
|
|||||||
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