]> git.corax.cc Git - corax/commitdiff
Add pg_dir_clone_region() method for copying a region from one page directory into...
authorMatthias Kruk <m@m10k.eu>
Mon, 18 Nov 2019 08:55:30 +0000 (17:55 +0900)
committerMatthias Kruk <m@m10k.eu>
Mon, 18 Nov 2019 08:55:30 +0000 (17:55 +0900)
kernel/arch/paging.c
kernel/include/arch.h

index 1b71822b5a155b8654f5697ca5b2d05cc96ce171..339638e4e77344b07b49884af6adc1d4bcb69dd7 100644 (file)
@@ -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);
index 7ac705de062cbd7f63ef5b54e6bb585ad299ebd0..522e0dcc9d61da8a194d4c5d7177d7576b8d44ca 100644 (file)
@@ -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*);