github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/arm/mmu.go (about) 1 // ARM processor support 2 // https://github.com/f-secure-foundry/tamago 3 // 4 // Copyright (c) F-Secure Corporation 5 // https://foundry.f-secure.com 6 // 7 // Use of this source code is governed by the license 8 // that can be found in the LICENSE file. 9 10 package arm 11 12 import ( 13 "runtime" 14 15 "github.com/f-secure-foundry/tamago/internal/reg" 16 ) 17 18 const ( 19 l1pageTableOffset = 0x4000 20 l1pageTableSize = 0x4000 21 l2pageTableOffset = 0xc000 22 l2pageTableSize = 0x4000 23 ) 24 25 // Memory region attributes 26 // (Table B3-10, ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition). 27 const ( 28 TTE_PAGE_TABLE uint32 = (1 << 0) 29 TTE_SECTION uint32 = (1 << 1) 30 TTE_BUFFERABLE uint32 = (1 << 2) 31 TTE_CACHEABLE uint32 = (1 << 3) 32 TTE_EXECUTE_NEVER uint32 = (1 << 4) 33 TTE_SUPERSECTION uint32 = (1 << 18) | (1 << 1) 34 TTE_NS uint32 = (1 << 19) 35 ) 36 37 // MMU access permissions 38 // (Table B3-8, ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition). 39 const ( 40 // PL1: no access PL0: no access 41 TTE_AP_000 uint32 = 0b000 42 // PL1: read/write PL0: no access 43 TTE_AP_001 uint32 = 0b001 44 // PL1: read/write PL0: read only 45 TTE_AP_010 uint32 = 0b010 46 // PL1: read/write PL0: read/write 47 TTE_AP_011 uint32 = 0b011 48 // Reserved 49 TTE_AP_100 uint32 = 0b100 50 // PL1: read only PL0: no access 51 TTE_AP_101 uint32 = 0b101 52 // PL1: read only PL0: read only 53 TTE_AP_110 uint32 = 0b110 54 // PL1: read only PL0: read only 55 TTE_AP_111 uint32 = 0b111 56 ) 57 58 // defined in mmu.s 59 func set_ttbr0(addr uint32) 60 61 // ConfigureMMU (re)configures the first-level translation tables for the 62 // provided memory range with the passed attribute flags. 63 func (cpu *CPU) ConfigureMMU(start uint32, end uint32, flags uint32) { 64 ramStart, _ := runtime.MemRegion() 65 l1pageTableStart := ramStart + l1pageTableOffset 66 67 start = start >> 20 68 end = end >> 20 69 70 for i := uint32(0); i < l1pageTableSize/4; i++ { 71 page := l1pageTableStart + 4*i 72 pa := i << 20 73 74 if i < start { 75 continue 76 } 77 78 if i >= end { 79 break 80 } 81 82 reg.Write(page, pa|flags) 83 } 84 85 cpu.FlushDataCache() 86 set_ttbr0(l1pageTableStart) 87 } 88 89 // InitMMU initializes the first-level translation tables for all available 90 // memory with a flat mapping and privileged attribute flags. 91 // 92 // The first 4096 bytes (0x00000000 - 0x00001000) are flagged as invalid to 93 // trap null pointers, applications that need to make use of this memory space 94 // must use ConfigureMMU to reconfigure as required. 95 func (cpu *CPU) InitMMU() { 96 start, end := runtime.MemRegion() 97 98 l1pageTableStart := start + l1pageTableOffset 99 l2pageTableStart := start + l2pageTableOffset 100 101 // First level address translation 102 // 9.4, ARM® Cortex™ -A Series Programmer’s Guide 103 104 memAttr := (TTE_AP_001&0b11)<<10 | TTE_CACHEABLE | TTE_BUFFERABLE | TTE_SECTION 105 devAttr := (TTE_AP_001&0b11)<<10 | TTE_SECTION 106 107 // The first section is mapped with an L2 entry as we need to map the 108 // smallest possible section starting from 0x0 as invalid to trap null 109 // pointers. 110 firstSection := l2pageTableStart | TTE_PAGE_TABLE 111 reg.Write(l1pageTableStart, firstSection) 112 113 for i := uint32(1); i < l1pageTableSize/4; i++ { 114 page := l1pageTableStart + 4*i 115 pa := i << 20 116 117 if pa >= start && pa < end { 118 reg.Write(page, pa|memAttr) 119 } else { 120 reg.Write(page, pa|devAttr) 121 } 122 } 123 124 // Level 2 translation tables 125 // 9.5, ARM® Cortex™ -A Series Programmer’s Guide 126 127 memAttr = (TTE_AP_001&0b11)<<4 | TTE_CACHEABLE | TTE_BUFFERABLE | TTE_SECTION 128 devAttr = (TTE_AP_001&0b11)<<4 | TTE_SECTION 129 130 // trap nil pointers by setting the first 4KB section as invalid 131 reg.Write(l2pageTableStart, 0) 132 133 for i := uint32(1); i < 256; i++ { 134 page := l2pageTableStart + 4*i 135 pa := i << 12 136 137 if pa >= start && pa < end { 138 reg.Write(page, pa|memAttr) 139 } else { 140 reg.Write(page, pa|devAttr) 141 } 142 } 143 144 set_ttbr0(l1pageTableStart) 145 }