1/* $NetBSD: cpufunc_asm_sa1.S,v 1.5 2002/05/03 16:45:22 rjs Exp $ */ 2 3/* 4 * Copyright (c) 1997,1998 Mark Brinicombe. 5 * Copyright (c) 1997 Causality Limited 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Causality Limited. 19 * 4. The name of Causality Limited may not be used to endorse or promote 20 * products derived from this software without specific prior written 21 * permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS 24 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, 27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * SA-1 assembly functions for CPU / MMU / TLB specific operations 36 */ 37 38#include <machine/cpu.h> 39#include <machine/asm.h> 40 41Lblock_userspace_access: 42 .word _C_LABEL(block_userspace_access) 43 44/* 45 * Functions to set the MMU Translation Table Base register 46 * 47 * We need to clean and flush the cache as it uses virtual 48 * addresses that are about to change. 49 */ 50ENTRY(sa1_setttb) 51#ifdef CACHE_CLEAN_BLOCK_INTR 52 mrs r3, cpsr_all 53 orr r1, r3, #(I32_bit | F32_bit) 54 msr cpsr_all, r1 55#else 56 ldr r3, Lblock_userspace_access 57 ldr r2, [r3] 58 orr r1, r2, #1 59 str r1, [r3] 60#endif 61 stmfd sp!, {r0-r3, lr} 62 bl _C_LABEL(sa1_cache_cleanID) 63 ldmfd sp!, {r0-r3, lr} 64 mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */ 65 mcr p15, 0, r0, c7, c10, 4 /* drain write and fill buffer */ 66 67 /* Write the TTB */ 68 mcr p15, 0, r0, c2, c0, 0 69 70 /* If we have updated the TTB we must flush the TLB */ 71 mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLB */ 72 73 /* The cleanID above means we only need to flush the I cache here */ 74 mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */ 75 76 /* Make sure that pipeline is emptied */ 77 mov r0, r0 78 mov r0, r0 79#ifdef CACHE_CLEAN_BLOCK_INTR 80 msr cpsr_all, r3 81#else 82 str r2, [r3] 83#endif 84 mov pc, lr 85 86/* 87 * TLB functions 88 */ 89ENTRY(sa1_tlb_flushID_SE) 90 mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */ 91 mcr p15, 0, r0, c8, c5, 0 /* flush I tlb */ 92 mov pc, lr 93 94/* 95 * Cache functions 96 */ 97ENTRY(sa1_cache_flushID) 98 mcr p15, 0, r0, c7, c7, 0 /* flush I+D cache */ 99 mov pc, lr 100 101ENTRY(sa1_cache_flushI) 102 mcr p15, 0, r0, c7, c5, 0 /* flush I cache */ 103 mov pc, lr 104 105ENTRY(sa1_cache_flushD) 106 mcr p15, 0, r0, c7, c6, 0 /* flush D cache */ 107 mov pc, lr 108 109ENTRY(sa1_cache_flushD_SE) 110 mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 111 mov pc, lr 112 113ENTRY(sa1_cache_cleanD_E) 114 mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 115 mov pc, lr 116 117/* 118 * Information for the SA-1 cache clean/purge functions: 119 * 120 * * Virtual address of the memory region to use 121 * * Size of memory region 122 */ 123 .data 124 125 .global _C_LABEL(sa1_cache_clean_addr) 126_C_LABEL(sa1_cache_clean_addr): 127 .word 0xf0000000 128 129 .global _C_LABEL(sa1_cache_clean_size) 130_C_LABEL(sa1_cache_clean_size): 131#if defined(CPU_SA1100) || defined(CPU_SA1110) 132 .word 0x00004000 133#else 134 .word 0x00008000 135#endif 136 137 .text 138 139Lsa1_cache_clean_addr: 140 .word _C_LABEL(sa1_cache_clean_addr) 141Lsa1_cache_clean_size: 142 .word _C_LABEL(sa1_cache_clean_size) 143 144#ifdef CACHE_CLEAN_BLOCK_INTR 145#define SA1_CACHE_CLEAN_BLOCK \ 146 mrs r3, cpsr_all ; \ 147 orr r0, r3, #(I32_bit | F32_bit) ; \ 148 msr cpsr_all, r0 149 150#define SA1_CACHE_CLEAN_UNBLOCK \ 151 msr cpsr_all, r3 152#else 153#define SA1_CACHE_CLEAN_BLOCK \ 154 ldr r3, Lblock_userspace_access ; \ 155 ldr ip, [r3] ; \ 156 orr r0, ip, #1 ; \ 157 str r0, [r3] 158 159#define SA1_CACHE_CLEAN_UNBLOCK \ 160 str ip, [r3] 161#endif /* CACHE_CLEAN_BLOCK_INTR */ 162 163#ifdef DOUBLE_CACHE_CLEAN_BANK 164#define SA1_DOUBLE_CACHE_CLEAN_BANK \ 165 eor r0, r0, r1 ; \ 166 str r0, [r2] 167#else 168#define SA1_DOUBLE_CACHE_CLEAN_BANK /* nothing */ 169#endif /* DOUBLE_CACHE_CLEAN_BANK */ 170 171#define SA1_CACHE_CLEAN_PROLOGUE \ 172 SA1_CACHE_CLEAN_BLOCK ; \ 173 ldr r2, Lsa1_cache_clean_addr ; \ 174 ldmia r2, {r0, r1} ; \ 175 SA1_DOUBLE_CACHE_CLEAN_BANK 176 177#define SA1_CACHE_CLEAN_EPILOGUE \ 178 SA1_CACHE_CLEAN_UNBLOCK 179 180ENTRY_NP(sa1_cache_syncI) 181ENTRY_NP(sa1_cache_purgeID) 182 mcr p15, 0, r0, c7, c5, 0 /* flush I cache (D cleaned below) */ 183ENTRY_NP(sa1_cache_cleanID) 184ENTRY_NP(sa1_cache_purgeD) 185ENTRY(sa1_cache_cleanD) 186 SA1_CACHE_CLEAN_PROLOGUE 187 1881: ldr r2, [r0], #32 189 subs r1, r1, #32 190 bne 1b 191 192 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 193 194 SA1_CACHE_CLEAN_EPILOGUE 195 mov pc, lr 196 197ENTRY(sa1_cache_purgeID_E) 198 mcr p15, 0, r0, c7, c10, 1 /* clean dcache entry */ 199 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 200 mcr p15, 0, r0, c7, c5, 0 /* flush I cache */ 201 mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 202 mov pc, lr 203 204ENTRY(sa1_cache_purgeD_E) 205 mcr p15, 0, r0, c7, c10, 1 /* clean dcache entry */ 206 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 207 mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 208 mov pc, lr 209 210/* 211 * Soft functions 212 */ 213/* sa1_cache_syncI is identical to sa1_cache_purgeID */ 214 215ENTRY(sa1_cache_cleanID_rng) 216ENTRY(sa1_cache_cleanD_rng) 217 cmp r1, #0x4000 218 bcs _C_LABEL(sa1_cache_cleanID) 219 220 and r2, r0, #0x1f 221 add r1, r1, r2 222 bic r0, r0, #0x1f 223 2241: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 225 add r0, r0, #32 226 subs r1, r1, #32 227 bpl 1b 228 229 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 230 mov pc, lr 231 232ENTRY(sa1_cache_purgeID_rng) 233 cmp r1, #0x4000 234 bcs _C_LABEL(sa1_cache_purgeID) 235 236 and r2, r0, #0x1f 237 add r1, r1, r2 238 bic r0, r0, #0x1f 239 2401: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 241 mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 242 add r0, r0, #32 243 subs r1, r1, #32 244 bpl 1b 245 246 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 247 mcr p15, 0, r0, c7, c5, 0 /* flush I cache */ 248 mov pc, lr 249 250ENTRY(sa1_cache_purgeD_rng) 251 cmp r1, #0x4000 252 bcs _C_LABEL(sa1_cache_purgeD) 253 254 and r2, r0, #0x1f 255 add r1, r1, r2 256 bic r0, r0, #0x1f 257 2581: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 259 mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 260 add r0, r0, #32 261 subs r1, r1, #32 262 bpl 1b 263 264 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 265 mov pc, lr 266 267ENTRY(sa1_cache_syncI_rng) 268 cmp r1, #0x4000 269 bcs _C_LABEL(sa1_cache_syncI) 270 271 and r2, r0, #0x1f 272 add r1, r1, r2 273 bic r0, r0, #0x1f 274 2751: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 276 add r0, r0, #32 277 subs r1, r1, #32 278 bpl 1b 279 280 mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 281 mcr p15, 0, r0, c7, c5, 0 /* flush I cache */ 282 283 mov pc, lr 284 285/* 286 * Context switch. 287 * 288 * These is the CPU-specific parts of the context switcher cpu_switch() 289 * These functions actually perform the TTB reload. 290 * 291 * NOTE: Special calling convention 292 * r1, r4-r13 must be preserved 293 */ 294#if defined(CPU_SA110) 295ENTRY(sa110_context_switch) 296 /* 297 * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this. 298 * Thus the data cache will contain only kernel data and the 299 * instruction cache will contain only kernel code, and all 300 * kernel mappings are shared by all processes. 301 */ 302 303 /* Write the TTB */ 304 mcr p15, 0, r0, c2, c0, 0 305 306 /* If we have updated the TTB we must flush the TLB */ 307 mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */ 308 309 /* Make sure that pipeline is emptied */ 310 mov r0, r0 311 mov r0, r0 312 mov pc, lr 313#endif 314 315 316