From 41cc7fea778a5cf75ce681030d6e001b448aae5c Mon Sep 17 00:00:00 2001 From: Marvin Friedrich Date: Sun, 11 Oct 2026 17:43:21 +0200 Subject: [PATCH] oops --- boot/limine/entry.c | 40 ++++++++++++++--- boot/main.c | 12 +++-- core/lib/string.c | 93 +++++++++++++++------------------------ core/mem/init.c | 12 +++-- core/mem/vmo.c | 2 +- fs/vfs/init.c | 3 ++ fs/vfs/meson.build | 1 + include/zinnia/compiler.h | 3 +- include/zinnia/dpc.h | 2 +- include/zinnia/file.h | 3 -- include/zinnia/init.h | 14 +++++- include/zinnia/iovec.h | 6 ++- include/zinnia/module.h | 10 +++++ include/zinnia/percpu.h | 7 +-- meson.build | 1 + 15 files changed, 125 insertions(+), 84 deletions(-) create mode 100644 fs/vfs/init.c delete mode 100644 include/zinnia/file.h diff --git a/boot/limine/entry.c b/boot/limine/entry.c index 804979e..d9081e5 100644 --- a/boot/limine/entry.c +++ b/boot/limine/entry.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -41,10 +42,15 @@ void kernel_entry() { struct boot_info info = {}; - struct limine_memmap_response* mm_res = memmap_request.response; - struct limine_module_response* module_res = module_request.response; - struct limine_executable_address_response* exec_res = executable_address_request.response; - struct limine_executable_file_response* exec_file_res = executable_file_request.response; + const struct limine_memmap_response* mm_res = memmap_request.response; + const struct limine_hhdm_response* hhdm_res = hhdm_request.response; + const struct limine_module_response* module_res = module_request.response; + const struct limine_executable_address_response* exec_res = executable_address_request.response; + const struct limine_executable_file_response* exec_file_res = executable_file_request.response; + const struct limine_rsdp_response* rsdp_res = rsdp_request.response; + + assert(mm_res, "memmap_request returned no response!"); + assert(hhdm_res, "hhdm_request returned no response!"); info.cmdline = exec_file_res->executable_file->string; @@ -74,7 +80,7 @@ void kernel_entry() { info.files = files; info.num_files = MIN(ARRAY_SIZE(files), module_res->module_count); for (size_t i = 0; i < info.num_files; i++) { - files[i].data = (phys_t)module_res->modules[i]->address - hhdm_request.response->offset; + files[i].data = (phys_t)module_res->modules[i]->address - hhdm_res->offset; files[i].length = module_res->modules[i]->size; strncpy(files[i].path, module_res->modules[i]->path, sizeof(files[i].path) - 1); files[i].path[sizeof(files[i].path) - 1] = 0; @@ -84,7 +90,29 @@ void kernel_entry() { info.mem_map = mem; info.phys_base = (phys_t)exec_res->physical_base; info.virt_base = (uintptr_t)exec_res->virtual_base; - info.hhdm_base = (uintptr_t)hhdm_request.response->offset; + info.hhdm_base = (uintptr_t)hhdm_res->offset; + + const struct limine_framebuffer_response* fb_res = framebuffer_request.response; + if (fb_res) { + // Only use the first framebuffer. + if (fb_res->framebuffer_count >= 1) { + const struct limine_framebuffer* fb = framebuffer_request.response->framebuffers[0]; + info.fb.base = (phys_t)((uintptr_t)fb->address - hhdm_res->offset); + info.fb.width = fb->width; + info.fb.height = fb->height; + info.fb.pitch = fb->pitch; + info.fb.bytes_per_pixel = fb->bpp / 8; + + info.fb.red.shift = fb->red_mask_shift; + info.fb.red.size = fb->red_mask_size; + + info.fb.green.shift = fb->green_mask_shift; + info.fb.green.size = fb->green_mask_size; + + info.fb.blue.shift = fb->blue_mask_shift; + info.fb.blue.size = fb->blue_mask_size; + } + } #if CONFIG_ACPI if (rsdp_request.response) { diff --git a/boot/main.c b/boot/main.c index 5dc0154..6b779ff 100644 --- a/boot/main.c +++ b/boot/main.c @@ -25,6 +25,7 @@ static const char zinnia_banner[] = "Zinnia " ZINNIA_VERSION " " CONFIG_KERNEL_F ", " ZINNIA_COMPILER_ID ", " ZINNIA_LINKER_ID ")"; static void kernel_main_task(uintptr_t arg0) { + errno_t status = 0; struct boot_info* info = (struct boot_info*)arg0; log("main: Hello from main task!\n"); @@ -38,8 +39,12 @@ static void kernel_main_task(uintptr_t arg0) { assert(vma_new(&init_space) == EOK, ""); struct boot_file* file_data = &info->files[0]; + struct task* init_task = nullptr; + struct paged_vmo* init_file; - assert(vmo_new_phys(&init_file) == EOK, ""); + status = vmo_new_phys(&init_file); + assert(status == EOK, "Failed to allocate a memory object"); + vmo_write(&init_file->object, 0, HHDM_PTR(file_data->data), file_data->length, nullptr); // Load init. @@ -53,11 +58,10 @@ static void kernel_main_task(uintptr_t arg0) { .envp = init_envp, }; - struct task* init_task = nullptr; - errno_t status = elf_load(&exec, &init_task); + status = elf_load(&exec, &init_task); vmo_unref(&init_file->object); - assert(status == 0, "Failed to load init process (%i)\n", status); + assert(status == 0, "Failed to load init process (%i)", status); sched_add_task(&percpu_get()->sched, init_task); while (true) { diff --git a/core/lib/string.c b/core/lib/string.c index 3539d62..9fbfef6 100644 --- a/core/lib/string.c +++ b/core/lib/string.c @@ -1,8 +1,8 @@ #include +#include #include #include #include -#include [[__hot]] size_t strlen(const char* str) { @@ -29,45 +29,37 @@ int memcmp(const void* s1, const void* s2, size_t size) { for (size_t i = 0; i < size; i++) { if (s1ptr[i] != s2ptr[i]) - return s1ptr[i] - s2ptr[i]; + return (int)s1ptr[i] - (int)s2ptr[i]; } return 0; } +typedef size_t word_t [[__may_alias]] +; + [[__hot]] void* memcpy(void* restrict dest, const void* restrict src, size_t n) { - if (__unlikely(n == 0)) - return dest; + uint8_t* d = dest; + const uint8_t* s = src; - size_t d = (size_t)dest; - size_t s = (size_t)src; - - if (d % sizeof(size_t) != 0 || s % sizeof(size_t) != 0) { - while (n && (d % sizeof(size_t) != 0) && (s % sizeof(size_t) != 0)) { - *((uint8_t*)d) = *((uint8_t*)s); - d++; - s++; + // Word copies are only possible if both pointers can be aligned at the same time. + if (((uintptr_t)d - (uintptr_t)s) % sizeof(word_t) == 0) { + while (n && (uintptr_t)d % sizeof(word_t) != 0) { + *d++ = *s++; n--; } + + word_t* word_dest = (word_t*)d; + const word_t* word_src = (const word_t*)s; + for (; n >= sizeof(word_t); n -= sizeof(word_t)) + *word_dest++ = *word_src++; + + d = (uint8_t*)word_dest; + s = (const uint8_t*)word_src; } - size_t* qword_dest = (size_t*)d; - const size_t* qword_src = (const size_t*)s; - const size_t word_count = n / sizeof(size_t); - - for (size_t i = 0; i < word_count; i++) { - qword_dest[i] = qword_src[i]; - } - - size_t remaining_bytes = n % sizeof(size_t); - d = (size_t)(qword_dest + word_count); - s = (size_t)(qword_src + word_count); - - while (remaining_bytes--) { - *((uint8_t*)d) = *((uint8_t*)s); - d++; - s++; - } + while (n--) + *d++ = *s++; return dest; } @@ -76,7 +68,8 @@ void* memcpy(void* restrict dest, const void* restrict src, size_t n) { void* memmove(void* dstptr, const void* srcptr, size_t size) { uint8_t* dst = (uint8_t*)dstptr; const uint8_t* src = (const uint8_t*)srcptr; - if (dst < src) { + + if ((uintptr_t)dst < (uintptr_t)src) { for (size_t i = 0; i < size; i++) dst[i] = src[i]; } else { @@ -88,38 +81,22 @@ void* memmove(void* dstptr, const void* srcptr, size_t size) { [[__hot]] void* memset(void* dest, int value, size_t n) { - if (__unlikely(n == 0)) - return dest; + uint8_t* d = dest; + const uint8_t byte = (uint8_t)value; - size_t d = (size_t)dest; - - if (d % sizeof(size_t) != 0) { - while (n && (d % sizeof(size_t) != 0)) { - *((uint8_t*)d) = value; - d++; - n--; - } + while (n && (uintptr_t)d % sizeof(word_t) != 0) { + *d++ = byte; + n--; } - size_t* qword_dest = (size_t*)d; - size_t qword_value = (uint8_t)value; - qword_value |= (qword_value << 8); - qword_value |= (qword_value << 16); - qword_value |= (qword_value << 32); + const word_t word_value = (SIZE_MAX / 0xFF) * byte; + word_t* word_dest = (word_t*)d; + for (; n >= sizeof(word_t); n -= sizeof(word_t)) + *word_dest++ = word_value; - const size_t word_count = n / sizeof(size_t); - - for (size_t i = 0; i < word_count; i++) { - qword_dest[i] = qword_value; - } - - size_t remaining_bytes = n % sizeof(size_t); - d = (size_t)(qword_dest + word_count); - - while (remaining_bytes--) { - *((uint8_t*)d) = value; - d++; - } + d = (uint8_t*)word_dest; + while (n--) + *d++ = byte; return dest; } diff --git a/core/mem/init.c b/core/mem/init.c index 156b9ef..deccb0e 100644 --- a/core/mem/init.c +++ b/core/mem/init.c @@ -3,9 +3,9 @@ #include #include #include +#include #include #include -#include extern uint8_t __ld_text_start[]; extern uint8_t __ld_text_end[]; @@ -48,11 +48,12 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_ } // Set up the bootstrap allocator. - struct phys_mem* largest = map; + struct phys_mem* largest = nullptr; for (size_t i = 0; i < map_len; i++) { - if (map[i].length > largest->length && map[i].usage == PHYS_USABLE) + if (map[i].usage == PHYS_USABLE && (!largest || map[i].length > largest->length)) largest = &map[i]; } + assert(largest && largest->length >= pgsz, "No usable memory for bootstrap allocator"); mem_phys_bootstrap(largest); log("mem: Using region [%p - %p] for bootstrap allocator\n", (void*)largest->address, @@ -150,7 +151,10 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_ for (size_t page = 0; page < length; page += pgsz) { phys_t paddr; assert(!mem_phys_alloc(1, 0, &paddr), "Failed to allocate memory for PFNDB!\n"); - pmap_map(&kernel_vma.pmap, vaddr + page, paddr, PTE_READ | PTE_WRITE, CACHE_ANY); + assert( + !pmap_map(&kernel_vma.pmap, vaddr + page, paddr, PTE_READ | PTE_WRITE, CACHE_ANY), + "Failed to map PFNDB memory" + ); } } vm_pfndb = (struct page*)arch_mem_pfndb_addr(); diff --git a/core/mem/vmo.c b/core/mem/vmo.c index 5cc4be0..f36a1e3 100644 --- a/core/mem/vmo.c +++ b/core/mem/vmo.c @@ -213,7 +213,7 @@ errno_t vmo_new_phys(struct paged_vmo** out) { void vmo_truncate_paged(struct paged_vmo* paged, size_t length) { const size_t page_size = arch_mem_page_size(); - const size_t keep_pages = ROUND_UP(length, page_size) / page_size; + const size_t keep_pages = ROUND_UP(length, page_size); spin_lock(&paged->lock); struct page_list** pp = &list_first(&paged->cache); diff --git a/fs/vfs/init.c b/fs/vfs/init.c new file mode 100644 index 0000000..ed9caf7 --- /dev/null +++ b/fs/vfs/init.c @@ -0,0 +1,3 @@ +#include + +void vfs_init() {} diff --git a/fs/vfs/meson.build b/fs/vfs/meson.build index 9d4787d..8731070 100644 --- a/fs/vfs/meson.build +++ b/fs/vfs/meson.build @@ -1,3 +1,4 @@ kernel_sources += files( 'ident.c', + 'init.c', ) diff --git a/include/zinnia/compiler.h b/include/zinnia/compiler.h index f325788..c3ea2c0 100644 --- a/include/zinnia/compiler.h +++ b/include/zinnia/compiler.h @@ -4,6 +4,7 @@ #define __section(x) gnu::section(x) #define __aligned(x) gnu::aligned(x) #define __packed gnu::packed +#define __may_alias gnu::may_alias #define __naked gnu::naked // These hints may improve code generation. @@ -12,7 +13,7 @@ #define __used gnu::used #define __unused gnu::unused #define __format(like, ...) gnu::format(like, __VA_ARGS__) -#define __always_inline gnu::always_inline +#define __force_inline gnu::always_inline #define __visibility gnu::visibility #define __pure gnu::pure diff --git a/include/zinnia/dpc.h b/include/zinnia/dpc.h index d0620fc..c9e95cd 100644 --- a/include/zinnia/dpc.h +++ b/include/zinnia/dpc.h @@ -5,7 +5,7 @@ #include struct dpc { - void (*const callback)(struct dpc* dpc, void* data); + void (*callback)(struct dpc* dpc, void* data); void* data; atomic_bool inserted; diff --git a/include/zinnia/file.h b/include/zinnia/file.h deleted file mode 100644 index 5c9fb0a..0000000 --- a/include/zinnia/file.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -struct file_desc {}; diff --git a/include/zinnia/init.h b/include/zinnia/init.h index d011dca..bc0b2fa 100644 --- a/include/zinnia/init.h +++ b/include/zinnia/init.h @@ -17,6 +17,17 @@ struct boot_file { char path[128]; }; +struct boot_color { + uint8_t shift, size; +}; + +struct boot_framebuffer { + phys_t base; + size_t width, height, pitch; + uint8_t bytes_per_pixel; + struct boot_color red, green, blue; +}; + struct boot_info { char* cmdline; struct phys_mem* mem_map; @@ -26,8 +37,9 @@ struct boot_info { uintptr_t hhdm_base; struct boot_file* files; size_t num_files; - + struct boot_framebuffer fb; void* dtb; + size_t dtb_size; #if CONFIG_ACPI phys_t rsdp; #endif diff --git a/include/zinnia/iovec.h b/include/zinnia/iovec.h index fea7e4a..a135b4a 100644 --- a/include/zinnia/iovec.h +++ b/include/zinnia/iovec.h @@ -7,8 +7,10 @@ #include #include +typedef struct __iovec iovec_t; + struct iovec_iter { - struct __iovec* iovecs; + iovec_t* iovecs; size_t iovecs_len; size_t total_len; size_t total_offset; @@ -21,7 +23,7 @@ static inline size_t iovec_iter_len(struct iovec_iter* iter) { } // Creates an iovec iterator over kernel memory. -static inline struct iovec_iter iovec_iter_kernel(struct __iovec* iovecs, size_t count) { +static inline struct iovec_iter iovec_iter_kernel(iovec_t* iovecs, size_t count) { size_t total = 0; for (size_t i = 0; i < count; i++) total += iovecs[i].len; diff --git a/include/zinnia/module.h b/include/zinnia/module.h index 8998ee9..3b2701d 100644 --- a/include/zinnia/module.h +++ b/include/zinnia/module.h @@ -13,6 +13,7 @@ #define MODULE_VERSION(version) MODULE_PROPERTY("version", version) #define MODULE_LICENSE(license) MODULE_PROPERTY("license", license) +#ifdef IN_MODULE #define MODULE_ENTRY(func) \ [[__used]] \ errno_t __module_entry(struct module* __module) { \ @@ -28,6 +29,15 @@ } \ [[__used, __section(".mod.exit")]] \ static const void* __exit_fn = &__module_exit +#else +#define MODULE_ENTRY(func) \ + [[__used, __section(".mod.entry")]] \ + static const void* UNIQUE_IDENT(module_entry) = &(func) + +#define MODULE_EXIT(func) \ + [[__used, __section(".mod.exit")]] \ + static const void* UNIQUE_IDENT(module_exit) = &(func) +#endif struct module { const char* name; diff --git a/include/zinnia/percpu.h b/include/zinnia/percpu.h index ac3bc49..410a618 100644 --- a/include/zinnia/percpu.h +++ b/include/zinnia/percpu.h @@ -9,7 +9,7 @@ // // 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`. +// caller's CPU, use `percpu_ref`. To access another CPU's copy, use `percpu_ref_on`. // // ## Example // @@ -22,8 +22,9 @@ // } // ``` -#define __percpu __used, __section(".percpu.data") -#define percpu_ref(x) ((typeof(&(x)))((void*)percpu_get() + ((void*)&(x) - (void*)&percpu_bsp))) +#define __percpu __used, __section(".percpu.data") +#define percpu_ref_on(cpu, x) ((typeof(&(x)))((void*)(cpu) + ((void*)&(x) - (void*)&percpu_bsp))) +#define percpu_ref(x) percpu_ref_on(percpu_get(), x) // CPU-relative information. struct percpu { diff --git a/meson.build b/meson.build index cde4827..aac58b0 100644 --- a/meson.build +++ b/meson.build @@ -124,6 +124,7 @@ foreach name, v : modules name_suffix: 'kso', link_with: mod_link, override_options: ['b_lundef=false'], + install_dir: get_option('datadir') / 'zinnia' / 'modules', #link_depends: kernel.full_path(), ) else