| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 1996-2000 Russell King |
|---|
| 5 | 6 | * 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 | 7 | */ |
|---|
| 19 | 8 | #ifndef __ASSEMBLY__ |
|---|
| 20 | 9 | #error "Only include this from assembly code" |
|---|
| .. | .. |
|---|
| 26 | 15 | #include <asm-generic/export.h> |
|---|
| 27 | 16 | |
|---|
| 28 | 17 | #include <asm/asm-offsets.h> |
|---|
| 18 | +#include <asm/asm-bug.h> |
|---|
| 19 | +#include <asm/alternative.h> |
|---|
| 29 | 20 | #include <asm/cpufeature.h> |
|---|
| 21 | +#include <asm/cputype.h> |
|---|
| 30 | 22 | #include <asm/debug-monitors.h> |
|---|
| 31 | 23 | #include <asm/page.h> |
|---|
| 32 | 24 | #include <asm/pgtable-hwdef.h> |
|---|
| 33 | 25 | #include <asm/ptrace.h> |
|---|
| 34 | 26 | #include <asm/thread_info.h> |
|---|
| 27 | + |
|---|
| 28 | + /* |
|---|
| 29 | + * Provide a wxN alias for each wN register so what we can paste a xN |
|---|
| 30 | + * reference after a 'w' to obtain the 32-bit version. |
|---|
| 31 | + */ |
|---|
| 32 | + .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 | + wx\n .req w\n |
|---|
| 34 | + .endr |
|---|
| 35 | 35 | |
|---|
| 36 | 36 | .macro save_and_disable_daif, flags |
|---|
| 37 | 37 | mrs \flags, daif |
|---|
| .. | .. |
|---|
| 50 | 50 | msr daif, \flags |
|---|
| 51 | 51 | .endm |
|---|
| 52 | 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 | 53 | /* IRQ is the lowest priority flag, unconditionally unmask the rest. */ |
|---|
| 60 | 54 | .macro enable_da_f |
|---|
| 61 | 55 | msr daifclr, #(8 | 4 | 1) |
|---|
| 62 | 56 | .endm |
|---|
| 63 | 57 | |
|---|
| 64 | 58 | /* |
|---|
| 65 | | - * Enable and disable interrupts. |
|---|
| 59 | + * Save/restore interrupts. |
|---|
| 66 | 60 | */ |
|---|
| 67 | | - .macro disable_irq |
|---|
| 68 | | - msr daifset, #2 |
|---|
| 69 | | - .endm |
|---|
| 70 | | - |
|---|
| 71 | | - .macro enable_irq |
|---|
| 72 | | - msr daifclr, #2 |
|---|
| 73 | | - .endm |
|---|
| 74 | | - |
|---|
| 75 | 61 | .macro save_and_disable_irq, flags |
|---|
| 76 | 62 | mrs \flags, daif |
|---|
| 77 | 63 | msr daifset, #2 |
|---|
| .. | .. |
|---|
| 79 | 65 | |
|---|
| 80 | 66 | .macro restore_irq, flags |
|---|
| 81 | 67 | msr daif, \flags |
|---|
| 82 | | - .endm |
|---|
| 83 | | - |
|---|
| 84 | | -/* |
|---|
| 85 | | - * Save/disable and restore interrupts. |
|---|
| 86 | | - */ |
|---|
| 87 | | - .macro save_and_disable_irqs, olddaif |
|---|
| 88 | | - mrs \olddaif, daif |
|---|
| 89 | | - disable_irq |
|---|
| 90 | | - .endm |
|---|
| 91 | | - |
|---|
| 92 | | - .macro restore_irqs, olddaif |
|---|
| 93 | | - msr daif, \olddaif |
|---|
| 94 | 68 | .endm |
|---|
| 95 | 69 | |
|---|
| 96 | 70 | .macro enable_dbg |
|---|
| .. | .. |
|---|
| 116 | 90 | .endm |
|---|
| 117 | 91 | |
|---|
| 118 | 92 | /* |
|---|
| 119 | | - * SMP data memory barrier |
|---|
| 120 | | - */ |
|---|
| 121 | | - .macro smp_dmb, opt |
|---|
| 122 | | - dmb \opt |
|---|
| 123 | | - .endm |
|---|
| 124 | | - |
|---|
| 125 | | -/* |
|---|
| 126 | 93 | * RAS Error Synchronization barrier |
|---|
| 127 | 94 | */ |
|---|
| 128 | 95 | .macro esb |
|---|
| .. | .. |
|---|
| 141 | 108 | .endm |
|---|
| 142 | 109 | |
|---|
| 143 | 110 | /* |
|---|
| 144 | | - * Sanitise a 64-bit bounded index wrt speculation, returning zero if out |
|---|
| 145 | | - * of bounds. |
|---|
| 111 | + * Clear Branch History instruction |
|---|
| 146 | 112 | */ |
|---|
| 147 | | - .macro mask_nospec64, idx, limit, tmp |
|---|
| 148 | | - sub \tmp, \idx, \limit |
|---|
| 149 | | - bic \tmp, \tmp, \idx |
|---|
| 150 | | - and \idx, \idx, \tmp, asr #63 |
|---|
| 151 | | - csdb |
|---|
| 113 | + .macro clearbhb |
|---|
| 114 | + hint #22 |
|---|
| 152 | 115 | .endm |
|---|
| 153 | 116 | |
|---|
| 154 | 117 | /* |
|---|
| 155 | 118 | * Speculation barrier |
|---|
| 156 | 119 | */ |
|---|
| 157 | 120 | .macro sb |
|---|
| 121 | +alternative_if_not ARM64_HAS_SB |
|---|
| 158 | 122 | dsb nsh |
|---|
| 159 | 123 | isb |
|---|
| 124 | +alternative_else |
|---|
| 125 | + SB_BARRIER_INSN |
|---|
| 126 | + nop |
|---|
| 127 | +alternative_endif |
|---|
| 160 | 128 | .endm |
|---|
| 161 | 129 | |
|---|
| 162 | 130 | /* |
|---|
| .. | .. |
|---|
| 268 | 236 | .endm |
|---|
| 269 | 237 | |
|---|
| 270 | 238 | /* |
|---|
| 239 | + * @dst: destination register |
|---|
| 240 | + */ |
|---|
| 241 | +#if defined(__KVM_NVHE_HYPERVISOR__) || defined(__KVM_VHE_HYPERVISOR__) |
|---|
| 242 | + .macro this_cpu_offset, dst |
|---|
| 243 | + mrs \dst, tpidr_el2 |
|---|
| 244 | + .endm |
|---|
| 245 | +#else |
|---|
| 246 | + .macro this_cpu_offset, dst |
|---|
| 247 | +alternative_if_not ARM64_HAS_VIRT_HOST_EXTN |
|---|
| 248 | + mrs \dst, tpidr_el1 |
|---|
| 249 | +alternative_else |
|---|
| 250 | + mrs \dst, tpidr_el2 |
|---|
| 251 | +alternative_endif |
|---|
| 252 | + .endm |
|---|
| 253 | +#endif |
|---|
| 254 | + |
|---|
| 255 | + /* |
|---|
| 271 | 256 | * @dst: Result of per_cpu(sym, smp_processor_id()) (can be SP) |
|---|
| 272 | 257 | * @sym: The name of the per-cpu variable |
|---|
| 273 | 258 | * @tmp: scratch register |
|---|
| .. | .. |
|---|
| 275 | 260 | .macro adr_this_cpu, dst, sym, tmp |
|---|
| 276 | 261 | adrp \tmp, \sym |
|---|
| 277 | 262 | add \dst, \tmp, #:lo12:\sym |
|---|
| 278 | | -alternative_if_not ARM64_HAS_VIRT_HOST_EXTN |
|---|
| 279 | | - mrs \tmp, tpidr_el1 |
|---|
| 280 | | -alternative_else |
|---|
| 281 | | - mrs \tmp, tpidr_el2 |
|---|
| 282 | | -alternative_endif |
|---|
| 263 | + this_cpu_offset \tmp |
|---|
| 283 | 264 | add \dst, \dst, \tmp |
|---|
| 284 | 265 | .endm |
|---|
| 285 | 266 | |
|---|
| .. | .. |
|---|
| 290 | 271 | */ |
|---|
| 291 | 272 | .macro ldr_this_cpu dst, sym, tmp |
|---|
| 292 | 273 | adr_l \dst, \sym |
|---|
| 293 | | -alternative_if_not ARM64_HAS_VIRT_HOST_EXTN |
|---|
| 294 | | - mrs \tmp, tpidr_el1 |
|---|
| 295 | | -alternative_else |
|---|
| 296 | | - mrs \tmp, tpidr_el2 |
|---|
| 297 | | -alternative_endif |
|---|
| 274 | + this_cpu_offset \tmp |
|---|
| 298 | 275 | ldr \dst, [\dst, \tmp] |
|---|
| 299 | 276 | .endm |
|---|
| 300 | 277 | |
|---|
| .. | .. |
|---|
| 306 | 283 | .endm |
|---|
| 307 | 284 | |
|---|
| 308 | 285 | /* |
|---|
| 309 | | - * mmid - get context id from mm pointer (mm->context.id) |
|---|
| 310 | | - */ |
|---|
| 311 | | - .macro mmid, rd, rn |
|---|
| 312 | | - ldr \rd, [\rn, #MM_CONTEXT_ID] |
|---|
| 313 | | - .endm |
|---|
| 314 | | -/* |
|---|
| 315 | | - * read_ctr - read CTR_EL0. If the system has mismatched |
|---|
| 316 | | - * cache line sizes, provide the system wide safe value |
|---|
| 317 | | - * from arm64_ftr_reg_ctrel0.sys_val |
|---|
| 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 |
|---|
| 318 | 288 | */ |
|---|
| 319 | 289 | .macro read_ctr, reg |
|---|
| 320 | | -alternative_if_not ARM64_MISMATCHED_CACHE_LINE_SIZE |
|---|
| 290 | +#ifndef __KVM_NVHE_HYPERVISOR__ |
|---|
| 291 | +alternative_if_not ARM64_MISMATCHED_CACHE_TYPE |
|---|
| 321 | 292 | mrs \reg, ctr_el0 // read CTR |
|---|
| 322 | 293 | nop |
|---|
| 323 | 294 | alternative_else |
|---|
| 324 | 295 | ldr_l \reg, arm64_ftr_reg_ctrel0 + ARM64_FTR_SYSVAL |
|---|
| 325 | 296 | alternative_endif |
|---|
| 297 | +#else |
|---|
| 298 | +alternative_if_not ARM64_KVM_PROTECTED_MODE |
|---|
| 299 | + ASM_BUG() |
|---|
| 300 | +alternative_else_nop_endif |
|---|
| 301 | +alternative_cb kvm_compute_final_ctr_el0 |
|---|
| 302 | + movz \reg, #0 |
|---|
| 303 | + movk \reg, #0, lsl #16 |
|---|
| 304 | + movk \reg, #0, lsl #32 |
|---|
| 305 | + movk \reg, #0, lsl #48 |
|---|
| 306 | +alternative_cb_end |
|---|
| 307 | +#endif |
|---|
| 326 | 308 | .endm |
|---|
| 327 | 309 | |
|---|
| 328 | 310 | |
|---|
| .. | .. |
|---|
| 369 | 351 | .endm |
|---|
| 370 | 352 | |
|---|
| 371 | 353 | /* |
|---|
| 372 | | - * tcr_set_idmap_t0sz - update TCR.T0SZ so that we can load the ID map |
|---|
| 354 | + * tcr_set_t0sz - update TCR.T0SZ so that we can load the ID map |
|---|
| 373 | 355 | */ |
|---|
| 374 | | - .macro tcr_set_idmap_t0sz, valreg, tmpreg |
|---|
| 375 | | - ldr_l \tmpreg, idmap_t0sz |
|---|
| 376 | | - bfi \valreg, \tmpreg, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH |
|---|
| 356 | + .macro tcr_set_t0sz, valreg, t0sz |
|---|
| 357 | + bfi \valreg, \t0sz, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH |
|---|
| 358 | + .endm |
|---|
| 359 | + |
|---|
| 360 | +/* |
|---|
| 361 | + * tcr_set_t1sz - update TCR.T1SZ |
|---|
| 362 | + */ |
|---|
| 363 | + .macro tcr_set_t1sz, valreg, t1sz |
|---|
| 364 | + bfi \valreg, \t1sz, #TCR_T1SZ_OFFSET, #TCR_TxSZ_WIDTH |
|---|
| 377 | 365 | .endm |
|---|
| 378 | 366 | |
|---|
| 379 | 367 | /* |
|---|
| .. | .. |
|---|
| 427 | 415 | .ifc \op, cvap |
|---|
| 428 | 416 | sys 3, c7, c12, 1, \kaddr // dc cvap |
|---|
| 429 | 417 | .else |
|---|
| 418 | + .ifc \op, cvadp |
|---|
| 419 | + sys 3, c7, c13, 1, \kaddr // dc cvadp |
|---|
| 420 | + .else |
|---|
| 430 | 421 | dc \op, \kaddr |
|---|
| 422 | + .endif |
|---|
| 431 | 423 | .endif |
|---|
| 432 | 424 | .endif |
|---|
| 433 | 425 | .endif |
|---|
| .. | .. |
|---|
| 462 | 454 | * reset_pmuserenr_el0 - reset PMUSERENR_EL0 if PMUv3 present |
|---|
| 463 | 455 | */ |
|---|
| 464 | 456 | .macro reset_pmuserenr_el0, tmpreg |
|---|
| 465 | | - mrs \tmpreg, id_aa64dfr0_el1 // Check ID_AA64DFR0_EL1 PMUVer |
|---|
| 466 | | - sbfx \tmpreg, \tmpreg, #8, #4 |
|---|
| 457 | + mrs \tmpreg, id_aa64dfr0_el1 |
|---|
| 458 | + sbfx \tmpreg, \tmpreg, #ID_AA64DFR0_PMUVER_SHIFT, #4 |
|---|
| 467 | 459 | cmp \tmpreg, #1 // Skip if no PMU present |
|---|
| 468 | 460 | b.lt 9000f |
|---|
| 469 | 461 | msr pmuserenr_el0, xzr // Disable PMU access from EL0 |
|---|
| 470 | 462 | 9000: |
|---|
| 471 | 463 | .endm |
|---|
| 472 | 464 | |
|---|
| 465 | +/* |
|---|
| 466 | + * reset_amuserenr_el0 - reset AMUSERENR_EL0 if AMUv1 present |
|---|
| 467 | + */ |
|---|
| 468 | + .macro reset_amuserenr_el0, tmpreg |
|---|
| 469 | + mrs \tmpreg, id_aa64pfr0_el1 // Check ID_AA64PFR0_EL1 |
|---|
| 470 | + ubfx \tmpreg, \tmpreg, #ID_AA64PFR0_AMU_SHIFT, #4 |
|---|
| 471 | + cbz \tmpreg, .Lskip_\@ // Skip if no AMU present |
|---|
| 472 | + msr_s SYS_AMUSERENR_EL0, xzr // Disable AMU access from EL0 |
|---|
| 473 | +.Lskip_\@: |
|---|
| 474 | + .endm |
|---|
| 473 | 475 | /* |
|---|
| 474 | 476 | * copy_page - copy src to dest using temp registers t1-t8 |
|---|
| 475 | 477 | */ |
|---|
| .. | .. |
|---|
| 489 | 491 | .endm |
|---|
| 490 | 492 | |
|---|
| 491 | 493 | /* |
|---|
| 492 | | - * Annotate a function as position independent, i.e., safe to be called before |
|---|
| 493 | | - * the kernel virtual mapping is activated. |
|---|
| 494 | | - */ |
|---|
| 495 | | -#define ENDPIPROC(x) \ |
|---|
| 496 | | - .globl __pi_##x; \ |
|---|
| 497 | | - .type __pi_##x, %function; \ |
|---|
| 498 | | - .set __pi_##x, x; \ |
|---|
| 499 | | - .size __pi_##x, . - x; \ |
|---|
| 500 | | - ENDPROC(x) |
|---|
| 501 | | - |
|---|
| 502 | | -/* |
|---|
| 503 | 494 | * Annotate a function as being unsuitable for kprobes. |
|---|
| 504 | 495 | */ |
|---|
| 505 | 496 | #ifdef CONFIG_KPROBES |
|---|
| .. | .. |
|---|
| 511 | 502 | #define NOKPROBE(x) |
|---|
| 512 | 503 | #endif |
|---|
| 513 | 504 | |
|---|
| 514 | | -#ifdef CONFIG_KASAN |
|---|
| 505 | +#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) |
|---|
| 515 | 506 | #define EXPORT_SYMBOL_NOKASAN(name) |
|---|
| 516 | 507 | #else |
|---|
| 517 | 508 | #define EXPORT_SYMBOL_NOKASAN(name) EXPORT_SYMBOL(name) |
|---|
| .. | .. |
|---|
| 549 | 540 | .endm |
|---|
| 550 | 541 | |
|---|
| 551 | 542 | /* |
|---|
| 552 | | - * Return the current thread_info. |
|---|
| 543 | + * Return the current task_struct. |
|---|
| 553 | 544 | */ |
|---|
| 554 | | - .macro get_thread_info, rd |
|---|
| 545 | + .macro get_current_task, rd |
|---|
| 555 | 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 |
|---|
| 556 | 574 | .endm |
|---|
| 557 | 575 | |
|---|
| 558 | 576 | /* |
|---|
| .. | .. |
|---|
| 592 | 610 | #else |
|---|
| 593 | 611 | and \phys, \pte, #PTE_ADDR_MASK |
|---|
| 594 | 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 |
|---|
| 630 | +10: |
|---|
| 631 | +#endif /* CONFIG_FUJITSU_ERRATUM_010001 */ |
|---|
| 595 | 632 | .endm |
|---|
| 596 | 633 | |
|---|
| 597 | 634 | /** |
|---|
| .. | .. |
|---|
| 668 | 705 | .endm |
|---|
| 669 | 706 | |
|---|
| 670 | 707 | /* |
|---|
| 671 | | - * Check whether to yield to another runnable task from kernel mode NEON code |
|---|
| 672 | | - * (which runs with preemption disabled). |
|---|
| 673 | | - * |
|---|
| 674 | | - * if_will_cond_yield_neon |
|---|
| 675 | | - * // pre-yield patchup code |
|---|
| 676 | | - * do_cond_yield_neon |
|---|
| 677 | | - * // post-yield patchup code |
|---|
| 678 | | - * endif_yield_neon <label> |
|---|
| 679 | | - * |
|---|
| 680 | | - * where <label> is optional, and marks the point where execution will resume |
|---|
| 681 | | - * after a yield has been performed. If omitted, execution resumes right after |
|---|
| 682 | | - * the endif_yield_neon invocation. Note that the entire sequence, including |
|---|
| 683 | | - * the provided patchup code, will be omitted from the image if CONFIG_PREEMPT |
|---|
| 684 | | - * is not defined. |
|---|
| 685 | | - * |
|---|
| 686 | | - * As a convenience, in the case where no patchup code is required, the above |
|---|
| 687 | | - * sequence may be abbreviated to |
|---|
| 688 | | - * |
|---|
| 689 | | - * cond_yield_neon <label> |
|---|
| 690 | | - * |
|---|
| 691 | | - * Note that the patchup code does not support assembler directives that change |
|---|
| 692 | | - * the output section, any use of such directives is undefined. |
|---|
| 693 | | - * |
|---|
| 694 | | - * The yield itself consists of the following: |
|---|
| 695 | | - * - Check whether the preempt count is exactly 1, in which case disabling |
|---|
| 696 | | - * preemption once will make the task preemptible. If this is not the case, |
|---|
| 697 | | - * yielding is pointless. |
|---|
| 698 | | - * - Check whether TIF_NEED_RESCHED is set, and if so, disable and re-enable |
|---|
| 699 | | - * kernel mode NEON (which will trigger a reschedule), and branch to the |
|---|
| 700 | | - * yield fixup code. |
|---|
| 701 | | - * |
|---|
| 702 | | - * This macro sequence may clobber all CPU state that is not guaranteed by the |
|---|
| 703 | | - * AAPCS to be preserved across an ordinary function call. |
|---|
| 708 | + * Set SCTLR_ELx to the @reg value, and invalidate the local icache |
|---|
| 709 | + * in the process. This is called when setting the MMU on. |
|---|
| 710 | + */ |
|---|
| 711 | +.macro set_sctlr, sreg, reg |
|---|
| 712 | + msr \sreg, \reg |
|---|
| 713 | + isb |
|---|
| 714 | + /* |
|---|
| 715 | + * Invalidate the local I-cache so that any instructions fetched |
|---|
| 716 | + * speculatively from the PoC are discarded, since they may have |
|---|
| 717 | + * been dynamically patched at the PoU. |
|---|
| 718 | + */ |
|---|
| 719 | + ic iallu |
|---|
| 720 | + dsb nsh |
|---|
| 721 | + isb |
|---|
| 722 | +.endm |
|---|
| 723 | + |
|---|
| 724 | +.macro set_sctlr_el1, reg |
|---|
| 725 | + set_sctlr sctlr_el1, \reg |
|---|
| 726 | +.endm |
|---|
| 727 | + |
|---|
| 728 | +.macro set_sctlr_el2, reg |
|---|
| 729 | + set_sctlr sctlr_el2, \reg |
|---|
| 730 | +.endm |
|---|
| 731 | + |
|---|
| 732 | + /* |
|---|
| 733 | + * Check whether preempt/bh-disabled asm code should yield as soon as |
|---|
| 734 | + * it is able. This is the case if we are currently running in task |
|---|
| 735 | + * context, and either a softirq is pending, or the TIF_NEED_RESCHED |
|---|
| 736 | + * flag is set and re-enabling preemption a single time would result in |
|---|
| 737 | + * a preempt count of zero. (Note that the TIF_NEED_RESCHED flag is |
|---|
| 738 | + * stored negated in the top word of the thread_info::preempt_count |
|---|
| 739 | + * field) |
|---|
| 740 | + */ |
|---|
| 741 | + .macro cond_yield, lbl:req, tmp:req, tmp2:req |
|---|
| 742 | + get_current_task \tmp |
|---|
| 743 | + ldr \tmp, [\tmp, #TSK_TI_PREEMPT] |
|---|
| 744 | + /* |
|---|
| 745 | + * If we are serving a softirq, there is no point in yielding: the |
|---|
| 746 | + * softirq will not be preempted no matter what we do, so we should |
|---|
| 747 | + * run to completion as quickly as we can. |
|---|
| 748 | + */ |
|---|
| 749 | + tbnz \tmp, #SOFTIRQ_SHIFT, .Lnoyield_\@ |
|---|
| 750 | +#ifdef CONFIG_PREEMPTION |
|---|
| 751 | + sub \tmp, \tmp, #PREEMPT_DISABLE_OFFSET |
|---|
| 752 | + cbz \tmp, \lbl |
|---|
| 753 | +#endif |
|---|
| 754 | + adr_l \tmp, irq_stat + IRQ_CPUSTAT_SOFTIRQ_PENDING |
|---|
| 755 | + this_cpu_offset \tmp2 |
|---|
| 756 | + ldr w\tmp, [\tmp, \tmp2] |
|---|
| 757 | + cbnz w\tmp, \lbl // yield on pending softirq in task context |
|---|
| 758 | +.Lnoyield_\@: |
|---|
| 759 | + .endm |
|---|
| 760 | + |
|---|
| 761 | +/* |
|---|
| 762 | + * This macro emits a program property note section identifying |
|---|
| 763 | + * architecture features which require special handling, mainly for |
|---|
| 764 | + * use in assembly files included in the VDSO. |
|---|
| 704 | 765 | */ |
|---|
| 705 | 766 | |
|---|
| 706 | | - .macro cond_yield_neon, lbl |
|---|
| 707 | | - if_will_cond_yield_neon |
|---|
| 708 | | - do_cond_yield_neon |
|---|
| 709 | | - endif_yield_neon \lbl |
|---|
| 710 | | - .endm |
|---|
| 767 | +#define NT_GNU_PROPERTY_TYPE_0 5 |
|---|
| 768 | +#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 |
|---|
| 711 | 769 | |
|---|
| 712 | | - .macro if_will_cond_yield_neon |
|---|
| 713 | | -#ifdef CONFIG_PREEMPT |
|---|
| 714 | | - get_thread_info x0 |
|---|
| 715 | | - ldr w1, [x0, #TSK_TI_PREEMPT] |
|---|
| 716 | | - ldr x0, [x0, #TSK_TI_FLAGS] |
|---|
| 717 | | - cmp w1, #PREEMPT_DISABLE_OFFSET |
|---|
| 718 | | - csel x0, x0, xzr, eq |
|---|
| 719 | | - tbnz x0, #TIF_NEED_RESCHED, .Lyield_\@ // needs rescheduling? |
|---|
| 720 | | - /* fall through to endif_yield_neon */ |
|---|
| 721 | | - .subsection 1 |
|---|
| 722 | | -.Lyield_\@ : |
|---|
| 723 | | -#else |
|---|
| 724 | | - .section ".discard.cond_yield_neon", "ax" |
|---|
| 770 | +#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) |
|---|
| 771 | +#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1U << 1) |
|---|
| 772 | + |
|---|
| 773 | +#ifdef CONFIG_ARM64_BTI_KERNEL |
|---|
| 774 | +#define GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT \ |
|---|
| 775 | + ((GNU_PROPERTY_AARCH64_FEATURE_1_BTI | \ |
|---|
| 776 | + GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) |
|---|
| 725 | 777 | #endif |
|---|
| 778 | + |
|---|
| 779 | +#ifdef GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT |
|---|
| 780 | +.macro emit_aarch64_feature_1_and, feat=GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT |
|---|
| 781 | + .pushsection .note.gnu.property, "a" |
|---|
| 782 | + .align 3 |
|---|
| 783 | + .long 2f - 1f |
|---|
| 784 | + .long 6f - 3f |
|---|
| 785 | + .long NT_GNU_PROPERTY_TYPE_0 |
|---|
| 786 | +1: .string "GNU" |
|---|
| 787 | +2: |
|---|
| 788 | + .align 3 |
|---|
| 789 | +3: .long GNU_PROPERTY_AARCH64_FEATURE_1_AND |
|---|
| 790 | + .long 5f - 4f |
|---|
| 791 | +4: |
|---|
| 792 | + /* |
|---|
| 793 | + * This is described with an array of char in the Linux API |
|---|
| 794 | + * spec but the text and all other usage (including binutils, |
|---|
| 795 | + * clang and GCC) treat this as a 32 bit value so no swizzling |
|---|
| 796 | + * is required for big endian. |
|---|
| 797 | + */ |
|---|
| 798 | + .long \feat |
|---|
| 799 | +5: |
|---|
| 800 | + .align 3 |
|---|
| 801 | +6: |
|---|
| 802 | + .popsection |
|---|
| 803 | +.endm |
|---|
| 804 | + |
|---|
| 805 | +#else |
|---|
| 806 | +.macro emit_aarch64_feature_1_and, feat=0 |
|---|
| 807 | +.endm |
|---|
| 808 | + |
|---|
| 809 | +#endif /* GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT */ |
|---|
| 810 | + |
|---|
| 811 | + .macro __mitigate_spectre_bhb_loop tmp |
|---|
| 812 | +#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY |
|---|
| 813 | +alternative_cb spectre_bhb_patch_loop_iter |
|---|
| 814 | + mov \tmp, #32 // Patched to correct the immediate |
|---|
| 815 | +alternative_cb_end |
|---|
| 816 | +.Lspectre_bhb_loop\@: |
|---|
| 817 | + b . + 4 |
|---|
| 818 | + subs \tmp, \tmp, #1 |
|---|
| 819 | + b.ne .Lspectre_bhb_loop\@ |
|---|
| 820 | + sb |
|---|
| 821 | +#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ |
|---|
| 726 | 822 | .endm |
|---|
| 727 | 823 | |
|---|
| 728 | | - .macro do_cond_yield_neon |
|---|
| 729 | | - bl kernel_neon_end |
|---|
| 730 | | - bl kernel_neon_begin |
|---|
| 824 | + .macro mitigate_spectre_bhb_loop tmp |
|---|
| 825 | +#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY |
|---|
| 826 | +alternative_cb spectre_bhb_patch_loop_mitigation_enable |
|---|
| 827 | + b .L_spectre_bhb_loop_done\@ // Patched to NOP |
|---|
| 828 | +alternative_cb_end |
|---|
| 829 | + __mitigate_spectre_bhb_loop \tmp |
|---|
| 830 | +.L_spectre_bhb_loop_done\@: |
|---|
| 831 | +#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ |
|---|
| 731 | 832 | .endm |
|---|
| 732 | 833 | |
|---|
| 733 | | - .macro endif_yield_neon, lbl |
|---|
| 734 | | - .ifnb \lbl |
|---|
| 735 | | - b \lbl |
|---|
| 736 | | - .else |
|---|
| 737 | | - b .Lyield_out_\@ |
|---|
| 738 | | - .endif |
|---|
| 739 | | - .previous |
|---|
| 740 | | -.Lyield_out_\@ : |
|---|
| 834 | + /* Save/restores x0-x3 to the stack */ |
|---|
| 835 | + .macro __mitigate_spectre_bhb_fw |
|---|
| 836 | +#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY |
|---|
| 837 | + stp x0, x1, [sp, #-16]! |
|---|
| 838 | + stp x2, x3, [sp, #-16]! |
|---|
| 839 | + mov w0, #ARM_SMCCC_ARCH_WORKAROUND_3 |
|---|
| 840 | +alternative_cb smccc_patch_fw_mitigation_conduit |
|---|
| 841 | + nop // Patched to SMC/HVC #0 |
|---|
| 842 | +alternative_cb_end |
|---|
| 843 | + ldp x2, x3, [sp], #16 |
|---|
| 844 | + ldp x0, x1, [sp], #16 |
|---|
| 845 | +#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ |
|---|
| 741 | 846 | .endm |
|---|
| 742 | 847 | |
|---|
| 848 | + .macro mitigate_spectre_bhb_clear_insn |
|---|
| 849 | +#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY |
|---|
| 850 | +alternative_cb spectre_bhb_patch_clearbhb |
|---|
| 851 | + /* Patched to NOP when not supported */ |
|---|
| 852 | + clearbhb |
|---|
| 853 | + isb |
|---|
| 854 | +alternative_cb_end |
|---|
| 855 | +#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ |
|---|
| 856 | + .endm |
|---|
| 743 | 857 | #endif /* __ASM_ASSEMBLER_H */ |
|---|