1/* 2 * cortex arm arch v7 cache flushing and invalidation 3 * included by l.s and rebootcode.s 4 */ 5 6TEXT cacheiinv(SB), $-4 /* I invalidate */ 7 MOVW $0, R0 8 MTCP CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall /* ok on cortex */ 9 ISB 10 RET 11 12/* 13 * set/way operators, passed a suitable set/way value in R0. 14 */ 15TEXT cachedwb_sw(SB), $-4 16 MTCP CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEsi 17 RET 18 19TEXT cachedwbinv_sw(SB), $-4 20 MTCP CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEsi 21 RET 22 23TEXT cachedinv_sw(SB), $-4 24 MTCP CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEsi 25 RET 26 27 /* set cache size select */ 28TEXT setcachelvl(SB), $-4 29 MTCP CpSC, CpIDcssel, R0, C(CpID), C(CpIDidct), 0 30 ISB 31 RET 32 33 /* return cache sizes */ 34TEXT getwayssets(SB), $-4 35 MFCP CpSC, CpIDcsize, R0, C(CpID), C(CpIDidct), 0 36 RET 37 38/* 39 * l1 cache operations. 40 * l1 and l2 ops are intended to be called from C, thus need save no 41 * caller's regs, only those we need to preserve across calls. 42 */ 43 44TEXT cachedwb(SB), $-4 45 MOVW.W R14, -8(R13) 46 MOVW $cachedwb_sw(SB), R0 47 MOVW $1, R8 48 BL wholecache(SB) 49 MOVW.P 8(R13), R15 50 51TEXT cachedwbinv(SB), $-4 52 MOVW.W R14, -8(R13) 53 MOVW $cachedwbinv_sw(SB), R0 54 MOVW $1, R8 55 BL wholecache(SB) 56 MOVW.P 8(R13), R15 57 58TEXT cachedinv(SB), $-4 59 MOVW.W R14, -8(R13) 60 MOVW $cachedinv_sw(SB), R0 61 MOVW $1, R8 62 BL wholecache(SB) 63 MOVW.P 8(R13), R15 64 65TEXT cacheuwbinv(SB), $-4 66 MOVM.DB.W [R14], (R13) /* save lr on stack */ 67 MOVW CPSR, R1 68 CPSID /* splhi */ 69 70 MOVM.DB.W [R1], (R13) /* save R1 on stack */ 71 72 BL cachedwbinv(SB) 73 BL cacheiinv(SB) 74 75 MOVM.IA.W (R13), [R1] /* restore R1 (saved CPSR) */ 76 MOVW R1, CPSR 77 MOVM.IA.W (R13), [R14] /* restore lr */ 78 RET 79 80/* 81 * architectural l2 cache operations 82 */ 83 84TEXT _l2cacheuwb(SB), $-4 85 MOVW.W R14, -8(R13) 86 MOVW $cachedwb_sw(SB), R0 87 MOVW $2, R8 88 BL wholecache(SB) 89 MOVW.P 8(R13), R15 /* return */ 90 91TEXT _l2cacheuwbinv(SB), $-4 92 MOVW.W R14, -8(R13) 93 MOVW CPSR, R1 94 CPSID /* splhi */ 95 96 MOVM.DB.W [R1], (R13) /* save R1 on stack */ 97 98 MOVW $cachedwbinv_sw(SB), R0 99 MOVW $2, R8 100 BL wholecache(SB) 101 102 BL _l2cacheuinv(SB) 103 104 MOVM.IA.W (R13), [R1] /* restore R1 (saved CPSR) */ 105 MOVW R1, CPSR 106 MOVW.P 8(R13), R15 /* return */ 107 108TEXT _l2cacheuinv(SB), $-4 109 MOVW.W R14, -8(R13) 110 MOVW $cachedinv_sw(SB), R0 111 MOVW $2, R8 112 BL wholecache(SB) 113 MOVW.P 8(R13), R15 /* return */ 114 115/* 116 * callers are assumed to be the above l1 and l2 ops. 117 * R0 is the function to call in the innermost loop. 118 * R8 is the cache level (1-origin: 1 or 2). 119 * 120 * R0 func to call at entry 121 * R1 func to call after entry 122 * R2 nsets 123 * R3 way shift (computed from R8) 124 * R4 set shift (computed from R8) 125 * R5 nways 126 * R6 set scratch 127 * R7 way scratch 128 * R8 cache level, 0-origin 129 * R9 extern reg up 130 * R10 extern reg m 131 * 132 * initial translation by 5c, then massaged by hand. 133 */ 134TEXT wholecache+0(SB), $-4 135 MOVW CPSR, R2 136 MOVM.DB.W [R2,R14], (SP) /* save regs on stack */ 137 138 MOVW R0, R1 /* save argument for inner loop in R1 */ 139 SUB $1, R8 /* convert cache level to zero origin */ 140 141 /* we might not have the MMU on yet, so map R1 (func) to R14's space */ 142 MOVW R14, R0 /* get R14's segment ... */ 143 AND $KSEGM, R0 144 BIC $KSEGM, R1 /* strip segment from func address */ 145 ORR R0, R1 /* combine them */ 146 147 /* get cache sizes */ 148 SLL $1, R8, R0 /* R0 = (cache - 1) << 1 */ 149 MTCP CpSC, CpIDcssel, R0, C(CpID), C(CpIDidct), 0 /* set cache select */ 150 ISB 151 MFCP CpSC, CpIDcsize, R0, C(CpID), C(CpIDidct), 0 /* get cache sizes */ 152 153 /* compute # of ways and sets for this cache level */ 154 SRA $3, R0, R5 /* R5 (ways) = R0 >> 3 */ 155 AND $((1<<10)-1), R5 /* R5 = (R0 >> 3) & MASK(10) */ 156 ADD $1, R5 /* R5 (ways) = ((R0 >> 3) & MASK(10)) + 1 */ 157 158 SRA $13, R0, R2 /* R2 = R0 >> 13 */ 159 AND $((1<<15)-1), R2 /* R2 = (R0 >> 13) & MASK(15) */ 160 ADD $1, R2 /* R2 (sets) = ((R0 >> 13) & MASK(15)) + 1 */ 161 162 /* precompute set/way shifts for inner loop */ 163 MOVW $(CACHECONF+0), R3 /* +0 = l1waysh */ 164 MOVW $(CACHECONF+4), R4 /* +4 = l1setsh */ 165 CMP $0, R8 /* cache == 1? */ 166 ADD.NE $(4*2), R3 /* no, assume l2: +8 = l2waysh */ 167 ADD.NE $(4*2), R3 /* +12 = l2setsh */ 168 169 MOVW R14, R0 /* get R14's segment ... */ 170 AND $KSEGM, R0 171 172 BIC $KSEGM, R3 /* strip segment from address */ 173 ORR R0, R3 /* combine them */ 174 BIC $KSEGM, R4 /* strip segment from address */ 175 ORR R0, R4 /* combine them */ 176 MOVW (R3), R3 177 MOVW (R4), R4 178 179 CMP $0, R3 /* sanity checks */ 180 BEQ wbuggery 181 CMP $0, R4 182 BEQ sbuggery 183 184 CPSID /* splhi to make entire op atomic */ 185 BARRIERS 186 187 /* iterate over ways */ 188 MOVW $0, R7 /* R7: way */ 189outer: 190 /* iterate over sets */ 191 MOVW $0, R6 /* R6: set */ 192inner: 193 /* compute set/way register contents */ 194 SLL R3, R7, R0 /* R0 = way << R3 (L?WAYSH) */ 195 ORR R8<<1, R0 /* R0 = way << L?WAYSH | (cache - 1) << 1 */ 196 ORR R6<<R4, R0 /* R0 = way<<L?WAYSH | (cache-1)<<1 |set<<R4 */ 197 198 BL (R1) /* call set/way operation with R0 arg. */ 199 200 ADD $1, R6 /* set++ */ 201 CMP R2, R6 /* set >= sets? */ 202 BLT inner /* no, do next set */ 203 204 ADD $1, R7 /* way++ */ 205 CMP R5, R7 /* way >= ways? */ 206 BLT outer /* no, do next way */ 207 208 MOVM.IA.W (SP), [R2,R14] /* restore regs */ 209 BARRIERS 210 MOVW R2, CPSR /* splx */ 211 212 RET 213 214wbuggery: 215 PUTC('?') 216 PUTC('c') 217 PUTC('w') 218 B topanic 219sbuggery: 220 PUTC('?') 221 PUTC('c') 222 PUTC('s') 223topanic: 224 MOVW $.string<>+0(SB), R0 225 BIC $KSEGM, R0 /* strip segment from address */ 226 MOVW R14, R1 /* get R14's segment ... */ 227 AND $KSEGM, R1 228 ORR R1, R0 /* combine them */ 229 SUB $12, R13 /* not that it matters, since we're panicing */ 230 MOVW R14, 8(R13) 231 BL panic(SB) /* panic("msg %#p", LR) */ 232bugloop: 233 WFI 234 B bugloop 235 236 DATA .string<>+0(SB)/8,$"bad cach" 237 DATA .string<>+8(SB)/8,$"e params" 238 DATA .string<>+16(SB)/8,$"\073 pc %\043p" 239 DATA .string<>+24(SB)/1,$"\z" 240 GLOBL .string<>+0(SB),$25 241