diff --git a/kernel/boot/k_bootstrap.cc b/kernel/boot/k_bootstrap.cc index 593b5ca..2607fd1 100644 --- a/kernel/boot/k_bootstrap.cc +++ b/kernel/boot/k_bootstrap.cc @@ -47,6 +47,7 @@ u32_t k_bootstrap(mb_info_t * mb_info, u32_t mb_magic) * before calling them. */ mm_bootstrap(); + stack_bootstrap(); kio_bootstrap(); return 0; diff --git a/kernel/mm/mm.cc b/kernel/mm/mm.cc index d530169..fc61054 100644 --- a/kernel/mm/mm.cc +++ b/kernel/mm/mm.cc @@ -9,8 +9,6 @@ #define MM_MAX_MMAP_ENTRIES 64 -static bool mm_use_virtual_offset; - static pagedirectory_entry_t * page_directory; static mm_mem_range_t mm_mmap_entries[MM_MAX_MMAP_ENTRIES]; static int mm_mmap_num_entries = 0; @@ -48,7 +46,6 @@ 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) { @@ -116,7 +113,7 @@ void mm_bootstrap() /* ok, now mm_page_alloc() should be functional */ /* allocate the page directory */ - u32_t page_directory_phys = mm_page_alloc(); + u32_t page_directory_phys = mm_early_page_alloc(); page_directory = (pagedirectory_entry_t *) page_directory_phys; pagedirectory_entry_t * page_dir_virt = (pagedirectory_entry_t *) (page_directory_phys + KERNEL_OFFSET); @@ -135,7 +132,7 @@ void mm_bootstrap() page_base < max_ram_address; page_base += PAGE_SIZE) { - mm_map(page_base, page_base, 0, 1); + mm_early_map(page_base, page_base, 0, 1); } /* now map the kernel's virtual address space into RAM */ @@ -144,11 +141,11 @@ void mm_bootstrap() page_base += PAGE_SIZE) { /* map page_base to page_base - KERNEL_OFFSET */ - mm_map(page_base, page_base - KERNEL_OFFSET, 0, 1); + mm_early_map(page_base, page_base - KERNEL_OFFSET, 0, 1); } /* set up the global descriptor table */ - u32_t gdt_base = mm_page_alloc(); + u32_t gdt_base = mm_early_page_alloc(); mm_gdt = (u64_t *) ((u32_t) gdt_base + (u32_t) KERNEL_OFFSET); mm_gdt[0] = 0x0ull; mm_gdt[1] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 1); @@ -158,10 +155,45 @@ void mm_bootstrap() /* set the page directory base register */ set_cr3(page_directory); +} - stack_bootstrap(); +/************************************************************************** + * Map virtual_address to physical_address. * + * Both addresses should be page-aligned. * + * This 'early' version can be used during segmented bootstrapping * + *************************************************************************/ +int mm_early_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; + pagedirectory_entry_t * page_dir = page_directory; + page_dir = (pagedirectory_entry_t *)((u32_t)page_dir + KERNEL_OFFSET); - mm_use_virtual_offset = false; + if (page_dir[directory_index] == 0) + { + /* allocate a new page table */ + u32_t page_table_address = mm_early_page_alloc(); + if (page_table_address == 0) + { + return 0; + } + page_dir[directory_index] = page_table_address + | 0x1 << 2 /* PTs can be user mode */ + | 0x1 << 1 /* writable */ + | 0x1; /* present */ + } + u32_t page_table_address = page_dir[directory_index] & PAGE_HIGH_MASK; + + u32_t * page_table = (u32_t *) page_table_address; + 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 1; } /************************************************************************** @@ -174,10 +206,6 @@ int mm_map(u32_t virtual_address, u32_t physical_address, u32_t directory_index = (virtual_address >> 22) & 0x3FF; u32_t table_index = (virtual_address >> 12) & 0x3FF; pagedirectory_entry_t * page_dir = page_directory; - if (mm_use_virtual_offset) - { - page_dir = (pagedirectory_entry_t *)((u32_t)page_dir + KERNEL_OFFSET); - } if (page_dir[directory_index] == 0) { @@ -195,10 +223,6 @@ int mm_map(u32_t virtual_address, u32_t physical_address, u32_t page_table_address = page_dir[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 @@ -208,25 +232,41 @@ int mm_map(u32_t virtual_address, u32_t physical_address, return 1; } +/************************************************************************** + * Returns the physical base address of a page in RAM * + * or 0 if no pages were available * + * This 'early' version is to be called during segmented bootstrapping * + *************************************************************************/ +u32_t mm_early_page_alloc() +{ + u32_t page_address = 0; + if (mm_free_page_ptr != NULL) + { + u32_t * page_ptr = mm_free_page_ptr; + page_ptr = (u32_t *) ((u32_t)page_ptr + (u32_t)KERNEL_OFFSET); + page_address = (u32_t) mm_free_page_ptr; + mm_free_page_ptr = (u32_t *) *page_ptr; + mm_num_free_pages--; + mm_num_used_pages++; + } + return page_address; +} + /************************************************************************** * 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) + u32_t page_address = 0; + if (mm_free_page_ptr != NULL) { - return 0; + u32_t * page_ptr = mm_free_page_ptr; + page_address = (u32_t) mm_free_page_ptr; + mm_free_page_ptr = (u32_t *) *page_ptr; + mm_num_free_pages--; + mm_num_used_pages++; } - 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--; - mm_num_used_pages++; return page_address; } diff --git a/kernel/mm/mm.h b/kernel/mm/mm.h index c695b91..1562d32 100644 --- a/kernel/mm/mm.h +++ b/kernel/mm/mm.h @@ -21,9 +21,12 @@ typedef struct void mm_record_mmap_entry(mb_mmap_t * mmap); void mm_bootstrap(); +int mm_early_map(u32_t virtual_address, u32_t physical_address, + u32_t user_mode, u32_t writable); int mm_map(u32_t virtual_address, u32_t physical_address, u32_t user_mode, u32_t writable); +u32_t mm_early_page_alloc(); u32_t mm_page_alloc(); typedef struct diff --git a/kernel/mm/stack.cc b/kernel/mm/stack.cc index 952019b..30ebdf4 100755 --- a/kernel/mm/stack.cc +++ b/kernel/mm/stack.cc @@ -9,6 +9,6 @@ void stack_bootstrap() * running from our temporary stack while segmentation is enabled, * set up the "permanent" stack for use while paging */ - u32_t first_stack_page_base = mm_page_alloc(); - mm_map(KERNEL_STACK_TOP - PAGE_SIZE, first_stack_page_base, 0, 1); + u32_t first_stack_page_base = mm_early_page_alloc(); + mm_early_map(KERNEL_STACK_TOP - PAGE_SIZE, first_stack_page_base, 0, 1); }