1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 1996-2000 Russell King 6*4882a593Smuzhiyun * Copyright (C) 2012 ARM Ltd. 7*4882a593Smuzhiyun */ 8*4882a593Smuzhiyun #ifndef __ASSEMBLY__ 9*4882a593Smuzhiyun #error "Only include this from assembly code" 10*4882a593Smuzhiyun #endif 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun #ifndef __ASM_ASSEMBLER_H 13*4882a593Smuzhiyun #define __ASM_ASSEMBLER_H 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun #include <asm-generic/export.h> 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun #include <asm/asm-offsets.h> 18*4882a593Smuzhiyun #include <asm/asm-bug.h> 19*4882a593Smuzhiyun #include <asm/alternative.h> 20*4882a593Smuzhiyun #include <asm/cpufeature.h> 21*4882a593Smuzhiyun #include <asm/cputype.h> 22*4882a593Smuzhiyun #include <asm/debug-monitors.h> 23*4882a593Smuzhiyun #include <asm/page.h> 24*4882a593Smuzhiyun #include <asm/pgtable-hwdef.h> 25*4882a593Smuzhiyun #include <asm/ptrace.h> 26*4882a593Smuzhiyun #include <asm/thread_info.h> 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun /* 29*4882a593Smuzhiyun * Provide a wxN alias for each wN register so what we can paste a xN 30*4882a593Smuzhiyun * reference after a 'w' to obtain the 32-bit version. 31*4882a593Smuzhiyun */ 32*4882a593Smuzhiyun .irp n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 33*4882a593Smuzhiyun wx\n .req w\n 34*4882a593Smuzhiyun .endr 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun .macro save_and_disable_daif, flags 37*4882a593Smuzhiyun mrs \flags, daif 38*4882a593Smuzhiyun msr daifset, #0xf 39*4882a593Smuzhiyun .endm 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun .macro disable_daif 42*4882a593Smuzhiyun msr daifset, #0xf 43*4882a593Smuzhiyun .endm 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun .macro enable_daif 46*4882a593Smuzhiyun msr daifclr, #0xf 47*4882a593Smuzhiyun .endm 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun .macro restore_daif, flags:req 50*4882a593Smuzhiyun msr daif, \flags 51*4882a593Smuzhiyun .endm 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun /* IRQ is the lowest priority flag, unconditionally unmask the rest. */ 54*4882a593Smuzhiyun .macro enable_da_f 55*4882a593Smuzhiyun msr daifclr, #(8 | 4 | 1) 56*4882a593Smuzhiyun .endm 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun /* 59*4882a593Smuzhiyun * Save/restore interrupts. 60*4882a593Smuzhiyun */ 61*4882a593Smuzhiyun .macro save_and_disable_irq, flags 62*4882a593Smuzhiyun mrs \flags, daif 63*4882a593Smuzhiyun msr daifset, #2 64*4882a593Smuzhiyun .endm 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun .macro restore_irq, flags 67*4882a593Smuzhiyun msr daif, \flags 68*4882a593Smuzhiyun .endm 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun .macro enable_dbg 71*4882a593Smuzhiyun msr daifclr, #8 72*4882a593Smuzhiyun .endm 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun .macro disable_step_tsk, flgs, tmp 75*4882a593Smuzhiyun tbz \flgs, #TIF_SINGLESTEP, 9990f 76*4882a593Smuzhiyun mrs \tmp, mdscr_el1 77*4882a593Smuzhiyun bic \tmp, \tmp, #DBG_MDSCR_SS 78*4882a593Smuzhiyun msr mdscr_el1, \tmp 79*4882a593Smuzhiyun isb // Synchronise with enable_dbg 80*4882a593Smuzhiyun 9990: 81*4882a593Smuzhiyun .endm 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun /* call with daif masked */ 84*4882a593Smuzhiyun .macro enable_step_tsk, flgs, tmp 85*4882a593Smuzhiyun tbz \flgs, #TIF_SINGLESTEP, 9990f 86*4882a593Smuzhiyun mrs \tmp, mdscr_el1 87*4882a593Smuzhiyun orr \tmp, \tmp, #DBG_MDSCR_SS 88*4882a593Smuzhiyun msr mdscr_el1, \tmp 89*4882a593Smuzhiyun 9990: 90*4882a593Smuzhiyun .endm 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun /* 93*4882a593Smuzhiyun * RAS Error Synchronization barrier 94*4882a593Smuzhiyun */ 95*4882a593Smuzhiyun .macro esb 96*4882a593Smuzhiyun #ifdef CONFIG_ARM64_RAS_EXTN 97*4882a593Smuzhiyun hint #16 98*4882a593Smuzhiyun #else 99*4882a593Smuzhiyun nop 100*4882a593Smuzhiyun #endif 101*4882a593Smuzhiyun .endm 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun /* 104*4882a593Smuzhiyun * Value prediction barrier 105*4882a593Smuzhiyun */ 106*4882a593Smuzhiyun .macro csdb 107*4882a593Smuzhiyun hint #20 108*4882a593Smuzhiyun .endm 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun /* 111*4882a593Smuzhiyun * Clear Branch History instruction 112*4882a593Smuzhiyun */ 113*4882a593Smuzhiyun .macro clearbhb 114*4882a593Smuzhiyun hint #22 115*4882a593Smuzhiyun .endm 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun /* 118*4882a593Smuzhiyun * Speculation barrier 119*4882a593Smuzhiyun */ 120*4882a593Smuzhiyun .macro sb 121*4882a593Smuzhiyun alternative_if_not ARM64_HAS_SB 122*4882a593Smuzhiyun dsb nsh 123*4882a593Smuzhiyun isb 124*4882a593Smuzhiyun alternative_else 125*4882a593Smuzhiyun SB_BARRIER_INSN 126*4882a593Smuzhiyun nop 127*4882a593Smuzhiyun alternative_endif 128*4882a593Smuzhiyun .endm 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun /* 131*4882a593Smuzhiyun * NOP sequence 132*4882a593Smuzhiyun */ 133*4882a593Smuzhiyun .macro nops, num 134*4882a593Smuzhiyun .rept \num 135*4882a593Smuzhiyun nop 136*4882a593Smuzhiyun .endr 137*4882a593Smuzhiyun .endm 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun /* 140*4882a593Smuzhiyun * Emit an entry into the exception table 141*4882a593Smuzhiyun */ 142*4882a593Smuzhiyun .macro _asm_extable, from, to 143*4882a593Smuzhiyun .pushsection __ex_table, "a" 144*4882a593Smuzhiyun .align 3 145*4882a593Smuzhiyun .long (\from - .), (\to - .) 146*4882a593Smuzhiyun .popsection 147*4882a593Smuzhiyun .endm 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun #define USER(l, x...) \ 150*4882a593Smuzhiyun 9999: x; \ 151*4882a593Smuzhiyun _asm_extable 9999b, l 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun /* 154*4882a593Smuzhiyun * Register aliases. 155*4882a593Smuzhiyun */ 156*4882a593Smuzhiyun lr .req x30 // link register 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun /* 159*4882a593Smuzhiyun * Vector entry 160*4882a593Smuzhiyun */ 161*4882a593Smuzhiyun .macro ventry label 162*4882a593Smuzhiyun .align 7 163*4882a593Smuzhiyun b \label 164*4882a593Smuzhiyun .endm 165*4882a593Smuzhiyun 166*4882a593Smuzhiyun /* 167*4882a593Smuzhiyun * Select code when configured for BE. 168*4882a593Smuzhiyun */ 169*4882a593Smuzhiyun #ifdef CONFIG_CPU_BIG_ENDIAN 170*4882a593Smuzhiyun #define CPU_BE(code...) code 171*4882a593Smuzhiyun #else 172*4882a593Smuzhiyun #define CPU_BE(code...) 173*4882a593Smuzhiyun #endif 174*4882a593Smuzhiyun 175*4882a593Smuzhiyun /* 176*4882a593Smuzhiyun * Select code when configured for LE. 177*4882a593Smuzhiyun */ 178*4882a593Smuzhiyun #ifdef CONFIG_CPU_BIG_ENDIAN 179*4882a593Smuzhiyun #define CPU_LE(code...) 180*4882a593Smuzhiyun #else 181*4882a593Smuzhiyun #define CPU_LE(code...) code 182*4882a593Smuzhiyun #endif 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun /* 185*4882a593Smuzhiyun * Define a macro that constructs a 64-bit value by concatenating two 186*4882a593Smuzhiyun * 32-bit registers. Note that on big endian systems the order of the 187*4882a593Smuzhiyun * registers is swapped. 188*4882a593Smuzhiyun */ 189*4882a593Smuzhiyun #ifndef CONFIG_CPU_BIG_ENDIAN 190*4882a593Smuzhiyun .macro regs_to_64, rd, lbits, hbits 191*4882a593Smuzhiyun #else 192*4882a593Smuzhiyun .macro regs_to_64, rd, hbits, lbits 193*4882a593Smuzhiyun #endif 194*4882a593Smuzhiyun orr \rd, \lbits, \hbits, lsl #32 195*4882a593Smuzhiyun .endm 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun /* 198*4882a593Smuzhiyun * Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where 199*4882a593Smuzhiyun * <symbol> is within the range +/- 4 GB of the PC. 200*4882a593Smuzhiyun */ 201*4882a593Smuzhiyun /* 202*4882a593Smuzhiyun * @dst: destination register (64 bit wide) 203*4882a593Smuzhiyun * @sym: name of the symbol 204*4882a593Smuzhiyun */ 205*4882a593Smuzhiyun .macro adr_l, dst, sym 206*4882a593Smuzhiyun adrp \dst, \sym 207*4882a593Smuzhiyun add \dst, \dst, :lo12:\sym 208*4882a593Smuzhiyun .endm 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun /* 211*4882a593Smuzhiyun * @dst: destination register (32 or 64 bit wide) 212*4882a593Smuzhiyun * @sym: name of the symbol 213*4882a593Smuzhiyun * @tmp: optional 64-bit scratch register to be used if <dst> is a 214*4882a593Smuzhiyun * 32-bit wide register, in which case it cannot be used to hold 215*4882a593Smuzhiyun * the address 216*4882a593Smuzhiyun */ 217*4882a593Smuzhiyun .macro ldr_l, dst, sym, tmp= 218*4882a593Smuzhiyun .ifb \tmp 219*4882a593Smuzhiyun adrp \dst, \sym 220*4882a593Smuzhiyun ldr \dst, [\dst, :lo12:\sym] 221*4882a593Smuzhiyun .else 222*4882a593Smuzhiyun adrp \tmp, \sym 223*4882a593Smuzhiyun ldr \dst, [\tmp, :lo12:\sym] 224*4882a593Smuzhiyun .endif 225*4882a593Smuzhiyun .endm 226*4882a593Smuzhiyun 227*4882a593Smuzhiyun /* 228*4882a593Smuzhiyun * @src: source register (32 or 64 bit wide) 229*4882a593Smuzhiyun * @sym: name of the symbol 230*4882a593Smuzhiyun * @tmp: mandatory 64-bit scratch register to calculate the address 231*4882a593Smuzhiyun * while <src> needs to be preserved. 232*4882a593Smuzhiyun */ 233*4882a593Smuzhiyun .macro str_l, src, sym, tmp 234*4882a593Smuzhiyun adrp \tmp, \sym 235*4882a593Smuzhiyun str \src, [\tmp, :lo12:\sym] 236*4882a593Smuzhiyun .endm 237*4882a593Smuzhiyun 238*4882a593Smuzhiyun /* 239*4882a593Smuzhiyun * @dst: destination register 240*4882a593Smuzhiyun */ 241*4882a593Smuzhiyun #if defined(__KVM_NVHE_HYPERVISOR__) || defined(__KVM_VHE_HYPERVISOR__) 242*4882a593Smuzhiyun .macro this_cpu_offset, dst 243*4882a593Smuzhiyun mrs \dst, tpidr_el2 244*4882a593Smuzhiyun .endm 245*4882a593Smuzhiyun #else 246*4882a593Smuzhiyun .macro this_cpu_offset, dst 247*4882a593Smuzhiyun alternative_if_not ARM64_HAS_VIRT_HOST_EXTN 248*4882a593Smuzhiyun mrs \dst, tpidr_el1 249*4882a593Smuzhiyun alternative_else 250*4882a593Smuzhiyun mrs \dst, tpidr_el2 251*4882a593Smuzhiyun alternative_endif 252*4882a593Smuzhiyun .endm 253*4882a593Smuzhiyun #endif 254*4882a593Smuzhiyun 255*4882a593Smuzhiyun /* 256*4882a593Smuzhiyun * @dst: Result of per_cpu(sym, smp_processor_id()) (can be SP) 257*4882a593Smuzhiyun * @sym: The name of the per-cpu variable 258*4882a593Smuzhiyun * @tmp: scratch register 259*4882a593Smuzhiyun */ 260*4882a593Smuzhiyun .macro adr_this_cpu, dst, sym, tmp 261*4882a593Smuzhiyun adrp \tmp, \sym 262*4882a593Smuzhiyun add \dst, \tmp, #:lo12:\sym 263*4882a593Smuzhiyun this_cpu_offset \tmp 264*4882a593Smuzhiyun add \dst, \dst, \tmp 265*4882a593Smuzhiyun .endm 266*4882a593Smuzhiyun 267*4882a593Smuzhiyun /* 268*4882a593Smuzhiyun * @dst: Result of READ_ONCE(per_cpu(sym, smp_processor_id())) 269*4882a593Smuzhiyun * @sym: The name of the per-cpu variable 270*4882a593Smuzhiyun * @tmp: scratch register 271*4882a593Smuzhiyun */ 272*4882a593Smuzhiyun .macro ldr_this_cpu dst, sym, tmp 273*4882a593Smuzhiyun adr_l \dst, \sym 274*4882a593Smuzhiyun this_cpu_offset \tmp 275*4882a593Smuzhiyun ldr \dst, [\dst, \tmp] 276*4882a593Smuzhiyun .endm 277*4882a593Smuzhiyun 278*4882a593Smuzhiyun /* 279*4882a593Smuzhiyun * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm) 280*4882a593Smuzhiyun */ 281*4882a593Smuzhiyun .macro vma_vm_mm, rd, rn 282*4882a593Smuzhiyun ldr \rd, [\rn, #VMA_VM_MM] 283*4882a593Smuzhiyun .endm 284*4882a593Smuzhiyun 285*4882a593Smuzhiyun /* 286*4882a593Smuzhiyun * read_ctr - read CTR_EL0. If the system has mismatched register fields, 287*4882a593Smuzhiyun * provide the system wide safe value from arm64_ftr_reg_ctrel0.sys_val 288*4882a593Smuzhiyun */ 289*4882a593Smuzhiyun .macro read_ctr, reg 290*4882a593Smuzhiyun #ifndef __KVM_NVHE_HYPERVISOR__ 291*4882a593Smuzhiyun alternative_if_not ARM64_MISMATCHED_CACHE_TYPE 292*4882a593Smuzhiyun mrs \reg, ctr_el0 // read CTR 293*4882a593Smuzhiyun nop 294*4882a593Smuzhiyun alternative_else 295*4882a593Smuzhiyun ldr_l \reg, arm64_ftr_reg_ctrel0 + ARM64_FTR_SYSVAL 296*4882a593Smuzhiyun alternative_endif 297*4882a593Smuzhiyun #else 298*4882a593Smuzhiyun alternative_if_not ARM64_KVM_PROTECTED_MODE 299*4882a593Smuzhiyun ASM_BUG() 300*4882a593Smuzhiyun alternative_else_nop_endif 301*4882a593Smuzhiyun alternative_cb kvm_compute_final_ctr_el0 302*4882a593Smuzhiyun movz \reg, #0 303*4882a593Smuzhiyun movk \reg, #0, lsl #16 304*4882a593Smuzhiyun movk \reg, #0, lsl #32 305*4882a593Smuzhiyun movk \reg, #0, lsl #48 306*4882a593Smuzhiyun alternative_cb_end 307*4882a593Smuzhiyun #endif 308*4882a593Smuzhiyun .endm 309*4882a593Smuzhiyun 310*4882a593Smuzhiyun 311*4882a593Smuzhiyun /* 312*4882a593Smuzhiyun * raw_dcache_line_size - get the minimum D-cache line size on this CPU 313*4882a593Smuzhiyun * from the CTR register. 314*4882a593Smuzhiyun */ 315*4882a593Smuzhiyun .macro raw_dcache_line_size, reg, tmp 316*4882a593Smuzhiyun mrs \tmp, ctr_el0 // read CTR 317*4882a593Smuzhiyun ubfm \tmp, \tmp, #16, #19 // cache line size encoding 318*4882a593Smuzhiyun mov \reg, #4 // bytes per word 319*4882a593Smuzhiyun lsl \reg, \reg, \tmp // actual cache line size 320*4882a593Smuzhiyun .endm 321*4882a593Smuzhiyun 322*4882a593Smuzhiyun /* 323*4882a593Smuzhiyun * dcache_line_size - get the safe D-cache line size across all CPUs 324*4882a593Smuzhiyun */ 325*4882a593Smuzhiyun .macro dcache_line_size, reg, tmp 326*4882a593Smuzhiyun read_ctr \tmp 327*4882a593Smuzhiyun ubfm \tmp, \tmp, #16, #19 // cache line size encoding 328*4882a593Smuzhiyun mov \reg, #4 // bytes per word 329*4882a593Smuzhiyun lsl \reg, \reg, \tmp // actual cache line size 330*4882a593Smuzhiyun .endm 331*4882a593Smuzhiyun 332*4882a593Smuzhiyun /* 333*4882a593Smuzhiyun * raw_icache_line_size - get the minimum I-cache line size on this CPU 334*4882a593Smuzhiyun * from the CTR register. 335*4882a593Smuzhiyun */ 336*4882a593Smuzhiyun .macro raw_icache_line_size, reg, tmp 337*4882a593Smuzhiyun mrs \tmp, ctr_el0 // read CTR 338*4882a593Smuzhiyun and \tmp, \tmp, #0xf // cache line size encoding 339*4882a593Smuzhiyun mov \reg, #4 // bytes per word 340*4882a593Smuzhiyun lsl \reg, \reg, \tmp // actual cache line size 341*4882a593Smuzhiyun .endm 342*4882a593Smuzhiyun 343*4882a593Smuzhiyun /* 344*4882a593Smuzhiyun * icache_line_size - get the safe I-cache line size across all CPUs 345*4882a593Smuzhiyun */ 346*4882a593Smuzhiyun .macro icache_line_size, reg, tmp 347*4882a593Smuzhiyun read_ctr \tmp 348*4882a593Smuzhiyun and \tmp, \tmp, #0xf // cache line size encoding 349*4882a593Smuzhiyun mov \reg, #4 // bytes per word 350*4882a593Smuzhiyun lsl \reg, \reg, \tmp // actual cache line size 351*4882a593Smuzhiyun .endm 352*4882a593Smuzhiyun 353*4882a593Smuzhiyun /* 354*4882a593Smuzhiyun * tcr_set_t0sz - update TCR.T0SZ so that we can load the ID map 355*4882a593Smuzhiyun */ 356*4882a593Smuzhiyun .macro tcr_set_t0sz, valreg, t0sz 357*4882a593Smuzhiyun bfi \valreg, \t0sz, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH 358*4882a593Smuzhiyun .endm 359*4882a593Smuzhiyun 360*4882a593Smuzhiyun /* 361*4882a593Smuzhiyun * tcr_set_t1sz - update TCR.T1SZ 362*4882a593Smuzhiyun */ 363*4882a593Smuzhiyun .macro tcr_set_t1sz, valreg, t1sz 364*4882a593Smuzhiyun bfi \valreg, \t1sz, #TCR_T1SZ_OFFSET, #TCR_TxSZ_WIDTH 365*4882a593Smuzhiyun .endm 366*4882a593Smuzhiyun 367*4882a593Smuzhiyun /* 368*4882a593Smuzhiyun * tcr_compute_pa_size - set TCR.(I)PS to the highest supported 369*4882a593Smuzhiyun * ID_AA64MMFR0_EL1.PARange value 370*4882a593Smuzhiyun * 371*4882a593Smuzhiyun * tcr: register with the TCR_ELx value to be updated 372*4882a593Smuzhiyun * pos: IPS or PS bitfield position 373*4882a593Smuzhiyun * tmp{0,1}: temporary registers 374*4882a593Smuzhiyun */ 375*4882a593Smuzhiyun .macro tcr_compute_pa_size, tcr, pos, tmp0, tmp1 376*4882a593Smuzhiyun mrs \tmp0, ID_AA64MMFR0_EL1 377*4882a593Smuzhiyun // Narrow PARange to fit the PS field in TCR_ELx 378*4882a593Smuzhiyun ubfx \tmp0, \tmp0, #ID_AA64MMFR0_PARANGE_SHIFT, #3 379*4882a593Smuzhiyun mov \tmp1, #ID_AA64MMFR0_PARANGE_MAX 380*4882a593Smuzhiyun cmp \tmp0, \tmp1 381*4882a593Smuzhiyun csel \tmp0, \tmp1, \tmp0, hi 382*4882a593Smuzhiyun bfi \tcr, \tmp0, \pos, #3 383*4882a593Smuzhiyun .endm 384*4882a593Smuzhiyun 385*4882a593Smuzhiyun /* 386*4882a593Smuzhiyun * Macro to perform a data cache maintenance for the interval 387*4882a593Smuzhiyun * [kaddr, kaddr + size) 388*4882a593Smuzhiyun * 389*4882a593Smuzhiyun * op: operation passed to dc instruction 390*4882a593Smuzhiyun * domain: domain used in dsb instruciton 391*4882a593Smuzhiyun * kaddr: starting virtual address of the region 392*4882a593Smuzhiyun * size: size of the region 393*4882a593Smuzhiyun * Corrupts: kaddr, size, tmp1, tmp2 394*4882a593Smuzhiyun */ 395*4882a593Smuzhiyun .macro __dcache_op_workaround_clean_cache, op, kaddr 396*4882a593Smuzhiyun alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE 397*4882a593Smuzhiyun dc \op, \kaddr 398*4882a593Smuzhiyun alternative_else 399*4882a593Smuzhiyun dc civac, \kaddr 400*4882a593Smuzhiyun alternative_endif 401*4882a593Smuzhiyun .endm 402*4882a593Smuzhiyun 403*4882a593Smuzhiyun .macro dcache_by_line_op op, domain, kaddr, size, tmp1, tmp2 404*4882a593Smuzhiyun dcache_line_size \tmp1, \tmp2 405*4882a593Smuzhiyun add \size, \kaddr, \size 406*4882a593Smuzhiyun sub \tmp2, \tmp1, #1 407*4882a593Smuzhiyun bic \kaddr, \kaddr, \tmp2 408*4882a593Smuzhiyun 9998: 409*4882a593Smuzhiyun .ifc \op, cvau 410*4882a593Smuzhiyun __dcache_op_workaround_clean_cache \op, \kaddr 411*4882a593Smuzhiyun .else 412*4882a593Smuzhiyun .ifc \op, cvac 413*4882a593Smuzhiyun __dcache_op_workaround_clean_cache \op, \kaddr 414*4882a593Smuzhiyun .else 415*4882a593Smuzhiyun .ifc \op, cvap 416*4882a593Smuzhiyun sys 3, c7, c12, 1, \kaddr // dc cvap 417*4882a593Smuzhiyun .else 418*4882a593Smuzhiyun .ifc \op, cvadp 419*4882a593Smuzhiyun sys 3, c7, c13, 1, \kaddr // dc cvadp 420*4882a593Smuzhiyun .else 421*4882a593Smuzhiyun dc \op, \kaddr 422*4882a593Smuzhiyun .endif 423*4882a593Smuzhiyun .endif 424*4882a593Smuzhiyun .endif 425*4882a593Smuzhiyun .endif 426*4882a593Smuzhiyun add \kaddr, \kaddr, \tmp1 427*4882a593Smuzhiyun cmp \kaddr, \size 428*4882a593Smuzhiyun b.lo 9998b 429*4882a593Smuzhiyun dsb \domain 430*4882a593Smuzhiyun .endm 431*4882a593Smuzhiyun 432*4882a593Smuzhiyun /* 433*4882a593Smuzhiyun * Macro to perform an instruction cache maintenance for the interval 434*4882a593Smuzhiyun * [start, end) 435*4882a593Smuzhiyun * 436*4882a593Smuzhiyun * start, end: virtual addresses describing the region 437*4882a593Smuzhiyun * label: A label to branch to on user fault. 438*4882a593Smuzhiyun * Corrupts: tmp1, tmp2 439*4882a593Smuzhiyun */ 440*4882a593Smuzhiyun .macro invalidate_icache_by_line start, end, tmp1, tmp2, label 441*4882a593Smuzhiyun icache_line_size \tmp1, \tmp2 442*4882a593Smuzhiyun sub \tmp2, \tmp1, #1 443*4882a593Smuzhiyun bic \tmp2, \start, \tmp2 444*4882a593Smuzhiyun 9997: 445*4882a593Smuzhiyun USER(\label, ic ivau, \tmp2) // invalidate I line PoU 446*4882a593Smuzhiyun add \tmp2, \tmp2, \tmp1 447*4882a593Smuzhiyun cmp \tmp2, \end 448*4882a593Smuzhiyun b.lo 9997b 449*4882a593Smuzhiyun dsb ish 450*4882a593Smuzhiyun isb 451*4882a593Smuzhiyun .endm 452*4882a593Smuzhiyun 453*4882a593Smuzhiyun /* 454*4882a593Smuzhiyun * reset_pmuserenr_el0 - reset PMUSERENR_EL0 if PMUv3 present 455*4882a593Smuzhiyun */ 456*4882a593Smuzhiyun .macro reset_pmuserenr_el0, tmpreg 457*4882a593Smuzhiyun mrs \tmpreg, id_aa64dfr0_el1 458*4882a593Smuzhiyun sbfx \tmpreg, \tmpreg, #ID_AA64DFR0_PMUVER_SHIFT, #4 459*4882a593Smuzhiyun cmp \tmpreg, #1 // Skip if no PMU present 460*4882a593Smuzhiyun b.lt 9000f 461*4882a593Smuzhiyun msr pmuserenr_el0, xzr // Disable PMU access from EL0 462*4882a593Smuzhiyun 9000: 463*4882a593Smuzhiyun .endm 464*4882a593Smuzhiyun 465*4882a593Smuzhiyun /* 466*4882a593Smuzhiyun * reset_amuserenr_el0 - reset AMUSERENR_EL0 if AMUv1 present 467*4882a593Smuzhiyun */ 468*4882a593Smuzhiyun .macro reset_amuserenr_el0, tmpreg 469*4882a593Smuzhiyun mrs \tmpreg, id_aa64pfr0_el1 // Check ID_AA64PFR0_EL1 470*4882a593Smuzhiyun ubfx \tmpreg, \tmpreg, #ID_AA64PFR0_AMU_SHIFT, #4 471*4882a593Smuzhiyun cbz \tmpreg, .Lskip_\@ // Skip if no AMU present 472*4882a593Smuzhiyun msr_s SYS_AMUSERENR_EL0, xzr // Disable AMU access from EL0 473*4882a593Smuzhiyun .Lskip_\@: 474*4882a593Smuzhiyun .endm 475*4882a593Smuzhiyun /* 476*4882a593Smuzhiyun * copy_page - copy src to dest using temp registers t1-t8 477*4882a593Smuzhiyun */ 478*4882a593Smuzhiyun .macro copy_page dest:req src:req t1:req t2:req t3:req t4:req t5:req t6:req t7:req t8:req 479*4882a593Smuzhiyun 9998: ldp \t1, \t2, [\src] 480*4882a593Smuzhiyun ldp \t3, \t4, [\src, #16] 481*4882a593Smuzhiyun ldp \t5, \t6, [\src, #32] 482*4882a593Smuzhiyun ldp \t7, \t8, [\src, #48] 483*4882a593Smuzhiyun add \src, \src, #64 484*4882a593Smuzhiyun stnp \t1, \t2, [\dest] 485*4882a593Smuzhiyun stnp \t3, \t4, [\dest, #16] 486*4882a593Smuzhiyun stnp \t5, \t6, [\dest, #32] 487*4882a593Smuzhiyun stnp \t7, \t8, [\dest, #48] 488*4882a593Smuzhiyun add \dest, \dest, #64 489*4882a593Smuzhiyun tst \src, #(PAGE_SIZE - 1) 490*4882a593Smuzhiyun b.ne 9998b 491*4882a593Smuzhiyun .endm 492*4882a593Smuzhiyun 493*4882a593Smuzhiyun /* 494*4882a593Smuzhiyun * Annotate a function as being unsuitable for kprobes. 495*4882a593Smuzhiyun */ 496*4882a593Smuzhiyun #ifdef CONFIG_KPROBES 497*4882a593Smuzhiyun #define NOKPROBE(x) \ 498*4882a593Smuzhiyun .pushsection "_kprobe_blacklist", "aw"; \ 499*4882a593Smuzhiyun .quad x; \ 500*4882a593Smuzhiyun .popsection; 501*4882a593Smuzhiyun #else 502*4882a593Smuzhiyun #define NOKPROBE(x) 503*4882a593Smuzhiyun #endif 504*4882a593Smuzhiyun 505*4882a593Smuzhiyun #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) 506*4882a593Smuzhiyun #define EXPORT_SYMBOL_NOKASAN(name) 507*4882a593Smuzhiyun #else 508*4882a593Smuzhiyun #define EXPORT_SYMBOL_NOKASAN(name) EXPORT_SYMBOL(name) 509*4882a593Smuzhiyun #endif 510*4882a593Smuzhiyun 511*4882a593Smuzhiyun /* 512*4882a593Smuzhiyun * Emit a 64-bit absolute little endian symbol reference in a way that 513*4882a593Smuzhiyun * ensures that it will be resolved at build time, even when building a 514*4882a593Smuzhiyun * PIE binary. This requires cooperation from the linker script, which 515*4882a593Smuzhiyun * must emit the lo32/hi32 halves individually. 516*4882a593Smuzhiyun */ 517*4882a593Smuzhiyun .macro le64sym, sym 518*4882a593Smuzhiyun .long \sym\()_lo32 519*4882a593Smuzhiyun .long \sym\()_hi32 520*4882a593Smuzhiyun .endm 521*4882a593Smuzhiyun 522*4882a593Smuzhiyun /* 523*4882a593Smuzhiyun * mov_q - move an immediate constant into a 64-bit register using 524*4882a593Smuzhiyun * between 2 and 4 movz/movk instructions (depending on the 525*4882a593Smuzhiyun * magnitude and sign of the operand) 526*4882a593Smuzhiyun */ 527*4882a593Smuzhiyun .macro mov_q, reg, val 528*4882a593Smuzhiyun .if (((\val) >> 31) == 0 || ((\val) >> 31) == 0x1ffffffff) 529*4882a593Smuzhiyun movz \reg, :abs_g1_s:\val 530*4882a593Smuzhiyun .else 531*4882a593Smuzhiyun .if (((\val) >> 47) == 0 || ((\val) >> 47) == 0x1ffff) 532*4882a593Smuzhiyun movz \reg, :abs_g2_s:\val 533*4882a593Smuzhiyun .else 534*4882a593Smuzhiyun movz \reg, :abs_g3:\val 535*4882a593Smuzhiyun movk \reg, :abs_g2_nc:\val 536*4882a593Smuzhiyun .endif 537*4882a593Smuzhiyun movk \reg, :abs_g1_nc:\val 538*4882a593Smuzhiyun .endif 539*4882a593Smuzhiyun movk \reg, :abs_g0_nc:\val 540*4882a593Smuzhiyun .endm 541*4882a593Smuzhiyun 542*4882a593Smuzhiyun /* 543*4882a593Smuzhiyun * Return the current task_struct. 544*4882a593Smuzhiyun */ 545*4882a593Smuzhiyun .macro get_current_task, rd 546*4882a593Smuzhiyun mrs \rd, sp_el0 547*4882a593Smuzhiyun .endm 548*4882a593Smuzhiyun 549*4882a593Smuzhiyun /* 550*4882a593Smuzhiyun * Offset ttbr1 to allow for 48-bit kernel VAs set with 52-bit PTRS_PER_PGD. 551*4882a593Smuzhiyun * orr is used as it can cover the immediate value (and is idempotent). 552*4882a593Smuzhiyun * In future this may be nop'ed out when dealing with 52-bit kernel VAs. 553*4882a593Smuzhiyun * ttbr: Value of ttbr to set, modified. 554*4882a593Smuzhiyun */ 555*4882a593Smuzhiyun .macro offset_ttbr1, ttbr, tmp 556*4882a593Smuzhiyun #ifdef CONFIG_ARM64_VA_BITS_52 557*4882a593Smuzhiyun mrs_s \tmp, SYS_ID_AA64MMFR2_EL1 558*4882a593Smuzhiyun and \tmp, \tmp, #(0xf << ID_AA64MMFR2_LVA_SHIFT) 559*4882a593Smuzhiyun cbnz \tmp, .Lskipoffs_\@ 560*4882a593Smuzhiyun orr \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET 561*4882a593Smuzhiyun .Lskipoffs_\@ : 562*4882a593Smuzhiyun #endif 563*4882a593Smuzhiyun .endm 564*4882a593Smuzhiyun 565*4882a593Smuzhiyun /* 566*4882a593Smuzhiyun * Perform the reverse of offset_ttbr1. 567*4882a593Smuzhiyun * bic is used as it can cover the immediate value and, in future, won't need 568*4882a593Smuzhiyun * to be nop'ed out when dealing with 52-bit kernel VAs. 569*4882a593Smuzhiyun */ 570*4882a593Smuzhiyun .macro restore_ttbr1, ttbr 571*4882a593Smuzhiyun #ifdef CONFIG_ARM64_VA_BITS_52 572*4882a593Smuzhiyun bic \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET 573*4882a593Smuzhiyun #endif 574*4882a593Smuzhiyun .endm 575*4882a593Smuzhiyun 576*4882a593Smuzhiyun /* 577*4882a593Smuzhiyun * Arrange a physical address in a TTBR register, taking care of 52-bit 578*4882a593Smuzhiyun * addresses. 579*4882a593Smuzhiyun * 580*4882a593Smuzhiyun * phys: physical address, preserved 581*4882a593Smuzhiyun * ttbr: returns the TTBR value 582*4882a593Smuzhiyun */ 583*4882a593Smuzhiyun .macro phys_to_ttbr, ttbr, phys 584*4882a593Smuzhiyun #ifdef CONFIG_ARM64_PA_BITS_52 585*4882a593Smuzhiyun orr \ttbr, \phys, \phys, lsr #46 586*4882a593Smuzhiyun and \ttbr, \ttbr, #TTBR_BADDR_MASK_52 587*4882a593Smuzhiyun #else 588*4882a593Smuzhiyun mov \ttbr, \phys 589*4882a593Smuzhiyun #endif 590*4882a593Smuzhiyun .endm 591*4882a593Smuzhiyun 592*4882a593Smuzhiyun .macro phys_to_pte, pte, phys 593*4882a593Smuzhiyun #ifdef CONFIG_ARM64_PA_BITS_52 594*4882a593Smuzhiyun /* 595*4882a593Smuzhiyun * We assume \phys is 64K aligned and this is guaranteed by only 596*4882a593Smuzhiyun * supporting this configuration with 64K pages. 597*4882a593Smuzhiyun */ 598*4882a593Smuzhiyun orr \pte, \phys, \phys, lsr #36 599*4882a593Smuzhiyun and \pte, \pte, #PTE_ADDR_MASK 600*4882a593Smuzhiyun #else 601*4882a593Smuzhiyun mov \pte, \phys 602*4882a593Smuzhiyun #endif 603*4882a593Smuzhiyun .endm 604*4882a593Smuzhiyun 605*4882a593Smuzhiyun .macro pte_to_phys, phys, pte 606*4882a593Smuzhiyun #ifdef CONFIG_ARM64_PA_BITS_52 607*4882a593Smuzhiyun ubfiz \phys, \pte, #(48 - 16 - 12), #16 608*4882a593Smuzhiyun bfxil \phys, \pte, #16, #32 609*4882a593Smuzhiyun lsl \phys, \phys, #16 610*4882a593Smuzhiyun #else 611*4882a593Smuzhiyun and \phys, \pte, #PTE_ADDR_MASK 612*4882a593Smuzhiyun #endif 613*4882a593Smuzhiyun .endm 614*4882a593Smuzhiyun 615*4882a593Smuzhiyun /* 616*4882a593Smuzhiyun * tcr_clear_errata_bits - Clear TCR bits that trigger an errata on this CPU. 617*4882a593Smuzhiyun */ 618*4882a593Smuzhiyun .macro tcr_clear_errata_bits, tcr, tmp1, tmp2 619*4882a593Smuzhiyun #ifdef CONFIG_FUJITSU_ERRATUM_010001 620*4882a593Smuzhiyun mrs \tmp1, midr_el1 621*4882a593Smuzhiyun 622*4882a593Smuzhiyun mov_q \tmp2, MIDR_FUJITSU_ERRATUM_010001_MASK 623*4882a593Smuzhiyun and \tmp1, \tmp1, \tmp2 624*4882a593Smuzhiyun mov_q \tmp2, MIDR_FUJITSU_ERRATUM_010001 625*4882a593Smuzhiyun cmp \tmp1, \tmp2 626*4882a593Smuzhiyun b.ne 10f 627*4882a593Smuzhiyun 628*4882a593Smuzhiyun mov_q \tmp2, TCR_CLEAR_FUJITSU_ERRATUM_010001 629*4882a593Smuzhiyun bic \tcr, \tcr, \tmp2 630*4882a593Smuzhiyun 10: 631*4882a593Smuzhiyun #endif /* CONFIG_FUJITSU_ERRATUM_010001 */ 632*4882a593Smuzhiyun .endm 633*4882a593Smuzhiyun 634*4882a593Smuzhiyun /** 635*4882a593Smuzhiyun * Errata workaround prior to disable MMU. Insert an ISB immediately prior 636*4882a593Smuzhiyun * to executing the MSR that will change SCTLR_ELn[M] from a value of 1 to 0. 637*4882a593Smuzhiyun */ 638*4882a593Smuzhiyun .macro pre_disable_mmu_workaround 639*4882a593Smuzhiyun #ifdef CONFIG_QCOM_FALKOR_ERRATUM_E1041 640*4882a593Smuzhiyun isb 641*4882a593Smuzhiyun #endif 642*4882a593Smuzhiyun .endm 643*4882a593Smuzhiyun 644*4882a593Smuzhiyun /* 645*4882a593Smuzhiyun * frame_push - Push @regcount callee saved registers to the stack, 646*4882a593Smuzhiyun * starting at x19, as well as x29/x30, and set x29 to 647*4882a593Smuzhiyun * the new value of sp. Add @extra bytes of stack space 648*4882a593Smuzhiyun * for locals. 649*4882a593Smuzhiyun */ 650*4882a593Smuzhiyun .macro frame_push, regcount:req, extra 651*4882a593Smuzhiyun __frame st, \regcount, \extra 652*4882a593Smuzhiyun .endm 653*4882a593Smuzhiyun 654*4882a593Smuzhiyun /* 655*4882a593Smuzhiyun * frame_pop - Pop the callee saved registers from the stack that were 656*4882a593Smuzhiyun * pushed in the most recent call to frame_push, as well 657*4882a593Smuzhiyun * as x29/x30 and any extra stack space that may have been 658*4882a593Smuzhiyun * allocated. 659*4882a593Smuzhiyun */ 660*4882a593Smuzhiyun .macro frame_pop 661*4882a593Smuzhiyun __frame ld 662*4882a593Smuzhiyun .endm 663*4882a593Smuzhiyun 664*4882a593Smuzhiyun .macro __frame_regs, reg1, reg2, op, num 665*4882a593Smuzhiyun .if .Lframe_regcount == \num 666*4882a593Smuzhiyun \op\()r \reg1, [sp, #(\num + 1) * 8] 667*4882a593Smuzhiyun .elseif .Lframe_regcount > \num 668*4882a593Smuzhiyun \op\()p \reg1, \reg2, [sp, #(\num + 1) * 8] 669*4882a593Smuzhiyun .endif 670*4882a593Smuzhiyun .endm 671*4882a593Smuzhiyun 672*4882a593Smuzhiyun .macro __frame, op, regcount, extra=0 673*4882a593Smuzhiyun .ifc \op, st 674*4882a593Smuzhiyun .if (\regcount) < 0 || (\regcount) > 10 675*4882a593Smuzhiyun .error "regcount should be in the range [0 ... 10]" 676*4882a593Smuzhiyun .endif 677*4882a593Smuzhiyun .if ((\extra) % 16) != 0 678*4882a593Smuzhiyun .error "extra should be a multiple of 16 bytes" 679*4882a593Smuzhiyun .endif 680*4882a593Smuzhiyun .ifdef .Lframe_regcount 681*4882a593Smuzhiyun .if .Lframe_regcount != -1 682*4882a593Smuzhiyun .error "frame_push/frame_pop may not be nested" 683*4882a593Smuzhiyun .endif 684*4882a593Smuzhiyun .endif 685*4882a593Smuzhiyun .set .Lframe_regcount, \regcount 686*4882a593Smuzhiyun .set .Lframe_extra, \extra 687*4882a593Smuzhiyun .set .Lframe_local_offset, ((\regcount + 3) / 2) * 16 688*4882a593Smuzhiyun stp x29, x30, [sp, #-.Lframe_local_offset - .Lframe_extra]! 689*4882a593Smuzhiyun mov x29, sp 690*4882a593Smuzhiyun .endif 691*4882a593Smuzhiyun 692*4882a593Smuzhiyun __frame_regs x19, x20, \op, 1 693*4882a593Smuzhiyun __frame_regs x21, x22, \op, 3 694*4882a593Smuzhiyun __frame_regs x23, x24, \op, 5 695*4882a593Smuzhiyun __frame_regs x25, x26, \op, 7 696*4882a593Smuzhiyun __frame_regs x27, x28, \op, 9 697*4882a593Smuzhiyun 698*4882a593Smuzhiyun .ifc \op, ld 699*4882a593Smuzhiyun .if .Lframe_regcount == -1 700*4882a593Smuzhiyun .error "frame_push/frame_pop may not be nested" 701*4882a593Smuzhiyun .endif 702*4882a593Smuzhiyun ldp x29, x30, [sp], #.Lframe_local_offset + .Lframe_extra 703*4882a593Smuzhiyun .set .Lframe_regcount, -1 704*4882a593Smuzhiyun .endif 705*4882a593Smuzhiyun .endm 706*4882a593Smuzhiyun 707*4882a593Smuzhiyun /* 708*4882a593Smuzhiyun * Set SCTLR_ELx to the @reg value, and invalidate the local icache 709*4882a593Smuzhiyun * in the process. This is called when setting the MMU on. 710*4882a593Smuzhiyun */ 711*4882a593Smuzhiyun .macro set_sctlr, sreg, reg 712*4882a593Smuzhiyun msr \sreg, \reg 713*4882a593Smuzhiyun isb 714*4882a593Smuzhiyun /* 715*4882a593Smuzhiyun * Invalidate the local I-cache so that any instructions fetched 716*4882a593Smuzhiyun * speculatively from the PoC are discarded, since they may have 717*4882a593Smuzhiyun * been dynamically patched at the PoU. 718*4882a593Smuzhiyun */ 719*4882a593Smuzhiyun ic iallu 720*4882a593Smuzhiyun dsb nsh 721*4882a593Smuzhiyun isb 722*4882a593Smuzhiyun .endm 723*4882a593Smuzhiyun 724*4882a593Smuzhiyun .macro set_sctlr_el1, reg 725*4882a593Smuzhiyun set_sctlr sctlr_el1, \reg 726*4882a593Smuzhiyun .endm 727*4882a593Smuzhiyun 728*4882a593Smuzhiyun .macro set_sctlr_el2, reg 729*4882a593Smuzhiyun set_sctlr sctlr_el2, \reg 730*4882a593Smuzhiyun .endm 731*4882a593Smuzhiyun 732*4882a593Smuzhiyun /* 733*4882a593Smuzhiyun * Check whether preempt/bh-disabled asm code should yield as soon as 734*4882a593Smuzhiyun * it is able. This is the case if we are currently running in task 735*4882a593Smuzhiyun * context, and either a softirq is pending, or the TIF_NEED_RESCHED 736*4882a593Smuzhiyun * flag is set and re-enabling preemption a single time would result in 737*4882a593Smuzhiyun * a preempt count of zero. (Note that the TIF_NEED_RESCHED flag is 738*4882a593Smuzhiyun * stored negated in the top word of the thread_info::preempt_count 739*4882a593Smuzhiyun * field) 740*4882a593Smuzhiyun */ 741*4882a593Smuzhiyun .macro cond_yield, lbl:req, tmp:req, tmp2:req 742*4882a593Smuzhiyun get_current_task \tmp 743*4882a593Smuzhiyun ldr \tmp, [\tmp, #TSK_TI_PREEMPT] 744*4882a593Smuzhiyun /* 745*4882a593Smuzhiyun * If we are serving a softirq, there is no point in yielding: the 746*4882a593Smuzhiyun * softirq will not be preempted no matter what we do, so we should 747*4882a593Smuzhiyun * run to completion as quickly as we can. 748*4882a593Smuzhiyun */ 749*4882a593Smuzhiyun tbnz \tmp, #SOFTIRQ_SHIFT, .Lnoyield_\@ 750*4882a593Smuzhiyun #ifdef CONFIG_PREEMPTION 751*4882a593Smuzhiyun sub \tmp, \tmp, #PREEMPT_DISABLE_OFFSET 752*4882a593Smuzhiyun cbz \tmp, \lbl 753*4882a593Smuzhiyun #endif 754*4882a593Smuzhiyun adr_l \tmp, irq_stat + IRQ_CPUSTAT_SOFTIRQ_PENDING 755*4882a593Smuzhiyun this_cpu_offset \tmp2 756*4882a593Smuzhiyun ldr w\tmp, [\tmp, \tmp2] 757*4882a593Smuzhiyun cbnz w\tmp, \lbl // yield on pending softirq in task context 758*4882a593Smuzhiyun .Lnoyield_\@: 759*4882a593Smuzhiyun .endm 760*4882a593Smuzhiyun 761*4882a593Smuzhiyun /* 762*4882a593Smuzhiyun * This macro emits a program property note section identifying 763*4882a593Smuzhiyun * architecture features which require special handling, mainly for 764*4882a593Smuzhiyun * use in assembly files included in the VDSO. 765*4882a593Smuzhiyun */ 766*4882a593Smuzhiyun 767*4882a593Smuzhiyun #define NT_GNU_PROPERTY_TYPE_0 5 768*4882a593Smuzhiyun #define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 769*4882a593Smuzhiyun 770*4882a593Smuzhiyun #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) 771*4882a593Smuzhiyun #define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1U << 1) 772*4882a593Smuzhiyun 773*4882a593Smuzhiyun #ifdef CONFIG_ARM64_BTI_KERNEL 774*4882a593Smuzhiyun #define GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT \ 775*4882a593Smuzhiyun ((GNU_PROPERTY_AARCH64_FEATURE_1_BTI | \ 776*4882a593Smuzhiyun GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) 777*4882a593Smuzhiyun #endif 778*4882a593Smuzhiyun 779*4882a593Smuzhiyun #ifdef GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT 780*4882a593Smuzhiyun .macro emit_aarch64_feature_1_and, feat=GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT 781*4882a593Smuzhiyun .pushsection .note.gnu.property, "a" 782*4882a593Smuzhiyun .align 3 783*4882a593Smuzhiyun .long 2f - 1f 784*4882a593Smuzhiyun .long 6f - 3f 785*4882a593Smuzhiyun .long NT_GNU_PROPERTY_TYPE_0 786*4882a593Smuzhiyun 1: .string "GNU" 787*4882a593Smuzhiyun 2: 788*4882a593Smuzhiyun .align 3 789*4882a593Smuzhiyun 3: .long GNU_PROPERTY_AARCH64_FEATURE_1_AND 790*4882a593Smuzhiyun .long 5f - 4f 791*4882a593Smuzhiyun 4: 792*4882a593Smuzhiyun /* 793*4882a593Smuzhiyun * This is described with an array of char in the Linux API 794*4882a593Smuzhiyun * spec but the text and all other usage (including binutils, 795*4882a593Smuzhiyun * clang and GCC) treat this as a 32 bit value so no swizzling 796*4882a593Smuzhiyun * is required for big endian. 797*4882a593Smuzhiyun */ 798*4882a593Smuzhiyun .long \feat 799*4882a593Smuzhiyun 5: 800*4882a593Smuzhiyun .align 3 801*4882a593Smuzhiyun 6: 802*4882a593Smuzhiyun .popsection 803*4882a593Smuzhiyun .endm 804*4882a593Smuzhiyun 805*4882a593Smuzhiyun #else 806*4882a593Smuzhiyun .macro emit_aarch64_feature_1_and, feat=0 807*4882a593Smuzhiyun .endm 808*4882a593Smuzhiyun 809*4882a593Smuzhiyun #endif /* GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT */ 810*4882a593Smuzhiyun 811*4882a593Smuzhiyun .macro __mitigate_spectre_bhb_loop tmp 812*4882a593Smuzhiyun #ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY 813*4882a593Smuzhiyun alternative_cb spectre_bhb_patch_loop_iter 814*4882a593Smuzhiyun mov \tmp, #32 // Patched to correct the immediate 815*4882a593Smuzhiyun alternative_cb_end 816*4882a593Smuzhiyun .Lspectre_bhb_loop\@: 817*4882a593Smuzhiyun b . + 4 818*4882a593Smuzhiyun subs \tmp, \tmp, #1 819*4882a593Smuzhiyun b.ne .Lspectre_bhb_loop\@ 820*4882a593Smuzhiyun sb 821*4882a593Smuzhiyun #endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ 822*4882a593Smuzhiyun .endm 823*4882a593Smuzhiyun 824*4882a593Smuzhiyun .macro mitigate_spectre_bhb_loop tmp 825*4882a593Smuzhiyun #ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY 826*4882a593Smuzhiyun alternative_cb spectre_bhb_patch_loop_mitigation_enable 827*4882a593Smuzhiyun b .L_spectre_bhb_loop_done\@ // Patched to NOP 828*4882a593Smuzhiyun alternative_cb_end 829*4882a593Smuzhiyun __mitigate_spectre_bhb_loop \tmp 830*4882a593Smuzhiyun .L_spectre_bhb_loop_done\@: 831*4882a593Smuzhiyun #endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ 832*4882a593Smuzhiyun .endm 833*4882a593Smuzhiyun 834*4882a593Smuzhiyun /* Save/restores x0-x3 to the stack */ 835*4882a593Smuzhiyun .macro __mitigate_spectre_bhb_fw 836*4882a593Smuzhiyun #ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY 837*4882a593Smuzhiyun stp x0, x1, [sp, #-16]! 838*4882a593Smuzhiyun stp x2, x3, [sp, #-16]! 839*4882a593Smuzhiyun mov w0, #ARM_SMCCC_ARCH_WORKAROUND_3 840*4882a593Smuzhiyun alternative_cb smccc_patch_fw_mitigation_conduit 841*4882a593Smuzhiyun nop // Patched to SMC/HVC #0 842*4882a593Smuzhiyun alternative_cb_end 843*4882a593Smuzhiyun ldp x2, x3, [sp], #16 844*4882a593Smuzhiyun ldp x0, x1, [sp], #16 845*4882a593Smuzhiyun #endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ 846*4882a593Smuzhiyun .endm 847*4882a593Smuzhiyun 848*4882a593Smuzhiyun .macro mitigate_spectre_bhb_clear_insn 849*4882a593Smuzhiyun #ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY 850*4882a593Smuzhiyun alternative_cb spectre_bhb_patch_clearbhb 851*4882a593Smuzhiyun /* Patched to NOP when not supported */ 852*4882a593Smuzhiyun clearbhb 853*4882a593Smuzhiyun isb 854*4882a593Smuzhiyun alternative_cb_end 855*4882a593Smuzhiyun #endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ 856*4882a593Smuzhiyun .endm 857*4882a593Smuzhiyun #endif /* __ASM_ASSEMBLER_H */ 858