diff options
| author | Ada Christine <adachristine18@gmail.com> | 2021-04-23 01:12:23 +0000 |
|---|---|---|
| committer | Ada Christine <adachristine18@gmail.com> | 2021-04-23 01:12:23 +0000 |
| commit | b90e152c02aad225e83a3e6c1b80d1a0e396bb14 (patch) | |
| tree | 0eb899ca1213df0c677bf8721261d70c60ef68b4 | |
| parent | 73c73b2a8c9c3a6332942a1146fd18d74616e5b2 (diff) | |
less repetition, more flexibility with paging macros
| -rw-r--r-- | api/kernel/memory/paging.h | 9 | ||||
| -rw-r--r-- | api/kernel/memory/range.h | 21 | ||||
| -rw-r--r-- | kernel/memory.c | 66 | ||||
| -rw-r--r-- | kernel/memory.h | 18 | ||||
| -rw-r--r-- | loader/loader_efi.c | 15 |
5 files changed, 68 insertions, 61 deletions
diff --git a/api/kernel/memory/paging.h b/api/kernel/memory/paging.h index d3dc541..3f16930 100644 --- a/api/kernel/memory/paging.h +++ b/api/kernel/memory/paging.h @@ -1,5 +1,6 @@ #pragma once +#include <stddef.h> #define PAGE_MAP_LEVELS 4 #define PAGE_MAP_BITS 9 @@ -24,5 +25,9 @@ #define PAGE_TABLE_INDEX_MASK ((1 << PAGE_MAP_BITS) - 1) -#define page_table_index_bits(l) (PAGE_OFFSET_BITS + PAGE_MAP_BITS * (l - 1)) -#define page_table_index(v, l) (((uint64_t)v >> page_table_index_bits(l)) & PAGE_TABLE_INDEX_MASK) +#define pte_index_bits(l) (PAGE_OFFSET_BITS + PAGE_MAP_BITS * (l - 1)) +#define pte_index(v, l) (((uintptr_t)v >> pte_index_bits(l)) & PAGE_TABLE_INDEX_MASK) +#define page_size(l) (1 << pte_index_bits(l)) +#define page_address(a, l) (a & ~(page_size(l) - 1)) +#define page_offset(a, l) (a & (page_size(l) - 1)) +#define page_count(s, l) (((s + page_size(l) - 1) & ~(page_size(l) - 1)) / page_size(l)) diff --git a/api/kernel/memory/range.h b/api/kernel/memory/range.h new file mode 100644 index 0000000..6a68467 --- /dev/null +++ b/api/kernel/memory/range.h @@ -0,0 +1,21 @@ +#pragma once + +#include <stdint.h> +#include <stddef.h> + +typedef uintptr_t phys_addr_t; + +enum memory_range_type +{ + UNUSABLE_MEMORY, + RESERVED_MEMORY, + SYSTEM_MEMORY, + AVAILABLE_MEMORY, +}; + +struct memory_range +{ + enum memory_range_type type; + phys_addr_t base; + size_t size; +}; diff --git a/kernel/memory.c b/kernel/memory.c index 9d44be5..08028c6 100644 --- a/kernel/memory.c +++ b/kernel/memory.c @@ -2,6 +2,8 @@ #include "kprint.h" #include "panic.h" +#include <stdint.h> + #include <kernel/entry.h> #include <kernel/memory/paging.h> @@ -13,8 +15,8 @@ * own mapping tables begin at +0x7fffe000. */ -#define kpm1_index(v) (((uint64_t)v >> page_table_index_bits(1)) & 0x7ffff) -#define kpm2_index(v) (((uint64_t)v >> page_table_index_bits(2)) & 0x3ff) +#define kpm1_index(v) (((uint64_t)v >> pte_index_bits(1)) & 0x7ffff) +#define kpm2_index(v) (((uint64_t)v >> pte_index_bits(2)) & 0x3ff) #define align_next(v, a) (((uint64_t)v + a - 1) & ~(a - 1)) @@ -132,12 +134,10 @@ static phys_addr_t get_kernel_pm4_phys(void) phys_addr_t pm4_phys; __asm__ ( "mov %%cr3, %0\n\t" - "and %0, %1\n\t" : "=r"(pm4_phys) - : "r"((uint64_t)PAGE_ADDRESS_MASK) ); - return pm4_phys; + return page_address(pm4_phys, 1); } static phys_addr_t get_kernel_pm3_phys(void) @@ -145,11 +145,11 @@ static phys_addr_t get_kernel_pm3_phys(void) phys_addr_t pm3_phys; // make a temporary mapping to read pm4 uint64_t *pm4 = page_map_at(temp, - get_kernel_pm4_phys(), - CONTENT_RODATA|SIZE_2M); + get_kernel_pm4_phys(), + CONTENT_RODATA|SIZE_2M); // pm3_phys is in pm4. - pm3_phys = pm4[page_table_index(&k_virt_base, 4)] & PAGE_ADDRESS_MASK; + pm3_phys = page_address(pm4[pte_index(&k_virt_base, 4)], 1); // never leave a temporary mapping page_unmap(pm4); @@ -161,15 +161,14 @@ static void init_map_page_array_pm2(struct memory_range *pm2_pages) // now we need to write the physical address of each pm2 page for the // page_array in the kernel's pm3. uint64_t *pm3 = page_map_at(temp, - get_kernel_pm3_phys(), - CONTENT_RWDATA|SIZE_2M); + get_kernel_pm3_phys(), + CONTENT_RWDATA|SIZE_2M); // the first index is NOT zero! for (size_t i = 0; i < (pm2_pages->size / PAGE_SIZE); i++) { - pm3[page_table_index(page_array, 3) + i] = (pm2_pages->base + i * - PAGE_SIZE)|PAGE_NX|PAGE_WR| - PAGE_PR; + pm3[pte_index(page_array, 3) + i] = (pm2_pages->base + i * + PAGE_SIZE)|PAGE_NX|PAGE_WR|PAGE_PR; } // never forget to unmap temporary mappings. page_unmap(pm3); @@ -233,7 +232,7 @@ static void init_create_page_array(struct memory_range *ranges, int count) { // the highest actual physical memory address. size_t max_paddr = init_get_max_paddr(ranges, count); - page_array_entries = max_paddr / PAGE_SIZE; + page_array_entries = max_paddr / page_size(1); size_t page_array_size = page_array_entries * sizeof(struct page); // the physical pages that will contain page_array @@ -241,20 +240,20 @@ static void init_create_page_array(struct memory_range *ranges, int count) // the number of page tables needed to map pa_pages // this will be 1 on systems with less than 2GB of memory. - size_t pm1_count = align_next(pa_pages.size, PAGE_SIZE_LARGE) / PAGE_SIZE_LARGE; + size_t pm1_count = page_count(pa_pages.size, 2); struct memory_range pm1_pages = init_grab_pages(ranges, count, - pm1_count * PAGE_SIZE); + pm1_count * page_size(1)); init_create_page_array_map(&pa_pages, &pm1_pages); // the number of page directories needed to map pa_pages // this will be 1 on systems with less than 1TB of memory. // who the fuck has 1TB of memory lol - size_t pm2_count = align_next(pa_pages.size, PAGE_SIZE_HUGE) / PAGE_SIZE_HUGE; + size_t pm2_count = page_count(pa_pages.size, 3); struct memory_range pm2_pages = init_grab_pages(ranges, count, - pm2_count * PAGE_SIZE); + pm2_count * page_size(1)); init_create_page_array_map(&pm1_pages, &pm2_pages); @@ -322,8 +321,8 @@ void memory_init(struct memory_range *ranges, int count) } static void *page_map_at(void *vaddr, - phys_addr_t paddr, - enum page_map_flags flags) + phys_addr_t paddr, + enum page_map_flags flags) { uint64_t entry = PAGE_PR; @@ -345,13 +344,13 @@ static void *page_map_at(void *vaddr, switch (flags & SIZE_MASK) { case SIZE_2M: - entry |= (paddr & PAGE_ADDRESS_MASK_LARGE)|PAGE_LG; - offset = paddr % PAGE_SIZE_LARGE; + entry |= page_address(paddr, 2)|PAGE_LG; + offset = page_offset(paddr, 2); pte = get_kernel_pm2e(vaddr); break; case SIZE_4K: - entry |= (paddr & PAGE_ADDRESS_MASK); - offset = paddr % PAGE_SIZE; + entry |= page_address(paddr, 1); + offset = page_offset(paddr, 1); pte = get_kernel_pm1e(vaddr); break; default: @@ -359,13 +358,13 @@ static void *page_map_at(void *vaddr, pte = NULL; } - if (pte) + if (!pte) { - *pte = entry; - return (char *)vaddr + offset; + return NULL; } - return NULL; + *pte = entry; + return (char *)vaddr + offset; } void *page_map(phys_addr_t paddr, enum page_map_flags flags) @@ -400,12 +399,12 @@ phys_addr_t page_alloc(void) free_pages--; } - return (phys_addr_t)index * PAGE_SIZE; + return (phys_addr_t)index * page_size(1); } void page_free(phys_addr_t paddr) { - int index = paddr / PAGE_SIZE; + int index = paddr / page_size(1); if ((size_t)index > page_array_entries) { @@ -465,7 +464,7 @@ int anonymous_page_handler(uint32_t code, void *address) { uint64_t *pm2e = get_kernel_pm2e(address); - if (! (*pm2e & PAGE_ADDRESS_MASK)) + if (!page_address(*pm2e, 1)) { // create a page table and install it phys_addr_t pm1_phys = page_alloc(); @@ -481,7 +480,7 @@ int anonymous_page_handler(uint32_t code, void *address) // zero the page memset(pm1, 0, PAGE_SIZE); // put the table where it goes - *pm2e = (pm1_phys & PAGE_ADDRESS_MASK)|PAGE_WR|PAGE_PR; + *pm2e = page_address(pm1_phys, 1)|PAGE_WR|PAGE_PR; page_unmap(pm1); } @@ -492,10 +491,11 @@ int anonymous_page_handler(uint32_t code, void *address) phys_addr_t page_phys = page_alloc(); if (page_phys) { - *pm1e = (page_phys & PAGE_ADDRESS_MASK)|PAGE_WR|PAGE_PR; + *pm1e = page_address(page_phys, 1)|PAGE_WR|PAGE_PR; } } } + return 0; } diff --git a/kernel/memory.h b/kernel/memory.h index 7a259dd..9093985 100644 --- a/kernel/memory.h +++ b/kernel/memory.h @@ -1,24 +1,8 @@ #pragma once #include <stddef.h> -#include <stdint.h> -typedef uint64_t phys_addr_t; - -enum memory_range_type -{ - UNUSABLE_MEMORY, - RESERVED_MEMORY, - SYSTEM_MEMORY, - AVAILABLE_MEMORY, -}; - -struct memory_range -{ - enum memory_range_type type; - phys_addr_t base; - size_t size; -}; +#include <kernel/memory/range.h> enum page_map_flags { diff --git a/loader/loader_efi.c b/loader/loader_efi.c index 552dc06..2beb545 100644 --- a/loader/loader_efi.c +++ b/loader/loader_efi.c @@ -83,18 +83,15 @@ static uint64_t *get_page_table(uint64_t *map, uint64_t virt, int level) for (int i = PAGE_MAP_LEVELS; i > level; i--) { - if (!map[page_table_index(virt, i)]) + if (!map[pte_index(virt, i)]) { uint64_t *next_map = new_page_table(); - map[page_table_index(virt, i)] = - (uint64_t)next_map|PAGE_PR|PAGE_WR; + map[pte_index(virt, i)] = (uint64_t)next_map|PAGE_PR|PAGE_WR; map = next_map; } else { - uint64_t next_map_entry = map[page_table_index(virt, i)]; - next_map_entry &= PAGE_ADDRESS_MASK; - map = (uint64_t *)next_map_entry; + map = (uint64_t *)page_address(map[pte_index(virt, i)], 1); } } @@ -105,7 +102,7 @@ static uint64_t *get_page_entry(uint64_t *map, uint64_t virt) { int level = 1; uint64_t *table = get_page_table(map, virt, level); - return &table[page_table_index(virt, level)]; + return &table[pte_index(virt, level)]; } static void map_page(void *map, @@ -181,9 +178,9 @@ static void create_kernel_maps(struct system_image *image) 2); upper_page_dir[PAGE_TABLE_INDEX_MASK] = - (uint64_t)upper_page_dir|PAGE_PR|PAGE_WR; + (uint64_t)upper_page_dir|DATA_PAGE_TYPE; upper_page_dir[PAGE_TABLE_INDEX_MASK - 1] = - (uint64_t)lower_page_dir|PAGE_PR|PAGE_WR; + (uint64_t)lower_page_dir|DATA_PAGE_TYPE; } |
