From 564f585608f4e170442da186c5df40bb46e26c27 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Mon, 18 Nov 2019 17:55:30 +0900 Subject: [PATCH] Add pg_dir_clone_region() method for copying a region from one page directory into another one --- kernel/arch/paging.c | 47 +++++++++++++++++++++++++++++++++++++++++++ kernel/include/arch.h | 1 + 2 files changed, 48 insertions(+) diff --git a/kernel/arch/paging.c b/kernel/arch/paging.c index 1b71822..339638e 100644 --- a/kernel/arch/paging.c +++ b/kernel/arch/paging.c @@ -1171,6 +1171,53 @@ gtfo: return(ret_val); } +int pg_dir_clone_region(pg_dir_t *dpd, pg_dir_t *spd, region_t *reg) +{ + int ret_val; + int idx; + + ret_val = -EFAULT; + + /* like in pg_dir_map_region(), get a slot for the new region */ + for(idx = 0; idx < CONFIG_PAGING_DIR_MAXREGIONS; idx++) { + if(!dpd->pd_regions[idx]) { + break; + } + } + + if(idx >= CONFIG_PAGING_DIR_MAXREGIONS) { + ret_val = -ERANGE; + goto gtfo; + } + + /* attempt to map the region */ + ret_val = pg_dir_map(dpd, NULL, reg->reg_base, + reg->reg_size, reg->reg_attrs); + + if(ret_val < 0) { + goto gtfo; + } + + /* copy the contents of the region */ + ret_val = pg_dir_memcpy(dpd, reg->reg_base, + spd, reg->reg_base, + reg->reg_size); + + if(ret_val >= 0) { + /* also keep track of the region */ + ret_val = _pg_dir_add_region(dpd, reg->reg_base, reg->reg_size, + reg->reg_type, reg->reg_attrs, reg->reg_flags); + } + + if(ret_val < 0) { + /* if pg_dir_memcpy() or _pg_dir_add_region() failed, undo the mapping */ + pg_dir_unmap(dpd, reg->reg_base, reg->reg_size); + } + +gtfo: + return(ret_val); +} + int pg_dir_unmap(pg_dir_t *pd, const void *base, const u32_t size) { return(-ENOSYS); diff --git a/kernel/include/arch.h b/kernel/include/arch.h index 7ac705d..522e0dc 100644 --- a/kernel/include/arch.h +++ b/kernel/include/arch.h @@ -141,6 +141,7 @@ 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_map_region(pg_dir_t*, pg_dir_t*, region_t*); +int pg_dir_clone_region(pg_dir_t*, pg_dir_t*, region_t*); int pg_dir_unmap(pg_dir_t*, const void*, const u32_t); void* pg_dir_get_pdbr(pg_dir_t*); -- 2.47.3