18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Based on arch/arm/mm/proc.S 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2001 Deep Blue Solutions Ltd. 68c2ecf20Sopenharmony_ci * Copyright (C) 2012 ARM Ltd. 78c2ecf20Sopenharmony_ci * Author: Catalin Marinas <catalin.marinas@arm.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/linkage.h> 128c2ecf20Sopenharmony_ci#include <linux/pgtable.h> 138c2ecf20Sopenharmony_ci#include <asm/assembler.h> 148c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h> 158c2ecf20Sopenharmony_ci#include <asm/asm_pointer_auth.h> 168c2ecf20Sopenharmony_ci#include <asm/hwcap.h> 178c2ecf20Sopenharmony_ci#include <asm/pgtable-hwdef.h> 188c2ecf20Sopenharmony_ci#include <asm/cpufeature.h> 198c2ecf20Sopenharmony_ci#include <asm/alternative.h> 208c2ecf20Sopenharmony_ci#include <asm/smp.h> 218c2ecf20Sopenharmony_ci#include <asm/sysreg.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM64_64K_PAGES 248c2ecf20Sopenharmony_ci#define TCR_TG_FLAGS TCR_TG0_64K | TCR_TG1_64K 258c2ecf20Sopenharmony_ci#elif defined(CONFIG_ARM64_16K_PAGES) 268c2ecf20Sopenharmony_ci#define TCR_TG_FLAGS TCR_TG0_16K | TCR_TG1_16K 278c2ecf20Sopenharmony_ci#else /* CONFIG_ARM64_4K_PAGES */ 288c2ecf20Sopenharmony_ci#define TCR_TG_FLAGS TCR_TG0_4K | TCR_TG1_4K 298c2ecf20Sopenharmony_ci#endif 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#ifdef CONFIG_RANDOMIZE_BASE 328c2ecf20Sopenharmony_ci#define TCR_KASLR_FLAGS TCR_NFD1 338c2ecf20Sopenharmony_ci#else 348c2ecf20Sopenharmony_ci#define TCR_KASLR_FLAGS 0 358c2ecf20Sopenharmony_ci#endif 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#define TCR_SMP_FLAGS TCR_SHARED 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* PTWs cacheable, inner/outer WBWA */ 408c2ecf20Sopenharmony_ci#define TCR_CACHE_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#ifdef CONFIG_KASAN_SW_TAGS 438c2ecf20Sopenharmony_ci#define TCR_KASAN_FLAGS TCR_TBI1 448c2ecf20Sopenharmony_ci#else 458c2ecf20Sopenharmony_ci#define TCR_KASAN_FLAGS 0 468c2ecf20Sopenharmony_ci#endif 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* 498c2ecf20Sopenharmony_ci * Default MAIR_EL1. MT_NORMAL_TAGGED is initially mapped as Normal memory and 508c2ecf20Sopenharmony_ci * changed during __cpu_setup to Normal Tagged if the system supports MTE. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci#define MAIR_EL1_SET \ 538c2ecf20Sopenharmony_ci (MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \ 548c2ecf20Sopenharmony_ci MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \ 558c2ecf20Sopenharmony_ci MAIR_ATTRIDX(MAIR_ATTR_DEVICE_GRE, MT_DEVICE_GRE) | \ 568c2ecf20Sopenharmony_ci MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \ 578c2ecf20Sopenharmony_ci MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \ 588c2ecf20Sopenharmony_ci MAIR_ATTRIDX(MAIR_ATTR_NORMAL_WT, MT_NORMAL_WT) | \ 598c2ecf20Sopenharmony_ci MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED)) 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_PM 628c2ecf20Sopenharmony_ci/** 638c2ecf20Sopenharmony_ci * cpu_do_suspend - save CPU registers context 648c2ecf20Sopenharmony_ci * 658c2ecf20Sopenharmony_ci * x0: virtual address of context pointer 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * This must be kept in sync with struct cpu_suspend_ctx in <asm/suspend.h>. 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_ciSYM_FUNC_START(cpu_do_suspend) 708c2ecf20Sopenharmony_ci mrs x2, tpidr_el0 718c2ecf20Sopenharmony_ci mrs x3, tpidrro_el0 728c2ecf20Sopenharmony_ci mrs x4, contextidr_el1 738c2ecf20Sopenharmony_ci mrs x5, osdlr_el1 748c2ecf20Sopenharmony_ci mrs x6, cpacr_el1 758c2ecf20Sopenharmony_ci mrs x7, tcr_el1 768c2ecf20Sopenharmony_ci mrs x8, vbar_el1 778c2ecf20Sopenharmony_ci mrs x9, mdscr_el1 788c2ecf20Sopenharmony_ci mrs x10, oslsr_el1 798c2ecf20Sopenharmony_ci mrs x11, sctlr_el1 808c2ecf20Sopenharmony_cialternative_if_not ARM64_HAS_VIRT_HOST_EXTN 818c2ecf20Sopenharmony_ci mrs x12, tpidr_el1 828c2ecf20Sopenharmony_cialternative_else 838c2ecf20Sopenharmony_ci mrs x12, tpidr_el2 848c2ecf20Sopenharmony_cialternative_endif 858c2ecf20Sopenharmony_ci mrs x13, sp_el0 868c2ecf20Sopenharmony_ci stp x2, x3, [x0] 878c2ecf20Sopenharmony_ci stp x4, x5, [x0, #16] 888c2ecf20Sopenharmony_ci stp x6, x7, [x0, #32] 898c2ecf20Sopenharmony_ci stp x8, x9, [x0, #48] 908c2ecf20Sopenharmony_ci stp x10, x11, [x0, #64] 918c2ecf20Sopenharmony_ci stp x12, x13, [x0, #80] 928c2ecf20Sopenharmony_ci /* 938c2ecf20Sopenharmony_ci * Save x18 as it may be used as a platform register, e.g. by shadow 948c2ecf20Sopenharmony_ci * call stack. 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_ci str x18, [x0, #96] 978c2ecf20Sopenharmony_ci ret 988c2ecf20Sopenharmony_ciSYM_FUNC_END(cpu_do_suspend) 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/** 1018c2ecf20Sopenharmony_ci * cpu_do_resume - restore CPU register context 1028c2ecf20Sopenharmony_ci * 1038c2ecf20Sopenharmony_ci * x0: Address of context pointer 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_ci .pushsection ".idmap.text", "awx" 1068c2ecf20Sopenharmony_ciSYM_FUNC_START(cpu_do_resume) 1078c2ecf20Sopenharmony_ci ldp x2, x3, [x0] 1088c2ecf20Sopenharmony_ci ldp x4, x5, [x0, #16] 1098c2ecf20Sopenharmony_ci ldp x6, x8, [x0, #32] 1108c2ecf20Sopenharmony_ci ldp x9, x10, [x0, #48] 1118c2ecf20Sopenharmony_ci ldp x11, x12, [x0, #64] 1128c2ecf20Sopenharmony_ci ldp x13, x14, [x0, #80] 1138c2ecf20Sopenharmony_ci /* 1148c2ecf20Sopenharmony_ci * Restore x18, as it may be used as a platform register, and clear 1158c2ecf20Sopenharmony_ci * the buffer to minimize the risk of exposure when used for shadow 1168c2ecf20Sopenharmony_ci * call stack. 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_ci ldr x18, [x0, #96] 1198c2ecf20Sopenharmony_ci str xzr, [x0, #96] 1208c2ecf20Sopenharmony_ci msr tpidr_el0, x2 1218c2ecf20Sopenharmony_ci msr tpidrro_el0, x3 1228c2ecf20Sopenharmony_ci msr contextidr_el1, x4 1238c2ecf20Sopenharmony_ci msr cpacr_el1, x6 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* Don't change t0sz here, mask those bits when restoring */ 1268c2ecf20Sopenharmony_ci mrs x7, tcr_el1 1278c2ecf20Sopenharmony_ci bfi x8, x7, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci msr tcr_el1, x8 1308c2ecf20Sopenharmony_ci msr vbar_el1, x9 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* 1338c2ecf20Sopenharmony_ci * __cpu_setup() cleared MDSCR_EL1.MDE and friends, before unmasking 1348c2ecf20Sopenharmony_ci * debug exceptions. By restoring MDSCR_EL1 here, we may take a debug 1358c2ecf20Sopenharmony_ci * exception. Mask them until local_daif_restore() in cpu_suspend() 1368c2ecf20Sopenharmony_ci * resets them. 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_ci disable_daif 1398c2ecf20Sopenharmony_ci msr mdscr_el1, x10 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci msr sctlr_el1, x12 1428c2ecf20Sopenharmony_cialternative_if_not ARM64_HAS_VIRT_HOST_EXTN 1438c2ecf20Sopenharmony_ci msr tpidr_el1, x13 1448c2ecf20Sopenharmony_cialternative_else 1458c2ecf20Sopenharmony_ci msr tpidr_el2, x13 1468c2ecf20Sopenharmony_cialternative_endif 1478c2ecf20Sopenharmony_ci msr sp_el0, x14 1488c2ecf20Sopenharmony_ci /* 1498c2ecf20Sopenharmony_ci * Restore oslsr_el1 by writing oslar_el1 1508c2ecf20Sopenharmony_ci */ 1518c2ecf20Sopenharmony_ci msr osdlr_el1, x5 1528c2ecf20Sopenharmony_ci ubfx x11, x11, #1, #1 1538c2ecf20Sopenharmony_ci msr oslar_el1, x11 1548c2ecf20Sopenharmony_ci reset_pmuserenr_el0 x0 // Disable PMU access from EL0 1558c2ecf20Sopenharmony_ci reset_amuserenr_el0 x0 // Disable AMU access from EL0 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cialternative_if ARM64_HAS_RAS_EXTN 1588c2ecf20Sopenharmony_ci msr_s SYS_DISR_EL1, xzr 1598c2ecf20Sopenharmony_cialternative_else_nop_endif 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci ptrauth_keys_install_kernel_nosync x14, x1, x2, x3 1628c2ecf20Sopenharmony_ci isb 1638c2ecf20Sopenharmony_ci ret 1648c2ecf20Sopenharmony_ciSYM_FUNC_END(cpu_do_resume) 1658c2ecf20Sopenharmony_ci .popsection 1668c2ecf20Sopenharmony_ci#endif 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci .pushsection ".idmap.text", "awx" 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci.macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2 1718c2ecf20Sopenharmony_ci adrp \tmp1, reserved_pg_dir 1728c2ecf20Sopenharmony_ci phys_to_ttbr \tmp2, \tmp1 1738c2ecf20Sopenharmony_ci offset_ttbr1 \tmp2, \tmp1 1748c2ecf20Sopenharmony_ci msr ttbr1_el1, \tmp2 1758c2ecf20Sopenharmony_ci isb 1768c2ecf20Sopenharmony_ci tlbi vmalle1 1778c2ecf20Sopenharmony_ci dsb nsh 1788c2ecf20Sopenharmony_ci isb 1798c2ecf20Sopenharmony_ci.endm 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci/* 1828c2ecf20Sopenharmony_ci * void idmap_cpu_replace_ttbr1(phys_addr_t ttbr1) 1838c2ecf20Sopenharmony_ci * 1848c2ecf20Sopenharmony_ci * This is the low-level counterpart to cpu_replace_ttbr1, and should not be 1858c2ecf20Sopenharmony_ci * called by anything else. It can only be executed from a TTBR0 mapping. 1868c2ecf20Sopenharmony_ci */ 1878c2ecf20Sopenharmony_ciSYM_FUNC_START(idmap_cpu_replace_ttbr1) 1888c2ecf20Sopenharmony_ci save_and_disable_daif flags=x2 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci __idmap_cpu_set_reserved_ttbr1 x1, x3 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci offset_ttbr1 x0, x3 1938c2ecf20Sopenharmony_ci msr ttbr1_el1, x0 1948c2ecf20Sopenharmony_ci isb 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci restore_daif x2 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci ret 1998c2ecf20Sopenharmony_ciSYM_FUNC_END(idmap_cpu_replace_ttbr1) 2008c2ecf20Sopenharmony_ci .popsection 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 2038c2ecf20Sopenharmony_ci .pushsection ".idmap.text", "awx" 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci .macro __idmap_kpti_get_pgtable_ent, type 2068c2ecf20Sopenharmony_ci dc cvac, cur_\()\type\()p // Ensure any existing dirty 2078c2ecf20Sopenharmony_ci dmb sy // lines are written back before 2088c2ecf20Sopenharmony_ci ldr \type, [cur_\()\type\()p] // loading the entry 2098c2ecf20Sopenharmony_ci tbz \type, #0, skip_\()\type // Skip invalid and 2108c2ecf20Sopenharmony_ci tbnz \type, #11, skip_\()\type // non-global entries 2118c2ecf20Sopenharmony_ci .endm 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci .macro __idmap_kpti_put_pgtable_ent_ng, type 2148c2ecf20Sopenharmony_ci orr \type, \type, #PTE_NG // Same bit for blocks and pages 2158c2ecf20Sopenharmony_ci str \type, [cur_\()\type\()p] // Update the entry and ensure 2168c2ecf20Sopenharmony_ci dmb sy // that it is visible to all 2178c2ecf20Sopenharmony_ci dc civac, cur_\()\type\()p // CPUs. 2188c2ecf20Sopenharmony_ci .endm 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci/* 2218c2ecf20Sopenharmony_ci * void __kpti_install_ng_mappings(int cpu, int num_cpus, phys_addr_t swapper) 2228c2ecf20Sopenharmony_ci * 2238c2ecf20Sopenharmony_ci * Called exactly once from stop_machine context by each CPU found during boot. 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_ci__idmap_kpti_flag: 2268c2ecf20Sopenharmony_ci .long 1 2278c2ecf20Sopenharmony_ciSYM_FUNC_START(idmap_kpti_install_ng_mappings) 2288c2ecf20Sopenharmony_ci cpu .req w0 2298c2ecf20Sopenharmony_ci num_cpus .req w1 2308c2ecf20Sopenharmony_ci swapper_pa .req x2 2318c2ecf20Sopenharmony_ci swapper_ttb .req x3 2328c2ecf20Sopenharmony_ci flag_ptr .req x4 2338c2ecf20Sopenharmony_ci cur_pgdp .req x5 2348c2ecf20Sopenharmony_ci end_pgdp .req x6 2358c2ecf20Sopenharmony_ci pgd .req x7 2368c2ecf20Sopenharmony_ci cur_pudp .req x8 2378c2ecf20Sopenharmony_ci end_pudp .req x9 2388c2ecf20Sopenharmony_ci pud .req x10 2398c2ecf20Sopenharmony_ci cur_pmdp .req x11 2408c2ecf20Sopenharmony_ci end_pmdp .req x12 2418c2ecf20Sopenharmony_ci pmd .req x13 2428c2ecf20Sopenharmony_ci cur_ptep .req x14 2438c2ecf20Sopenharmony_ci end_ptep .req x15 2448c2ecf20Sopenharmony_ci pte .req x16 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci mrs swapper_ttb, ttbr1_el1 2478c2ecf20Sopenharmony_ci restore_ttbr1 swapper_ttb 2488c2ecf20Sopenharmony_ci adr flag_ptr, __idmap_kpti_flag 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci cbnz cpu, __idmap_kpti_secondary 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /* We're the boot CPU. Wait for the others to catch up */ 2538c2ecf20Sopenharmony_ci sevl 2548c2ecf20Sopenharmony_ci1: wfe 2558c2ecf20Sopenharmony_ci ldaxr w17, [flag_ptr] 2568c2ecf20Sopenharmony_ci eor w17, w17, num_cpus 2578c2ecf20Sopenharmony_ci cbnz w17, 1b 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* We need to walk swapper, so turn off the MMU. */ 2608c2ecf20Sopenharmony_ci pre_disable_mmu_workaround 2618c2ecf20Sopenharmony_ci mrs x17, sctlr_el1 2628c2ecf20Sopenharmony_ci bic x17, x17, #SCTLR_ELx_M 2638c2ecf20Sopenharmony_ci msr sctlr_el1, x17 2648c2ecf20Sopenharmony_ci isb 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* Everybody is enjoying the idmap, so we can rewrite swapper. */ 2678c2ecf20Sopenharmony_ci /* PGD */ 2688c2ecf20Sopenharmony_ci mov cur_pgdp, swapper_pa 2698c2ecf20Sopenharmony_ci add end_pgdp, cur_pgdp, #(PTRS_PER_PGD * 8) 2708c2ecf20Sopenharmony_cido_pgd: __idmap_kpti_get_pgtable_ent pgd 2718c2ecf20Sopenharmony_ci tbnz pgd, #1, walk_puds 2728c2ecf20Sopenharmony_cinext_pgd: 2738c2ecf20Sopenharmony_ci __idmap_kpti_put_pgtable_ent_ng pgd 2748c2ecf20Sopenharmony_ciskip_pgd: 2758c2ecf20Sopenharmony_ci add cur_pgdp, cur_pgdp, #8 2768c2ecf20Sopenharmony_ci cmp cur_pgdp, end_pgdp 2778c2ecf20Sopenharmony_ci b.ne do_pgd 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* Publish the updated tables and nuke all the TLBs */ 2808c2ecf20Sopenharmony_ci dsb sy 2818c2ecf20Sopenharmony_ci tlbi vmalle1is 2828c2ecf20Sopenharmony_ci dsb ish 2838c2ecf20Sopenharmony_ci isb 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci /* We're done: fire up the MMU again */ 2868c2ecf20Sopenharmony_ci mrs x17, sctlr_el1 2878c2ecf20Sopenharmony_ci orr x17, x17, #SCTLR_ELx_M 2888c2ecf20Sopenharmony_ci msr sctlr_el1, x17 2898c2ecf20Sopenharmony_ci isb 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* 2928c2ecf20Sopenharmony_ci * Invalidate the local I-cache so that any instructions fetched 2938c2ecf20Sopenharmony_ci * speculatively from the PoC are discarded, since they may have 2948c2ecf20Sopenharmony_ci * been dynamically patched at the PoU. 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ci ic iallu 2978c2ecf20Sopenharmony_ci dsb nsh 2988c2ecf20Sopenharmony_ci isb 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* Set the flag to zero to indicate that we're all done */ 3018c2ecf20Sopenharmony_ci str wzr, [flag_ptr] 3028c2ecf20Sopenharmony_ci ret 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci /* PUD */ 3058c2ecf20Sopenharmony_ciwalk_puds: 3068c2ecf20Sopenharmony_ci .if CONFIG_PGTABLE_LEVELS > 3 3078c2ecf20Sopenharmony_ci pte_to_phys cur_pudp, pgd 3088c2ecf20Sopenharmony_ci add end_pudp, cur_pudp, #(PTRS_PER_PUD * 8) 3098c2ecf20Sopenharmony_cido_pud: __idmap_kpti_get_pgtable_ent pud 3108c2ecf20Sopenharmony_ci tbnz pud, #1, walk_pmds 3118c2ecf20Sopenharmony_cinext_pud: 3128c2ecf20Sopenharmony_ci __idmap_kpti_put_pgtable_ent_ng pud 3138c2ecf20Sopenharmony_ciskip_pud: 3148c2ecf20Sopenharmony_ci add cur_pudp, cur_pudp, 8 3158c2ecf20Sopenharmony_ci cmp cur_pudp, end_pudp 3168c2ecf20Sopenharmony_ci b.ne do_pud 3178c2ecf20Sopenharmony_ci b next_pgd 3188c2ecf20Sopenharmony_ci .else /* CONFIG_PGTABLE_LEVELS <= 3 */ 3198c2ecf20Sopenharmony_ci mov pud, pgd 3208c2ecf20Sopenharmony_ci b walk_pmds 3218c2ecf20Sopenharmony_cinext_pud: 3228c2ecf20Sopenharmony_ci b next_pgd 3238c2ecf20Sopenharmony_ci .endif 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* PMD */ 3268c2ecf20Sopenharmony_ciwalk_pmds: 3278c2ecf20Sopenharmony_ci .if CONFIG_PGTABLE_LEVELS > 2 3288c2ecf20Sopenharmony_ci pte_to_phys cur_pmdp, pud 3298c2ecf20Sopenharmony_ci add end_pmdp, cur_pmdp, #(PTRS_PER_PMD * 8) 3308c2ecf20Sopenharmony_cido_pmd: __idmap_kpti_get_pgtable_ent pmd 3318c2ecf20Sopenharmony_ci tbnz pmd, #1, walk_ptes 3328c2ecf20Sopenharmony_cinext_pmd: 3338c2ecf20Sopenharmony_ci __idmap_kpti_put_pgtable_ent_ng pmd 3348c2ecf20Sopenharmony_ciskip_pmd: 3358c2ecf20Sopenharmony_ci add cur_pmdp, cur_pmdp, #8 3368c2ecf20Sopenharmony_ci cmp cur_pmdp, end_pmdp 3378c2ecf20Sopenharmony_ci b.ne do_pmd 3388c2ecf20Sopenharmony_ci b next_pud 3398c2ecf20Sopenharmony_ci .else /* CONFIG_PGTABLE_LEVELS <= 2 */ 3408c2ecf20Sopenharmony_ci mov pmd, pud 3418c2ecf20Sopenharmony_ci b walk_ptes 3428c2ecf20Sopenharmony_cinext_pmd: 3438c2ecf20Sopenharmony_ci b next_pud 3448c2ecf20Sopenharmony_ci .endif 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* PTE */ 3478c2ecf20Sopenharmony_ciwalk_ptes: 3488c2ecf20Sopenharmony_ci pte_to_phys cur_ptep, pmd 3498c2ecf20Sopenharmony_ci add end_ptep, cur_ptep, #(PTRS_PER_PTE * 8) 3508c2ecf20Sopenharmony_cido_pte: __idmap_kpti_get_pgtable_ent pte 3518c2ecf20Sopenharmony_ci __idmap_kpti_put_pgtable_ent_ng pte 3528c2ecf20Sopenharmony_ciskip_pte: 3538c2ecf20Sopenharmony_ci add cur_ptep, cur_ptep, #8 3548c2ecf20Sopenharmony_ci cmp cur_ptep, end_ptep 3558c2ecf20Sopenharmony_ci b.ne do_pte 3568c2ecf20Sopenharmony_ci b next_pmd 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci .unreq cpu 3598c2ecf20Sopenharmony_ci .unreq num_cpus 3608c2ecf20Sopenharmony_ci .unreq swapper_pa 3618c2ecf20Sopenharmony_ci .unreq cur_pgdp 3628c2ecf20Sopenharmony_ci .unreq end_pgdp 3638c2ecf20Sopenharmony_ci .unreq pgd 3648c2ecf20Sopenharmony_ci .unreq cur_pudp 3658c2ecf20Sopenharmony_ci .unreq end_pudp 3668c2ecf20Sopenharmony_ci .unreq pud 3678c2ecf20Sopenharmony_ci .unreq cur_pmdp 3688c2ecf20Sopenharmony_ci .unreq end_pmdp 3698c2ecf20Sopenharmony_ci .unreq pmd 3708c2ecf20Sopenharmony_ci .unreq cur_ptep 3718c2ecf20Sopenharmony_ci .unreq end_ptep 3728c2ecf20Sopenharmony_ci .unreq pte 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci /* Secondary CPUs end up here */ 3758c2ecf20Sopenharmony_ci__idmap_kpti_secondary: 3768c2ecf20Sopenharmony_ci /* Uninstall swapper before surgery begins */ 3778c2ecf20Sopenharmony_ci __idmap_cpu_set_reserved_ttbr1 x16, x17 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci /* Increment the flag to let the boot CPU we're ready */ 3808c2ecf20Sopenharmony_ci1: ldxr w16, [flag_ptr] 3818c2ecf20Sopenharmony_ci add w16, w16, #1 3828c2ecf20Sopenharmony_ci stxr w17, w16, [flag_ptr] 3838c2ecf20Sopenharmony_ci cbnz w17, 1b 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci /* Wait for the boot CPU to finish messing around with swapper */ 3868c2ecf20Sopenharmony_ci sevl 3878c2ecf20Sopenharmony_ci1: wfe 3888c2ecf20Sopenharmony_ci ldxr w16, [flag_ptr] 3898c2ecf20Sopenharmony_ci cbnz w16, 1b 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* All done, act like nothing happened */ 3928c2ecf20Sopenharmony_ci offset_ttbr1 swapper_ttb, x16 3938c2ecf20Sopenharmony_ci msr ttbr1_el1, swapper_ttb 3948c2ecf20Sopenharmony_ci isb 3958c2ecf20Sopenharmony_ci ret 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci .unreq swapper_ttb 3988c2ecf20Sopenharmony_ci .unreq flag_ptr 3998c2ecf20Sopenharmony_ciSYM_FUNC_END(idmap_kpti_install_ng_mappings) 4008c2ecf20Sopenharmony_ci .popsection 4018c2ecf20Sopenharmony_ci#endif 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci/* 4048c2ecf20Sopenharmony_ci * __cpu_setup 4058c2ecf20Sopenharmony_ci * 4068c2ecf20Sopenharmony_ci * Initialise the processor for turning the MMU on. 4078c2ecf20Sopenharmony_ci * 4088c2ecf20Sopenharmony_ci * Output: 4098c2ecf20Sopenharmony_ci * Return in x0 the value of the SCTLR_EL1 register. 4108c2ecf20Sopenharmony_ci */ 4118c2ecf20Sopenharmony_ci .pushsection ".idmap.text", "awx" 4128c2ecf20Sopenharmony_ciSYM_FUNC_START(__cpu_setup) 4138c2ecf20Sopenharmony_ci tlbi vmalle1 // Invalidate local TLB 4148c2ecf20Sopenharmony_ci dsb nsh 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci mov x1, #3 << 20 4178c2ecf20Sopenharmony_ci msr cpacr_el1, x1 // Enable FP/ASIMD 4188c2ecf20Sopenharmony_ci mov x1, #1 << 12 // Reset mdscr_el1 and disable 4198c2ecf20Sopenharmony_ci msr mdscr_el1, x1 // access to the DCC from EL0 4208c2ecf20Sopenharmony_ci isb // Unmask debug exceptions now, 4218c2ecf20Sopenharmony_ci enable_dbg // since this is per-cpu 4228c2ecf20Sopenharmony_ci reset_pmuserenr_el0 x1 // Disable PMU access from EL0 4238c2ecf20Sopenharmony_ci reset_amuserenr_el0 x1 // Disable AMU access from EL0 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci /* 4268c2ecf20Sopenharmony_ci * Memory region attributes 4278c2ecf20Sopenharmony_ci */ 4288c2ecf20Sopenharmony_ci mov_q x5, MAIR_EL1_SET 4298c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM64_MTE 4308c2ecf20Sopenharmony_ci /* 4318c2ecf20Sopenharmony_ci * Update MAIR_EL1, GCR_EL1 and TFSR*_EL1 if MTE is supported 4328c2ecf20Sopenharmony_ci * (ID_AA64PFR1_EL1[11:8] > 1). 4338c2ecf20Sopenharmony_ci */ 4348c2ecf20Sopenharmony_ci mrs x10, ID_AA64PFR1_EL1 4358c2ecf20Sopenharmony_ci ubfx x10, x10, #ID_AA64PFR1_MTE_SHIFT, #4 4368c2ecf20Sopenharmony_ci cmp x10, #ID_AA64PFR1_MTE 4378c2ecf20Sopenharmony_ci b.lt 1f 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* Normal Tagged memory type at the corresponding MAIR index */ 4408c2ecf20Sopenharmony_ci mov x10, #MAIR_ATTR_NORMAL_TAGGED 4418c2ecf20Sopenharmony_ci bfi x5, x10, #(8 * MT_NORMAL_TAGGED), #8 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci /* initialize GCR_EL1: all non-zero tags excluded by default */ 4448c2ecf20Sopenharmony_ci mov x10, #(SYS_GCR_EL1_RRND | SYS_GCR_EL1_EXCL_MASK) 4458c2ecf20Sopenharmony_ci msr_s SYS_GCR_EL1, x10 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci /* 4488c2ecf20Sopenharmony_ci * If GCR_EL1.RRND=1 is implemented the same way as RRND=0, then 4498c2ecf20Sopenharmony_ci * RGSR_EL1.SEED must be non-zero for IRG to produce 4508c2ecf20Sopenharmony_ci * pseudorandom numbers. As RGSR_EL1 is UNKNOWN out of reset, we 4518c2ecf20Sopenharmony_ci * must initialize it. 4528c2ecf20Sopenharmony_ci */ 4538c2ecf20Sopenharmony_ci mrs x10, CNTVCT_EL0 4548c2ecf20Sopenharmony_ci ands x10, x10, #SYS_RGSR_EL1_SEED_MASK 4558c2ecf20Sopenharmony_ci csinc x10, x10, xzr, ne 4568c2ecf20Sopenharmony_ci lsl x10, x10, #SYS_RGSR_EL1_SEED_SHIFT 4578c2ecf20Sopenharmony_ci msr_s SYS_RGSR_EL1, x10 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci /* clear any pending tag check faults in TFSR*_EL1 */ 4608c2ecf20Sopenharmony_ci msr_s SYS_TFSR_EL1, xzr 4618c2ecf20Sopenharmony_ci msr_s SYS_TFSRE0_EL1, xzr 4628c2ecf20Sopenharmony_ci1: 4638c2ecf20Sopenharmony_ci#endif 4648c2ecf20Sopenharmony_ci msr mair_el1, x5 4658c2ecf20Sopenharmony_ci /* 4668c2ecf20Sopenharmony_ci * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for 4678c2ecf20Sopenharmony_ci * both user and kernel. 4688c2ecf20Sopenharmony_ci */ 4698c2ecf20Sopenharmony_ci mov_q x10, TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \ 4708c2ecf20Sopenharmony_ci TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \ 4718c2ecf20Sopenharmony_ci TCR_TBI0 | TCR_A1 | TCR_KASAN_FLAGS 4728c2ecf20Sopenharmony_ci tcr_clear_errata_bits x10, x9, x5 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM64_VA_BITS_52 4758c2ecf20Sopenharmony_ci ldr_l x9, vabits_actual 4768c2ecf20Sopenharmony_ci sub x9, xzr, x9 4778c2ecf20Sopenharmony_ci add x9, x9, #64 4788c2ecf20Sopenharmony_ci tcr_set_t1sz x10, x9 4798c2ecf20Sopenharmony_ci#else 4808c2ecf20Sopenharmony_ci ldr_l x9, idmap_t0sz 4818c2ecf20Sopenharmony_ci#endif 4828c2ecf20Sopenharmony_ci tcr_set_t0sz x10, x9 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci /* 4858c2ecf20Sopenharmony_ci * Set the IPS bits in TCR_EL1. 4868c2ecf20Sopenharmony_ci */ 4878c2ecf20Sopenharmony_ci tcr_compute_pa_size x10, #TCR_IPS_SHIFT, x5, x6 4888c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM64_HW_AFDBM 4898c2ecf20Sopenharmony_ci /* 4908c2ecf20Sopenharmony_ci * Enable hardware update of the Access Flags bit. 4918c2ecf20Sopenharmony_ci * Hardware dirty bit management is enabled later, 4928c2ecf20Sopenharmony_ci * via capabilities. 4938c2ecf20Sopenharmony_ci */ 4948c2ecf20Sopenharmony_ci mrs x9, ID_AA64MMFR1_EL1 4958c2ecf20Sopenharmony_ci and x9, x9, #0xf 4968c2ecf20Sopenharmony_ci cbz x9, 1f 4978c2ecf20Sopenharmony_ci orr x10, x10, #TCR_HA // hardware Access flag update 4988c2ecf20Sopenharmony_ci1: 4998c2ecf20Sopenharmony_ci#endif /* CONFIG_ARM64_HW_AFDBM */ 5008c2ecf20Sopenharmony_ci msr tcr_el1, x10 5018c2ecf20Sopenharmony_ci /* 5028c2ecf20Sopenharmony_ci * Prepare SCTLR 5038c2ecf20Sopenharmony_ci */ 5048c2ecf20Sopenharmony_ci mov_q x0, SCTLR_EL1_SET 5058c2ecf20Sopenharmony_ci ret // return to head.S 5068c2ecf20Sopenharmony_ciSYM_FUNC_END(__cpu_setup) 507