Home | History | Annotate | Line # | Download | only in arm
      1 /*	$NetBSD: cpufunc_asm_armv5.S,v 1.9 2022/10/20 06:58:38 skrll Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2002, 2005 ARM Limited
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. The name of the company may not be used to endorse or promote
     16  *    products derived from this software without specific prior written
     17  *    permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     20  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  *
     31  * ARMv5 assembly functions for manipulating caches.
     32  * These routines can be used by any core that supports the set/index
     33  * operations.
     34  */
     35 
     36 #include "assym.h"
     37 #include <machine/asm.h>
     38 #include <arm/locore.h>
     39 
     40 /*
     41  * Functions to set the MMU Translation Table Base register
     42  *
     43  * We need to clean and flush the cache as it uses virtual
     44  * addresses that are about to change.
     45  */
     46 ENTRY(armv5_setttb)
     47 	cmp	r1, #0
     48 	beq	1f
     49 
     50 	stmfd	sp!, {r0, lr}
     51 	bl	_C_LABEL(armv5_idcache_wbinv_all)
     52 	ldmfd	sp!, {r0, lr}
     53 	cmp	r0, #1
     54 
     55 1:	mcr	p15, 0, r0, c2, c0, 0	/* load new TTB */
     56 	mcrne	p15, 0, r0, c8, c7, 0	/* invalidate I+D TLBs */
     57 	RET
     58 
     59 /*
     60  * Cache operations.  For the entire cache we use the set/index
     61  * operations.
     62  */
     63 	s_max	.req r0
     64 	i_max	.req r1
     65 	s_inc	.req r2
     66 	i_inc	.req r3
     67 
     68 ENTRY_NP(armv5_icache_sync_range)
     69 	ldr	ip, .Larmv5_line_size
     70 	cmp	r1, #0x4000
     71 	bcs	.Larmv5_icache_sync_all
     72 	ldr	ip, [ip]
     73 	sub	r1, r1, #1		/* Don't overrun */
     74 	sub	r3, ip, #1
     75 	and	r2, r0, r3
     76 	add	r1, r1, r2
     77 	bic	r0, r0, r3
     78 1:
     79 	mcr	p15, 0, r0, c7, c5, 1	/* Invalidate I cache SE with VA */
     80 	mcr	p15, 0, r0, c7, c10, 1	/* Clean D cache SE with VA */
     81 	add	r0, r0, ip
     82 	subs	r1, r1, ip
     83 	bpl	1b
     84 	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
     85 	RET
     86 
     87 ENTRY_NP(armv5_icache_sync_all)
     88 .Larmv5_icache_sync_all:
     89 	/*
     90 	 * We assume that the code here can never be out of sync with the
     91 	 * dcache, so that we can safely flush the Icache and fall through
     92 	 * into the Dcache cleaning code.
     93 	 */
     94 	mcr	p15, 0, r0, c7, c5, 0	/* Flush I cache */
     95 	/* Fall through to clean Dcache. */
     96 
     97 .Larmv5_dcache_wb:
     98 	ldr	ip, .Larmv5_cache_data
     99 	ldmia	ip, {s_max, i_max, s_inc, i_inc}
    100 1:
    101 	orr	ip, s_max, i_max
    102 2:
    103 	mcr	p15, 0, ip, c7, c10, 2	/* Clean D cache SE with Set/Index */
    104 	sub	ip, ip, i_inc
    105 	tst	ip, i_max		/* Index 0 is last one */
    106 	bne	2b			/* Next index */
    107 	mcr	p15, 0, ip, c7, c10, 2	/* Clean D cache SE with Set/Index */
    108 	subs	s_max, s_max, s_inc
    109 	bpl	1b			/* Next set */
    110 	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
    111 	RET
    112 
    113 .Larmv5_line_size:
    114 	.word	_C_LABEL(arm_pcache) + DCACHE_LINE_SIZE
    115 
    116 ENTRY(armv5_dcache_wb_range)
    117 	ldr	ip, .Larmv5_line_size
    118 	cmp	r1, #0x4000
    119 	bcs	.Larmv5_dcache_wb
    120 	ldr	ip, [ip]
    121 	sub	r1, r1, #1		/* Don't overrun */
    122 	sub	r3, ip, #1
    123 	and	r2, r0, r3
    124 	add	r1, r1, r2
    125 	bic	r0, r0, r3
    126 1:
    127 	mcr	p15, 0, r0, c7, c10, 1	/* Clean D cache SE with VA */
    128 	add	r0, r0, ip
    129 	subs	r1, r1, ip
    130 	bpl	1b
    131 	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
    132 	RET
    133 
    134 ENTRY(armv5_dcache_wbinv_range)
    135 	ldr	ip, .Larmv5_line_size
    136 	cmp	r1, #0x4000
    137 	bcs	.Larmv5_dcache_wbinv_all
    138 	ldr	ip, [ip]
    139 	sub	r1, r1, #1		/* Don't overrun */
    140 	sub	r3, ip, #1
    141 	and	r2, r0, r3
    142 	add	r1, r1, r2
    143 	bic	r0, r0, r3
    144 1:
    145 	mcr	p15, 0, r0, c7, c14, 1	/* Purge D cache SE with VA */
    146 	add	r0, r0, ip
    147 	subs	r1, r1, ip
    148 	bpl	1b
    149 	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
    150 	RET
    151 
    152 /*
    153  * Note, we must not invalidate everything.  If the range is too big we
    154  * must use wb-inv of the entire cache.
    155  */
    156 ENTRY(armv5_dcache_inv_range)
    157 	ldr	ip, .Larmv5_line_size
    158 	cmp	r1, #0x4000
    159 	bcs	.Larmv5_dcache_wbinv_all
    160 	ldr	ip, [ip]
    161 	sub	r1, r1, #1		/* Don't overrun */
    162 	sub	r3, ip, #1
    163 	and	r2, r0, r3
    164 	add	r1, r1, r2
    165 	bic	r0, r0, r3
    166 1:
    167 	mcr	p15, 0, r0, c7, c6, 1	/* Invalidate D cache SE with VA */
    168 	add	r0, r0, ip
    169 	subs	r1, r1, ip
    170 	bpl	1b
    171 	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
    172 	RET
    173 
    174 ENTRY(armv5_idcache_wbinv_range)
    175 	ldr	ip, .Larmv5_line_size
    176 	cmp	r1, #0x4000
    177 	bcs	.Larmv5_idcache_wbinv_all
    178 	ldr	ip, [ip]
    179 	sub	r1, r1, #1		/* Don't overrun */
    180 	sub	r3, ip, #1
    181 	and	r2, r0, r3
    182 	add	r1, r1, r2
    183 	bic	r0, r0, r3
    184 1:
    185 	mcr	p15, 0, r0, c7, c5, 1	/* Invalidate I cache SE with VA */
    186 	mcr	p15, 0, r0, c7, c14, 1	/* Purge D cache SE with VA */
    187 	add	r0, r0, ip
    188 	subs	r1, r1, ip
    189 	bpl	1b
    190 	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
    191 	RET
    192 
    193 ENTRY_NP(armv5_idcache_wbinv_all)
    194 .Larmv5_idcache_wbinv_all:
    195 	/*
    196 	 * We assume that the code here can never be out of sync with the
    197 	 * dcache, so that we can safely flush the Icache and fall through
    198 	 * into the Dcache purging code.
    199 	 */
    200 	mcr	p15, 0, r0, c7, c5, 0	/* Flush I cache */
    201 	/* Fall through to purge Dcache. */
    202 
    203 ENTRY(armv5_dcache_wbinv_all)
    204 .Larmv5_dcache_wbinv_all:
    205 	ldr	ip, .Larmv5_cache_data
    206 	ldmia	ip, {s_max, i_max, s_inc, i_inc}
    207 1:
    208 	orr	ip, s_max, i_max
    209 2:
    210 	mcr	p15, 0, ip, c7, c14, 2	/* Purge D cache SE with Set/Index */
    211 	sub	ip, ip, i_inc
    212 	tst	ip, i_max		/* Index 0 is last one */
    213 	bne	2b			/* Next index */
    214 	mcr	p15, 0, ip, c7, c14, 2	/* Purge D cache SE with Set/Index */
    215 	subs	s_max, s_max, s_inc
    216 	bpl	1b			/* Next set */
    217 	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
    218 	RET
    219 
    220 .Larmv5_cache_data:
    221 	.word	_C_LABEL(armv5_dcache_sets_max)
    222 
    223 	.bss
    224 
    225 /* XXX The following macros should probably be moved to asm.h */
    226 #define _DATA_OBJECT(x) .globl x; .type x,_ASM_TYPE_OBJECT; x:
    227 #define C_OBJECT(x)	_DATA_OBJECT(_C_LABEL(x))
    228 
    229 /*
    230  * Parameters for the cache cleaning code.  Note that the order of these
    231  * four variables is assumed in the code above.  Hence the reason for
    232  * declaring them in the assembler file.
    233  */
    234 	.align 0
    235 C_OBJECT(armv5_dcache_sets_max)
    236 	.space	4
    237 C_OBJECT(armv5_dcache_index_max)
    238 	.space	4
    239 C_OBJECT(armv5_dcache_sets_inc)
    240 	.space	4
    241 C_OBJECT(armv5_dcache_index_inc)
    242 	.space	4
    243