_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,
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;
}
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
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;
+ }
}
}