Enable the MMU even if the kernel is not loaded in physical memory at
the same place it was linked against.
This commit is contained in:
31
kernel/mmu.c
31
kernel/mmu.c
@ -10,20 +10,41 @@
|
||||
#define cp_read(var, ...) _cp_read(var, __VA_ARGS__)
|
||||
#define cp_write(var, ...) _cp_write(var, __VA_ARGS__)
|
||||
|
||||
#define TT_BASE_SIZE (1<<14) /* 16k */
|
||||
|
||||
unsigned int *kernel_start_phys, *kernel_start_virt, *kernel_end_phys, *kernel_end_virt;
|
||||
|
||||
void mmu_reinit() {
|
||||
unsigned int *curr_tt_entry;
|
||||
extern unsigned int tt_base_virtual, tt_base_physical, start;
|
||||
unsigned int curr_addr;
|
||||
unsigned int *curr_tt_entry;
|
||||
int virt_phys_offset;
|
||||
|
||||
virt_phys_offset = tt_base_virtual - tt_base_physical;
|
||||
kernel_start_virt = &start;
|
||||
kernel_start_phys = kernel_start_virt - virt_phys_offset/4;
|
||||
kernel_end_virt = (unsigned int *)(tt_base_virtual + TT_BASE_SIZE);
|
||||
kernel_end_phys = (unsigned int *)(tt_base_physical + TT_BASE_SIZE);
|
||||
|
||||
//get the current translation table base address
|
||||
cp_read(curr_tt_entry, TTBR0);
|
||||
curr_tt_entry = (unsigned int *)tt_base_virtual;
|
||||
|
||||
//do first loop iteration outside the loop, because we have to check against wrapping back around to know we're done
|
||||
*curr_tt_entry = 0xc02;
|
||||
*curr_tt_entry = 0xc02; /* 0xc02 means read/write at any priviledge level, and that it's a section w/o PXN bit set */
|
||||
curr_tt_entry++;
|
||||
|
||||
//create identity mapping for entire address space using sections
|
||||
//create identity mapping for entire address space using sections.
|
||||
//BUT, if we've relocated the kernel from where it is in physical
|
||||
//memory, make sure we keep those mappings correct, and we'll actually
|
||||
//swap the twp mappings so all of memory is addressable.
|
||||
for (curr_addr = 0x00100000; curr_addr != 0; curr_addr += 0x00100000) {
|
||||
*curr_tt_entry = curr_addr | 0xc02;
|
||||
if ((unsigned int *)curr_addr >= kernel_start_phys && (unsigned int *)curr_addr < kernel_end_phys) {
|
||||
*curr_tt_entry = (curr_addr + virt_phys_offset) | 0xc02;
|
||||
} else if ((unsigned int *)curr_addr >= kernel_start_virt && (unsigned int *)curr_addr < kernel_end_virt) {
|
||||
*curr_tt_entry = (curr_addr - virt_phys_offset) | 0xc02;
|
||||
} else {
|
||||
*curr_tt_entry = curr_addr | 0xc02;
|
||||
}
|
||||
curr_tt_entry++;
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,6 @@
|
||||
#include <framebuffer.h>
|
||||
#include <console.h>
|
||||
|
||||
extern const unsigned int kernel_end;
|
||||
|
||||
struct fb myfb;
|
||||
|
||||
void video(void) {
|
||||
@ -64,7 +62,8 @@ int main(void) {
|
||||
//setup memory
|
||||
mm_init();
|
||||
mm_add_free_region((void*)0x60000000, (void*)0x7FFFFFFF);
|
||||
lower = (char*) &kernel_end;
|
||||
mm_add_free_region((void*)0x80000000, (void*)0x800FFFFF);
|
||||
lower = (char*) &kernel_end_virt;
|
||||
if ((unsigned int)lower % MM_PAGE_SIZE != 0)
|
||||
lower += (MM_PAGE_SIZE - ((unsigned int)lower % MM_PAGE_SIZE));
|
||||
mm_add_free_region((void*)lower, (void*)0x9FFFFFFF); //subtract the memory used by the kernel
|
||||
|
Reference in New Issue
Block a user