1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
//! # MMU Functions
pub mod MMU {
pub const CACHABLE: u32 = 1 << 3;
pub const BUFFERABLE: u32 = 1 << 2;
pub const NO_PERMISSIONS_REQUIRED: u32 = 0b11 << 10;
pub const PERMISSIONS_REQUIRED: u32 = 0b01 << 10;
pub const BASE: u32 = 0x0004000;
pub const MASK: u32 = 0x1005;
}
/// # Start
pub fn mmu_start(init: u32, mask: u32) {
unsafe {
core::arch::asm!("mov r2, #0
// Invalidate Caches
mcr p15,0,r2,c7,c1,6
// Invalidate TLB entries
mcr p15,0,r2,c8,c7,0
// Data synchronisation barrier
dsb
// Set all domains to 0b11
mvn r2, #0
bic r2, #0xC
mcr p15,0,r2,c3,c0,0
// Set the translation table base address (remember to align 16 KiB!)
mcr p15,0,r0,c2,c0,0
mcr p15,0,r0,c2,c0,1
mov r3, #0
mcr p15,0,r3,c2,c0,2
// Set the bits mentioned above
mrc p15,0,r2,c1,c0,0
orr r2,r2,r1
mcr p15,0,r2,c1,c0,0", in("r0") init, in("r1") mask);
}
}
/// # Stop
pub fn mmu_stop() {
unsafe {
core::arch::asm!(
"mrc p15,0,r2,c1,c0,0
bic r2,#0x1000
bic r2,#0x0004
bic r2,#0x0001
mcr p15,0,r2,c1,c0,0"
);
}
}
pub fn tlb_invalidate() {
unsafe {
core::arch::asm!(
"mov r2, #0
// Invalidate Entries
mcr p15, 0, r2, c8, c7, 0
// DSB
mcr p15, 0, r2, c7, c10, 4"
);
}
}
pub fn mmu_section(virt: u32, phys: u32, flags: u32) {
use crate::cpu::store32;
let offset: u32 = virt >> 20;
let entry: u32 = MMU::BASE | (offset << 2);
let physv: u32 = (phys & 0xFFF00000) | (flags & 0x7FFC) | 0x00C02;
store32(entry, physv)
}
pub fn mmu_init() {
let mut addr: u32 = 0;
loop {
mmu_section(
addr,
addr,
MMU::CACHABLE | MMU::BUFFERABLE | MMU::NO_PERMISSIONS_REQUIRED,
);
if addr == 0xFFF00000 {
break;
}
addr += 0x00100000;
}
mmu_section(
0x3F200000,
0x3F200000,
MMU::CACHABLE | MMU::BUFFERABLE | MMU::PERMISSIONS_REQUIRED,
);
mmu_start(MMU::BASE, MMU::MASK);
}
|