1171617Scognet/* $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $ */ 2171617Scognet 3171617Scognet/*- 4171617Scognet * Copyright (c) 2007 Olivier Houchard 5171617Scognet * Copyright (c) 2001, 2002 Wasabi Systems, Inc. 6171617Scognet * All rights reserved. 7171617Scognet * 8171617Scognet * Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc. 9171617Scognet * 10171617Scognet * Redistribution and use in source and binary forms, with or without 11171617Scognet * modification, are permitted provided that the following conditions 12171617Scognet * are met: 13171617Scognet * 1. Redistributions of source code must retain the above copyright 14171617Scognet * notice, this list of conditions and the following disclaimer. 15171617Scognet * 2. Redistributions in binary form must reproduce the above copyright 16171617Scognet * notice, this list of conditions and the following disclaimer in the 17171617Scognet * documentation and/or other materials provided with the distribution. 18171617Scognet * 3. All advertising materials mentioning features or use of this software 19171617Scognet * must display the following acknowledgement: 20171617Scognet * This product includes software developed for the NetBSD Project by 21171617Scognet * Wasabi Systems, Inc. 22171617Scognet * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23171617Scognet * or promote products derived from this software without specific prior 24171617Scognet * written permission. 25171617Scognet * 26171617Scognet * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27171617Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28171617Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29171617Scognet * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30171617Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31171617Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32171617Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33171617Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34171617Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35171617Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36171617Scognet * POSSIBILITY OF SUCH DAMAGE. 37171617Scognet * 38171617Scognet */ 39171617Scognet 40171617Scognet/*- 41171617Scognet * Copyright (c) 2001 Matt Thomas. 42171617Scognet * Copyright (c) 1997,1998 Mark Brinicombe. 43171617Scognet * Copyright (c) 1997 Causality Limited 44171617Scognet * All rights reserved. 45171617Scognet * 46171617Scognet * Redistribution and use in source and binary forms, with or without 47171617Scognet * modification, are permitted provided that the following conditions 48171617Scognet * are met: 49171617Scognet * 1. Redistributions of source code must retain the above copyright 50171617Scognet * notice, this list of conditions and the following disclaimer. 51171617Scognet * 2. Redistributions in binary form must reproduce the above copyright 52171617Scognet * notice, this list of conditions and the following disclaimer in the 53171617Scognet * documentation and/or other materials provided with the distribution. 54171617Scognet * 3. All advertising materials mentioning features or use of this software 55171617Scognet * must display the following acknowledgement: 56171617Scognet * This product includes software developed by Causality Limited. 57171617Scognet * 4. The name of Causality Limited may not be used to endorse or promote 58171617Scognet * products derived from this software without specific prior written 59171617Scognet * permission. 60171617Scognet * 61171617Scognet * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS 62171617Scognet * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 63171617Scognet * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 64171617Scognet * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, 65171617Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 66171617Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 67171617Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68171617Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69171617Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70171617Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71171617Scognet * SUCH DAMAGE. 72171617Scognet * 73171617Scognet * XScale core 3 assembly functions for CPU / MMU / TLB specific operations 74171617Scognet */ 75251866Sscottl 76171617Scognet#include <machine/asm.h> 77171617Scognet__FBSDID("$FreeBSD$"); 78171617Scognet 79171617Scognet/* 80171617Scognet * Size of the XScale core D-cache. 81171617Scognet */ 82171617Scognet#define DCACHE_SIZE 0x00008000 83171617Scognet 84171617Scognet.Lblock_userspace_access: 85171617Scognet .word _C_LABEL(block_userspace_access) 86171617Scognet 87171617Scognet/* 88171617Scognet * CPWAIT -- Canonical method to wait for CP15 update. 89171617Scognet * From: Intel 80200 manual, section 2.3.3. 90171617Scognet * 91171617Scognet * NOTE: Clobbers the specified temp reg. 92171617Scognet */ 93171617Scognet#define CPWAIT_BRANCH \ 94171617Scognet sub pc, pc, #4 95171617Scognet 96171617Scognet#define CPWAIT(tmp) \ 97171617Scognet mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 98171617Scognet mov tmp, tmp /* wait for it to complete */ ;\ 99171617Scognet CPWAIT_BRANCH /* branch to next insn */ 100171617Scognet 101171617Scognet#define CPWAIT_AND_RETURN_SHIFTER lsr #32 102171617Scognet 103171617Scognet#define CPWAIT_AND_RETURN(tmp) \ 104171617Scognet mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 105171617Scognet /* Wait for it to complete and branch to the return address */ \ 106171617Scognet sub pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER 107171617Scognet 108171617Scognet#define ARM_USE_L2_CACHE 109171617Scognet 110171617Scognet#define L2_CACHE_SIZE 0x80000 111171617Scognet#define L2_CACHE_WAYS 8 112171617Scognet#define L2_CACHE_LINE_SIZE 32 113171617Scognet#define L2_CACHE_SETS (L2_CACHE_SIZE / \ 114171617Scognet (L2_CACHE_WAYS * L2_CACHE_LINE_SIZE)) 115171617Scognet 116171617Scognet#define L1_DCACHE_SIZE 32 * 1024 117171617Scognet#define L1_DCACHE_WAYS 4 118171617Scognet#define L1_DCACHE_LINE_SIZE 32 119171617Scognet#define L1_DCACHE_SETS (L1_DCACHE_SIZE / \ 120171617Scognet (L1_DCACHE_WAYS * L1_DCACHE_LINE_SIZE)) 121171617Scognet#ifdef CACHE_CLEAN_BLOCK_INTR 122171617Scognet#define XSCALE_CACHE_CLEAN_BLOCK \ 123171617Scognet stmfd sp!, {r4} ; \ 124171617Scognet mrs r4, cpsr_all ; \ 125171617Scognet orr r0, r4, #(I32_bit | F32_bit) ; \ 126171617Scognet msr cpsr_all, r0 127171617Scognet 128171617Scognet#define XSCALE_CACHE_CLEAN_UNBLOCK \ 129171617Scognet msr cpsr_all, r4 ; \ 130171617Scognet ldmfd sp!, {r4} 131171617Scognet#else 132171617Scognet#define XSCALE_CACHE_CLEAN_BLOCK \ 133171617Scognet stmfd sp!, {r4} ; \ 134171617Scognet ldr r4, .Lblock_userspace_access ; \ 135171617Scognet ldr ip, [r4] ; \ 136171617Scognet orr r0, ip, #1 ; \ 137171617Scognet str r0, [r4] 138171617Scognet 139171617Scognet#define XSCALE_CACHE_CLEAN_UNBLOCK \ 140171617Scognet str ip, [r3] ; \ 141171617Scognet ldmfd sp!, {r4} 142171617Scognet#endif /* CACHE_CLEAN_BLOCK_INTR */ 143171617Scognet 144171617Scognet 145171617ScognetENTRY_NP(xscalec3_cache_syncI) 146171617ScognetENTRY_NP(xscalec3_cache_purgeID) 147171617Scognet mcr p15, 0, r0, c7, c5, 0 /* flush I cache (D cleaned below) */ 148171617ScognetENTRY_NP(xscalec3_cache_cleanID) 149171617ScognetENTRY_NP(xscalec3_cache_purgeD) 150171617ScognetENTRY(xscalec3_cache_cleanD) 151171617Scognet 152171617Scognet XSCALE_CACHE_CLEAN_BLOCK 153171617Scognet mov r0, #0 154171617Scognet1: 155171617Scognet mov r1, r0, asl #30 156171617Scognet mov r2, #0 157171617Scognet2: 158171617Scognet orr r3, r1, r2, asl #5 159171617Scognet mcr p15, 0, r3, c7, c14, 2 /* clean and invalidate */ 160171617Scognet add r2, r2, #1 161171617Scognet cmp r2, #L1_DCACHE_SETS 162171617Scognet bne 2b 163171617Scognet add r0, r0, #1 164171617Scognet cmp r0, #4 165171617Scognet bne 1b 166171617Scognet CPWAIT(r0) 167171617Scognet XSCALE_CACHE_CLEAN_UNBLOCK 168171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 169171617Scognet 170171617Scognet RET 171171617Scognet 172171617ScognetENTRY(xscalec3_cache_purgeID_rng) 173171617Scognet 174171617Scognet cmp r1, #0x4000 175171617Scognet bcs _C_LABEL(xscalec3_cache_cleanID) 176171617Scognet and r2, r0, #0x1f 177171617Scognet add r1, r1, r2 178171617Scognet bic r0, r0, #0x1f 179171617Scognet 180171617Scognet1: mcr p15, 0, r0, c7, c14, 1 /* clean/invalidate L1 D cache entry */ 181171617Scognet nop 182171617Scognet mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ 183171617Scognet add r0, r0, #32 184171617Scognet subs r1, r1, #32 185171617Scognet bhi 1b 186171617Scognet 187171617Scognet CPWAIT(r0) 188171617Scognet 189171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 190171617Scognet 191171617Scognet CPWAIT_AND_RETURN(r0) 192171617Scognet 193171617ScognetENTRY(xscalec3_cache_syncI_rng) 194171617Scognet cmp r1, #0x4000 195171617Scognet bcs _C_LABEL(xscalec3_cache_syncI) 196171617Scognet 197171617Scognet and r2, r0, #0x1f 198171617Scognet add r1, r1, r2 199171617Scognet bic r0, r0, #0x1f 200171617Scognet 201171617Scognet1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 202171617Scognet mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ 203171617Scognet add r0, r0, #32 204171617Scognet subs r1, r1, #32 205171617Scognet bhi 1b 206171617Scognet 207171617Scognet CPWAIT(r0) 208171617Scognet 209171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 210171617Scognet 211171617Scognet CPWAIT_AND_RETURN(r0) 212171617Scognet 213171617ScognetENTRY(xscalec3_cache_purgeD_rng) 214171617Scognet 215171617Scognet cmp r1, #0x4000 216171617Scognet bcs _C_LABEL(xscalec3_cache_cleanID) 217171617Scognet and r2, r0, #0x1f 218171617Scognet add r1, r1, r2 219171617Scognet bic r0, r0, #0x1f 220171617Scognet 221171617Scognet1: mcr p15, 0, r0, c7, c14, 1 /* Clean and invalidate D cache entry */ 222171617Scognet add r0, r0, #32 223171617Scognet subs r1, r1, #32 224171617Scognet bhi 1b 225171617Scognet 226171617Scognet CPWAIT(r0) 227171617Scognet 228171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 229171617Scognet 230171617Scognet CPWAIT_AND_RETURN(r0) 231171617ScognetENTRY(xscalec3_cache_cleanID_rng) 232171617ScognetENTRY(xscalec3_cache_cleanD_rng) 233171617Scognet 234171617Scognet cmp r1, #0x4000 235171617Scognet bcs _C_LABEL(xscalec3_cache_cleanID) 236171617Scognet and r2, r0, #0x1f 237171617Scognet add r1, r1, r2 238171617Scognet bic r0, r0, #0x1f 239171617Scognet 240171617Scognet1: mcr p15, 0, r0, c7, c10, 1 /* clean L1 D cache entry */ 241171617Scognet nop 242171617Scognet add r0, r0, #32 243171617Scognet subs r1, r1, #32 244171617Scognet bhi 1b 245171617Scognet 246171617Scognet CPWAIT(r0) 247171617Scognet 248171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 249171617Scognet 250171617Scognet CPWAIT_AND_RETURN(r0) 251171617Scognet 252171617Scognet 253171617ScognetENTRY(xscalec3_l2cache_purge) 254171617Scognet /* Clean-up the L2 cache */ 255171617Scognet mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */ 256171617Scognet mov r0, #0 257171617Scognet1: 258171617Scognet mov r1, r0, asl #29 259171617Scognet mov r2, #0 260171617Scognet2: 261171617Scognet orr r3, r1, r2, asl #5 262171617Scognet mcr p15, 1, r3, c7, c15, 2 263171617Scognet add r2, r2, #1 264171617Scognet cmp r2, #L2_CACHE_SETS 265171617Scognet bne 2b 266171617Scognet add r0, r0, #1 267171617Scognet cmp r0, #8 268171617Scognet bne 1b 269171617Scognet mcr p15, 0, r0, c7, c10, 4 @ data write barrier 270171617Scognet 271171617Scognet CPWAIT(r0) 272171617Scognet mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */ 273171617Scognet RET 274171617Scognet 275171617ScognetENTRY(xscalec3_l2cache_clean_rng) 276171617Scognet mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */ 277171617Scognet 278171617Scognet and r2, r0, #0x1f 279171617Scognet add r1, r1, r2 280171617Scognet bic r0, r0, #0x1f 281171617Scognet 282171617Scognet1: mcr p15, 1, r0, c7, c11, 1 /* Clean L2 D cache entry */ 283171617Scognet add r0, r0, #32 284171617Scognet subs r1, r1, #32 285171617Scognet bhi 1b 286171617Scognet 287171617Scognet 288171617Scognet CPWAIT(r0) 289171617Scognet 290171617Scognet mcr p15, 0, r0, c7, c10, 4 @ data write barrier 291171617Scognet mcr p15, 0, r0, c7, c10, 5 292171617Scognet 293171617Scognet CPWAIT_AND_RETURN(r0) 294171617Scognet 295171617ScognetENTRY(xscalec3_l2cache_purge_rng) 296171617Scognet 297171617Scognet mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */ 298171617Scognet 299171617Scognet and r2, r0, #0x1f 300171617Scognet add r1, r1, r2 301171617Scognet bic r0, r0, #0x1f 302171617Scognet 303171617Scognet1: mcr p15, 1, r0, c7, c11, 1 /* Clean L2 D cache entry */ 304171617Scognet mcr p15, 1, r0, c7, c7, 1 /* Invalidate L2 D cache entry */ 305171617Scognet add r0, r0, #32 306171617Scognet subs r1, r1, #32 307171617Scognet bhi 1b 308171617Scognet 309171617Scognet mcr p15, 0, r0, c7, c10, 4 @ data write barrier 310171617Scognet mcr p15, 0, r0, c7, c10, 5 311171617Scognet 312171617Scognet CPWAIT_AND_RETURN(r0) 313171617Scognet 314171617ScognetENTRY(xscalec3_l2cache_flush_rng) 315171617Scognet mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */ 316171617Scognet 317171617Scognet and r2, r0, #0x1f 318171617Scognet add r1, r1, r2 319171617Scognet bic r0, r0, #0x1f 320171617Scognet 321171617Scognet1: mcr p15, 1, r0, c7, c7, 1 /* Invalidate L2 cache line */ 322171617Scognet add r0, r0, #32 323171617Scognet subs r1, r1, #32 324171617Scognet bhi 1b 325171617Scognet mcr p15, 0, r0, c7, c10, 4 @ data write barrier 326171617Scognet mcr p15, 0, r0, c7, c10, 5 327171617Scognet CPWAIT_AND_RETURN(r0) 328171617Scognet/* 329171617Scognet * Functions to set the MMU Translation Table Base register 330171617Scognet * 331171617Scognet * We need to clean and flush the cache as it uses virtual 332171617Scognet * addresses that are about to change. 333171617Scognet */ 334171617ScognetENTRY(xscalec3_setttb) 335171617Scognet#ifdef CACHE_CLEAN_BLOCK_INTR 336171617Scognet mrs r3, cpsr_all 337171617Scognet orr r1, r3, #(I32_bit | F32_bit) 338171617Scognet msr cpsr_all, r1 339171617Scognet#else 340171617Scognet ldr r3, .Lblock_userspace_access 341171617Scognet ldr r2, [r3] 342251866Sscottl orr r1, r2, #1 343171617Scognet str r1, [r3] 344171617Scognet#endif 345171617Scognet stmfd sp!, {r0-r3, lr} 346171617Scognet bl _C_LABEL(xscalec3_cache_cleanID) 347171617Scognet mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */ 348171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write and fill buffer */ 349171617Scognet 350171617Scognet CPWAIT(r0) 351171617Scognet 352171617Scognet ldmfd sp!, {r0-r3, lr} 353171617Scognet 354171617Scognet#ifdef ARM_USE_L2_CACHE 355171617Scognet orr r0, r0, #0x18 /* cache the page table in L2 */ 356171617Scognet#endif 357251866Sscottl /* Write the TTB */ 358171617Scognet mcr p15, 0, r0, c2, c0, 0 359171617Scognet 360171617Scognet /* If we have updated the TTB we must flush the TLB */ 361171617Scognet mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLB */ 362171617Scognet 363171617Scognet CPWAIT(r0) 364171617Scognet 365171617Scognet#ifdef CACHE_CLEAN_BLOCK_INTR 366171617Scognet msr cpsr_all, r3 367171617Scognet#else 368171617Scognet str r2, [r3] 369171617Scognet#endif 370171617Scognet RET 371171617Scognet 372171617Scognet/* 373171617Scognet * Context switch. 374171617Scognet * 375171617Scognet * These is the CPU-specific parts of the context switcher cpu_switch() 376171617Scognet * These functions actually perform the TTB reload. 377171617Scognet * 378171617Scognet * NOTE: Special calling convention 379171617Scognet * r1, r4-r13 must be preserved 380171617Scognet */ 381171617ScognetENTRY(xscalec3_context_switch) 382171617Scognet /* 383171617Scognet * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this. 384171617Scognet * Thus the data cache will contain only kernel data and the 385171617Scognet * instruction cache will contain only kernel code, and all 386171617Scognet * kernel mappings are shared by all processes. 387171617Scognet */ 388171617Scognet#ifdef ARM_USE_L2_CACHE 389171617Scognet orr r0, r0, #0x18 /* Cache the page table in L2 */ 390171617Scognet#endif 391171617Scognet /* Write the TTB */ 392171617Scognet mcr p15, 0, r0, c2, c0, 0 393171617Scognet 394171617Scognet /* If we have updated the TTB we must flush the TLB */ 395171617Scognet mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */ 396171617Scognet 397171617Scognet CPWAIT_AND_RETURN(r0) 398