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