diff --git a/Makefile b/Makefile index 4cdc89b..39e23f9 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ include arch/$(SOCKS_ARCH)/config.mk # Platform-independent kernel source files #################################### -KERNEL_SRC_DIRS := init kernel vm ds util obj +KERNEL_SRC_DIRS := init kernel vm ds util obj test KERNEL_C_FILES := $(foreach dir,$(KERNEL_SRC_DIRS),$(wildcard $(dir)/*.c)) KERNEL_OBJ := $(addprefix $(BUILD_DIR)/,$(KERNEL_C_FILES:.c=.o)) @@ -34,10 +34,10 @@ LIBC_OBJ := $(addprefix $(BUILD_DIR)/,$(LIBC_C_FILES:.c=.o)) BUILD_ID := $(shell tools/generate_build_id.py --arch $(SOCKS_ARCH)) CFLAGS := $(CFLAGS) -DBUILD_ID=\"$(BUILD_ID)\" -g -Wall -Werror -pedantic \ - -Iinclude -Iarch/$(SOCKS_ARCH)/include -Ilibc/include -Os + -Iinclude -Iarch/$(SOCKS_ARCH)/include -Ilibc/include ASMFLAGS := $(ASMFLAGS) -DBUILD_ID=\"$(BUILD_ID)\" -LDFLAGS := $(LDFLAGS) -g -Os +LDFLAGS := $(LDFLAGS) -g ALL_KERNEL_OBJECT_FILES := $(KERNEL_OBJ) $(ARCH_OBJ) $(LIBC_OBJ) ALL_KERNEL_DEPS := $(ALL_KERNEL_OBJECT_FILES:.o=.d) diff --git a/arch/user/extra.mk b/arch/user/extra.mk index 3f37719..c6b4581 100644 --- a/arch/user/extra.mk +++ b/arch/user/extra.mk @@ -3,11 +3,11 @@ run: $(BUILD_DIR)/$(KERNEL_EXEC) @$(BUILD_DIR)/$(KERNEL_EXEC) -debug: $(BUILD_DIR)/$(KERNEL_EXEC) +debug: $(BUILD_DIR)/$(KERNEL_EXEC) $(BUILD_DIR)/$(KERNEL_EXEC).dbg @if command -v gdb &> /dev/null; then \ - gdb -tui $(BUILD_DIR)/$(KERNEL_EXEC) \ - elif commad -v lldb &> /dev/null; then \ - lldb -- $(BUILD_DIR)/$(KERNEL_EXEC) \ + gdb -tui $(BUILD_DIR)/$(KERNEL_EXEC).dbg; \ + elif command -v lldb &> /dev/null; then \ + lldb -- $(BUILD_DIR)/$(KERNEL_EXEC).dbg; \ else \ - printf "No debuggers available." \ - endif + printf "No debuggers available.\n"; \ + fi diff --git a/arch/user/include/socks/machine/init.h b/arch/user/include/socks/machine/init.h index 6c594e6..f5c94f3 100644 --- a/arch/user/include/socks/machine/init.h +++ b/arch/user/include/socks/machine/init.h @@ -3,6 +3,19 @@ #include +#define __X2(x) #x +#define __X(x) __X2(x) + +#ifdef __APPLE__ +#define __define_initcall(fn, id) \ + static initcall_t __initcall_##fn##id __used \ + __section("__DATA,__initcall" __X(id) ".init") = (fn) +#else +#define __define_initcall(fn, id) \ + static initcall_t __initcall_##fn##id __used \ + __section("initcall" __X(id) "_init") = (fn) +#endif + extern int ml_init(uintptr_t arg); #endif diff --git a/arch/user/init.c b/arch/user/init.c index 6436daa..a35da3b 100644 --- a/arch/user/init.c +++ b/arch/user/init.c @@ -9,7 +9,7 @@ #include #include -#define PMEM_SIZE 0x2000000 +#define PMEM_SIZE 0x4000000 extern void kernel_init(uintptr_t arg); @@ -56,6 +56,7 @@ int ml_init(uintptr_t arg) vm_bootstrap(vm_zones, sizeof vm_zones / sizeof vm_zones[0]); object_bootstrap(); + return 0; } diff --git a/arch/user/initcall.c b/arch/user/initcall.c new file mode 100644 index 0000000..ef4f5a9 --- /dev/null +++ b/arch/user/initcall.c @@ -0,0 +1,96 @@ +#include + +#ifdef __APPLE__ +extern char __start_initcall0[] __asm("section$start$__DATA$__initcall0.init"); +extern char __stop_initcall0[] __asm("section$end$__DATA$__initcall0.init"); +extern char __start_initcall1[] __asm("section$start$__DATA$__initcall1.init"); +extern char __stop_initcall1[] __asm("section$end$__DATA$__initcall1.init"); +extern char __start_initcall2[] __asm("section$start$__DATA$__initcall2.init"); +extern char __stop_initcall2[] __asm("section$end$__DATA$__initcall2.init"); +extern char __start_initcall3[] __asm("section$start$__DATA$__initcall3.init"); +extern char __stop_initcall3[] __asm("section$end$__DATA$__initcall3.init"); +extern char __start_initcall4[] __asm("section$start$__DATA$__initcall4.init"); +extern char __stop_initcall4[] __asm("section$end$__DATA$__initcall4.init"); +extern char __start_initcall5[] __asm("section$start$__DATA$__initcall5.init"); +extern char __stop_initcall5[] __asm("section$end$__DATA$__initcall5.init"); +extern char __start_initcall6[] __asm("section$start$__DATA$__initcall6.init"); +extern char __stop_initcall6[] __asm("section$end$__DATA$__initcall6.init"); +extern char __start_initcall7[] __asm("section$start$__DATA$__initcall7.init"); +extern char __stop_initcall7[] __asm("section$end$__DATA$__initcall7.init"); +extern char __start_initcall8[] __asm("section$start$__DATA$__initcall8.init"); +extern char __stop_initcall8[] __asm("section$end$__DATA$__initcall8.init"); +#else +extern char __start_initcall0_init[]; +extern char __stop_initcall0_init[]; +extern char __start_initcall1_init[]; +extern char __stop_initcall1_init[]; +extern char __start_initcall2_init[]; +extern char __stop_initcall2_init[]; +extern char __start_initcall3_init[]; +extern char __stop_initcall3_init[]; +extern char __start_initcall4_init[]; +extern char __stop_initcall4_init[]; +extern char __start_initcall5_init[]; +extern char __stop_initcall5_init[]; +extern char __start_initcall6_init[]; +extern char __stop_initcall6_init[]; +extern char __start_initcall7_init[]; +extern char __stop_initcall7_init[]; +extern char __start_initcall8_init[]; +extern char __stop_initcall8_init[]; +#endif + +static initcall_t *initcall_start[] = { + (initcall_t *)__start_initcall0_init, + (initcall_t *)__start_initcall1_init, + (initcall_t *)__start_initcall2_init, + (initcall_t *)__start_initcall3_init, + (initcall_t *)__start_initcall4_init, + (initcall_t *)__start_initcall5_init, + (initcall_t *)__start_initcall6_init, + (initcall_t *)__start_initcall7_init, + (initcall_t *)__start_initcall8_init, +}; + +static initcall_t *initcall_end[] = { + (initcall_t *)__stop_initcall0_init, + (initcall_t *)__stop_initcall1_init, + (initcall_t *)__stop_initcall2_init, + (initcall_t *)__stop_initcall3_init, + (initcall_t *)__stop_initcall4_init, + (initcall_t *)__stop_initcall5_init, + (initcall_t *)__stop_initcall6_init, + (initcall_t *)__stop_initcall7_init, + (initcall_t *)__stop_initcall8_init, +}; + +int start_initlevel(int level) +{ + if (initcall_start[level] == initcall_end[level]) { + return 0; + } + + for (initcall_t *fn = initcall_start[level]; fn < initcall_end[level]; fn++) { + int res = (*fn)(); + + if (res != 0) { + return res; + } + } + + return 0; +} + +/* define a stub initcall for each initlevel to ensure + the corresponding exec section gets created */ +static int stub_initcall(void) { return 0; } + +__define_initcall(stub_initcall, 0); +__define_initcall(stub_initcall, 1); +__define_initcall(stub_initcall, 2); +__define_initcall(stub_initcall, 3); +__define_initcall(stub_initcall, 4); +__define_initcall(stub_initcall, 5); +__define_initcall(stub_initcall, 6); +__define_initcall(stub_initcall, 7); +__define_initcall(stub_initcall, 8); diff --git a/arch/x86_64/include/socks/machine/init.h b/arch/x86_64/include/socks/machine/init.h index 6c594e6..d95555e 100644 --- a/arch/x86_64/include/socks/machine/init.h +++ b/arch/x86_64/include/socks/machine/init.h @@ -3,6 +3,13 @@ #include +#define __X2(x) #x +#define __X(x) __X2(x) + +#define __define_initcall(fn, id) \ + static initcall_t __initcall_##fn##id __used \ + __section(".initcall" __X(id) ".init") = (fn) + extern int ml_init(uintptr_t arg); #endif diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index e40d848..576f228 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86_64/initcall.c b/arch/x86_64/initcall.c new file mode 100644 index 0000000..9a97bea --- /dev/null +++ b/arch/x86_64/initcall.c @@ -0,0 +1,41 @@ +#include + +extern char __initcall0_start[]; +extern char __initcall1_start[]; +extern char __initcall2_start[]; +extern char __initcall3_start[]; +extern char __initcall4_start[]; +extern char __initcall5_start[]; +extern char __initcall6_start[]; +extern char __initcall7_start[]; +extern char __initcall8_start[]; +extern char __initcall_end[]; + +static initcall_t *m_init_func_levels[] = { + (initcall_t *)__initcall0_start, + (initcall_t *)__initcall1_start, + (initcall_t *)__initcall2_start, + (initcall_t *)__initcall3_start, + (initcall_t *)__initcall4_start, + (initcall_t *)__initcall5_start, + (initcall_t *)__initcall6_start, + (initcall_t *)__initcall7_start, + (initcall_t *)__initcall8_start, + (initcall_t *)__initcall_end, +}; + +int start_initlevel(int level) { + if (m_init_func_levels[level] == m_init_func_levels[level + 1]) { + return 0; + } + + for (initcall_t *fn = m_init_func_levels[level]; fn < m_init_func_levels[level + 1]; fn++) { + int res = (*fn)(); + + if (res != 0) { + return res; + } + } + + return 0; +} diff --git a/arch/x86_64/layout.ld b/arch/x86_64/layout.ld index e0bd1d1..85f0c82 100644 --- a/arch/x86_64/layout.ld +++ b/arch/x86_64/layout.ld @@ -31,6 +31,28 @@ SECTIONS { *(.data) } + .initcall ALIGN(4K) : AT(ADDR(.initcall) - KERNEL_VMA) { + __initcall0_start = .; + *(.initcall0.init) + __initcall1_start = .; + *(.initcall1.init) + __initcall2_start = .; + *(.initcall2.init) + __initcall3_start = .; + *(.initcall3.init) + __initcall4_start = .; + *(.initcall4.init) + __initcall5_start = .; + *(.initcall5.init) + __initcall6_start = .; + *(.initcall6.init) + __initcall7_start = .; + *(.initcall7.init) + __initcall8_start = .; + *(.initcall8.init) + __initcall_end = .; + } + .eh_frame ALIGN(4K) : AT(ADDR(.eh_frame) - KERNEL_VMA) { _ehframe = .; diff --git a/include/socks/init.h b/include/socks/init.h index 21d30a0..c9e2e6f 100644 --- a/include/socks/init.h +++ b/include/socks/init.h @@ -2,32 +2,32 @@ #define SOCKS_INIT_H_ #include +#include typedef int (*initcall_t)(void); -#define __INITLEVEL_EARLY 0 -#define __INITLEVEL_CORE 1 -#define __INITLEVEL_POSTCORE 2 -#define __INITLEVEL_ARCH 3 -#define __INITLEVEL_SUBSYS 4 -#define __INITLEVEL_ROOTFS 5 -#define __INITLEVEL_DEVICE 6 -#define __INITLEVEL_LATE 7 +#define INITLEVEL_EARLY 0 +#define INITLEVEL_CORE 1 +#define INITLEVEL_POSTCORE 2 +#define INITLEVEL_ARCH 3 +#define INITLEVEL_SUBSYS 4 +#define INITLEVEL_ROOTFS 5 +#define INITLEVEL_DEVICE 6 +#define INITLEVEL_LATE 7 +#define INITLEVEL_TESTS 8 -#define __define_initcall(fn, id) \ - static initcall_t __initcall_##fn##id __used \ - __section(".initcall" #id ".init") = (fn) - -#define early_initcall(fn) __define_initcall(fn, __INITLEVEL_EARLY) -#define core_initcall(fn) __define_initcall(fn, __INITLEVEL_CORE) -#define postcore_initcall(fn) __define_initcall(fn, __INITLEVEL_POSTCORE) -#define arch_initcall(fn) __define_initcall(fn, __INITLEVEL_ARCH) -#define subsys_initcall(fn) __define_initcall(fn, __INITLEVEL_SUBSYS) -#define rootfs_initcall(fn) __define_initcall(fn, __INITLEVEL_ROOTFS) -#define device_initcall(fn) __define_initcall(fn, __INITLEVEL_DEVICE) -#define late_initcall(fn) __define_initcall(fn, __INITLEVEL_LATE) +#define early_initcall(fn) __define_initcall(fn, INITLEVEL_EARLY) +#define core_initcall(fn) __define_initcall(fn, INITLEVEL_CORE) +#define postcore_initcall(fn) __define_initcall(fn, INITLEVEL_POSTCORE) +#define arch_initcall(fn) __define_initcall(fn, INITLEVEL_ARCH) +#define subsys_initcall(fn) __define_initcall(fn, INITLEVEL_SUBSYS) +#define rootfs_initcall(fn) __define_initcall(fn, INITLEVEL_ROOTFS) +#define device_initcall(fn) __define_initcall(fn, INITLEVEL_DEVICE) +#define late_initcall(fn) __define_initcall(fn, INITLEVEL_LATE) +#define test_initcall(fn) __define_initcall(fn, INITLEVEL_TESTS) extern void print_kernel_banner(void); extern int do_initcalls(void); +extern int start_initlevel(int level); #endif diff --git a/include/socks/test.h b/include/socks/test.h new file mode 100644 index 0000000..7511ba4 --- /dev/null +++ b/include/socks/test.h @@ -0,0 +1,6 @@ +#ifndef SOCKS_TEST_H_ +#define SOCKS_TEST_H_ + +extern int run_all_tests(void); + +#endif diff --git a/init/init.c b/init/init.c index 0074da7..2a4a6b4 100644 --- a/init/init.c +++ b/init/init.c @@ -1,5 +1,6 @@ #include + int do_initcalls(void) { return 0; diff --git a/init/main.c b/init/main.c index d42c187..9aeb11d 100644 --- a/init/main.c +++ b/init/main.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -16,6 +17,8 @@ void print_kernel_banner(void) void kernel_init(uintptr_t arg) { ml_init(arg); + + run_all_tests(); ml_halt_cpu(); } diff --git a/libc/string/strlen.c b/libc/string/strlen.c index ee0685a..49967b6 100644 --- a/libc/string/strlen.c +++ b/libc/string/strlen.c @@ -1,14 +1,10 @@ #include size_t strlen(const char *str) { - if (!str) { - return 0; - } - - size_t res = 0; - while (str[res]) { - res++; - } - - return res; + size_t res = 0; + while (str[res]) { + res++; + } + + return res; } diff --git a/test/obj.c b/test/obj.c new file mode 100644 index 0000000..dd020ad --- /dev/null +++ b/test/obj.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include + +struct test_object { + char name[OBJECT_NAME_MAX]; +}; + +static kern_status_t test_query_name(object_t *obj, char out[OBJECT_NAME_MAX]) +{ + struct test_object *test = object_data(obj); + strncpy(out, test->name, OBJECT_NAME_MAX); + out[OBJECT_NAME_MAX - 1] = 0; + return KERN_OK; +} + +static object_type_t test_type = { + .ob_name = "test", + .ob_size = sizeof(struct test_object), + .ob_ops = { + .query_name = test_query_name, + }, +}; + +static void print_object_tree(object_t *obj, int depth) +{ + char msg[256] = {0}; + int len = 0; + + for (int i = 0; i < depth; i++) { + len += snprintf(msg + len, sizeof msg - len, " "); + } + + char name[OBJECT_NAME_MAX]; + object_query_name(obj, name); + + len += snprintf(msg + len, sizeof msg - len, "%s", name); + printk(msg); + + object_t *child = NULL; + size_t i = 0; + + while (1) { + kern_status_t status = object_get_child_at(obj, i, &child); + if (status != KERN_OK) { + break; + } + + print_object_tree(child, depth + 1); + i++; + } +} + +static int run_obj_tests(void) +{ + object_type_register(&test_type); + + object_t *test_obj = object_create(&test_type); + struct test_object *test = object_data(test_obj); + snprintf(test->name, sizeof test->name, "object1"); + kern_status_t status = object_publish(global_namespace(), "/misc/objects", test_obj); + if (status == KERN_OK) { + printk("published object at /misc/objects/object1"); + } else { + printk("publish failed"); + return -1; + } + + if (object_publish(global_namespace(), "/misc/objects/object1", test_obj) == KERN_OK) { + printk("second publish succeeded but shouldn't have"); + return -1; + } + + print_object_tree(object_header(global_namespace()), 0); + return 0; +} + +test_initcall(run_obj_tests); diff --git a/test/test.c b/test/test.c new file mode 100644 index 0000000..a42817f --- /dev/null +++ b/test/test.c @@ -0,0 +1,8 @@ +#include +#include + +int run_all_tests(void) +{ + printk("############ RUNNING KERNEL TESTS ############"); + return start_initlevel(INITLEVEL_TESTS); +}