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