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