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