1/* 2 * Boot entry point and assembler functions for aarch64 tests. 3 * 4 * Copyright (C) 2017, Red Hat Inc, Andrew Jones <drjones@redhat.com> 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2. 7 */ 8#define __ASSEMBLY__ 9#include <auxinfo.h> 10#include <asm/asm-offsets.h> 11#include <asm/ptrace.h> 12#include <asm/processor.h> 13#include <asm/page.h> 14#include <asm/pgtable-hwdef.h> 15#include <asm/thread_info.h> 16 17.macro zero_range, tmp1, tmp2 189998: cmp \tmp1, \tmp2 19 b.eq 9997f 20 stp xzr, xzr, [\tmp1], #16 21 b 9998b 229997: 23.endm 24 25.section .init 26 27/* 28 * Bootloader params are in x0-x3. See kernel doc 29 * Documentation/arm64/booting.txt 30 */ 31.globl start 32start: 33 /* get our base address */ 34 adrp x4, start 35 add x4, x4, :lo12:start 36 37 /* 38 * Update all R_AARCH64_RELATIVE relocations using the table 39 * of Elf64_Rela entries between reloc_start/end. The build 40 * will not emit other relocation types. 41 * 42 * struct Elf64_Rela { 43 * uint64_t r_offset; 44 * uint64_t r_info; 45 * int64_t r_addend; 46 * } 47 */ 48 adrp x5, reloc_start 49 add x5, x5, :lo12:reloc_start 50 adrp x6, reloc_end 51 add x6, x6, :lo12:reloc_end 521: 53 cmp x5, x6 54 b.hs 1f 55 ldr x7, [x5] // r_offset 56 ldr x8, [x5, #16] // r_addend 57 add x8, x8, x4 // val = base + r_addend 58 str x8, [x4, x7] // base[r_offset] = val 59 add x5, x5, #24 60 b 1b 61 621: 63 /* zero BSS */ 64 adrp x4, bss 65 add x4, x4, :lo12:bss 66 adrp x5, ebss 67 add x5, x5, :lo12:ebss 68 zero_range x4, x5 69 70 /* zero and set up stack */ 71 adrp x5, stacktop 72 add x5, x5, :lo12:stacktop 73 sub x4, x5, #THREAD_SIZE 74 zero_range x4, x5 75 mov x4, #1 76 msr spsel, x4 77 isb 78 adrp x4, stackptr 79 add sp, x4, :lo12:stackptr 80 81 /* enable FP/ASIMD */ 82 mov x4, #(3 << 20) 83 msr cpacr_el1, x4 84 85 /* set up exception handling */ 86 bl exceptions_init 87 88 /* complete setup */ 89 bl setup // x0 is the addr of the dtb 90 bl get_mmu_off 91 cbnz x0, 1f 92 bl setup_vm 93 941: 95 /* run the test */ 96 adrp x0, __argc 97 ldr x0, [x0, :lo12:__argc] 98 adrp x1, __argv 99 add x1, x1, :lo12:__argv 100 adrp x2, __environ 101 add x2, x2, :lo12:__environ 102 bl main 103 bl exit 104 b halt 105 106exceptions_init: 107 adrp x4, vector_table 108 add x4, x4, :lo12:vector_table 109 msr vbar_el1, x4 110 isb 111 ret 112 113.text 114 115.globl get_mmu_off 116get_mmu_off: 117 adrp x0, auxinfo 118 ldr x0, [x0, :lo12:auxinfo + 8] 119 and x0, x0, #AUXINFO_MMU_OFF 120 ret 121 122.globl secondary_entry 123secondary_entry: 124 /* Enable FP/ASIMD */ 125 mov x0, #(3 << 20) 126 msr cpacr_el1, x0 127 128 /* set up exception handling */ 129 bl exceptions_init 130 131 /* enable the MMU unless requested off */ 132 bl get_mmu_off 133 cbnz x0, 1f 134 adrp x0, mmu_idmap 135 ldr x0, [x0, :lo12:mmu_idmap] 136 bl asm_mmu_enable 137 1381: 139 /* set the stack */ 140 adrp x0, secondary_data 141 ldr x0, [x0, :lo12:secondary_data] 142 mov sp, x0 143 144 /* finish init in C code */ 145 bl secondary_cinit 146 147 /* x0 is now the entry function, run it */ 148 blr x0 149 b do_idle 150 151.globl halt 152halt: 1531: wfi 154 b 1b 155 156/* 157 * asm_mmu_enable 158 * Inputs: 159 * x0 is the base address of the translation table 160 * Outputs: none 161 * 162 * Adapted from 163 * arch/arm64/kernel/head.S 164 * arch/arm64/mm/proc.S 165 */ 166 167/* 168 * Memory region attributes for LPAE: 169 * 170 * n = AttrIndx[2:0] 171 * n MAIR 172 * DEVICE_nGnRnE 000 00000000 173 * DEVICE_nGnRE 001 00000100 174 * DEVICE_GRE 010 00001100 175 * NORMAL_NC 011 01000100 176 * NORMAL 100 11111111 177 * NORMAL_WT 101 10111011 178 * DEVICE_nGRE 110 00001000 179 */ 180#define MAIR(attr, mt) ((attr) << ((mt) * 8)) 181 182#if PAGE_SIZE == SZ_64K 183#define TCR_TG_FLAGS TCR_TG0_64K | TCR_TG1_64K 184#elif PAGE_SIZE == SZ_16K 185#define TCR_TG_FLAGS TCR_TG0_16K | TCR_TG1_16K 186#elif PAGE_SIZE == SZ_4K 187#define TCR_TG_FLAGS TCR_TG0_4K | TCR_TG1_4K 188#endif 189 190.globl asm_mmu_enable 191asm_mmu_enable: 192 tlbi vmalle1 // invalidate I + D TLBs 193 dsb nsh 194 195 /* TCR */ 196 ldr x1, =TCR_TxSZ(VA_BITS) | \ 197 TCR_TG_FLAGS | \ 198 TCR_IRGN_WBWA | TCR_ORGN_WBWA | \ 199 TCR_SHARED 200 mrs x2, id_aa64mmfr0_el1 201 bfi x1, x2, #32, #3 202 msr tcr_el1, x1 203 204 /* MAIR */ 205 ldr x1, =MAIR(0x00, MT_DEVICE_nGnRnE) | \ 206 MAIR(0x04, MT_DEVICE_nGnRE) | \ 207 MAIR(0x0c, MT_DEVICE_GRE) | \ 208 MAIR(0x44, MT_NORMAL_NC) | \ 209 MAIR(0xff, MT_NORMAL) | \ 210 MAIR(0xbb, MT_NORMAL_WT) | \ 211 MAIR(0x08, MT_DEVICE_nGRE) 212 msr mair_el1, x1 213 214 /* TTBR0 */ 215 msr ttbr0_el1, x0 216 isb 217 218 /* SCTLR */ 219 mrs x1, sctlr_el1 220 orr x1, x1, SCTLR_EL1_C 221 orr x1, x1, SCTLR_EL1_I 222 orr x1, x1, SCTLR_EL1_M 223 msr sctlr_el1, x1 224 isb 225 226 ret 227 228/* Taken with small changes from arch/arm64/incluse/asm/assembler.h */ 229.macro dcache_by_line_op op, domain, start, end, tmp1, tmp2 230 adrp \tmp1, dcache_line_size 231 ldr \tmp1, [\tmp1, :lo12:dcache_line_size] 232 sub \tmp2, \tmp1, #1 233 bic \start, \start, \tmp2 2349998: 235 dc \op , \start 236 add \start, \start, \tmp1 237 cmp \start, \end 238 b.lo 9998b 239 dsb \domain 240.endm 241 242.globl asm_mmu_disable 243asm_mmu_disable: 244 mrs x0, sctlr_el1 245 bic x0, x0, SCTLR_EL1_M 246 msr sctlr_el1, x0 247 isb 248 249 /* Clean + invalidate the entire memory */ 250 adrp x0, __phys_offset 251 ldr x0, [x0, :lo12:__phys_offset] 252 adrp x1, __phys_end 253 ldr x1, [x1, :lo12:__phys_end] 254 dcache_by_line_op civac, sy, x0, x1, x2, x3 255 isb 256 257 ret 258 259/* 260 * Vectors 261 * Adapted from arch/arm64/kernel/entry.S 262 */ 263.macro vector_stub, name, vec 264\name: 265 stp x0, x1, [sp, #-S_FRAME_SIZE]! 266 stp x2, x3, [sp, #16] 267 stp x4, x5, [sp, #32] 268 stp x6, x7, [sp, #48] 269 stp x8, x9, [sp, #64] 270 stp x10, x11, [sp, #80] 271 stp x12, x13, [sp, #96] 272 stp x14, x15, [sp, #112] 273 stp x16, x17, [sp, #128] 274 stp x18, x19, [sp, #144] 275 stp x20, x21, [sp, #160] 276 stp x22, x23, [sp, #176] 277 stp x24, x25, [sp, #192] 278 stp x26, x27, [sp, #208] 279 stp x28, x29, [sp, #224] 280 281 str x30, [sp, #S_LR] 282 283 .if \vec >= 8 284 mrs x1, sp_el0 285 .else 286 add x1, sp, #S_FRAME_SIZE 287 .endif 288 str x1, [sp, #S_SP] 289 290 mrs x1, elr_el1 291 mrs x2, spsr_el1 292 stp x1, x2, [sp, #S_PC] 293 294 mov x0, \vec 295 mov x1, sp 296 mrs x2, esr_el1 297 bl do_handle_exception 298 299 ldp x1, x2, [sp, #S_PC] 300 msr spsr_el1, x2 301 msr elr_el1, x1 302 303 .if \vec >= 8 304 ldr x1, [sp, #S_SP] 305 msr sp_el0, x1 306 .endif 307 308 ldr x30, [sp, #S_LR] 309 310 ldp x28, x29, [sp, #224] 311 ldp x26, x27, [sp, #208] 312 ldp x24, x25, [sp, #192] 313 ldp x22, x23, [sp, #176] 314 ldp x20, x21, [sp, #160] 315 ldp x18, x19, [sp, #144] 316 ldp x16, x17, [sp, #128] 317 ldp x14, x15, [sp, #112] 318 ldp x12, x13, [sp, #96] 319 ldp x10, x11, [sp, #80] 320 ldp x8, x9, [sp, #64] 321 ldp x6, x7, [sp, #48] 322 ldp x4, x5, [sp, #32] 323 ldp x2, x3, [sp, #16] 324 ldp x0, x1, [sp], #S_FRAME_SIZE 325 326 eret 327.endm 328 329vector_stub el1t_sync, 0 330vector_stub el1t_irq, 1 331vector_stub el1t_fiq, 2 332vector_stub el1t_error, 3 333 334vector_stub el1h_sync, 4 335vector_stub el1h_irq, 5 336vector_stub el1h_fiq, 6 337vector_stub el1h_error, 7 338 339vector_stub el0_sync_64, 8 340vector_stub el0_irq_64, 9 341vector_stub el0_fiq_64, 10 342vector_stub el0_error_64, 11 343 344vector_stub el0_sync_32, 12 345vector_stub el0_irq_32, 13 346vector_stub el0_fiq_32, 14 347vector_stub el0_error_32, 15 348 349.section .text.ex 350 351.macro ventry, label 352.align 7 353 b \label 354.endm 355 356.align 11 357vector_table: 358 ventry el1t_sync // Synchronous EL1t 359 ventry el1t_irq // IRQ EL1t 360 ventry el1t_fiq // FIQ EL1t 361 ventry el1t_error // Error EL1t 362 363 ventry el1h_sync // Synchronous EL1h 364 ventry el1h_irq // IRQ EL1h 365 ventry el1h_fiq // FIQ EL1h 366 ventry el1h_error // Error EL1h 367 368 ventry el0_sync_64 // Synchronous 64-bit EL0 369 ventry el0_irq_64 // IRQ 64-bit EL0 370 ventry el0_fiq_64 // FIQ 64-bit EL0 371 ventry el0_error_64 // Error 64-bit EL0 372 373 ventry el0_sync_32 // Synchronous 32-bit EL0 374 ventry el0_irq_32 // IRQ 32-bit EL0 375 ventry el0_fiq_32 // FIQ 32-bit EL0 376 ventry el0_error_32 // Error 32-bit EL0 377