From 3e4fadbeb4887fbbf1b780280438c36b8c9800a5 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Thu, 16 Mar 2023 11:04:14 +0100 Subject: [PATCH] noxos (docs): merged 'mm' docs from .wiki --- .../projects/noxos/docs/codebase/mm/heap.h.md | 16 ++-- .../noxos/docs/codebase/mm/memory_map.h.md | 10 ++ .../noxos/docs/codebase/mm/page_frame.h.md | 47 ++++++++++ .../noxos/docs/codebase/mm/page_map.h.md | 92 +++++++++++++++++++ .../noxos/docs/codebase/mm/region.h.md | 10 +- .../noxos/docs/codebase/mm/stack.h.md | 11 +++ 6 files changed, 173 insertions(+), 13 deletions(-) create mode 100644 content/projects/noxos/docs/codebase/mm/memory_map.h.md create mode 100644 content/projects/noxos/docs/codebase/mm/page_frame.h.md create mode 100644 content/projects/noxos/docs/codebase/mm/page_map.h.md create mode 100644 content/projects/noxos/docs/codebase/mm/stack.h.md diff --git a/content/projects/noxos/docs/codebase/mm/heap.h.md b/content/projects/noxos/docs/codebase/mm/heap.h.md index 234f2d2..0fb65e3 100644 --- a/content/projects/noxos/docs/codebase/mm/heap.h.md +++ b/content/projects/noxos/docs/codebase/mm/heap.h.md @@ -3,7 +3,7 @@ title: "heap.h" summary: "dynamic memory allocator" --- -#### `heap_segment_T` - struct +# `heap_segment_T` - struct This header lies in memory, directly before the accessible buffer of the related segment. | Name | Type | Description | @@ -15,7 +15,7 @@ This header lies in memory, directly before the accessible buffer of the related | prev | [heap_segment_T](https://nerdcult.net/projects/noxos/docs/codebase/mm/heap.h/#heap_segment_t---struct)* | The previous segment in the heap | -#### `heap_T` - struct +# `heap_T` - struct | Name | Type | Description | |--------------|---------------------------------------------------------------------------------------------------------|-------------------------------------------------------------| @@ -23,23 +23,23 @@ This header lies in memory, directly before the accessible buffer of the related | end | void* | The current end of the heaps segment pool (growing upwards) | | last_segment | [heap_segment_T](https://nerdcult.net/projects/noxos/docs/codebase/mm/heap.h/#heap_segment_t---struct)* | The current last segment in the heaps segment pool | -#### `heap_init(heap*, base)` - function (void) +# `heap_init(heap*, base)` - function (void) Initializes **_heap_** at **_base_** (virtual address). It will automatically map some page frames to that address. -#### `heap_memory_allocate(heap*, size)` - function (void) +# `heap_memory_allocate(heap*, size)` - function (void) Returns a pointer to a free usable memory location, that has at least the given **_size_**. It will return `NULL` and log an error, if the heap is corrupted. Because this function iterates over the entire heap to find a free segment, it is kinda slow. -#### `heap_memory_free(heap*, address)` - function (void) -Frees a with [heap_memory_allocate](https://nerdcult.net/projects/noxos/docs/codebase/mm/heap.h/#heap_memory_allocateheap-size---function-void)* created heap segment, and makes it usable again. +# `heap_memory_free(heap*, address)` - function (void) +Frees a with [heap_memory_allocate](https://nerdcult.net/projects/noxos/docs/codebase/mm/heap.h/#heap_memory_allocateheap-size---function-void) created heap segment, and makes it usable again. Does nothing, if the address doesn't point to a valid heap segment. -#### `heap_dump_segments(heap*)` - function (void) +# `heap_dump_segments(heap*)` - function (void) Logs a complete list, of all heap segments. Useful, when debugging / testing the heap. -#### `heap_destruct(heap*)` - function (void) +# `heap_destruct(heap*)` - function (void) Invalidates all segments of a heap, frees all used page frames and unmaps them. diff --git a/content/projects/noxos/docs/codebase/mm/memory_map.h.md b/content/projects/noxos/docs/codebase/mm/memory_map.h.md new file mode 100644 index 0000000..bfc80f2 --- /dev/null +++ b/content/projects/noxos/docs/codebase/mm/memory_map.h.md @@ -0,0 +1,10 @@ +--- +title: "memory_map.h" +summary: "functions to parse the memory map provided by the bootloader" +--- + +# `memory_map_get_total_memory_size(boot_info*)` - function (uint64_t) +Calculates the total amount of memory available, by iterating over the memory map. +The size is stored in a static variable, so no matter how often you call this function, the size will only be calculated once. +The total amount of memory is returned in bytes. + diff --git a/content/projects/noxos/docs/codebase/mm/page_frame.h.md b/content/projects/noxos/docs/codebase/mm/page_frame.h.md new file mode 100644 index 0000000..428868a --- /dev/null +++ b/content/projects/noxos/docs/codebase/mm/page_frame.h.md @@ -0,0 +1,47 @@ +--- +title: "page_frame.h" +summary: "physical memory management" +--- + +# `PFRAME_SIZE` - macro +The size of one page (4KB). + +# `page_frame_manager_T` - struct + +| Name | Type | Description | +|-------------------|----------|------------------------------------------------------------------------------------| +| free_memory | uint64_t | The amount of free/usable memory in bytes | +| reserved_memory | uint64_t | The amount of reserved memory in bytes | +| used_memory | uint64_t | The amount of memory used by noxos in bytes | +| page_bitmap_index | uint64_t | The index to the first free page | +| page_bitmap | bitmap_T | A huge bitmap, that stores, which pages are claimable and which are already in use | +| blocked | bool | Thread safety guard | + + +#### `pframe_manager_init()` - function (void) +Initializes the page frame manager, needs to be called once at kernel init. + +#### `pframe_reserve(address)` - function (void) [Thread Safe] +Blocks a page, so it can't be requested or anything else. +If the page is already blocked by anything else, e.g. by a request, it won't be reserved. + +#### `pframe_reserve_multi(address, n)` - function (void) [Thread Safe] +Reserves the page at the given address, plus *n* pages after that page. + +#### `pframe_unreserve(address)` - function (void) [Thread Safe] +Unreserves a reserved page and makes it accessible again. + +#### `pframe_unreserve_multi(address, n)` - function (void) [Thread Safe] +Unreserves the page at the given address, plus *n* pages after that page. + +#### `pframe_request()` - function (void*) [Thread Safe] +Returns the physical address of a page. +This is kind of the low level version of `memory_allocate`. + +#### `pframe_free(address)` - function (void) [Thread Safe] +Needs a valid page address produced by [pframe_request](https://nerdcult.net/projects/noxos/docs/codebase/mm/page_frame.h/#pframe_request---function-void-thread-safe) as argument. +Invalidates the address and frees it, so it can be requested again. +This is kind of the low level version of `memory_free`. + +#### `pframe_free_multi(address, n)` - function (void) [Thread Safe] +Frees the page at the given address, plus *n* pages after that page. diff --git a/content/projects/noxos/docs/codebase/mm/page_map.h.md b/content/projects/noxos/docs/codebase/mm/page_map.h.md new file mode 100644 index 0000000..e61f23c --- /dev/null +++ b/content/projects/noxos/docs/codebase/mm/page_map.h.md @@ -0,0 +1,92 @@ +--- +title: "page_map.h" +summary: "virtual memory management" +--- + +Virtual memory spaces are a bit more tricky than the physical memory space. +To understand them, we have to understand first, that the physical memory space is divided into so-called **pages** / **page frames**. +These pages have a size of 4KB. + +A virtual memory space is a table of page mappings. +Per default there are no pages mapped to such a table. +When the OS maps a page to a **page table**, it says: +"This page is now accessible from this virtual space, at this address". +When the Computer is in paging mode, only mapped pages are accessible. +Now every Process gets its own page table and tada: we have successfully isolated the processes from each other, +because every process can only access the data that it needs to access. + +# `VIRTUAL_ADDRESS_MAX` - macro +The highest mappable virtual address. +4 level page maps have a maximum address space of 256TB. + +# `page_map_flag_E` - enum +- **Present** - This indicates if the entry is used or should be ignored. Automatically set when mapping a page. +- **Read & Write** - A mapped Page is always readable. This flag allows writing to that page. +- **User Super** - If set, user mode access to the page is allowed. +- **Write Through** - Enables _Write Through Caching_ for this page. +- **Cache Disabled** - If this bit is set, the page won't be cached. +- **Accessed** - Set by the CPU, when this PDE or PTE was read. Won't be reset by the CPU. +- **Dirty** - Set when the page has been modified. +- **Larger Pages** - When this bit is set in a PDE or PTE, the entry points to a 1GB or 2MB page. +- **Custom 1 - 3** - Not used in NoxOS. +- **No Execute** - When this bit is set, the CPU won't execute code that lies in that page. + +# `page_map_T` - struct [page aligned] +This struct contains 512 entries. +These entries contain an address and flags. +The addresses link like this: +- **PML4** --> **Page Directory** or _1GB Page_ +- **Page Directory** --> **Page Table** or _2MB Page_ +- **Page Table** --> _4KB Page_ + +A pointer to a [page_map_T](https://nerdcult.net/projects/noxos/docs/codebase/mm/page_map.h/#page_map_t---struct-page-aligned) can be loaded into `cr3` to load this pagemap. + +# `page_map_create()` - function (page_map_T*) +Allocates a [page_map_T](https://nerdcult.net/projects/noxos/docs/codebase/mm/page_map.h/#page_map_t---struct-page-aligned) and returns a pointer to it. +The page map is populated with the mappings for the kernel executable and the loaded IDT. + +# `page_map_fetch_current()` - function (page_map_T*) [ASM implementation] +This function will return the page map, that is currently loaded. +To achieve this, it just reads the `cr3` register. + +# `page_map_load(page_map*)` - function (void) [ASM implementation] +Loads the given page map. +To achieve this, it writes the `cr3` register. + +# `page_map_map_memory(page_map*, virtual_address, physical_address, flags)` - function (void) +This maps **_physical_address_** to **_virtual_address_** in **_page_map_**. +The **_flags_** will be applied to the page mapping / page table entry. +It always applies the _Present_ flag automatically. + +# `page_map_unmap_memory(page_map*, virtual_address)` - function (void) +Removes a page mapping from the **_page_map_**. +Page map structure intern pages won't be checked if they're still needed or not. + +# `page_map_get_physical_address(page_map*, virtual_address)` - function (void*) +Returns the physical address of the page, that is mapped to **_virtual_address_**. + +# `page_map_destruct(page_map*)` - function (void) +Clears a page map and frees all page map structure intern pages. + +# `page_map_dump_info(page_map)` - function (void) +Logs information about **_page_map_**, including a map of all mapped regions. +A region is a block of continuously mapped pages. + +# `page_map_entry_set_flags(entry, uint64_t flags)` - function (void) +This will set the provided flags to a page map entry. + +# `page_map_entry_get_flag(entry, page_map_flag_E flag)` - function (bool) +Returns if the given flag is set in the page map entry, or not. + +# `page_map_entry_set_address(entry, void* address)` - function (void) +This will set the provided address to a page map entry. + +# `page_map_entry_get_address(entry)` - function (void*) +This will read and return the address set in the page map entry. + +# `paging_init()` - function (void) +Initializes paging. +This reads the current page map set by the kernel and writes it to [g_kernel_page_map](https://nerdcult.net/projects/noxos/docs/codebase/mm/page_map.h/#g_kernel_page_map---global-variable). + +# `g_kernel_page_map` - global variable +The kernels page map. This page map is provided by the bootloader and read from `cr3` at [paging_init](https://nerdcult.net/projects/noxos/docs/codebase/mm/page_map.h/#paging_init---function-void). diff --git a/content/projects/noxos/docs/codebase/mm/region.h.md b/content/projects/noxos/docs/codebase/mm/region.h.md index b1f8d02..da259ae 100644 --- a/content/projects/noxos/docs/codebase/mm/region.h.md +++ b/content/projects/noxos/docs/codebase/mm/region.h.md @@ -18,19 +18,19 @@ See _General Concepts / Memory Layout_(todo: add reference) and _General Concept | `MEM_REGION_KERNEL_THREAD_BASE` | 0xFFFFFF0000000000 | The kernel processes' _Thread Data_ regions | | `MEM_REGION_KERNELEXEC` | 0xFFFFFFFF80000000 | The kernel executable is mapped here | -#### `MEM_REGION_THREAD_OFFSET` - macro +# `MEM_REGION_THREAD_OFFSET` - macro This time the threads id specifies its offset in its processes' _Thread Data_ region. -#### `KERNEL_START_ADDRESS` - macro +# `KERNEL_START_ADDRESS` - macro Returns the address of [_kernel_start](https://nerdcult.net/projects/noxos/docs/codebase/mm/region.h/#_kernel_start---global-variable). -#### `KERNEL_END_ADDRESS` - macro +# `KERNEL_END_ADDRESS` - macro Returns the address of [_kernel_end](https://nerdcult.net/projects/noxos/docs/codebase/mm/region.h/#_kernel_end---global-variable). -#### `_kernel_start` - global variable +# `_kernel_start` - global variable This symbol is inserted by the linker at the beginning of the kernel. To access its value use [KERNEL_START_ADDRESS](https://nerdcult.net/projects/noxos/docs/codebase/mm/region.h/#kernel_start_address---macro). -#### `_kernel_end` - global variable +# `_kernel_end` - global variable This symbol is inserted by the linker at the end of the kernel. To access its value use [KERNEL_END_ADDRESS](https://nerdcult.net/projects/noxos/docs/codebase/mm/region.h/#kernel_end_address---macro). diff --git a/content/projects/noxos/docs/codebase/mm/stack.h.md b/content/projects/noxos/docs/codebase/mm/stack.h.md new file mode 100644 index 0000000..7d24705 --- /dev/null +++ b/content/projects/noxos/docs/codebase/mm/stack.h.md @@ -0,0 +1,11 @@ +--- +title: "stack.h" +summary: "functions to extract data from the call stack" +--- + +# `stack_dump_call_info(rip, symbol)` - function (void) +Logs information about a call. +Give this function the **_rip_** of the call and the related **_symbol_**, to make it happy. + +# `stack_trace_call_stack(rbp)` - function (void) +Analyses the stack and recursively dumps information about all calls until it hits a call to `_start` or fails to resolve the calls symbol name. \ No newline at end of file