From abfe4a92c8137a2c9d0dd2917d00f10f24790245 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Fri, 20 Sep 2019 14:48:14 +0900 Subject: [PATCH] Implement pg_frame_free() function; add code for debugging physical page tables (legacy IA-32 mode) --- kernel/arch/paging.c | 119 +++++++++++++++++++++++++++++++++++++++++-- kernel/arch/paging.h | 6 +++ 2 files changed, 120 insertions(+), 5 deletions(-) diff --git a/kernel/arch/paging.c b/kernel/arch/paging.c index f473c01..8a9e042 100644 --- a/kernel/arch/paging.c +++ b/kernel/arch/paging.c @@ -126,6 +126,14 @@ void* pg_frame_alloc_end(void) return(NULL); } +void pg_frame_free(void *addr) +{ + _frame_clear((u32_t)addr); + + return; +} + + #if FEATURE(DEBUG) static void _pg_dir_debug_regions(pg_dir_t *pd) { @@ -138,6 +146,45 @@ static void _pg_dir_debug_regions(pg_dir_t *pd) return; } + +static void _pg_dir_debug_arch(pg_dir_t *pd) +{ + switch(_pg_flags & PG_MODE_MASK) { + case PG_MODE_LEGACY: { + struct page_table *dir; + u32_t i; + + dir = (struct page_table*)pd->pd_base; + + for(i = 0; i < 1024; i++) { + if(!(dir->pt_entries[i] & PAGE_ATTR_PRESENT)) { + continue; + } + + dbg_printf("cr3[%04u] = 0x%08x\n", i, dir->pt_entries[i]); + if(!(dir->pt_entries[i] & PAGE_ATTR_SIZE)) { + struct page_table *tbl; + u32_t j; + + tbl = (struct page_table*)(dir->pt_entries[i] & 0xfffff000); + + for(j = 0; j < 1024; j++) { + if(tbl->pt_entries[j] & PAGE_ATTR_PRESENT) { + dbg_printf("cr3[%04u][%04u] = 0x%08x\n", i, j, tbl->pt_entries[j]); + } + } + } + } + + break; + } + + case PG_MODE_PAE: + break; + } + + return; +} #endif /* FEATURE(DEBUG) */ void* pg_init(struct multiboot_info *info) @@ -316,6 +363,48 @@ void* pg_init(struct multiboot_info *info) return((void*)(cr3 | _pg_flags)); } +int _pg_dir_kstack_map(struct pagedir *pgdir) +{ + int ret_val; + void *frame; + + ret_val = -ENOMEM; + frame = pg_frame_alloc_end(); + + if(ret_val) { + u32_t attrs; + void* vaddr; + + vaddr = CONFIG_KERNEL_STACK_BASE; + attrs = PAGE_ATTR_PRESENT | PAGE_ATTR_WRITABLE | PAGE_ATTR_NO_EXEC; + + ret_val = pg_dir_map(pgdir, frame, vaddr, PAGE_SIZE, attrs); + + if(ret_val < 0) { + goto cleanup; + } + + ret_val = _pg_dir_add_region(pgdir, vaddr, PAGE_SIZE, REGION_KSTACK, attrs); + + if(ret_val < 0) { + goto cleanup; + } + + ret_val = 0; + } + +cleanup: + if(ret_val < 0) { + pg_dir_unmap(pgdir, CONFIG_KERNEL_STACK_BASE, PAGE_SIZE); + + if(frame) { + pg_frame_free(frame); + } + } + + return(ret_val); +} + int pg_dir_create(pg_dir_t **dst) { int ret_val; @@ -357,6 +446,10 @@ int pg_dir_create(pg_dir_t **dst) for(reg = _kernel_pgdir.pd_regions; reg; reg = reg->reg_next) { switch(reg->reg_type) { case REGION_TEXT: + case REGION_BSS: + case REGION_DATA: + case REGION_RODATA: + case REGION_HEAP: dbg_printf("Mapping region %02x at 0x%08x:%08x\n", reg->reg_type, reg->reg_base, reg->reg_size); @@ -369,6 +462,14 @@ int pg_dir_create(pg_dir_t **dst) } } + /* allocate the kernel stack */ + ret_val = _pg_dir_kstack_map(dir); + +#if FEATURE(DEBUG) + _pg_dir_debug_regions(dir); + _pg_dir_debug_arch(dir); +#endif /* FEATURE(DEBUG) */ + if(ret_val) { /* couldn't create the page dir - free allocations */ kfree(dir); @@ -381,7 +482,8 @@ int pg_dir_create(pg_dir_t **dst) return(ret_val); } -static int _pg_dir_map_legacy(page_table_t *pd, u32_t paddr, u32_t vaddr, u32_t size, const u32_t flags) +static int _pg_dir_map_legacy(page_table_t *pd, u32_t paddr, u32_t vaddr, + u32_t size, const u32_t flags) { int ret_val; @@ -456,7 +558,8 @@ static int _pg_dir_map_legacy(page_table_t *pd, u32_t paddr, u32_t vaddr, u32_t return(ret_val); } -static int _pg_dir_map_pae(pdpt_t *pd, u64_t paddr, u64_t vaddr, u32_t size, const u32_t flags) +static int _pg_dir_map_pae(pdpt_t *pd, u64_t paddr, u64_t vaddr, + u32_t size, const u32_t flags) { int ret_val; @@ -509,7 +612,8 @@ static int _pg_dir_map_pae(pdpt_t *pd, u64_t paddr, u64_t vaddr, u32_t size, con return(ret_val); } -int pg_dir_map(pg_dir_t *pd, const void *phys, const void *virt, const u32_t size, const u32_t flags) +int pg_dir_map(pg_dir_t *pd, const void *phys, const void *virt, + const u32_t size, const u32_t flags) { int ret_val; u32_t asize; @@ -523,13 +627,13 @@ int pg_dir_map(pg_dir_t *pd, const void *phys, const void *virt, const u32_t siz switch(_pg_flags & PG_MODE_MASK) { case PG_MODE_LEGACY: ret_val = _pg_dir_map_legacy((struct page_table*)pd->pd_base, - (u32_t)virt, (u32_t)phys, + (u32_t)phys, (u32_t)virt, asize, flags); break; case PG_MODE_PAE: ret_val = _pg_dir_map_pae((struct pdpt*)pd->pd_base, - (unsigned)virt, (unsigned)phys, + (unsigned)phys, (unsigned)virt, asize, flags); break; @@ -546,6 +650,11 @@ int pg_dir_map(pg_dir_t *pd, const void *phys, const void *virt, const u32_t siz return(ret_val); } +int pg_dir_unmap(pg_dir_t *pd, const void *base, const u32_t size) +{ + return(-ENOSYS); +} + static int _pg_dir_add_region(pg_dir_t *pd, void *base, u32_t size, u32_t type, u32_t attrs) { struct region *reg; diff --git a/kernel/arch/paging.h b/kernel/arch/paging.h index fc9fedc..9750143 100644 --- a/kernel/arch/paging.h +++ b/kernel/arch/paging.h @@ -28,6 +28,9 @@ #define REGION_BSS 3 #define REGION_DATA 4 #define REGION_RODATA 5 +#define REGION_KSTACK 6 + +#define FLAG_SHARED (1 << 0) struct region { struct region *reg_next; @@ -37,6 +40,7 @@ struct region { u32_t reg_size; u32_t reg_pgsize; u32_t reg_attrs; + u32_t reg_flags; }; typedef struct pagedir pg_dir_t; @@ -90,8 +94,10 @@ struct pae_page_table { void* pg_frame_alloc_start(void); void* pg_frame_alloc_end(void); +void pg_frame_free(void*); int pg_dir_create(pg_dir_t**); int pg_dir_map(pg_dir_t*, const void*, const void*, const u32_t, const u32_t); +int pg_dir_unmap(pg_dir_t*, const void*, const u32_t); #endif /* __PAGING_H */ -- 2.47.3