1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Copyright (C) 2012 Regents of the University of California 4 */ 5 6#include <asm/thread_info.h> 7#include <asm/asm-offsets.h> 8#include <asm/asm.h> 9#include <linux/init.h> 10#include <linux/linkage.h> 11#include <asm/thread_info.h> 12#include <asm/page.h> 13#include <asm/csr.h> 14#include <asm/hwcap.h> 15#include <asm/image.h> 16 17__HEAD 18ENTRY(_start) 19 /* 20 * Image header expected by Linux boot-loaders. The image header data 21 * structure is described in asm/image.h. 22 * Do not modify it without modifying the structure and all bootloaders 23 * that expects this header format!! 24 */ 25 /* jump to start kernel */ 26 j _start_kernel 27 /* reserved */ 28 .word 0 29 .balign 8 30#if __riscv_xlen == 64 31 /* Image load offset(2MB) from start of RAM */ 32 .dword 0x200000 33#else 34 /* Image load offset(4MB) from start of RAM */ 35 .dword 0x400000 36#endif 37 /* Effective size of kernel image */ 38 .dword _end - _start 39 .dword __HEAD_FLAGS 40 .word RISCV_HEADER_VERSION 41 .word 0 42 .dword 0 43 .ascii RISCV_IMAGE_MAGIC 44 .balign 4 45 .ascii RISCV_IMAGE_MAGIC2 46 .word 0 47 48.align 2 49#ifdef CONFIG_MMU 50relocate: 51 /* Relocate return address */ 52 li a1, PAGE_OFFSET 53 la a2, _start 54 sub a1, a1, a2 55 add ra, ra, a1 56 57 /* Point stvec to virtual address of intruction after satp write */ 58 la a2, 1f 59 add a2, a2, a1 60 csrw CSR_TVEC, a2 61 62 /* Compute satp for kernel page tables, but don't load it yet */ 63 srl a2, a0, PAGE_SHIFT 64 li a1, SATP_MODE 65 or a2, a2, a1 66 67 /* 68 * Load trampoline page directory, which will cause us to trap to 69 * stvec if VA != PA, or simply fall through if VA == PA. We need a 70 * full fence here because setup_vm() just wrote these PTEs and we need 71 * to ensure the new translations are in use. 72 */ 73 la a0, trampoline_pg_dir 74 srl a0, a0, PAGE_SHIFT 75 or a0, a0, a1 76 sfence.vma 77 csrw CSR_SATP, a0 78.align 2 791: 80 /* Set trap vector to spin forever to help debug */ 81 la a0, .Lsecondary_park 82 csrw CSR_TVEC, a0 83 84 /* Reload the global pointer */ 85.option push 86.option norelax 87 la gp, __global_pointer$ 88.option pop 89 90 /* 91 * Switch to kernel page tables. A full fence is necessary in order to 92 * avoid using the trampoline translations, which are only correct for 93 * the first superpage. Fetching the fence is guarnteed to work 94 * because that first superpage is translated the same way. 95 */ 96 csrw CSR_SATP, a2 97 sfence.vma 98 99 ret 100#endif /* CONFIG_MMU */ 101#ifdef CONFIG_SMP 102 .global secondary_start_sbi 103secondary_start_sbi: 104 /* Mask all interrupts */ 105 csrw CSR_IE, zero 106 csrw CSR_IP, zero 107 108 /* Load the global pointer */ 109 .option push 110 .option norelax 111 la gp, __global_pointer$ 112 .option pop 113 114 /* 115 * Disable FPU to detect illegal usage of 116 * floating point in kernel space 117 */ 118 li t0, SR_FS 119 csrc CSR_STATUS, t0 120 121 /* Set trap vector to spin forever to help debug */ 122 la a3, .Lsecondary_park 123 csrw CSR_TVEC, a3 124 125 slli a3, a0, LGREG 126 la a4, __cpu_up_stack_pointer 127 la a5, __cpu_up_task_pointer 128 add a4, a3, a4 129 add a5, a3, a5 130 REG_L sp, (a4) 131 REG_L tp, (a5) 132 133 .global secondary_start_common 134secondary_start_common: 135 136#ifdef CONFIG_MMU 137 /* Enable virtual memory and relocate to virtual address */ 138 la a0, swapper_pg_dir 139 call relocate 140#endif 141 tail smp_callin 142#endif /* CONFIG_SMP */ 143 144.Lsecondary_park: 145 /* We lack SMP support or have too many harts, so park this hart */ 146 wfi 147 j .Lsecondary_park 148 149END(_start) 150 151 __INIT 152ENTRY(_start_kernel) 153 /* Mask all interrupts */ 154 csrw CSR_IE, zero 155 csrw CSR_IP, zero 156 157#ifdef CONFIG_RISCV_M_MODE 158 /* flush the instruction cache */ 159 fence.i 160 161 /* Reset all registers except ra, a0, a1 */ 162 call reset_regs 163 164 /* Setup a PMP to permit access to all of memory. */ 165 li a0, -1 166 csrw CSR_PMPADDR0, a0 167 li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X) 168 csrw CSR_PMPCFG0, a0 169 170 /* 171 * The hartid in a0 is expected later on, and we have no firmware 172 * to hand it to us. 173 */ 174 csrr a0, CSR_MHARTID 175#endif /* CONFIG_RISCV_M_MODE */ 176 177 /* Load the global pointer */ 178.option push 179.option norelax 180 la gp, __global_pointer$ 181.option pop 182 183 /* 184 * Disable FPU to detect illegal usage of 185 * floating point in kernel space 186 */ 187 li t0, SR_FS 188 csrc CSR_STATUS, t0 189 190#ifdef CONFIG_SMP 191 li t0, CONFIG_NR_CPUS 192 blt a0, t0, .Lgood_cores 193 tail .Lsecondary_park 194.Lgood_cores: 195#endif 196 197 /* Pick one hart to run the main boot sequence */ 198 la a3, hart_lottery 199 li a2, 1 200 amoadd.w a3, a2, (a3) 201 bnez a3, .Lsecondary_start 202 203 /* Clear BSS for flat non-ELF images */ 204 la a3, __bss_start 205 la a4, __bss_stop 206 ble a4, a3, clear_bss_done 207clear_bss: 208 REG_S zero, (a3) 209 add a3, a3, RISCV_SZPTR 210 blt a3, a4, clear_bss 211clear_bss_done: 212 213 /* Save hart ID and DTB physical address */ 214 mv s0, a0 215 mv s1, a1 216 la a2, boot_cpu_hartid 217 REG_S a0, (a2) 218 219 /* Initialize page tables and relocate to virtual addresses */ 220 la sp, init_thread_union + THREAD_SIZE 221 mv a0, s1 222 call setup_vm 223#ifdef CONFIG_MMU 224 la a0, early_pg_dir 225 call relocate 226#endif /* CONFIG_MMU */ 227 228 /* Restore C environment */ 229 la tp, init_task 230 sw zero, TASK_TI_CPU(tp) 231 la sp, init_thread_union + THREAD_SIZE 232 233#ifdef CONFIG_KASAN 234 call kasan_early_init 235#endif 236 /* Start the kernel */ 237 call soc_early_init 238 call parse_dtb 239 tail start_kernel 240 241.Lsecondary_start: 242#ifdef CONFIG_SMP 243 /* Set trap vector to spin forever to help debug */ 244 la a3, .Lsecondary_park 245 csrw CSR_TVEC, a3 246 247 slli a3, a0, LGREG 248 la a1, __cpu_up_stack_pointer 249 la a2, __cpu_up_task_pointer 250 add a1, a3, a1 251 add a2, a3, a2 252 253 /* 254 * This hart didn't win the lottery, so we wait for the winning hart to 255 * get far enough along the boot process that it should continue. 256 */ 257.Lwait_for_cpu_up: 258 /* FIXME: We should WFI to save some energy here. */ 259 REG_L sp, (a1) 260 REG_L tp, (a2) 261 beqz sp, .Lwait_for_cpu_up 262 beqz tp, .Lwait_for_cpu_up 263 fence 264 265 tail secondary_start_common 266#endif 267 268END(_start_kernel) 269 270#ifdef CONFIG_RISCV_M_MODE 271ENTRY(reset_regs) 272 li sp, 0 273 li gp, 0 274 li tp, 0 275 li t0, 0 276 li t1, 0 277 li t2, 0 278 li s0, 0 279 li s1, 0 280 li a2, 0 281 li a3, 0 282 li a4, 0 283 li a5, 0 284 li a6, 0 285 li a7, 0 286 li s2, 0 287 li s3, 0 288 li s4, 0 289 li s5, 0 290 li s6, 0 291 li s7, 0 292 li s8, 0 293 li s9, 0 294 li s10, 0 295 li s11, 0 296 li t3, 0 297 li t4, 0 298 li t5, 0 299 li t6, 0 300 csrw CSR_SCRATCH, 0 301 302#ifdef CONFIG_FPU 303 csrr t0, CSR_MISA 304 andi t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D) 305 beqz t0, .Lreset_regs_done 306 307 li t1, SR_FS 308 csrs CSR_STATUS, t1 309 fmv.s.x f0, zero 310 fmv.s.x f1, zero 311 fmv.s.x f2, zero 312 fmv.s.x f3, zero 313 fmv.s.x f4, zero 314 fmv.s.x f5, zero 315 fmv.s.x f6, zero 316 fmv.s.x f7, zero 317 fmv.s.x f8, zero 318 fmv.s.x f9, zero 319 fmv.s.x f10, zero 320 fmv.s.x f11, zero 321 fmv.s.x f12, zero 322 fmv.s.x f13, zero 323 fmv.s.x f14, zero 324 fmv.s.x f15, zero 325 fmv.s.x f16, zero 326 fmv.s.x f17, zero 327 fmv.s.x f18, zero 328 fmv.s.x f19, zero 329 fmv.s.x f20, zero 330 fmv.s.x f21, zero 331 fmv.s.x f22, zero 332 fmv.s.x f23, zero 333 fmv.s.x f24, zero 334 fmv.s.x f25, zero 335 fmv.s.x f26, zero 336 fmv.s.x f27, zero 337 fmv.s.x f28, zero 338 fmv.s.x f29, zero 339 fmv.s.x f30, zero 340 fmv.s.x f31, zero 341 csrw fcsr, 0 342 /* note that the caller must clear SR_FS */ 343#endif /* CONFIG_FPU */ 344.Lreset_regs_done: 345 ret 346END(reset_regs) 347#endif /* CONFIG_RISCV_M_MODE */ 348 349__PAGE_ALIGNED_BSS 350 /* Empty zero page */ 351 .balign PAGE_SIZE 352