From 03d28e62ef31fc6b2c34a2c5825c79595dd28dc0 Mon Sep 17 00:00:00 2001 From: keyboard-slayer Date: Fri, 15 Dec 2023 22:31:51 +0100 Subject: [PATCH] feat: added paging --- src/kernel/archs/hal.h | 32 ++ src/kernel/archs/x86_64/acpi.c | 71 +++ src/kernel/archs/x86_64/acpi.h | 48 ++ src/kernel/archs/x86_64/cpuid.c | 38 ++ src/kernel/archs/x86_64/cpuid.h | 27 + src/kernel/archs/x86_64/handler.c | 2 +- src/kernel/archs/x86_64/manifest.json | 4 +- src/kernel/archs/x86_64/mod.c | 3 + src/kernel/archs/x86_64/paging.c | 245 +++++++++ src/kernel/archs/x86_64/paging.h | 29 + src/kernel/core/main.c | 4 +- src/kernel/core/manifest.json | 3 +- src/kernel/core/pmm.c | 141 +++++ src/kernel/core/pmm.h | 38 ++ src/kernel/klibs/limine/limine.h | 737 ++++++++++++++++++++++++++ src/kernel/klibs/limine/loader.c | 198 +++++++ src/kernel/klibs/limine/manifest.json | 16 + src/kernel/klibs/loader.h | 42 ++ src/libs/utils.h | 13 +- 19 files changed, 1685 insertions(+), 6 deletions(-) create mode 100644 src/kernel/archs/x86_64/acpi.c create mode 100644 src/kernel/archs/x86_64/acpi.h create mode 100644 src/kernel/archs/x86_64/cpuid.c create mode 100644 src/kernel/archs/x86_64/cpuid.h create mode 100644 src/kernel/archs/x86_64/paging.c create mode 100644 src/kernel/archs/x86_64/paging.h create mode 100644 src/kernel/core/pmm.c create mode 100644 src/kernel/core/pmm.h create mode 100644 src/kernel/klibs/limine/limine.h create mode 100644 src/kernel/klibs/limine/loader.c create mode 100644 src/kernel/klibs/limine/manifest.json create mode 100644 src/kernel/klibs/loader.h diff --git a/src/kernel/archs/hal.h b/src/kernel/archs/hal.h index ed0e21f..77399ec 100644 --- a/src/kernel/archs/hal.h +++ b/src/kernel/archs/hal.h @@ -1,6 +1,7 @@ #pragma once #include +#include Res hal_setup(void); @@ -21,3 +22,34 @@ void hal_panic(void); /* --- I/O ---------------------------------------------------------------- */ Stream hal_dbg_stream(void); + +/* --- Memory mapping ------------------------------------------------------ */ + +typedef struct _page HalPage; + +typedef enum +{ + HAL_MEM_NONE = 0, + HAL_MEM_READ = 1 << 0, + HAL_MEM_WRITE = 1 << 1, + HAL_MEM_EXEC = 1 << 2, + HAL_MEM_USER = 1 << 3, + HAL_MEM_HUGE = 1 << 4, +} HalMemFlags; + +uintptr_t hal_mmap_l2h(uintptr_t addr); + +uintptr_t hal_mmap_h2l(uintptr_t addr); + +Res hal_space_map(HalPage *space, uintptr_t virt, uintptr_t phys, size_t len, uint8_t flags); + +void hal_space_apply(HalPage *space); + +/* --- Arch Specific ------------------------------------------------------- */ + +#ifdef __ck_arch_x86_64__ +# include + +Rsdp *hal_acpi_rsdp(void); + +#endif diff --git a/src/kernel/archs/x86_64/acpi.c b/src/kernel/archs/x86_64/acpi.c new file mode 100644 index 0000000..930611e --- /dev/null +++ b/src/kernel/archs/x86_64/acpi.c @@ -0,0 +1,71 @@ +#include +#include +#include + +#include "acpi.h" + +static bool is_xsdt = false; +static Sdt *sdt; + +void acpi_init(void) +{ + Rsdp *rsdp = hal_acpi_rsdp(); + + if (rsdp->revision >= 2 && rsdp->xsdt_address != 0) + { + is_xsdt = true; + log$("XSDT is supported"); + sdt = (Sdt *)hal_mmap_l2h(rsdp->xsdt_address); + } + else + { + log$("XSDT is not supported, defaulting to RSDT"); + sdt = (Sdt *)hal_mmap_l2h(rsdp->rsdt_address); + } +} + +static int acpi_checksum(SdtHeader *table) +{ + uint8_t sum = 0; + + for (size_t i = 0; i < table->length; i++) + { + sum += ((char *)table)[i]; + } + + return sum == 0; +} + +Res acpi_parse_sdt(char tablename[static 1]) +{ + size_t entry_count = 0; + SdtHeader *tmp; + + if (is_xsdt) + { + entry_count = sdt->xsdt.header.length - sizeof(sdt->xsdt.header) / 8; + } + else + { + entry_count = sdt->rsdt.header.length - sizeof(sdt->rsdt.header) / 4; + } + + for (size_t i = 0; i < entry_count; i++) + { + if (is_xsdt) + { + tmp = (SdtHeader *)hal_mmap_l2h(sdt->xsdt.entry[i]); + } + else + { + tmp = (SdtHeader *)hal_mmap_l2h(sdt->rsdt.entry[i]); + } + + if (memcmp(tmp->signature, tablename, 4) == 0 && acpi_checksum(tmp)) + { + return uok$((uintptr_t)tmp); + } + } + + return err$(RES_NOENT); +} \ No newline at end of file diff --git a/src/kernel/archs/x86_64/acpi.h b/src/kernel/archs/x86_64/acpi.h new file mode 100644 index 0000000..8e9c1bc --- /dev/null +++ b/src/kernel/archs/x86_64/acpi.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +typedef struct [[gnu::packed]] +{ + char signature[8]; + uint8_t checksum; + char oemid[6]; + uint8_t revision; + uint32_t rsdt_address; + uint32_t length; + uint64_t xsdt_address; + uint8_t extended_checksum; + uint8_t reserved[3]; +} Rsdp; + +typedef struct [[gnu::packed]] +{ + char signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oemid[6]; + char oem_table_id[8]; + uint32_t oem_revision; + uint32_t creator_id; + uint32_t creator_revision; +} SdtHeader; + +typedef union +{ + SdtHeader *header; + struct [[gnu::packed]] RSDT + { + SdtHeader header; + uint32_t entry[]; + } rsdt; + struct [[gnu::packed]] XSDT + { + SdtHeader header; + uint64_t entry[]; + } xsdt; +} Sdt; + +void acpi_init(void); +Res acpi_parse_sdt(char tablename[static 1]); \ No newline at end of file diff --git a/src/kernel/archs/x86_64/cpuid.c b/src/kernel/archs/x86_64/cpuid.c new file mode 100644 index 0000000..657e05b --- /dev/null +++ b/src/kernel/archs/x86_64/cpuid.c @@ -0,0 +1,38 @@ +#include "cpuid.h" + +CpuidResult cpuid(uint32_t leaf, uint32_t subleaf) +{ + uint32_t cpuid_max; + CpuidResult result; + + __asm__ volatile( + "cpuid" + : "=a"(cpuid_max) + : "a"(leaf & 0x80000000) + : "ebx", "ecx", "edx"); + + if (leaf > cpuid_max) + { + return (CpuidResult){.success = false}; + } + + __asm__ volatile( + "cpuid" + : "=a"(result.eax), "=b"(result.ebx), "=c"(result.ecx), "=d"(result.edx) + : "a"(leaf), "c"(subleaf)); + + result.success = true; + return result; +} + +bool cpuid_has_1gb_pages(void) +{ + CpuidResult result = cpuid(CPUID_EXTENDED_LEAF, 0); + + if (!result.success) + { + return false; + } + + return result.edx & CPUID_EXFEATURE_PDPE1GB; +} \ No newline at end of file diff --git a/src/kernel/archs/x86_64/cpuid.h b/src/kernel/archs/x86_64/cpuid.h new file mode 100644 index 0000000..25e05b1 --- /dev/null +++ b/src/kernel/archs/x86_64/cpuid.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#define CPUID_EXTENDED_LEAF (0x80000001) +#define CPUID_EXFEATURE_PDPE1GB (1 << 26) +#define CPUID_SSE_SUPPORT (1 << 25) +#define CPUID_SSE2_SUPPORT (1 << 26) +#define CPUID_XSAVE_SUPPORT (1 << 26) +#define CPUID_FEATURE_IDENTIFIER (0x1) + +typedef struct +{ + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + + bool success; +} CpuidResult; + +CpuidResult cpuid(uint32_t leaf, uint32_t subleaf); + +bool cpuid_has_1gb_pages(void); +bool cpuid_has_sse(void); +bool cpuid_has_sse2(void); +bool cpuid_has_xsave(void); \ No newline at end of file diff --git a/src/kernel/archs/x86_64/handler.c b/src/kernel/archs/x86_64/handler.c index 9d8052f..9ee4b2c 100644 --- a/src/kernel/archs/x86_64/handler.c +++ b/src/kernel/archs/x86_64/handler.c @@ -36,7 +36,7 @@ static char *exception_messages[32] = { "Control Protection Exception", "Reserved", "Hypervisor Injection Exception", - "VMM Communication Exception", + "paging Communication Exception", "Security Exception", "Reserved", "Reserved", diff --git a/src/kernel/archs/x86_64/manifest.json b/src/kernel/archs/x86_64/manifest.json index 027cde4..d40408b 100644 --- a/src/kernel/archs/x86_64/manifest.json +++ b/src/kernel/archs/x86_64/manifest.json @@ -1,7 +1,7 @@ { "$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1", "type": "lib", - "id": "arch (x86_64)", + "id": "arch_x86_64", "enableIf": { "arch": [ "x86_64" @@ -13,4 +13,4 @@ "requires": [ "dbg" ] -} \ No newline at end of file +} diff --git a/src/kernel/archs/x86_64/mod.c b/src/kernel/archs/x86_64/mod.c index 52349f7..914be74 100644 --- a/src/kernel/archs/x86_64/mod.c +++ b/src/kernel/archs/x86_64/mod.c @@ -5,6 +5,7 @@ #include "e9.h" #include "gdt.h" #include "idt.h" +#include "paging.h" Stream hal_dbg_stream(void) { @@ -17,5 +18,7 @@ Res hal_setup(void) { gdt_init(); idt_init(); + paging_init(); + acpi_init(); return ok$(); } \ No newline at end of file diff --git a/src/kernel/archs/x86_64/paging.c b/src/kernel/archs/x86_64/paging.c new file mode 100644 index 0000000..f3ba5ba --- /dev/null +++ b/src/kernel/archs/x86_64/paging.c @@ -0,0 +1,245 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "../../kernel/core/pmm.h" +#include "asm.h" +#include "cpuid.h" +#include "dbg/log.h" +#include "loader.h" +#include "paging.h" + +static size_t page_size = mib$(2); +static uintptr_t *pml4 = NULL; + +extern char text_start_addr[]; +extern char text_end_addr[]; +extern char rodata_start_addr[]; +extern char rodata_end_addr[]; +extern char data_start_addr[]; +extern char data_end_addr[]; + +static int64_t transform_flags(HalMemFlags flags) +{ + int64_t ret_flags = PAGE_NO_EXECUTE | PAGE_PRESENT; + + if (flags & HAL_MEM_READ) + { + } + + if (flags & HAL_MEM_NONE) + { + ret_flags &= ~PAGE_PRESENT; + } + + if (flags & HAL_MEM_WRITE) + { + ret_flags |= PAGE_WRITABLE; + } + + if (flags & HAL_MEM_EXEC) + { + ret_flags &= ~PAGE_NO_EXECUTE; + } + + if (flags & HAL_MEM_USER) + { + ret_flags |= PAGE_USER; + } + + if (flags & HAL_MEM_HUGE) + { + ret_flags |= PAGE_HUGE; + } + + return ret_flags; +} + +static Res paging_get_pml_alloc(uintptr_t *pml, size_t index, bool alloc) +{ + if ((pml[index] & PAGE_PRESENT)) + { + return uok$(hal_mmap_l2h(PAGE_GET_PHYS(pml[index]))); + } + else if (alloc) + { + PmmObj obj = pmm_alloc(1); + memset((void *)obj.base, 0, obj.len); + uintptr_t ptr_hddm = hal_mmap_l2h(obj.base); + + pml[index] = obj.base | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; + + return uok$(ptr_hddm); + } + + return err$(RES_NOMEM); +} + +static Res kmmap_page(uintptr_t *pml, uint64_t virt, uint64_t phys, int64_t flags) +{ + if (phys % PMM_PAGE_SIZE != 0 || virt % PMM_PAGE_SIZE != 0) + { + return err$(RES_BADALIGN); + } + + size_t pml1_entry = PMLX_GET_INDEX(virt, 0); + size_t pml2_entry = PMLX_GET_INDEX(virt, 1); + size_t pml3_entry = PMLX_GET_INDEX(virt, 2); + size_t pml4_entry = PMLX_GET_INDEX(virt, 3); + + uintptr_t *pml3 = (uintptr_t *)try$(paging_get_pml_alloc(pml, pml4_entry, true)); + + if (page_size == gib$(1) && flags & PAGE_HUGE) + { + pml3[pml3_entry] = phys | flags; + return ok$(); + } + + uintptr_t *pml2 = (uintptr_t *)try$(paging_get_pml_alloc(pml3, pml3_entry, true)); + + if (flags & PAGE_HUGE) + { + pml2[pml2_entry] = phys | flags; + return ok$(); + } + + uintptr_t *pml1 = (uintptr_t *)try$(paging_get_pml_alloc(pml2, pml2_entry, true)); + + pml1[pml1_entry] = phys | flags; + return ok$(); +} + +static Res kmmap_section(uintptr_t start, uintptr_t end, uint8_t flags) +{ + KernelMmap kaddr = loader_get_kernel_mmap(); + int64_t flags_arch = transform_flags(flags); + size_t end_loop = align_up$(end, PMM_PAGE_SIZE); + + for (size_t i = align_down$(start, PMM_PAGE_SIZE); i < end_loop; i += PMM_PAGE_SIZE) + { + uintptr_t phys = i - kaddr.virt + kaddr.phys; + try$(kmmap_page(pml4, i, phys, flags_arch)); + } + + return ok$(); +} + +Res hal_space_map(HalPage *self, uintptr_t virt, uintptr_t phys, size_t len, uint8_t flags) +{ + if (phys % PMM_PAGE_SIZE != 0 || virt % PMM_PAGE_SIZE != 0 || len % PMM_PAGE_SIZE != 0) + { + return err$(RES_BADALIGN); + } + + int64_t flags_arch = transform_flags(flags); + const size_t map_psize = flags & HAL_MEM_HUGE ? page_size : PMM_PAGE_SIZE; + + size_t end = align_up$(len, map_psize); + size_t aligned_virt = align_down$(virt, map_psize); + size_t aligned_phys = align_down$(phys, map_psize); + + for (size_t i = 0; i < end; i += map_psize) + { + try$(kmmap_page((uintptr_t *)self, aligned_virt + i, aligned_phys + i, flags_arch)); + } + + return ok$(); +} + +Res paging_init(void) +{ + PmmObj obj = pmm_alloc(1); + if (obj.base == 0) + { + return err$(RES_NOMEM); + } + + memset((void *)obj.base, 0, obj.len); + + log$("PML4: 0x%p", obj.base); + pml4 = (uintptr_t *)hal_mmap_l2h((uintptr_t)obj.base); + + if (cpuid_has_1gb_pages()) + { + log$("1GB pages are supported"); + page_size = gib$(1); + } + else + { + log$("1GB pages are not supported, defaulting to 2MB pages"); + page_size = mib$(2); + } + + kmmap_section((uintptr_t)text_start_addr, (uintptr_t)text_end_addr, HAL_MEM_READ | HAL_MEM_EXEC); + kmmap_section((uintptr_t)rodata_start_addr, (uintptr_t)rodata_end_addr, HAL_MEM_READ); + kmmap_section((uintptr_t)data_start_addr, (uintptr_t)data_end_addr, HAL_MEM_READ | HAL_MEM_WRITE); + + log$("Kernel sections mapped"); + + size_t end = max$(gib$(4), pmm_available_pages() * PMM_PAGE_SIZE); + uint64_t flags = transform_flags(HAL_MEM_WRITE | HAL_MEM_READ | HAL_MEM_HUGE); + + for (size_t i = page_size; i < end; i += page_size) + { + try$(kmmap_page(pml4, hal_mmap_l2h(i), i, flags)); + } + + Mmap mmaps = loader_get_mmap(); + + for (size_t i = 0; i < mmaps.len; i++) + { + MmapEntry entry = mmaps.entries[i]; + + if (mmaps.entries[i].type != LOADER_FB) + { + try$(hal_space_map((HalPage *)pml4, + hal_mmap_l2h(entry.base), + entry.base, + entry.len, + HAL_MEM_READ | HAL_MEM_WRITE | HAL_MEM_HUGE)); + } + } + + log$("Memory mapped"); + hal_space_apply((HalPage *)pml4); + log$("Space applied"); + + return ok$(); +} + +void hal_space_apply(HalPage *space) +{ + asm_write_cr(3, hal_mmap_h2l((uintptr_t)space)); +} + +Res hal_space_create(HalPage **self) +{ + + PmmObj obj = pmm_alloc(1); + memset((void *)obj.base, 0, obj.len); + + if (obj.base == 0) + { + return err$(RES_NOMEM); + } + + uintptr_t *space = (uintptr_t *)hal_mmap_l2h(obj.base); + memset((void *)space, 0, PMM_PAGE_SIZE); + + for (size_t i = 255; i < 512; i++) + { + space[i] = pml4[i]; + } + + *self = (HalPage *)space; + return ok$(); +} + +HalPage *hal_space_kernel(void) +{ + return (HalPage *)pml4; +} \ No newline at end of file diff --git a/src/kernel/archs/x86_64/paging.h b/src/kernel/archs/x86_64/paging.h new file mode 100644 index 0000000..09fae94 --- /dev/null +++ b/src/kernel/archs/x86_64/paging.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +#define PAGE_GET_PHYS(x) (x & 0x000ffffffffff000) +#define PAGE_GET_FLAGS(x) (x & 0xfff) +#define PMLX_GET_INDEX(addr, level) (((uint64_t)addr & ((uint64_t)0x1ff << (12 + level * 9))) >> (12 + level * 9)) + +enum pml_fields : uint64_t +{ + PAGE_PRESENT = 1 << 0, + PAGE_WRITABLE = 1 << 1, + PAGE_USER = 1 << 2, + PAGE_WRITE_THROUGH = 1 << 3, + PAGE_NO_CACHE = 1 << 4, + PAGE_ACCESSED = 1 << 5, + PAGE_DIRTY = 1 << 6, + PAGE_HUGE = 1 << 7, + PAGE_GLOBAL = 1 << 8, + PAGE_NO_EXECUTE = (uint64_t)1 << 63, +}; + +struct [[gnu::packed]] _page +{ + uintptr_t *_raw; +}; + +Res paging_init(void); \ No newline at end of file diff --git a/src/kernel/core/main.c b/src/kernel/core/main.c index d1ab528..3c534b3 100644 --- a/src/kernel/core/main.c +++ b/src/kernel/core/main.c @@ -1,9 +1,11 @@ #include #include +#include "pmm.h" + _Noreturn int _start() { - log$("Hello, world!"); + pmm_init(); hal_setup(); for (;;) diff --git a/src/kernel/core/manifest.json b/src/kernel/core/manifest.json index 28739c4..d1b4a43 100644 --- a/src/kernel/core/manifest.json +++ b/src/kernel/core/manifest.json @@ -5,7 +5,8 @@ "requires": [ "arch", "dbg", - "stdc-shim" + "stdc-shim", + "loader" ], "tools": { "cc": { diff --git a/src/kernel/core/pmm.c b/src/kernel/core/pmm.c new file mode 100644 index 0000000..f7019da --- /dev/null +++ b/src/kernel/core/pmm.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include + +#include "pmm.h" + +static PmmBitmap bitmap = {0}; +static _Atomic(size_t) available = 0; +static bool try_again = false; +static Spinlock lock = SPINLOCK_INIT; + +static bool bitmap_is_bit_set(size_t bit) +{ + return bitmap.bitmap[bit / 8] & (1 << (bit % 8)); +} + +static void pmm_mark_free(uintptr_t base, size_t len) +{ + size_t start = align_up$(base, PMM_PAGE_SIZE) / PMM_PAGE_SIZE; + size_t end = align_down$(base + len, PMM_PAGE_SIZE) / PMM_PAGE_SIZE; + + for (size_t i = start; i < end; i++) + { + bitmap.bitmap[i / 8] &= ~(1 << (i % 8)); + } + + available += len / PMM_PAGE_SIZE; +} + +static void pmm_mark_used(uintptr_t base, size_t len) +{ + size_t start = align_up$(base, PMM_PAGE_SIZE) / PMM_PAGE_SIZE; + size_t end = align_down$(base + len, PMM_PAGE_SIZE) / PMM_PAGE_SIZE; + + for (size_t i = start; i < end; i++) + { + bitmap.bitmap[i / 8] |= 1 << (i % 8); + } + + available -= len / PMM_PAGE_SIZE; +} + +Res pmm_init(void) +{ + Mmap mmaps = loader_get_mmap(); + MmapEntry last_entry = mmaps.entries[mmaps.len - 1]; + + bitmap.len = align_up$((last_entry.base + last_entry.len) / (PMM_PAGE_SIZE * 8), PMM_PAGE_SIZE); + bitmap.last_high = bitmap.len - 1; + log$("Bitmap size: %d bytes", bitmap.len); + + for (size_t i = 0; i < mmaps.len; i++) + { + if (mmaps.entries[i].type == LOADER_FREE && mmaps.entries[i].len >= bitmap.len) + { + log$("Bitmap base: %p", mmaps.entries[i].base); + bitmap.bitmap = (uint8_t *)hal_mmap_l2h(mmaps.entries[i].base); + mmaps.entries[i].base += bitmap.len; + mmaps.entries[i].len -= bitmap.len; + break; + } + } + + if (bitmap.bitmap == NULL) + { + return err$(RES_NOMEM); + } + + memset(bitmap.bitmap, 0xFF, bitmap.len); + + for (size_t i = 0; i < mmaps.len; i++) + { + if (mmaps.entries[i].type == LOADER_FREE) + { + pmm_mark_free(mmaps.entries[i].base, mmaps.entries[i].len); + } + } + + return ok$(); +} + +PmmObj _pmm_alloc(size_t pages, struct pmm_alloc_param param) +{ + spinlock_acquire(&lock); + + size_t *start = !param.low ? &bitmap.last_low : &bitmap.last_high; + size_t end = !param.low ? bitmap.len : 0; + size_t size = 0; + size_t base = 0; + + while (*start < end) + { + if (!bitmap_is_bit_set(!param.low ? (*start)++ : (*start)--)) + { + if (++size == pages) + { + base = *start - pages; + pmm_mark_used(base, pages); + try_again = false; + + spinlock_release(&lock); + return (PmmObj){.base = base * PMM_PAGE_SIZE, .len = pages * PMM_PAGE_SIZE}; + } + } + else + { + size = 0; + } + } + + spinlock_release(&lock); + + if (!try_again) + { + warn$("End of the bitmap reached, trying again"); + try_again = true; + PmmObj obj = _pmm_alloc(pages, param); + return obj; + } + else + { + error$("Out of physical memory"); + hal_panic(); + } + + __builtin_unreachable(); +} + +void pmm_free(PmmObj obj) +{ + spinlock_acquire(&lock); + pmm_mark_free(obj.base, obj.len); + spinlock_release(&lock); +} + +size_t pmm_available_pages(void) +{ + return available; +} \ No newline at end of file diff --git a/src/kernel/core/pmm.h b/src/kernel/core/pmm.h new file mode 100644 index 0000000..0d6fbaf --- /dev/null +++ b/src/kernel/core/pmm.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include + +#define PMM_PAGE_SIZE (kib$(4)) + +typedef struct +{ + size_t len; + size_t last_high; + size_t last_low; + uint8_t *bitmap; +} PmmBitmap; + +typedef struct +{ + size_t len; + uintptr_t base; +} PmmObj; + +struct pmm_alloc_param +{ + size_t pages; + bool low; +}; + +PmmObj _pmm_alloc(size_t pages, struct pmm_alloc_param param); + +#define pmm_alloc(pages, ...) _pmm_alloc(pages, (struct pmm_alloc_param){__VA_ARGS__}) + +Res pmm_init(void); + +void pmm_free(PmmObj obj); + +size_t pmm_available_pages(void); \ No newline at end of file diff --git a/src/kernel/klibs/limine/limine.h b/src/kernel/klibs/limine/limine.h new file mode 100644 index 0000000..d5ae7f2 --- /dev/null +++ b/src/kernel/klibs/limine/limine.h @@ -0,0 +1,737 @@ +/* BSD Zero Clause License */ + +/* Copyright (C) 2022-2023 mintsuki and contributors. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIMINE_H +#define _LIMINE_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + + /* Misc */ + +#ifdef LIMINE_NO_POINTERS +# define LIMINE_PTR(TYPE) uint64_t +#else +# define LIMINE_PTR(TYPE) TYPE +#endif + +#ifdef __GNUC__ +# define LIMINE_DEPRECATED __attribute__((__deprecated__)) +# define LIMINE_DEPRECATED_IGNORE_START \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +# define LIMINE_DEPRECATED_IGNORE_END \ + _Pragma("GCC diagnostic pop") +#else +# define LIMINE_DEPRECATED +# define LIMINE_DEPRECATED_IGNORE_START +# define LIMINE_DEPRECATED_IGNORE_END +#endif + +#define LIMINE_BASE_REVISION(N) \ + uint64_t limine_base_revision[3] = {0xf9562b2d5c95a6c8, 0x6a7b384944536bdc, (N)}; + +#define LIMINE_BASE_REVISION_SUPPORTED (limine_base_revision[2] == 0) + +#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b + + struct limine_uuid + { + uint32_t a; + uint16_t b; + uint16_t c; + uint8_t d[8]; + }; + +#define LIMINE_MEDIA_TYPE_GENERIC 0 +#define LIMINE_MEDIA_TYPE_OPTICAL 1 +#define LIMINE_MEDIA_TYPE_TFTP 2 + + struct limine_file + { + uint64_t revision; + LIMINE_PTR(void *) + address; + uint64_t size; + LIMINE_PTR(char *) + path; + LIMINE_PTR(char *) + cmdline; + uint32_t media_type; + uint32_t unused; + uint32_t tftp_ip; + uint32_t tftp_port; + uint32_t partition_index; + uint32_t mbr_disk_id; + struct limine_uuid gpt_disk_uuid; + struct limine_uuid gpt_part_uuid; + struct limine_uuid part_uuid; + }; + + /* Boot info */ + +#define LIMINE_BOOTLOADER_INFO_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0xf55038d8e2a1202f, 0x279426fcf5f59740 \ + } + + struct limine_bootloader_info_response + { + uint64_t revision; + LIMINE_PTR(char *) + name; + LIMINE_PTR(char *) + version; + }; + + struct limine_bootloader_info_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_bootloader_info_response *) + response; + }; + + /* Stack size */ + +#define LIMINE_STACK_SIZE_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x224ef0460a8e8926, 0xe1cb0fc25f46ea3d \ + } + + struct limine_stack_size_response + { + uint64_t revision; + }; + + struct limine_stack_size_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_stack_size_response *) + response; + uint64_t stack_size; + }; + + /* HHDM */ + +#define LIMINE_HHDM_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x48dcf1cb8ad2b852, 0x63984e959a98244b \ + } + + struct limine_hhdm_response + { + uint64_t revision; + uint64_t offset; + }; + + struct limine_hhdm_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_hhdm_response *) + response; + }; + + /* Framebuffer */ + +#define LIMINE_FRAMEBUFFER_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x9d5827dcd881dd75, 0xa3148604f6fab11b \ + } + +#define LIMINE_FRAMEBUFFER_RGB 1 + + struct limine_video_mode + { + uint64_t pitch; + uint64_t width; + uint64_t height; + uint16_t bpp; + uint8_t memory_model; + uint8_t red_mask_size; + uint8_t red_mask_shift; + uint8_t green_mask_size; + uint8_t green_mask_shift; + uint8_t blue_mask_size; + uint8_t blue_mask_shift; + }; + + struct limine_framebuffer + { + LIMINE_PTR(void *) + address; + uint64_t width; + uint64_t height; + uint64_t pitch; + uint16_t bpp; + uint8_t memory_model; + uint8_t red_mask_size; + uint8_t red_mask_shift; + uint8_t green_mask_size; + uint8_t green_mask_shift; + uint8_t blue_mask_size; + uint8_t blue_mask_shift; + uint8_t unused[7]; + uint64_t edid_size; + LIMINE_PTR(void *) + edid; + /* Response revision 1 */ + uint64_t mode_count; + LIMINE_PTR(struct limine_video_mode **) + modes; + }; + + struct limine_framebuffer_response + { + uint64_t revision; + uint64_t framebuffer_count; + LIMINE_PTR(struct limine_framebuffer **) + framebuffers; + }; + + struct limine_framebuffer_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_framebuffer_response *) + response; + }; + + /* Terminal */ + +#define LIMINE_TERMINAL_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0xc8ac59310c2b0844, 0xa68d0c7265d38878 \ + } + +#define LIMINE_TERMINAL_CB_DEC 10 +#define LIMINE_TERMINAL_CB_BELL 20 +#define LIMINE_TERMINAL_CB_PRIVATE_ID 30 +#define LIMINE_TERMINAL_CB_STATUS_REPORT 40 +#define LIMINE_TERMINAL_CB_POS_REPORT 50 +#define LIMINE_TERMINAL_CB_KBD_LEDS 60 +#define LIMINE_TERMINAL_CB_MODE 70 +#define LIMINE_TERMINAL_CB_LINUX 80 + +#define LIMINE_TERMINAL_CTX_SIZE ((uint64_t)(-1)) +#define LIMINE_TERMINAL_CTX_SAVE ((uint64_t)(-2)) +#define LIMINE_TERMINAL_CTX_RESTORE ((uint64_t)(-3)) +#define LIMINE_TERMINAL_FULL_REFRESH ((uint64_t)(-4)) + +/* Response revision 1 */ +#define LIMINE_TERMINAL_OOB_OUTPUT_GET ((uint64_t)(-10)) +#define LIMINE_TERMINAL_OOB_OUTPUT_SET ((uint64_t)(-11)) + +#define LIMINE_TERMINAL_OOB_OUTPUT_OCRNL (1 << 0) +#define LIMINE_TERMINAL_OOB_OUTPUT_OFDEL (1 << 1) +#define LIMINE_TERMINAL_OOB_OUTPUT_OFILL (1 << 2) +#define LIMINE_TERMINAL_OOB_OUTPUT_OLCUC (1 << 3) +#define LIMINE_TERMINAL_OOB_OUTPUT_ONLCR (1 << 4) +#define LIMINE_TERMINAL_OOB_OUTPUT_ONLRET (1 << 5) +#define LIMINE_TERMINAL_OOB_OUTPUT_ONOCR (1 << 6) +#define LIMINE_TERMINAL_OOB_OUTPUT_OPOST (1 << 7) + + LIMINE_DEPRECATED_IGNORE_START + + struct LIMINE_DEPRECATED limine_terminal; + + typedef void (*limine_terminal_write)(struct limine_terminal *, const char *, uint64_t); + typedef void (*limine_terminal_callback)(struct limine_terminal *, uint64_t, uint64_t, uint64_t, uint64_t); + + struct LIMINE_DEPRECATED limine_terminal + { + uint64_t columns; + uint64_t rows; + LIMINE_PTR(struct limine_framebuffer *) + framebuffer; + }; + + struct LIMINE_DEPRECATED limine_terminal_response + { + uint64_t revision; + uint64_t terminal_count; + LIMINE_PTR(struct limine_terminal **) + terminals; + LIMINE_PTR(limine_terminal_write) + write; + }; + + struct LIMINE_DEPRECATED limine_terminal_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_terminal_response *) + response; + LIMINE_PTR(limine_terminal_callback) + callback; + }; + + LIMINE_DEPRECATED_IGNORE_END + + /* Paging mode */ + +#define LIMINE_PAGING_MODE_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x95c1a0edab0944cb, 0xa4e5cb3842f7488a \ + } + +#if defined(__x86_64__) || defined(__i386__) +# define LIMINE_PAGING_MODE_X86_64_4LVL 0 +# define LIMINE_PAGING_MODE_X86_64_5LVL 1 +# define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_X86_64_5LVL +# define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_X86_64_4LVL +#elif defined(__aarch64__) +# define LIMINE_PAGING_MODE_AARCH64_4LVL 0 +# define LIMINE_PAGING_MODE_AARCH64_5LVL 1 +# define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_AARCH64_5LVL +# define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_AARCH64_4LVL +#elif defined(__riscv) && (__riscv_xlen == 64) +# define LIMINE_PAGING_MODE_RISCV_SV39 0 +# define LIMINE_PAGING_MODE_RISCV_SV48 1 +# define LIMINE_PAGING_MODE_RISCV_SV57 2 +# define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_RISCV_SV57 +# define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_RISCV_SV48 +#else +# error Unknown architecture +#endif + + struct limine_paging_mode_response + { + uint64_t revision; + uint64_t mode; + uint64_t flags; + }; + + struct limine_paging_mode_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_paging_mode_response *) + response; + uint64_t mode; + uint64_t flags; + }; + + /* 5-level paging */ + +#define LIMINE_5_LEVEL_PAGING_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x94469551da9b3192, 0xebe5e86db7382888 \ + } + + LIMINE_DEPRECATED_IGNORE_START + + struct LIMINE_DEPRECATED limine_5_level_paging_response + { + uint64_t revision; + }; + + struct LIMINE_DEPRECATED limine_5_level_paging_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_5_level_paging_response *) + response; + }; + + LIMINE_DEPRECATED_IGNORE_END + + /* SMP */ + +#define LIMINE_SMP_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x95a67b819a1b857e, 0xa0b61b723b6a73e0 \ + } + + struct limine_smp_info; + + typedef void (*limine_goto_address)(struct limine_smp_info *); + +#if defined(__x86_64__) || defined(__i386__) + +# define LIMINE_SMP_X2APIC (1 << 0) + + struct limine_smp_info + { + uint32_t processor_id; + uint32_t lapic_id; + uint64_t reserved; + LIMINE_PTR(limine_goto_address) + goto_address; + uint64_t extra_argument; + }; + + struct limine_smp_response + { + uint64_t revision; + uint32_t flags; + uint32_t bsp_lapic_id; + uint64_t cpu_count; + LIMINE_PTR(struct limine_smp_info **) + cpus; + }; + +#elif defined(__aarch64__) + +struct limine_smp_info +{ + uint32_t processor_id; + uint32_t gic_iface_no; + uint64_t mpidr; + uint64_t reserved; + LIMINE_PTR(limine_goto_address) + goto_address; + uint64_t extra_argument; +}; + +struct limine_smp_response +{ + uint64_t revision; + uint64_t flags; + uint64_t bsp_mpidr; + uint64_t cpu_count; + LIMINE_PTR(struct limine_smp_info **) + cpus; +}; + +#elif defined(__riscv) && (__riscv_xlen == 64) + +struct limine_smp_info +{ + uint64_t processor_id; + uint64_t hartid; + uint64_t reserved; + LIMINE_PTR(limine_goto_address) + goto_address; + uint64_t extra_argument; +}; + +struct limine_smp_response +{ + uint64_t revision; + uint64_t flags; + uint64_t bsp_hartid; + uint64_t cpu_count; + LIMINE_PTR(struct limine_smp_info **) + cpus; +}; + +#else +# error Unknown architecture +#endif + + struct limine_smp_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_smp_response *) + response; + uint64_t flags; + }; + + /* Memory map */ + +#define LIMINE_MEMMAP_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806f, 0xe304acdfc50c3c62 \ + } + +#define LIMINE_MEMMAP_USABLE 0 +#define LIMINE_MEMMAP_RESERVED 1 +#define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2 +#define LIMINE_MEMMAP_ACPI_NVS 3 +#define LIMINE_MEMMAP_BAD_MEMORY 4 +#define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 5 +#define LIMINE_MEMMAP_KERNEL_AND_MODULES 6 +#define LIMINE_MEMMAP_FRAMEBUFFER 7 + + struct limine_memmap_entry + { + uint64_t base; + uint64_t length; + uint64_t type; + }; + + struct limine_memmap_response + { + uint64_t revision; + uint64_t entry_count; + LIMINE_PTR(struct limine_memmap_entry **) + entries; + }; + + struct limine_memmap_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_memmap_response *) + response; + }; + + /* Entry point */ + +#define LIMINE_ENTRY_POINT_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x13d86c035a1cd3e1, 0x2b0caa89d8f3026a \ + } + + typedef void (*limine_entry_point)(void); + + struct limine_entry_point_response + { + uint64_t revision; + }; + + struct limine_entry_point_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_entry_point_response *) + response; + LIMINE_PTR(limine_entry_point) + entry; + }; + + /* Kernel File */ + +#define LIMINE_KERNEL_FILE_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69 \ + } + + struct limine_kernel_file_response + { + uint64_t revision; + LIMINE_PTR(struct limine_file *) + kernel_file; + }; + + struct limine_kernel_file_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_kernel_file_response *) + response; + }; + + /* Module */ + +#define LIMINE_MODULE_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x3e7e279702be32af, 0xca1c4f3bd1280cee \ + } + +#define LIMINE_INTERNAL_MODULE_REQUIRED (1 << 0) + + struct limine_internal_module + { + LIMINE_PTR(const char *) + path; + LIMINE_PTR(const char *) + cmdline; + uint64_t flags; + }; + + struct limine_module_response + { + uint64_t revision; + uint64_t module_count; + LIMINE_PTR(struct limine_file **) + modules; + }; + + struct limine_module_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_module_response *) + response; + + /* Request revision 1 */ + uint64_t internal_module_count; + LIMINE_PTR(struct limine_internal_module **) + internal_modules; + }; + + /* RSDP */ + +#define LIMINE_RSDP_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0xc5e77b6b397e7b43, 0x27637845accdcf3c \ + } + + struct limine_rsdp_response + { + uint64_t revision; + LIMINE_PTR(void *) + address; + }; + + struct limine_rsdp_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_rsdp_response *) + response; + }; + + /* SMBIOS */ + +#define LIMINE_SMBIOS_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x9e9046f11e095391, 0xaa4a520fefbde5ee \ + } + + struct limine_smbios_response + { + uint64_t revision; + LIMINE_PTR(void *) + entry_32; + LIMINE_PTR(void *) + entry_64; + }; + + struct limine_smbios_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_smbios_response *) + response; + }; + + /* EFI system table */ + +#define LIMINE_EFI_SYSTEM_TABLE_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x5ceba5163eaaf6d6, 0x0a6981610cf65fcc \ + } + + struct limine_efi_system_table_response + { + uint64_t revision; + LIMINE_PTR(void *) + address; + }; + + struct limine_efi_system_table_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_efi_system_table_response *) + response; + }; + + /* EFI memory map */ + +#define LIMINE_EFI_MEMMAP_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x7df62a431d6872d5, 0xa4fcdfb3e57306c8 \ + } + + struct limine_efi_memmap_response + { + uint64_t revision; + LIMINE_PTR(void *) + memmap; + uint64_t memmap_size; + uint64_t desc_size; + uint64_t desc_version; + }; + + struct limine_efi_memmap_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_efi_memmap_response *) + response; + }; + + /* Boot time */ + +#define LIMINE_BOOT_TIME_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x502746e184c088aa, 0xfbc5ec83e6327893 \ + } + + struct limine_boot_time_response + { + uint64_t revision; + int64_t boot_time; + }; + + struct limine_boot_time_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_boot_time_response *) + response; + }; + + /* Kernel address */ + +#define LIMINE_KERNEL_ADDRESS_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63, 0xb2644a48c516a487 \ + } + + struct limine_kernel_address_response + { + uint64_t revision; + uint64_t physical_base; + uint64_t virtual_base; + }; + + struct limine_kernel_address_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_kernel_address_response *) + response; + }; + + /* Device Tree Blob */ + +#define LIMINE_DTB_REQUEST \ + { \ + LIMINE_COMMON_MAGIC, 0xb40ddb48fb54bac7, 0x545081493f81ffb7 \ + } + + struct limine_dtb_response + { + uint64_t revision; + LIMINE_PTR(void *) + dtb_ptr; + }; + + struct limine_dtb_request + { + uint64_t id[4]; + uint64_t revision; + LIMINE_PTR(struct limine_dtb_response *) + response; + }; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/kernel/klibs/limine/loader.c b/src/kernel/klibs/limine/loader.c new file mode 100644 index 0000000..ad0b1b9 --- /dev/null +++ b/src/kernel/klibs/limine/loader.c @@ -0,0 +1,198 @@ +#include +#include +#include + +#include "limine.h" +#include "loader.h" + +static Mmap mmap = {0}; + +/* --- Limine requests ----------------------------------------------------- */ + +static volatile struct limine_memmap_request memmap_req = { + .id = LIMINE_MEMMAP_REQUEST, + .revision = 0, + .response = NULL, +}; + +static volatile struct limine_hhdm_request hhdm_req = { + .id = LIMINE_HHDM_REQUEST, + .revision = 0, + .response = NULL, +}; + +static volatile struct limine_kernel_address_request kernel_addr_req = { + .id = LIMINE_KERNEL_ADDRESS_REQUEST, + .revision = 0, + .response = NULL, +}; + +static volatile struct limine_rsdp_request rsdp_req = { + .id = LIMINE_RSDP_REQUEST, + .revision = 0, + .response = NULL, +}; + +static volatile struct limine_smp_request smp_req = { + .id = LIMINE_SMP_REQUEST, + .revision = 0, + .response = NULL, +}; + +/* --- Loader functions ---------------------------------------------------- */ + +Mmap loader_get_mmap(void) +{ + if (mmap.len > 0) + { + return mmap; + } + + if (memmap_req.response == NULL) + { + error$("Couldn't retrieve memory map from Limine"); + hal_panic(); + } + + log$("Retrieved memory map from Limine"); + + log$("====================================================="); + log$(" TYPE | BASE | LIMIT "); + log$("====================================================="); + + size_t i; + for (i = 0; i < memmap_req.response->entry_count; i++) + { + struct limine_memmap_entry *entry = memmap_req.response->entries[i]; + MmapEntry *mmap_entry = &mmap.entries[i]; + + switch (entry->type) + { + case LIMINE_MEMMAP_USABLE: + { + log$("FREE | %p | %p", entry->base, entry->base + entry->length); + mmap_entry->type = LOADER_FREE; + break; + } + + case LIMINE_MEMMAP_ACPI_NVS: + case LIMINE_MEMMAP_RESERVED: + case LIMINE_MEMMAP_BAD_MEMORY: + { + log$("RESERVED | %p | %p", entry->base, entry->base + entry->length); + mmap_entry->type = LOADER_RESERVED; + break; + } + + case LIMINE_MEMMAP_ACPI_RECLAIMABLE: + case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE: + { + log$("RECLAIMABLE | %p | %p", entry->base, entry->base + entry->length); + mmap_entry->type = LOADER_RECLAIMABLE; + break; + } + + case LIMINE_MEMMAP_KERNEL_AND_MODULES: + { + log$("MODULE | %p | %p", entry->base, entry->base + entry->length); + mmap_entry->type = LOADER_KERNEL; + break; + } + + case LIMINE_MEMMAP_FRAMEBUFFER: + { + log$("FRAMEBUFFER| %p | %p", entry->base, entry->base + entry->length); + mmap_entry->type = LOADER_FB; + break; + } + + default: + { + error$("Unknown memory map entry type %d", entry->type); + hal_panic(); + } + } + + mmap_entry->base = entry->base; + mmap_entry->len = entry->length; + } + + log$("====================================================="); + + mmap.len = i; + return mmap; +} + +uintptr_t hal_mmap_l2h(uintptr_t addr) +{ + if (hhdm_req.response == NULL) + { + error$("Couldn't convert address from Limine"); + hal_panic(); + } + + return addr + hhdm_req.response->offset; +} + +uintptr_t hal_mmap_h2l(uintptr_t addr) +{ + if (hhdm_req.response == NULL) + { + error$("Couldn't convert address from Limine"); + hal_panic(); + } + + return addr - hhdm_req.response->offset; +} + +KernelMmap loader_get_kernel_mmap(void) +{ + if (kernel_addr_req.response == NULL) + { + error$("Couldn't retrieve kernel address from Limine"); + hal_panic(); + } + + KernelMmap kernel_mmap = { + .phys = kernel_addr_req.response->physical_base, + .virt = kernel_addr_req.response->virtual_base, + }; + + return kernel_mmap; +} + +Rsdp *hal_acpi_rsdp(void) +{ + if (rsdp_req.response == NULL) + { + error$("Couldn't retrieve RSDP from Limine"); + hal_panic(); + } + + return (Rsdp *)rsdp_req.response->address; +} + +size_t cpu_count(void) +{ + if (smp_req.response == NULL) + { + error$("Couldn't retrieve SMP info from Limine"); + hal_panic(); + } + + return smp_req.response->cpu_count; +} + +void hal_smp_boot(void (*entry)(void)) +{ + if (smp_req.response == NULL) + { + error$("Couldn't retrieve SMP info from Limine"); + hal_panic(); + } + + for (size_t i = 0; i < smp_req.response->cpu_count; i++) + { + smp_req.response->cpus[i]->goto_address = (limine_goto_address)entry; + } +} \ No newline at end of file diff --git a/src/kernel/klibs/limine/manifest.json b/src/kernel/klibs/limine/manifest.json new file mode 100644 index 0000000..f248de2 --- /dev/null +++ b/src/kernel/klibs/limine/manifest.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1", + "type": "lib", + "id": "loader-limine", + "enableIf": { + "loader": [ + "limine" + ], + "arch": [ + "x86_64" + ] + }, + "provides": [ + "loader" + ] +} \ No newline at end of file diff --git a/src/kernel/klibs/loader.h b/src/kernel/klibs/loader.h new file mode 100644 index 0000000..e20d256 --- /dev/null +++ b/src/kernel/klibs/loader.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +/* --- MEMMAPS ------------------------------------------------------------- */ + +#define LOADER_MAX (128) + +enum memmap_type +{ + LOADER_FREE, + LOADER_RESERVED, + LOADER_RECLAIMABLE, + LOADER_KERNEL, + LOADER_FB, +}; + +typedef struct +{ + size_t base; + size_t len; + enum memmap_type type; +} MmapEntry; + +typedef struct +{ + size_t len; + MmapEntry entries[LOADER_MAX]; +} Mmap; + +typedef struct +{ + size_t phys; + size_t virt; +} KernelMmap; + +Mmap loader_get_mmap(void); + +/* --- Misc ---------------------------------------------------------------- */ + +KernelMmap loader_get_kernel_mmap(void); \ No newline at end of file diff --git a/src/libs/utils.h b/src/libs/utils.h index 88dccd8..c896229 100644 --- a/src/libs/utils.h +++ b/src/libs/utils.h @@ -6,4 +6,15 @@ #define make_enum$(enum) enum, -#define make_str$(str) #str, \ No newline at end of file +#define make_str$(str) #str, + + +#define kib$(x) ((uintptr_t)(x)*1024) + +#define mib$(x) (kib$(x) * 1024) + +#define gib$(x) (mib$(x) * 1024) + +#define align_up$(x, align) (((x) + (align)-1) & ~((align)-1)) + +#define align_down$(x, align) ((x) & ~((align)-1)) \ No newline at end of file