diff --git a/kernel/mm/mm.cc b/kernel/mm/mm.cc index eefb3da..68ce2f3 100644 --- a/kernel/mm/mm.cc +++ b/kernel/mm/mm.cc @@ -6,6 +6,8 @@ #define MM_MAX_MMAP_ENTRIES 64 +static bool mm_use_virtual_offset; + extern "C" { pagedirectory_t page_directory __attribute__ ((aligned (4096))); @@ -43,6 +45,7 @@ void mm_record_mmap_entry(mb_mmap_t * mmap) void mm_bootstrap() { u32_t max_ram_address = KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE - 1; + mm_use_virtual_offset = true; if (mm_mmap_num_entries < 1) { @@ -78,9 +81,10 @@ void mm_bootstrap() u32_t * last_page = NULL; while (base_address < address_limit) { - /* check to make sure the RAM page isn't overlapping the kernel */ - if ( base_address + PAGE_SIZE <= KERNEL_PHYSICAL_ADDRESS - && base_address >= KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE ) + /* check to make sure the RAM page is ok */ + if ( base_address > 0 /* don't map address 0 */ + && ( base_address + PAGE_SIZE <= KERNEL_PHYSICAL_ADDRESS + || base_address >= KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE ) ) { /* we found a page to add to the free list */ u32_t * page_virtual_address = @@ -101,11 +105,83 @@ void mm_bootstrap() } } + if (mm_num_free_pages < 10) + { + k_early_panic("Not enough free pages of RAM!"); + } + /* Clear the page directory */ for (unsigned int i = 0; i < NUM_PAGETABLE_ENTRIES; i++) { page_directory[i] = 0; } + + /* now map all of RAM into the virtual address space + * starting at address 0x0 + */ + for (u32_t page_base = 0; + page_base < max_ram_address; + page_base += PAGE_SIZE) + { + mm_map(page_base, page_base, 0, 1); + } + + mm_use_virtual_offset = false; } } /* extern "C" */ + +int mm_map(u32_t virtual_address, u32_t physical_address, + u32_t user_mode, u32_t writable) +{ + u32_t directory_index = (virtual_address >> 22) & 0x3FF; + u32_t table_index = (virtual_address >> 12) & 0x3FF; + if (page_directory[directory_index] == 0) + { + /* allocate a new page table */ + u32_t page_table_address = mm_page_alloc(); + if (page_table_address == 0) + { + return 1; + } + page_directory[directory_index] = page_table_address + | 0x1 << 2 /* PTs can be user mode */ + | 0x1 << 1 /* writable */ + | 0x1; /* present */ + } + u32_t page_table_address = page_directory[directory_index] & PAGE_HIGH_MASK; + + u32_t * page_table = (u32_t *) page_table_address; + if (mm_use_virtual_offset) + { + page_table = (u32_t *)((u32_t)page_table + (u32_t)KERNEL_OFFSET); + } + + page_table[table_index] = (physical_address & PAGE_HIGH_MASK) + | (user_mode & 0x1) << 2 + | (writable & 0x1) << 1 + | 0x1; /* present */ + + return 0; +} + +/************************************************************************** + * Returns the physical base address of a page in RAM * + * or 0 if no pages were available * + *************************************************************************/ +u32_t mm_page_alloc() +{ + if (mm_free_page_ptr == NULL) + { + return 0; + } + u32_t * page_ptr = mm_free_page_ptr; + if (mm_use_virtual_offset) + { + page_ptr = (u32_t *) ((u32_t)page_ptr + (u32_t)KERNEL_OFFSET); + } + u32_t page_address = (u32_t) mm_free_page_ptr; + mm_free_page_ptr = (u32_t *) *page_ptr; + mm_num_free_pages--; + return page_address; +} diff --git a/kernel/mm/mm.h b/kernel/mm/mm.h index b545892..03d08d9 100644 --- a/kernel/mm/mm.h +++ b/kernel/mm/mm.h @@ -32,5 +32,10 @@ void mm_bootstrap(); } #endif +int mm_map(u32_t virtual_address, u32_t physical_address, + u32_t user_mode, u32_t writable); + +u32_t mm_page_alloc(); + #endif