.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Based on arch/arm/mm/proc.S |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2001 Deep Blue Solutions Ltd. |
---|
5 | 6 | * Copyright (C) 2012 ARM Ltd. |
---|
6 | 7 | * Author: Catalin Marinas <catalin.marinas@arm.com> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License version 2 as |
---|
10 | | - * published by the Free Software Foundation. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, |
---|
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | | - * GNU General Public License for more details. |
---|
16 | | - * |
---|
17 | | - * You should have received a copy of the GNU General Public License |
---|
18 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
19 | 8 | */ |
---|
20 | 9 | |
---|
21 | 10 | #include <linux/init.h> |
---|
22 | 11 | #include <linux/linkage.h> |
---|
| 12 | +#include <linux/pgtable.h> |
---|
23 | 13 | #include <asm/assembler.h> |
---|
24 | 14 | #include <asm/asm-offsets.h> |
---|
| 15 | +#include <asm/asm_pointer_auth.h> |
---|
25 | 16 | #include <asm/hwcap.h> |
---|
26 | | -#include <asm/pgtable.h> |
---|
27 | 17 | #include <asm/pgtable-hwdef.h> |
---|
28 | 18 | #include <asm/cpufeature.h> |
---|
29 | 19 | #include <asm/alternative.h> |
---|
| 20 | +#include <asm/smp.h> |
---|
| 21 | +#include <asm/sysreg.h> |
---|
30 | 22 | |
---|
31 | 23 | #ifdef CONFIG_ARM64_64K_PAGES |
---|
32 | 24 | #define TCR_TG_FLAGS TCR_TG0_64K | TCR_TG1_64K |
---|
.. | .. |
---|
48 | 40 | #define TCR_CACHE_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA |
---|
49 | 41 | |
---|
50 | 42 | #ifdef CONFIG_KASAN_SW_TAGS |
---|
51 | | -#define TCR_KASAN_FLAGS TCR_TBI1 |
---|
| 43 | +#define TCR_KASAN_SW_FLAGS TCR_TBI1 | TCR_TBID1 |
---|
52 | 44 | #else |
---|
53 | | -#define TCR_KASAN_FLAGS 0 |
---|
| 45 | +#define TCR_KASAN_SW_FLAGS 0 |
---|
54 | 46 | #endif |
---|
55 | 47 | |
---|
56 | | -#define MAIR(attr, mt) ((attr) << ((mt) * 8)) |
---|
| 48 | +#ifdef CONFIG_KASAN_HW_TAGS |
---|
| 49 | +#define TCR_MTE_FLAGS SYS_TCR_EL1_TCMA1 | TCR_TBI1 | TCR_TBID1 |
---|
| 50 | +#elif defined(CONFIG_ARM64_MTE) |
---|
| 51 | +/* |
---|
| 52 | + * The mte_zero_clear_page_tags() implementation uses DC GZVA, which relies on |
---|
| 53 | + * TBI being enabled at EL1. |
---|
| 54 | + */ |
---|
| 55 | +#define TCR_MTE_FLAGS TCR_TBI1 | TCR_TBID1 |
---|
| 56 | +#else |
---|
| 57 | +#define TCR_MTE_FLAGS 0 |
---|
| 58 | +#endif |
---|
57 | 59 | |
---|
58 | 60 | /* |
---|
59 | | - * cpu_cache_off() |
---|
60 | | - * |
---|
61 | | - * Turn the CPU D-cache off. |
---|
| 61 | + * Default MAIR_EL1. MT_NORMAL_TAGGED is initially mapped as Normal memory and |
---|
| 62 | + * changed during mte_cpu_setup to Normal Tagged if the system supports MTE. |
---|
62 | 63 | */ |
---|
63 | | -ENTRY(cpu_cache_off) |
---|
64 | | - mrs x0, sctlr_el1 |
---|
65 | | - bic x0, x0, #1 << 2 // clear SCTLR.C |
---|
66 | | - msr sctlr_el1, x0 |
---|
67 | | - isb |
---|
68 | | - ret |
---|
69 | | -ENDPROC(cpu_cache_off) |
---|
70 | | - |
---|
71 | | -/* |
---|
72 | | - * cpu_reset(loc) |
---|
73 | | - * |
---|
74 | | - * Perform a soft reset of the system. Put the CPU into the same state |
---|
75 | | - * as it would be if it had been reset, and branch to what would be the |
---|
76 | | - * reset vector. It must be executed with the flat identity mapping. |
---|
77 | | - * |
---|
78 | | - * - loc - location to jump to for soft reset |
---|
79 | | - */ |
---|
80 | | - .align 5 |
---|
81 | | -ENTRY(cpu_reset) |
---|
82 | | - mrs x1, sctlr_el1 |
---|
83 | | - bic x1, x1, #1 |
---|
84 | | - msr sctlr_el1, x1 // disable the MMU |
---|
85 | | - isb |
---|
86 | | - ret x0 |
---|
87 | | -ENDPROC(cpu_reset) |
---|
88 | | - |
---|
89 | | -/* |
---|
90 | | - * cpu_do_idle() |
---|
91 | | - * |
---|
92 | | - * Idle the processor (wait for interrupt). |
---|
93 | | - */ |
---|
94 | | -ENTRY(cpu_do_idle) |
---|
95 | | - dsb sy // WFI may enter a low-power mode |
---|
96 | | - wfi |
---|
97 | | - ret |
---|
98 | | -ENDPROC(cpu_do_idle) |
---|
| 64 | +#define MAIR_EL1_SET \ |
---|
| 65 | + (MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \ |
---|
| 66 | + MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \ |
---|
| 67 | + MAIR_ATTRIDX(MAIR_ATTR_DEVICE_GRE, MT_DEVICE_GRE) | \ |
---|
| 68 | + MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \ |
---|
| 69 | + MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \ |
---|
| 70 | + MAIR_ATTRIDX(MAIR_ATTR_NORMAL_WT, MT_NORMAL_WT) | \ |
---|
| 71 | + MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED) | \ |
---|
| 72 | + MAIR_ATTRIDX(MAIR_ATTR_NORMAL_iNC_oWB, MT_NORMAL_iNC_oWB)) |
---|
99 | 73 | |
---|
100 | 74 | #ifdef CONFIG_CPU_PM |
---|
101 | 75 | /** |
---|
.. | .. |
---|
105 | 79 | * |
---|
106 | 80 | * This must be kept in sync with struct cpu_suspend_ctx in <asm/suspend.h>. |
---|
107 | 81 | */ |
---|
108 | | -ENTRY(cpu_do_suspend) |
---|
| 82 | +SYM_FUNC_START(cpu_do_suspend) |
---|
109 | 83 | mrs x2, tpidr_el0 |
---|
110 | 84 | mrs x3, tpidrro_el0 |
---|
111 | 85 | mrs x4, contextidr_el1 |
---|
.. | .. |
---|
134 | 108 | */ |
---|
135 | 109 | str x18, [x0, #96] |
---|
136 | 110 | ret |
---|
137 | | -ENDPROC(cpu_do_suspend) |
---|
| 111 | +SYM_FUNC_END(cpu_do_suspend) |
---|
138 | 112 | |
---|
139 | 113 | /** |
---|
140 | 114 | * cpu_do_resume - restore CPU register context |
---|
.. | .. |
---|
142 | 116 | * x0: Address of context pointer |
---|
143 | 117 | */ |
---|
144 | 118 | .pushsection ".idmap.text", "awx" |
---|
145 | | -ENTRY(cpu_do_resume) |
---|
| 119 | +SYM_FUNC_START(cpu_do_resume) |
---|
146 | 120 | ldp x2, x3, [x0] |
---|
147 | 121 | ldp x4, x5, [x0, #16] |
---|
148 | 122 | ldp x6, x8, [x0, #32] |
---|
.. | .. |
---|
191 | 165 | ubfx x11, x11, #1, #1 |
---|
192 | 166 | msr oslar_el1, x11 |
---|
193 | 167 | reset_pmuserenr_el0 x0 // Disable PMU access from EL0 |
---|
| 168 | + reset_amuserenr_el0 x0 // Disable AMU access from EL0 |
---|
194 | 169 | |
---|
195 | 170 | alternative_if ARM64_HAS_RAS_EXTN |
---|
196 | 171 | msr_s SYS_DISR_EL1, xzr |
---|
197 | 172 | alternative_else_nop_endif |
---|
198 | 173 | |
---|
| 174 | + ptrauth_keys_install_kernel_nosync x14, x1, x2, x3 |
---|
199 | 175 | isb |
---|
200 | 176 | ret |
---|
201 | | -ENDPROC(cpu_do_resume) |
---|
| 177 | +SYM_FUNC_END(cpu_do_resume) |
---|
202 | 178 | .popsection |
---|
203 | 179 | #endif |
---|
204 | | - |
---|
205 | | -/* |
---|
206 | | - * cpu_do_switch_mm(pgd_phys, tsk) |
---|
207 | | - * |
---|
208 | | - * Set the translation table base pointer to be pgd_phys. |
---|
209 | | - * |
---|
210 | | - * - pgd_phys - physical address of new TTB |
---|
211 | | - */ |
---|
212 | | -ENTRY(cpu_do_switch_mm) |
---|
213 | | - mrs x2, ttbr1_el1 |
---|
214 | | - mmid x1, x1 // get mm->context.id |
---|
215 | | - phys_to_ttbr x3, x0 |
---|
216 | | -#ifdef CONFIG_ARM64_SW_TTBR0_PAN |
---|
217 | | - bfi x3, x1, #48, #16 // set the ASID field in TTBR0 |
---|
218 | | -#endif |
---|
219 | | - bfi x2, x1, #48, #16 // set the ASID |
---|
220 | | - msr ttbr1_el1, x2 // in TTBR1 (since TCR.A1 is set) |
---|
221 | | - isb |
---|
222 | | - msr ttbr0_el1, x3 // now update TTBR0 |
---|
223 | | - isb |
---|
224 | | - b post_ttbr_update_workaround // Back to C code... |
---|
225 | | -ENDPROC(cpu_do_switch_mm) |
---|
226 | 180 | |
---|
227 | 181 | .pushsection ".idmap.text", "awx" |
---|
228 | 182 | |
---|
229 | 183 | .macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2 |
---|
230 | | - adrp \tmp1, empty_zero_page |
---|
| 184 | + adrp \tmp1, reserved_pg_dir |
---|
231 | 185 | phys_to_ttbr \tmp2, \tmp1 |
---|
| 186 | + offset_ttbr1 \tmp2, \tmp1 |
---|
232 | 187 | msr ttbr1_el1, \tmp2 |
---|
233 | 188 | isb |
---|
234 | 189 | tlbi vmalle1 |
---|
.. | .. |
---|
237 | 192 | .endm |
---|
238 | 193 | |
---|
239 | 194 | /* |
---|
240 | | - * void idmap_cpu_replace_ttbr1(phys_addr_t new_pgd) |
---|
| 195 | + * void idmap_cpu_replace_ttbr1(phys_addr_t ttbr1) |
---|
241 | 196 | * |
---|
242 | 197 | * This is the low-level counterpart to cpu_replace_ttbr1, and should not be |
---|
243 | 198 | * called by anything else. It can only be executed from a TTBR0 mapping. |
---|
244 | 199 | */ |
---|
245 | | -ENTRY(idmap_cpu_replace_ttbr1) |
---|
| 200 | +SYM_FUNC_START(idmap_cpu_replace_ttbr1) |
---|
246 | 201 | save_and_disable_daif flags=x2 |
---|
247 | 202 | |
---|
248 | 203 | __idmap_cpu_set_reserved_ttbr1 x1, x3 |
---|
249 | 204 | |
---|
250 | | - phys_to_ttbr x3, x0 |
---|
251 | | - msr ttbr1_el1, x3 |
---|
| 205 | + offset_ttbr1 x0, x3 |
---|
| 206 | + msr ttbr1_el1, x0 |
---|
252 | 207 | isb |
---|
253 | 208 | |
---|
254 | 209 | restore_daif x2 |
---|
255 | 210 | |
---|
256 | 211 | ret |
---|
257 | | -ENDPROC(idmap_cpu_replace_ttbr1) |
---|
| 212 | +SYM_FUNC_END(idmap_cpu_replace_ttbr1) |
---|
258 | 213 | .popsection |
---|
259 | 214 | |
---|
260 | 215 | #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
---|
.. | .. |
---|
282 | 237 | */ |
---|
283 | 238 | __idmap_kpti_flag: |
---|
284 | 239 | .long 1 |
---|
285 | | -ENTRY(idmap_kpti_install_ng_mappings) |
---|
| 240 | +SYM_FUNC_START(idmap_kpti_install_ng_mappings) |
---|
286 | 241 | cpu .req w0 |
---|
287 | 242 | num_cpus .req w1 |
---|
288 | 243 | swapper_pa .req x2 |
---|
.. | .. |
---|
302 | 257 | pte .req x16 |
---|
303 | 258 | |
---|
304 | 259 | mrs swapper_ttb, ttbr1_el1 |
---|
| 260 | + restore_ttbr1 swapper_ttb |
---|
305 | 261 | adr flag_ptr, __idmap_kpti_flag |
---|
306 | 262 | |
---|
307 | 263 | cbnz cpu, __idmap_kpti_secondary |
---|
.. | .. |
---|
342 | 298 | /* We're done: fire up the MMU again */ |
---|
343 | 299 | mrs x17, sctlr_el1 |
---|
344 | 300 | orr x17, x17, #SCTLR_ELx_M |
---|
345 | | - msr sctlr_el1, x17 |
---|
346 | | - isb |
---|
347 | | - |
---|
348 | | - /* |
---|
349 | | - * Invalidate the local I-cache so that any instructions fetched |
---|
350 | | - * speculatively from the PoC are discarded, since they may have |
---|
351 | | - * been dynamically patched at the PoU. |
---|
352 | | - */ |
---|
353 | | - ic iallu |
---|
354 | | - dsb nsh |
---|
355 | | - isb |
---|
| 301 | + set_sctlr_el1 x17 |
---|
356 | 302 | |
---|
357 | 303 | /* Set the flag to zero to indicate that we're all done */ |
---|
358 | 304 | str wzr, [flag_ptr] |
---|
.. | .. |
---|
446 | 392 | cbnz w16, 1b |
---|
447 | 393 | |
---|
448 | 394 | /* All done, act like nothing happened */ |
---|
| 395 | + offset_ttbr1 swapper_ttb, x16 |
---|
449 | 396 | msr ttbr1_el1, swapper_ttb |
---|
450 | 397 | isb |
---|
451 | 398 | ret |
---|
452 | 399 | |
---|
453 | 400 | .unreq swapper_ttb |
---|
454 | 401 | .unreq flag_ptr |
---|
455 | | -ENDPROC(idmap_kpti_install_ng_mappings) |
---|
| 402 | +SYM_FUNC_END(idmap_kpti_install_ng_mappings) |
---|
456 | 403 | .popsection |
---|
457 | 404 | #endif |
---|
458 | 405 | |
---|
459 | 406 | /* |
---|
460 | 407 | * __cpu_setup |
---|
461 | 408 | * |
---|
462 | | - * Initialise the processor for turning the MMU on. Return in x0 the |
---|
463 | | - * value of the SCTLR_EL1 register. |
---|
| 409 | + * Initialise the processor for turning the MMU on. |
---|
| 410 | + * |
---|
| 411 | + * Output: |
---|
| 412 | + * Return in x0 the value of the SCTLR_EL1 register. |
---|
464 | 413 | */ |
---|
465 | 414 | .pushsection ".idmap.text", "awx" |
---|
466 | | -ENTRY(__cpu_setup) |
---|
| 415 | +SYM_FUNC_START(__cpu_setup) |
---|
467 | 416 | tlbi vmalle1 // Invalidate local TLB |
---|
468 | 417 | dsb nsh |
---|
469 | 418 | |
---|
470 | | - mov x0, #3 << 20 |
---|
471 | | - msr cpacr_el1, x0 // Enable FP/ASIMD |
---|
472 | | - mov x0, #1 << 12 // Reset mdscr_el1 and disable |
---|
473 | | - msr mdscr_el1, x0 // access to the DCC from EL0 |
---|
| 419 | + mov x1, #3 << 20 |
---|
| 420 | + msr cpacr_el1, x1 // Enable FP/ASIMD |
---|
| 421 | + mov x1, #1 << 12 // Reset mdscr_el1 and disable |
---|
| 422 | + msr mdscr_el1, x1 // access to the DCC from EL0 |
---|
474 | 423 | isb // Unmask debug exceptions now, |
---|
475 | 424 | enable_dbg // since this is per-cpu |
---|
476 | | - reset_pmuserenr_el0 x0 // Disable PMU access from EL0 |
---|
| 425 | + reset_pmuserenr_el0 x1 // Disable PMU access from EL0 |
---|
| 426 | + reset_amuserenr_el0 x1 // Disable AMU access from EL0 |
---|
| 427 | + |
---|
477 | 428 | /* |
---|
478 | | - * Memory region attributes for LPAE: |
---|
479 | | - * |
---|
480 | | - * n = AttrIndx[2:0] |
---|
481 | | - * n MAIR |
---|
482 | | - * DEVICE_nGnRnE 000 00000000 |
---|
483 | | - * DEVICE_nGnRE 001 00000100 |
---|
484 | | - * DEVICE_GRE 010 00001100 |
---|
485 | | - * NORMAL_NC 011 01000100 |
---|
486 | | - * NORMAL 100 11111111 |
---|
487 | | - * NORMAL_WT 101 10111011 |
---|
| 429 | + * Memory region attributes |
---|
488 | 430 | */ |
---|
489 | | - ldr x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \ |
---|
490 | | - MAIR(0x04, MT_DEVICE_nGnRE) | \ |
---|
491 | | - MAIR(0x0c, MT_DEVICE_GRE) | \ |
---|
492 | | - MAIR(0x44, MT_NORMAL_NC) | \ |
---|
493 | | - MAIR(0xff, MT_NORMAL) | \ |
---|
494 | | - MAIR(0xbb, MT_NORMAL_WT) |
---|
| 431 | + mov_q x5, MAIR_EL1_SET |
---|
495 | 432 | msr mair_el1, x5 |
---|
496 | 433 | /* |
---|
497 | | - * Prepare SCTLR |
---|
| 434 | + * Set/prepare TCR and TTBR. TCR_EL1.T1SZ gets further |
---|
| 435 | + * adjusted if the kernel is compiled with 52bit VA support. |
---|
498 | 436 | */ |
---|
499 | | - mov_q x0, SCTLR_EL1_SET |
---|
500 | | - /* |
---|
501 | | - * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for |
---|
502 | | - * both user and kernel. |
---|
503 | | - */ |
---|
504 | | - ldr x10, =TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \ |
---|
| 437 | + mov_q x10, TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \ |
---|
505 | 438 | TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \ |
---|
506 | | - TCR_TBI0 | TCR_A1 | TCR_KASAN_FLAGS |
---|
507 | | - tcr_set_idmap_t0sz x10, x9 |
---|
| 439 | + TCR_TBI0 | TCR_A1 | TCR_KASAN_SW_FLAGS | TCR_MTE_FLAGS |
---|
| 440 | + |
---|
| 441 | + tcr_clear_errata_bits x10, x9, x5 |
---|
| 442 | + |
---|
| 443 | +#ifdef CONFIG_ARM64_VA_BITS_52 |
---|
| 444 | + ldr_l x9, vabits_actual |
---|
| 445 | + sub x9, xzr, x9 |
---|
| 446 | + add x9, x9, #64 |
---|
| 447 | + tcr_set_t1sz x10, x9 |
---|
| 448 | +#else |
---|
| 449 | + ldr_l x9, idmap_t0sz |
---|
| 450 | +#endif |
---|
| 451 | + tcr_set_t0sz x10, x9 |
---|
508 | 452 | |
---|
509 | 453 | /* |
---|
510 | 454 | * Set the IPS bits in TCR_EL1. |
---|
.. | .. |
---|
523 | 467 | 1: |
---|
524 | 468 | #endif /* CONFIG_ARM64_HW_AFDBM */ |
---|
525 | 469 | msr tcr_el1, x10 |
---|
| 470 | + /* |
---|
| 471 | + * Prepare SCTLR |
---|
| 472 | + */ |
---|
| 473 | + mov_q x0, INIT_SCTLR_EL1_MMU_ON |
---|
526 | 474 | ret // return to head.S |
---|
527 | | -ENDPROC(__cpu_setup) |
---|
| 475 | +SYM_FUNC_END(__cpu_setup) |
---|