This commit is contained in:
2026-10-11 17:43:21 +02:00
parent 85cf698aae
commit 41cc7fea77
15 changed files with 125 additions and 84 deletions
+34 -6
View File
@@ -1,4 +1,5 @@
#include <zinnia/alloc.h>
#include <zinnia/assert.h>
#include <zinnia/cmdline.h>
#include <zinnia/init.h>
#include <zinnia/print.h>
@@ -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) {
+8 -4
View File
@@ -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) {
+35 -58
View File
@@ -1,8 +1,8 @@
#include <zinnia/compiler.h>
#include <zinnia/string.h>
#include <zinnia/utils.h>
#include <stddef.h>
#include <stdint.h>
#include <zinnia/string.h>
[[__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;
}
+8 -4
View File
@@ -3,9 +3,9 @@
#include <zinnia/init.h>
#include <zinnia/panic.h>
#include <zinnia/print.h>
#include <zinnia/string.h>
#include <zinnia/utils.h>
#include <zinnia/vma.h>
#include <zinnia/string.h>
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();
+1 -1
View File
@@ -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);
+3
View File
@@ -0,0 +1,3 @@
#include <zinnia/vfs.h>
void vfs_init() {}
+1
View File
@@ -1,3 +1,4 @@
kernel_sources += files(
'ident.c',
'init.c',
)
+2 -1
View File
@@ -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
+1 -1
View File
@@ -5,7 +5,7 @@
#include <stdatomic.h>
struct dpc {
void (*const callback)(struct dpc* dpc, void* data);
void (*callback)(struct dpc* dpc, void* data);
void* data;
atomic_bool inserted;
-3
View File
@@ -1,3 +0,0 @@
#pragma once
struct file_desc {};
+13 -1
View File
@@ -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
+4 -2
View File
@@ -7,8 +7,10 @@
#include <stddef.h>
#include <uapi/uio.h>
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;
+10
View File
@@ -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;
+4 -3
View File
@@ -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 {
+1
View File
@@ -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