1
0
Fork 0
aedrix-kernel/kernel/mmu.c

51 lines
2.1 KiB
C
Raw Normal View History

#include <print.h>
#define SCTLR 15,0,1,0,0
#define TTBR0 15,0,2,0,0
#define TTBR1 15,0,2,0,1
#define TTBCR 15,0,2,0,2
#define _cp_read(var, cp, opc1, CRn, CRm, opc2) asm("mrc p" #cp ", " #opc1 ", %0, c" #CRn ", c" #CRm ", " #opc2 ";" : "=r"(var) : )
#define _cp_write(var, cp, opc1, CRn, CRm, opc2) asm("mcr p" #cp ", " #opc1 ", %0, c" #CRn ", c" #CRm ", " #opc2 ";" : : "r"(var) )
#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() {
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
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; /* 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.
//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) {
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++;
}
}