]> git.corax.cc Git - corax/commitdiff
Add kernel regions correctly in pg_dir_map_region(), use pg_dir_map_region() in _clon...
authorMatthias Kruk <m@m10k.eu>
Mon, 18 Nov 2019 11:28:40 +0000 (20:28 +0900)
committerMatthias Kruk <m@m10k.eu>
Mon, 18 Nov 2019 11:28:40 +0000 (20:28 +0900)
kernel/arch/paging.c

index 339638e4e77344b07b49884af6adc1d4bcb69dd7..038eb19c052b8e8f8e84af236ea29cd34bcf797a 100644 (file)
@@ -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;
+                       }
                }
        }