Home | History | Annotate | Line # | Download | only in aarch64
      1  1.8  ryo /*	$NetBSD: cpufunc_asm_armv8.S,v 1.8 2021/02/11 08:35:11 ryo Exp $	*/
      2  1.1  ryo 
      3  1.1  ryo /*-
      4  1.1  ryo  * Copyright (c) 2014 Robin Randhawa
      5  1.1  ryo  * Copyright (c) 2015 The FreeBSD Foundation
      6  1.1  ryo  * All rights reserved.
      7  1.1  ryo  *
      8  1.1  ryo  * Portions of this software were developed by Andrew Turner
      9  1.1  ryo  * under sponsorship from the FreeBSD Foundation
     10  1.1  ryo  *
     11  1.1  ryo  * Redistribution and use in source and binary forms, with or without
     12  1.1  ryo  * modification, are permitted provided that the following conditions
     13  1.1  ryo  * are met:
     14  1.1  ryo  * 1. Redistributions of source code must retain the above copyright
     15  1.1  ryo  *    notice, this list of conditions and the following disclaimer.
     16  1.1  ryo  * 2. Redistributions in binary form must reproduce the above copyright
     17  1.1  ryo  *    notice, this list of conditions and the following disclaimer in the
     18  1.1  ryo  *    documentation and/or other materials provided with the distribution.
     19  1.1  ryo  *
     20  1.1  ryo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     21  1.1  ryo  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22  1.1  ryo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     23  1.1  ryo  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     24  1.1  ryo  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     25  1.1  ryo  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     26  1.1  ryo  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     27  1.1  ryo  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     28  1.1  ryo  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     29  1.1  ryo  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     30  1.1  ryo  * SUCH DAMAGE.
     31  1.1  ryo  *
     32  1.1  ryo  * $FreeBSD: head/sys/arm64/arm64/cpufunc_asm.S 313347 2017-02-06 17:50:09Z andrew $
     33  1.1  ryo  */
     34  1.1  ryo 
     35  1.3  ryo #include "opt_cputypes.h"
     36  1.8  ryo #include "opt_gprof.h"
     37  1.1  ryo #include "opt_multiprocessor.h"
     38  1.1  ryo #include <aarch64/asm.h>
     39  1.1  ryo 
     40  1.1  ryo 	.text
     41  1.1  ryo 	.align	2
     42  1.1  ryo 
     43  1.1  ryo /*
     44  1.1  ryo  * Macro to handle the cache. This takes the start address in x0, length
     45  1.5  ryo  * in x1. It will corrupt x2-x5.
     46  1.1  ryo  */
     47  1.7  ryo .macro cache_handle_range dcop = "", icop = ""
     48  1.1  ryo 	mrs	x3, ctr_el0
     49  1.5  ryo 	mov	x4, #4			/* size of word */
     50  1.7  ryo .ifnb \dcop
     51  1.1  ryo 	ubfx	x2, x3, #16, #4		/* x2 = D cache shift */
     52  1.5  ryo 	lsl	x2, x4, x2		/* x2 = D cache line size */
     53  1.5  ryo .endif
     54  1.7  ryo .ifnb \icop
     55  1.1  ryo 	and	x3, x3, #15		/* x3 = I cache shift */
     56  1.5  ryo 	lsl	x3, x4, x3		/* x3 = I cache line size */
     57  1.1  ryo .endif
     58  1.7  ryo .ifnb \dcop
     59  1.5  ryo 	sub	x4, x2, #1		/* Get the address mask */
     60  1.5  ryo 	and	x4, x0, x4		/* Get the low bits of the address */
     61  1.5  ryo 	add	x5, x1, x4		/* Add these to the size */
     62  1.5  ryo 	bic	x4, x0, x4		/* Clear the low bit of the address */
     63  1.1  ryo 1:
     64  1.5  ryo 	dc	\dcop, x4
     65  1.5  ryo 	add	x4, x4, x2		/* Move to the next line */
     66  1.5  ryo 	subs	x5, x5, x2		/* Reduce the size */
     67  1.5  ryo 	b.hi	1b			/* Check if we are done */
     68  1.1  ryo 	dsb	ish
     69  1.1  ryo .endif
     70  1.7  ryo .ifnb \icop
     71  1.5  ryo 	sub	x4, x3, #1		/* Get the address mask */
     72  1.5  ryo 	and	x4, x0, x4		/* Get the low bits of the address */
     73  1.5  ryo 	add	x5, x1, x4		/* Add these to the size */
     74  1.5  ryo 	bic	x4, x0, x4		/* Clear the low bit of the address */
     75  1.5  ryo 1:
     76  1.5  ryo 	ic	\icop, x4
     77  1.5  ryo 	add	x4, x4, x3		/* Move to the next line */
     78  1.5  ryo 	subs	x5, x5, x3		/* Reduce the size */
     79  1.1  ryo 	b.hi	1b			/* Check if we are done */
     80  1.5  ryo 	dsb	ish
     81  1.1  ryo 	isb
     82  1.1  ryo .endif
     83  1.1  ryo .endm
     84  1.1  ryo 
     85  1.1  ryo 
     86  1.1  ryo ENTRY(aarch64_nullop)
     87  1.1  ryo 	ret
     88  1.1  ryo END(aarch64_nullop)
     89  1.1  ryo 
     90  1.1  ryo ENTRY(aarch64_cpuid)
     91  1.1  ryo 	mrs	x0, midr_el1
     92  1.1  ryo 	ret
     93  1.1  ryo END(aarch64_cpuid)
     94  1.1  ryo 
     95  1.1  ryo /*
     96  1.1  ryo  * void aarch64_dcache_wb_range(vaddr_t, vsize_t)
     97  1.1  ryo  */
     98  1.1  ryo ENTRY(aarch64_dcache_wb_range)
     99  1.1  ryo 	cache_handle_range	dcop = cvac
    100  1.5  ryo 	ret
    101  1.1  ryo END(aarch64_dcache_wb_range)
    102  1.1  ryo 
    103  1.1  ryo /*
    104  1.1  ryo  * void aarch64_dcache_wbinv_range(vaddr_t, vsize_t)
    105  1.1  ryo  */
    106  1.1  ryo ENTRY(aarch64_dcache_wbinv_range)
    107  1.1  ryo 	cache_handle_range	dcop = civac
    108  1.5  ryo 	ret
    109  1.1  ryo END(aarch64_dcache_wbinv_range)
    110  1.1  ryo 
    111  1.1  ryo /*
    112  1.1  ryo  * void aarch64_dcache_inv_range(vaddr_t, vsize_t)
    113  1.1  ryo  *
    114  1.1  ryo  * Note, we must not invalidate everything.  If the range is too big we
    115  1.1  ryo  * must use wb-inv of the entire cache.
    116  1.1  ryo  */
    117  1.1  ryo ENTRY(aarch64_dcache_inv_range)
    118  1.1  ryo 	cache_handle_range	dcop = ivac
    119  1.5  ryo 	ret
    120  1.1  ryo END(aarch64_dcache_inv_range)
    121  1.1  ryo 
    122  1.1  ryo /*
    123  1.1  ryo  * void aarch64_idcache_wbinv_range(vaddr_t, vsize_t)
    124  1.1  ryo  */
    125  1.1  ryo ENTRY(aarch64_idcache_wbinv_range)
    126  1.5  ryo 	cache_handle_range	dcop = civac, icop = ivau
    127  1.5  ryo 	ret
    128  1.1  ryo END(aarch64_idcache_wbinv_range)
    129  1.1  ryo 
    130  1.1  ryo /*
    131  1.1  ryo  * void aarch64_icache_sync_range(vaddr_t, vsize_t)
    132  1.1  ryo  */
    133  1.1  ryo ENTRY(aarch64_icache_sync_range)
    134  1.5  ryo 	cache_handle_range	dcop = cvau, icop = ivau
    135  1.5  ryo 	ret
    136  1.1  ryo END(aarch64_icache_sync_range)
    137  1.1  ryo 
    138  1.1  ryo /*
    139  1.6  ryo  * void aarch64_icache_inv_range(vaddr_t, vsize_t)
    140  1.6  ryo  */
    141  1.6  ryo ENTRY(aarch64_icache_inv_range)
    142  1.6  ryo 	cache_handle_range	icop = ivau
    143  1.6  ryo 	ret
    144  1.6  ryo END(aarch64_icache_inv_range)
    145  1.6  ryo 
    146  1.6  ryo /*
    147  1.6  ryo  * void aarch64_icache_barrier_range(vaddr_t, vsize_t)
    148  1.6  ryo  */
    149  1.6  ryo ENTRY(aarch64_icache_barrier_range)
    150  1.6  ryo 	dsb	ishst
    151  1.6  ryo 	isb
    152  1.6  ryo 	ret
    153  1.6  ryo END(aarch64_icache_barrier_range)
    154  1.6  ryo 
    155  1.6  ryo /*
    156  1.1  ryo  * void aarch64_icache_inv_all(void)
    157  1.1  ryo  */
    158  1.1  ryo ENTRY(aarch64_icache_inv_all)
    159  1.1  ryo 	dsb	ish
    160  1.1  ryo #ifdef MULTIPROCESSOR
    161  1.2  ryo 	ic	ialluis
    162  1.2  ryo #else
    163  1.1  ryo 	ic	iallu
    164  1.1  ryo #endif
    165  1.1  ryo 	dsb	ish
    166  1.1  ryo 	isb
    167  1.1  ryo 	ret
    168  1.2  ryo END(aarch64_icache_inv_all)
    169  1.1  ryo 
    170  1.1  ryo 
    171  1.1  ryo 
    172  1.1  ryo ENTRY(aarch64_drain_writebuf)
    173  1.1  ryo 	dsb	sy
    174  1.1  ryo 	ret
    175  1.1  ryo END(aarch64_drain_writebuf)
    176  1.1  ryo 
    177  1.1  ryo 
    178  1.1  ryo /*
    179  1.1  ryo  * TLB ops
    180  1.1  ryo  */
    181  1.1  ryo 
    182  1.1  ryo /* void aarch64_set_ttbr0(uint64_t ttbr0) */
    183  1.1  ryo ENTRY(aarch64_set_ttbr0)
    184  1.1  ryo 	dsb	ish
    185  1.1  ryo 	msr	ttbr0_el1, x0
    186  1.1  ryo 	dsb	ish
    187  1.1  ryo 	isb
    188  1.1  ryo 	ret
    189  1.1  ryo END(aarch64_set_ttbr0)
    190  1.1  ryo 
    191  1.3  ryo #ifdef CPU_THUNDERX
    192  1.3  ryo /*
    193  1.3  ryo  * Cavium erratum 27456
    194  1.3  ryo  * void aarch64_set_ttbr0_thunderx(uint64_t ttbr0)
    195  1.3  ryo  */
    196  1.3  ryo ENTRY(aarch64_set_ttbr0_thunderx)
    197  1.3  ryo 	dsb	ish
    198  1.3  ryo 	msr	ttbr0_el1, x0
    199  1.3  ryo 	isb
    200  1.3  ryo 	ic	iallu
    201  1.3  ryo 	dsb	nsh
    202  1.3  ryo 	isb
    203  1.3  ryo 	ret
    204  1.3  ryo END(aarch64_set_ttbr0_thunderx)
    205  1.3  ryo #endif /* CPU_THUNDERX */
    206  1.3  ryo 
    207  1.1  ryo /* void aarch64_tlbi_all(void) */
    208  1.1  ryo ENTRY(aarch64_tlbi_all)
    209  1.1  ryo 	dsb	ishst
    210  1.1  ryo #ifdef MULTIPROCESSOR
    211  1.1  ryo 	tlbi	vmalle1is
    212  1.1  ryo #else
    213  1.1  ryo 	tlbi	vmalle1
    214  1.1  ryo #endif
    215  1.1  ryo 	dsb	ish
    216  1.1  ryo 	isb
    217  1.1  ryo 	ret
    218  1.1  ryo END(aarch64_tlbi_all)
    219  1.1  ryo 
    220  1.1  ryo /* void aarch64_tlbi_by_asid(int asid) */
    221  1.1  ryo ENTRY(aarch64_tlbi_by_asid)
    222  1.1  ryo 	/* x8 = bit 63[ASID]48, 47[RES0]0 */
    223  1.1  ryo 	lsl	x8, x0, #48
    224  1.1  ryo 	dsb	ishst
    225  1.1  ryo #ifdef MULTIPROCESSOR
    226  1.1  ryo 	tlbi	aside1is, x8
    227  1.1  ryo #else
    228  1.1  ryo 	tlbi	aside1, x8
    229  1.1  ryo #endif
    230  1.1  ryo 	dsb	ish
    231  1.1  ryo 	isb
    232  1.1  ryo 	ret
    233  1.1  ryo END(aarch64_tlbi_by_asid)
    234  1.1  ryo 
    235  1.1  ryo /* aarch64_tlbi_by_va(vaddr_t va) */
    236  1.1  ryo ENTRY(aarch64_tlbi_by_va)
    237  1.1  ryo 	/* x8 = bit 63[RES0]44, 43[VA(55:12)]0 */
    238  1.1  ryo 	ubfx	x8, x0, #12, #44
    239  1.1  ryo 	dsb	ishst
    240  1.1  ryo #ifdef MULTIPROCESSOR
    241  1.1  ryo 	tlbi	vaae1is, x8
    242  1.1  ryo #else
    243  1.1  ryo 	tlbi	vaae1, x8
    244  1.1  ryo #endif
    245  1.1  ryo 	dsb	ish
    246  1.1  ryo 	isb
    247  1.1  ryo 	ret
    248  1.1  ryo END(aarch64_tlbi_by_va)
    249  1.1  ryo 
    250  1.1  ryo /* aarch64_tlbi_by_va_ll(vaddr_t va) */
    251  1.1  ryo ENTRY(aarch64_tlbi_by_va_ll)
    252  1.1  ryo 	/* x8 = bit 63[RES0]44, 43[VA(55:12)]0 */
    253  1.1  ryo 	ubfx	x8, x0, #12, #44
    254  1.1  ryo 	dsb	ishst
    255  1.1  ryo #ifdef MULTIPROCESSOR
    256  1.1  ryo 	tlbi	vaale1is, x8
    257  1.1  ryo #else
    258  1.1  ryo 	tlbi	vaale1, x8
    259  1.1  ryo #endif
    260  1.1  ryo 	dsb	ish
    261  1.1  ryo 	isb
    262  1.1  ryo 	ret
    263  1.1  ryo END(aarch64_tlbi_by_va_ll)
    264  1.1  ryo 
    265  1.1  ryo /* aarch64_tlbi_by_asid_va(int asid, vaddr_t va) */
    266  1.1  ryo ENTRY(aarch64_tlbi_by_asid_va)
    267  1.1  ryo 	/* x8 = bit 63[ASID]48, 47[RES0]44, 43[VA(55:12)]0 */
    268  1.1  ryo 	lsl	x8, x0, #48
    269  1.1  ryo 	bfxil	x8, x1, #12, #44
    270  1.4  ryo 	dsb	ishst
    271  1.1  ryo #ifdef MULTIPROCESSOR
    272  1.1  ryo 	tlbi	vae1is, x8
    273  1.1  ryo #else
    274  1.1  ryo 	tlbi	vae1, x8
    275  1.1  ryo #endif
    276  1.4  ryo 	dsb	ish
    277  1.4  ryo 	isb
    278  1.1  ryo 	ret
    279  1.1  ryo END(aarch64_tlbi_by_asid_va)
    280  1.1  ryo 
    281  1.1  ryo /* aarch64_tlbi_by_asid_va_ll(int asid, vaddr_t va) */
    282  1.1  ryo ENTRY(aarch64_tlbi_by_asid_va_ll)
    283  1.1  ryo 	/* x8 = bit 63[ASID]48, 47[RES0]44, 43[VA(55:12)]0 */
    284  1.1  ryo 	lsl	x8, x0, #48
    285  1.1  ryo 	bfxil	x8, x1, #12, #44
    286  1.4  ryo 	dsb	ishst
    287  1.1  ryo #ifdef MULTIPROCESSOR
    288  1.1  ryo 	tlbi	vale1is, x8
    289  1.1  ryo #else
    290  1.1  ryo 	tlbi	vale1, x8
    291  1.1  ryo #endif
    292  1.4  ryo 	dsb	ish
    293  1.4  ryo 	isb
    294  1.1  ryo 	ret
    295  1.1  ryo END(aarch64_tlbi_by_asid_va_ll)
    296