From 690e8172d647e1f57045db4ec8923784831c9250 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Mon, 18 Nov 2019 20:28:40 +0900 Subject: [PATCH] Add kernel regions correctly in pg_dir_map_region(), use pg_dir_map_region() in _clone_kernel_region() function --- kernel/arch/paging.c | 56 +++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/kernel/arch/paging.c b/kernel/arch/paging.c index 339638e..038eb19 100644 --- a/kernel/arch/paging.c +++ b/kernel/arch/paging.c @@ -385,7 +385,7 @@ void* pg_init(struct multiboot_info *info) _kernel_pgdir.pd_base = (void*)cr3; _pg_dir_add_region(&_kernel_pgdir, TEXT_BASE, TEXT_SIZE, - REGION_TEXT, PAGE_ATTR_USER, + REGION_TEXT, 0, REGION_KERNEL | REGION_SHARED); _pg_dir_add_region(&_kernel_pgdir, RODATA_BASE, RODATA_SIZE, REGION_RODATA, PAGE_ATTR_NO_EXEC, @@ -705,7 +705,7 @@ int _pg_dir_kstack_map(struct pagedir *pgdir) REGION_PRIV); if(ret_val < 0) { - dbg_printf("_pg_dir_add_region() failed\n"); + dbg_printf("_pg_dir_add_region() failed with error %u\n", -ret_val); goto cleanup; } @@ -816,14 +816,7 @@ int _clone_kernel_region(pg_dir_t *kdir, region_t *reg, void *data) reg->reg_type, reg->reg_base, reg->reg_size, attrs); #endif /* FEATURE(DEBUG) */ - ret_val = pg_dir_map(dir, reg->reg_base, reg->reg_base, - reg->reg_size, attrs); - - if(ret_val >= 0) { - ret_val = _pg_dir_add_region(dir, reg->reg_base, reg->reg_size, - reg->reg_type, attrs, - REGION_KERNEL | REGION_SHARED); - } + ret_val = pg_dir_map_region(dir, kdir, reg); break; #if 0 @@ -1137,23 +1130,42 @@ int pg_dir_map_region(pg_dir_t *dpd, pg_dir_t *spd, region_t *reg) goto gtfo; } - for(vaddr = (u32_t)reg->reg_base; - vaddr < ((u32_t)reg->reg_base + reg->reg_size); - vaddr += reg->reg_pgsize) { - u32_t paddr; - - /* since the pages may not be continguous in memory, map each page separately */ - ret_val = _pg_dir_vpxlate(spd, vaddr, &paddr); + if(reg->reg_flags & REGION_KERNEL) { + /* + * Special case: kernel regions + * + * Kernel regions are continguous, so mapping them is more straight-forward. + * However, they need special treatment with regards to the attributes. In + * particular, the PAGE_ATTR_WRITABLE flag must be dropped since user-space + * processes are not supposed to write to kernel-owned memory. Furthermore, + * the PAGE_ATTR_USER flag must be added for the pages to be readable from + * user-space. + */ + ret_val = pg_dir_map(dpd, reg->reg_base, reg->reg_base, reg->reg_size, + (reg->reg_attrs | PAGE_ATTR_USER) & ~PAGE_ATTR_WRITABLE); if(ret_val < 0) { - break; + goto gtfo; } + } else { + for(vaddr = (u32_t)reg->reg_base; + vaddr < ((u32_t)reg->reg_base + reg->reg_size); + vaddr += reg->reg_pgsize) { + u32_t paddr; - ret_val = pg_dir_map(dpd, (void*)paddr, (void*)vaddr, - reg->reg_size, reg->reg_flags); + /* since the pages may not be continguous in memory, map each page separately */ + ret_val = _pg_dir_vpxlate(spd, vaddr, &paddr); - if(ret_val < 0) { - break; + if(ret_val < 0) { + break; + } + + ret_val = pg_dir_map(dpd, (void*)paddr, (void*)vaddr, + reg->reg_size, reg->reg_attrs); + + if(ret_val < 0) { + break; + } } } -- 2.47.3