From: Matthias Kruk Date: Thu, 19 Sep 2019 05:33:12 +0000 (+0900) Subject: Dynamically allocate the region structures that are associated with page directories X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=de5c22a168bac2e9ebae6fefafa484db216067c9;p=corax Dynamically allocate the region structures that are associated with page directories --- diff --git a/kernel/arch/paging.c b/kernel/arch/paging.c index 7991817..2ce5d49 100644 --- a/kernel/arch/paging.c +++ b/kernel/arch/paging.c @@ -29,13 +29,25 @@ #define _frame_clear(addr) _frame_map[(addr) >> 17] &= ~(1 << (((addr) >> 12) & 0x1f)) #define _frame_get(addr) (_frame_map[(addr) >> 17] & (1 << (((addr) >> 12) & 0x1f))) +extern u32_t _corax_rodata; +extern u32_t _corax_data; +extern u32_t _corax_bss; extern u32_t _mem_start; +#define TEXT_BASE ((void*)0x100000) +#define TEXT_SIZE ((u32_t)&_corax_rodata - 0x100000) +#define RODATA_BASE (&_corax_rodata) +#define RODATA_SIZE ((u32_t)&_corax_data - (u32_t)&_corax_rodata) +#define DATA_BASE (&_corax_data) +#define DATA_SIZE ((u32_t)&_corax_bss - (u32_t)&_corax_data) +#define BSS_BASE (&_corax_bss) +#define BSS_SIZE ((u32_t)&_mem_start - (u32_t)&_corax_bss) + static u32_t _kernel_cr3 = 0; static u32_t _pg_flags = 0; static u32_t *_frame_map; static u32_t _nframes; -static struct pagedir *_kernel_pgdir; +static struct pagedir _kernel_pgdir; static const char *_str_pg_mode[] = { "legacy IA-32 mode", @@ -44,6 +56,8 @@ static const char *_str_pg_mode[] = { "Intel64 mode" }; +static int _pg_dir_add_region(pg_dir_t*, void*, u32_t, u32_t, u32_t); + static void* _phys_alloc(u32_t size, u32_t align) { extern u32_t _mem_start; @@ -255,31 +269,26 @@ void* pg_init(struct multiboot_info *info) } } - _kernel_pgdir = _phys_alloc(sizeof(*_kernel_pgdir), ARCH_ALIGN); - - _kernel_pgdir->pd_base = (void*)cr3; - _kernel_pgdir->pd_regions[REGION_TEXT].reg_base = (void*)0x100000; - _kernel_pgdir->pd_regions[REGION_TEXT].reg_size = (u32_t)&_mem_start - 0x100000; - _kernel_pgdir->pd_regions[REGION_TEXT].reg_pgsize = PAGE_SIZE; - _kernel_pgdir->pd_regions[REGION_TEXT].reg_attrs = PAGE_ATTR_PRESENT | PAGE_ATTR_USER; - - /* what about the area between &_mem_start and _mem_start? */ - - _kernel_pgdir->pd_regions[REGION_HEAP].reg_base = (void*)ALIGN((u32_t)_mem_start, PAGE_SIZE); - _kernel_pgdir->pd_regions[REGION_HEAP].reg_size = ALIGN(CONFIG_KERNEL_HEAP_SIZE, PAGE_SIZE); - _kernel_pgdir->pd_regions[REGION_HEAP].reg_pgsize = PAGE_SIZE; - _kernel_pgdir->pd_regions[REGION_HEAP].reg_attrs = PAGE_ATTR_PRESENT | PAGE_ATTR_WRITABLE; - - _kernel_pgdir->pd_regions[REGION_STACK].reg_base = &(_cpu[CPU_ID].cpu_stack0); - _kernel_pgdir->pd_regions[REGION_STACK].reg_size = STACK0_SIZE; - _kernel_pgdir->pd_regions[REGION_STACK].reg_pgsize = PAGE_SIZE; - _kernel_pgdir->pd_regions[REGION_STACK].reg_attrs = PAGE_ATTR_PRESENT | PAGE_ATTR_WRITABLE; - - heap_init(_kernel_pgdir->pd_regions[REGION_HEAP].reg_base, - _kernel_pgdir->pd_regions[REGION_HEAP].reg_size); - - /* mark all page frames from 0x0 to the end of the last kernel page dir/table as used */ - for(i = 0; i < _mem_start; i += PAGE_SIZE) { + /* initialize the heap, since we'll need it now */ + heap_init((void*)_mem_start, CONFIG_KERNEL_HEAP_SIZE); + + _kernel_pgdir.pd_base = (void*)cr3; + + _pg_dir_add_region(&_kernel_pgdir, TEXT_BASE, TEXT_SIZE, + REGION_TEXT, PAGE_ATTR_USER); + _pg_dir_add_region(&_kernel_pgdir, RODATA_BASE, RODATA_SIZE, + REGION_RODATA, PAGE_ATTR_NO_EXEC); + _pg_dir_add_region(&_kernel_pgdir, DATA_BASE, DATA_SIZE, + REGION_DATA, PAGE_ATTR_WRITABLE | PAGE_ATTR_NO_EXEC); + _pg_dir_add_region(&_kernel_pgdir, BSS_BASE, BSS_SIZE, + REGION_BSS, PAGE_ATTR_WRITABLE | PAGE_ATTR_NO_EXEC); + /* heap region also includes allocations from _phys_alloc() */ + _pg_dir_add_region(&_kernel_pgdir, &_mem_start, + _mem_start - (u32_t)&_mem_start + CONFIG_KERNEL_HEAP_SIZE, + REGION_HEAP, PAGE_ATTR_WRITABLE | PAGE_ATTR_NO_EXEC); + + /* mark all page frames from 0x0 to the end of the kernel heap as used */ + for(i = 0; i < _mem_start + CONFIG_KERNEL_HEAP_SIZE; i += PAGE_SIZE) { _frame_set(i); } @@ -299,6 +308,8 @@ int pg_dir_alloc(pg_dir_t **dst) ret_val = -ENOMEM; if(dir) { + struct region *reg; + switch(_pg_flags & PG_MODE_MASK) { case PG_MODE_LEGACY: case PG_MODE_PAE: @@ -321,11 +332,21 @@ int pg_dir_alloc(pg_dir_t **dst) /* we have an empty page directory now - populate it */ - /* map the kernel text into the new pagedir */ - ret_val = pg_dir_map(dir, _kernel_pgdir->pd_regions[REGION_TEXT].reg_base, - _kernel_pgdir->pd_regions[REGION_TEXT].reg_base, - _kernel_pgdir->pd_regions[REGION_TEXT].reg_size, - _kernel_pgdir->pd_regions[REGION_TEXT].reg_attrs); + /* + * FIXME: Should we really map the kernel text segment into the pagedir? + * We should probably cleanly separate the two, to avoid design flaws + * with speculative execution behavior of certain processors + */ + for(reg = _kernel_pgdir.pd_regions; reg; reg = reg->reg_next) { + switch(reg->reg_flags) { + case REGION_TEXT: + ret_val = pg_dir_map(dir, reg->reg_base, reg->reg_base, reg->reg_size, reg->reg_attrs); + break; + + default: + break; + } + } if(ret_val) { /* couldn't create the page dir - free allocations */ @@ -503,3 +524,28 @@ int pg_dir_map(pg_dir_t *pd, const void *phys, const void *virt, const u32_t siz return(ret_val); } + +static int _pg_dir_add_region(pg_dir_t *pd, void *base, u32_t size, u32_t flags, u32_t attrs) +{ + struct region *reg; + int ret_val; + + ret_val = -ENOMEM; + reg = kmalloc(sizeof(*reg)); + + if(reg) { + dbg_printf("Region type %02x at 0x%08x:%08x\n", flags, base, size); + reg->reg_base = base; + reg->reg_size = size; + reg->reg_pgsize = PAGE_SIZE; + reg->reg_flags = flags; + reg->reg_attrs = attrs; + + reg->reg_next = pd->pd_regions; + pd->pd_regions = reg; + + ret_val = 0; + } + + return(ret_val); +}