Created
July 13, 2019 19:30
-
-
Save Thalhammer/da550b3bc1040699f01e34a9a877837c to your computer and use it in GitHub Desktop.
RPI mmu
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "mmu.h" | |
#include "dmesg.h" | |
#include <rpi/console.h> | |
namespace sys { | |
union mmu_descriptor { | |
uint32_t as_uint; | |
struct { | |
uint32_t state: 2; | |
uint32_t writebuffer: 1; | |
uint32_t cachable: 1; | |
uint32_t sbz2: 1; | |
uint32_t domain: 2; | |
uint32_t imp: 1; | |
uint32_t ap: 2; | |
uint32_t tex: 3; | |
uint32_t sbz: 5; | |
uint32_t base: 12; | |
}; | |
}; | |
static_assert(sizeof(mmu_descriptor) == sizeof(uint32_t)); | |
extern "C" void mmu_init(void* ptr); | |
extern "C" void tlb_invalidate(); | |
// Visual code complains such a large alignment, but gcc is fine and it works! | |
static mmu_descriptor base_table[4096] __attribute__ ((aligned(0x4000))); | |
void mmu::mmu_enable() noexcept { | |
mmu_init(base_table); | |
} | |
void mmu::init() noexcept { | |
dmesg::log("mmu","mmu base table = 0x%08x", (uint32_t)&base_table); | |
memset(base_table, 0, sizeof(base_table)); | |
// Map memory as cachable | |
for(size_t i = 0; i < 512; i++) // TODO: Automatic ram size detection | |
map_section(i*(1 << 20), i*(1 << 20), true, true); | |
// Map io as non cachable | |
for(size_t i = 0; i < 16; i++) | |
map_section(0x20000000 + i*(1 << 20), 0x20000000 + i*(1 << 20), false, false); | |
dmesg::log("mmu", "entry: %u %u %u %u %u %u %u %u %u %u", base_table[0].base, base_table[0].sbz, base_table[0].tex, base_table[0].ap, base_table[0].imp, base_table[0].domain, base_table[0].sbz2, base_table[0].cachable, base_table[0].writebuffer, base_table[0].state); | |
mmu_enable(); | |
dmesg::log("mmu", "mmu enabled"); | |
} | |
bool mmu::map_section(uint32_t virt, uint32_t phys, bool cachable, bool wrtbuffer) noexcept { | |
// mask lower 20 bits of physical address then ORR flags and 0x02 for 1 MiB | |
uint32_t physval = (phys & 0xfff00000) | (((cachable ? 0x08 : 0) | (wrtbuffer ? 0x04 : 0)) & 0x7ffc) | 0x02 | (0b11 << 8); | |
base_table[virt >> 20].as_uint = physval; | |
return true; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.global mmu_init | |
mmu_init: | |
mov r1,#0 | |
// invalidate caches | |
mcr p15,0,r1,c7,c7,0 | |
// invalidate TLB entries | |
mcr p15,0,r1,c8,c7,0 | |
// data synchronisation barrier | |
mcr p15,0,r1,c7,c10,4 | |
// set all domains | |
ldr r1, =0xffffffff | |
mcr p15,0,r1,c3,c0,0 | |
// set the translation table base address (remember to align 16 KiB!) | |
mcr p15,0,r0,c2,c0,0 | |
// set the bits mentioned above | |
ldr r1, =0x00401805 | |
//ldr r1, =0x00000001 | |
mrc p15,0,r2,c1,c0,0 | |
orr r2,r2,r1 | |
mcr p15,0,r2,c1,c0,0 | |
bx lr | |
.globl mmu_deinit | |
mmu_deinit: | |
mrc p15,0,r2,c1,c0,0 | |
bic r2,#0x1000 | |
bic r2,#0x0004 | |
bic r2,#0x0001 | |
mcr p15,0,r2,c1,c0,0 | |
bx lr | |
.globl tlb_invalidate | |
tlb_invalidate: | |
mov r2,#0 | |
// invalidate TLB entries | |
mcr p15,0,r1,c8,c7,0 | |
// data synchronisation barrier | |
mcr p15,0,r1,c7,c10,4 | |
mov pc,lr |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment