1/* 2 * Based on arch/arm/mm/proc.S 3 * 4 * Copyright (C) 2001 Deep Blue Solutions Ltd. 5 * Copyright (C) 2012 ARM Ltd. 6 * 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 */ 20 21#include <linux/init.h> 22#include <linux/linkage.h> 23#include <asm/assembler.h> 24#include <asm/asm-offsets.h> 25#include <asm/hwcap.h> 26#include <asm/pgtable-hwdef.h> 27#include <asm/pgtable.h> 28 29#include "proc-macros.S" 30 31#ifdef CONFIG_ARM64_64K_PAGES 32#define TCR_TG_FLAGS TCR_TG0_64K | TCR_TG1_64K 33#else 34#define TCR_TG_FLAGS TCR_TG0_4K | TCR_TG1_4K 35#endif 36 37#ifdef CONFIG_SMP 38#define TCR_SMP_FLAGS TCR_SHARED 39#else 40#define TCR_SMP_FLAGS 0 41#endif 42 43/* PTWs cacheable, inner/outer WBWA */ 44#define TCR_CACHE_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA 45 46#define MAIR(attr, mt) ((attr) << ((mt) * 8)) 47 48/* 49 * cpu_cache_off() 50 * 51 * Turn the CPU D-cache off. 52 */ 53ENTRY(cpu_cache_off) 54 mrs x0, sctlr_el1 55 bic x0, x0, #1 << 2 // clear SCTLR.C 56 msr sctlr_el1, x0 57 isb 58 ret 59ENDPROC(cpu_cache_off) 60 61/* 62 * cpu_reset(loc) 63 * 64 * Perform a soft reset of the system. Put the CPU into the same state 65 * as it would be if it had been reset, and branch to what would be the 66 * reset vector. It must be executed with the flat identity mapping. 67 * 68 * - loc - location to jump to for soft reset 69 */ 70 .align 5 71ENTRY(cpu_reset) 72 mrs x1, sctlr_el1 73 bic x1, x1, #1 74 msr sctlr_el1, x1 // disable the MMU 75 isb 76 ret x0 77ENDPROC(cpu_reset) 78 79ENTRY(cpu_soft_restart) 80 /* Save address of cpu_reset() and reset address */ 81 mov x19, x0 82 mov x20, x1 83 84 /* Turn D-cache off */ 85 bl cpu_cache_off 86 87 /* Push out all dirty data, and ensure cache is empty */ 88 bl flush_cache_all 89 90 mov x0, x20 91 ret x19 92ENDPROC(cpu_soft_restart) 93 94/* 95 * cpu_do_idle() 96 * 97 * Idle the processor (wait for interrupt). 98 */ 99ENTRY(cpu_do_idle) 100 dsb sy // WFI may enter a low-power mode 101 wfi 102 ret 103ENDPROC(cpu_do_idle) 104 105#ifdef CONFIG_ARM64_CPU_SUSPEND 106/** 107 * cpu_do_suspend - save CPU registers context 108 * 109 * x0: virtual address of context pointer 110 */ 111ENTRY(cpu_do_suspend) 112 mrs x2, tpidr_el0 113 mrs x3, tpidrro_el0 114 mrs x4, contextidr_el1 115 mrs x5, mair_el1 116 mrs x6, cpacr_el1 117 mrs x7, ttbr1_el1 118 mrs x8, tcr_el1 119 mrs x9, vbar_el1 120 mrs x10, mdscr_el1 121 mrs x11, oslsr_el1 122 mrs x12, sctlr_el1 123 stp x2, x3, [x0] 124 stp x4, x5, [x0, #16] 125 stp x6, x7, [x0, #32] 126 stp x8, x9, [x0, #48] 127 stp x10, x11, [x0, #64] 128 str x12, [x0, #80] 129 ret 130ENDPROC(cpu_do_suspend) 131 132/** 133 * cpu_do_resume - restore CPU register context 134 * 135 * x0: Physical address of context pointer 136 * x1: ttbr0_el1 to be restored 137 * 138 * Returns: 139 * sctlr_el1 value in x0 140 */ 141ENTRY(cpu_do_resume) 142 /* 143 * Invalidate local tlb entries before turning on MMU 144 */ 145 tlbi vmalle1 146 ldp x2, x3, [x0] 147 ldp x4, x5, [x0, #16] 148 ldp x6, x7, [x0, #32] 149 ldp x8, x9, [x0, #48] 150 ldp x10, x11, [x0, #64] 151 ldr x12, [x0, #80] 152 msr tpidr_el0, x2 153 msr tpidrro_el0, x3 154 msr contextidr_el1, x4 155 msr mair_el1, x5 156 msr cpacr_el1, x6 157 msr ttbr0_el1, x1 158 msr ttbr1_el1, x7 159 msr tcr_el1, x8 160 msr vbar_el1, x9 161 msr mdscr_el1, x10 162 /* 163 * Restore oslsr_el1 by writing oslar_el1 164 */ 165 ubfx x11, x11, #1, #1 166 msr oslar_el1, x11 167 mov x0, x12 168 dsb nsh // Make sure local tlb invalidation completed 169 isb 170 ret 171ENDPROC(cpu_do_resume) 172#endif 173 174/* 175 * cpu_do_switch_mm(pgd_phys, tsk) 176 * 177 * Set the translation table base pointer to be pgd_phys. 178 * 179 * - pgd_phys - physical address of new TTB 180 */ 181ENTRY(cpu_do_switch_mm) 182 mmid w1, x1 // get mm->context.id 183 bfi x0, x1, #48, #16 // set the ASID 184 msr ttbr0_el1, x0 // set TTBR0 185 isb 186 ret 187ENDPROC(cpu_do_switch_mm) 188 189 .section ".text.init", #alloc, #execinstr 190 191/* 192 * __cpu_setup 193 * 194 * Initialise the processor for turning the MMU on. Return in x0 the 195 * value of the SCTLR_EL1 register. 196 */ 197ENTRY(__cpu_setup) 198 ic iallu // I+BTB cache invalidate 199 tlbi vmalle1is // invalidate I + D TLBs 200 dsb ish 201 202 mov x0, #3 << 20 203 msr cpacr_el1, x0 // Enable FP/ASIMD 204 msr mdscr_el1, xzr // Reset mdscr_el1 205 /* 206 * Memory region attributes for LPAE: 207 * 208 * n = AttrIndx[2:0] 209 * n MAIR 210 * DEVICE_nGnRnE 000 00000000 211 * DEVICE_nGnRE 001 00000100 212 * DEVICE_GRE 010 00001100 213 * NORMAL_NC 011 01000100 214 * NORMAL 100 11111111 215 */ 216 ldr x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \ 217 MAIR(0x04, MT_DEVICE_nGnRE) | \ 218 MAIR(0x0c, MT_DEVICE_GRE) | \ 219 MAIR(0x44, MT_NORMAL_NC) | \ 220 MAIR(0xff, MT_NORMAL) 221 msr mair_el1, x5 222 /* 223 * Prepare SCTLR 224 */ 225 adr x5, crval 226 ldp w5, w6, [x5] 227 mrs x0, sctlr_el1 228 bic x0, x0, x5 // clear bits 229 orr x0, x0, x6 // set bits 230 /* 231 * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for 232 * both user and kernel. 233 */ 234 ldr x10, =TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \ 235 TCR_TG_FLAGS | TCR_ASID16 | TCR_TBI0 236 /* 237 * Read the PARange bits from ID_AA64MMFR0_EL1 and set the IPS bits in 238 * TCR_EL1. 239 */ 240 mrs x9, ID_AA64MMFR0_EL1 241 bfi x10, x9, #32, #3 242 msr tcr_el1, x10 243 ret // return to head.S 244ENDPROC(__cpu_setup) 245 246 /* 247 * n n T 248 * U E WT T UD US IHBS 249 * CE0 XWHW CZ ME TEEA S 250 * .... .IEE .... NEAI TE.I ..AD DEN0 ACAM 251 * 0011 0... 1101 ..0. ..0. 10.. .... .... < hardware reserved 252 * .... .1.. .... 01.1 11.1 ..01 0001 1101 < software settings 253 */ 254 .type crval, #object 255crval: 256 .word 0x000802e2 // clear 257 .word 0x0405d11d // set 258