#define BSS_BASE (&_corax_bss)
#define BSS_SIZE ((u32_t)&_mem_start - (u32_t)&_corax_bss)
-static u32_t _kernel_cr3 = 0;
+u32_t _kernel_cr3 = 0;
static u32_t _pg_flags = 0;
static u32_t *_frame_map;
static u32_t _nframes;
};
static int _pg_dir_add_region(pg_dir_t*, void*, u32_t, u32_t, u32_t);
+int _pg_dir_vpxlate(pg_dir_t*, u32_t, u32_t*);
static void* _phys_alloc(u32_t size, u32_t align)
{
return((void*)(cr3 | _pg_flags));
}
+void* pg_dir_get_kstack(struct pagedir *pgdir)
+{
+ struct region *reg;
+ void *ret_val;
+
+ for(ret_val = NULL, reg = pgdir->pd_regions; reg; reg = reg->reg_next) {
+ if(reg->reg_type == REGION_KSTACK) {
+ u32_t virt;
+ u32_t phys;
+
+ virt = (u32_t)reg->reg_base;
+ _pg_dir_vpxlate(pgdir, virt, &phys);
+
+ ret_val = (void*)phys;
+ break;
+ }
+ }
+
+ return(ret_val);
+}
+
+void* pg_dir_get_ustack(struct pagedir *pgdir)
+{
+ struct region *reg;
+ void *ret_val;
+
+ for(ret_val = NULL, reg = pgdir->pd_regions; reg; reg = reg->reg_next) {
+ if(reg->reg_type == REGION_STACK) {
+ ret_val = reg->reg_base;
+ break;
+ }
+ }
+
+ return(ret_val);
+}
+
+int _pg_dir_vpxlate(struct pagedir *pgdir, u32_t virt, u32_t *phys)
+{
+ int ret_val;
+
+ /*
+ * FIXME: This function will not work from any other page directory
+ * than _kernel_pgdir, since the other directories don't have the paging
+ * structures mapped
+ */
+ switch(_pg_flags & PG_MODE_MASK) {
+ case PG_MODE_LEGACY: {
+ struct page_table *dir;
+ u32_t i;
+
+ ret_val = -EFAULT;
+ dir = (struct page_table*)pgdir->pd_base;
+ i = virt >> 22;
+
+ /* check if the page directory entry is present */
+ if(!(dir->pt_entries[i] & PAGE_ATTR_PRESENT)) {
+ break;
+ }
+
+ /* check if a 4M page is referenced */
+ if(dir->pt_entries[i] & PAGE_ATTR_SIZE) {
+ ret_val = 0;
+ *phys = (dir->pt_entries[i] & ~0x3fffff) | (virt & 0x3fffff);
+ break;
+ }
+
+ /* get a pointer to the referenced page table */
+ dir = (struct page_table*)(dir->pt_entries[i] & 0xfffff000);
+ i = (virt >> 12) & 0x3ff;
+
+ /* resolve the page, if it is present */
+ if(dir->pt_entries[i] & PAGE_ATTR_PRESENT) {
+ *phys = (dir->pt_entries[i] & 0xfffff000) | (virt & 0xfff);
+ ret_val = 0;
+ }
+
+ break;
+ }
+
+ default:
+ ret_val = -ENOSYS;
+ break;
+ }
+
+ return(ret_val);
+}
+
int _pg_dir_kstack_map(struct pagedir *pgdir)
{
int ret_val;
ret_val = pg_dir_map(pgdir, frame, vaddr, PAGE_SIZE, attrs);
if(ret_val < 0) {
+ dbg_printf("pg_dir_map() failed\n");
goto cleanup;
}
ret_val = _pg_dir_add_region(pgdir, vaddr, PAGE_SIZE, REGION_KSTACK, attrs);
if(ret_val < 0) {
+ dbg_printf("_pg_dir_add_region() failed\n");
goto cleanup;
}
return(ret_val);
}
+int _pg_dir_ustack_map(struct pagedir *pgdir)
+{
+ int ret_val;
+ void *frame;
+
+ ret_val = -ENOMEM;
+ frame = pg_frame_alloc_end();
+
+ if(ret_val) {
+ u32_t attrs;
+ void* vaddr;
+
+ vaddr = (void*)((u32_t)CONFIG_KERNEL_STACK_BASE - PAGE_SIZE);
+ attrs = PAGE_ATTR_PRESENT | PAGE_ATTR_WRITABLE | PAGE_ATTR_USER | PAGE_ATTR_NO_EXEC;
+
+ ret_val = pg_dir_map(pgdir, frame, vaddr, PAGE_SIZE, attrs);
+
+ if(ret_val < 0) {
+ goto cleanup;
+ }
+
+ ret_val = _pg_dir_add_region(pgdir, vaddr, PAGE_SIZE, REGION_STACK, attrs);
+
+ if(ret_val < 0) {
+ goto cleanup;
+ }
+
+ ret_val = 0;
+ }
+
+cleanup:
+ if(ret_val < 0) {
+ pg_dir_unmap(pgdir, (void*)((u32_t)CONFIG_KERNEL_STACK_BASE - PAGE_SIZE),
+ PAGE_SIZE);
+
+ if(frame) {
+ pg_frame_free(frame);
+ }
+ }
+
+ return(ret_val);
+}
+
int pg_dir_create(pg_dir_t **dst)
{
int ret_val;
ret_val = pg_dir_map(dir, reg->reg_base, reg->reg_base,
reg->reg_size, reg->reg_attrs);
+
+ if(ret_val >= 0) {
+ ret_val = _pg_dir_add_region(dir, reg->reg_base, reg->reg_size,
+ reg->reg_type, reg->reg_attrs);
+ }
+
break;
default:
}
}
+ /* map the vesa memory into the pagedir */
+ pg_dir_map(dir, (void*)0xb8000, (void*)0xb8000, 0x2000, PAGE_ATTR_PRESENT | PAGE_ATTR_WRITABLE);
+
/* allocate the kernel stack */
ret_val = _pg_dir_kstack_map(dir);
+ /* allocate the user-space stack */
+ ret_val = _pg_dir_ustack_map(dir);
+
#if FEATURE(DEBUG)
_pg_dir_debug_regions(dir);
_pg_dir_debug_arch(dir);
#endif /* FEATURE(DEBUG) */
if(ret_val) {
+ dbg_printf("Failed to create the pagedir\n");
/* couldn't create the page dir - free allocations */
kfree(dir);
dir = NULL;
{
int ret_val;
- ret_val = -EINVAL;
+ ret_val = 0;
while(size > 0) {
struct page_table *pt;
return(-ENOSYS);
}
-static int _pg_dir_add_region(pg_dir_t *pd, void *base, u32_t size, u32_t type, u32_t attrs)
+static int _pg_dir_add_region(pg_dir_t *pd, void *base, u32_t size,
+ u32_t type, u32_t attrs)
{
struct region *reg;
int ret_val;