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/image.h> 15 16__INIT 17ENTRY(_start) 18 /* 19 * Image header expected by Linux boot-loaders. The image header data 20 * structure is described in asm/image.h. 21 * Do not modify it without modifying the structure and all bootloaders 22 * that expects this header format!! 23 */ 24 /* jump to start kernel */ 25 j _start_kernel 26 /* reserved */ 27 .word 0 28 .balign 8 29#if __riscv_xlen == 64 30 /* Image load offset(2MB) from start of RAM */ 31 .dword 0x200000 32#else 33 /* Image load offset(4MB) from start of RAM */ 34 .dword 0x400000 35#endif 36 /* Effective size of kernel image */ 37 .dword _end - _start 38 .dword __HEAD_FLAGS 39 .word RISCV_HEADER_VERSION 40 .word 0 41 .dword 0 42 .ascii RISCV_IMAGE_MAGIC 43 .balign 4 44 .ascii RISCV_IMAGE_MAGIC2 45 .word 0 46 47.global _start_kernel 48_start_kernel: 49 /* Mask all interrupts */ 50 csrw CSR_SIE, zero 51 csrw CSR_SIP, zero 52 53 /* Load the global pointer */ 54.option push 55.option norelax 56 la gp, __global_pointer$ 57.option pop 58 59 /* 60 * Disable FPU to detect illegal usage of 61 * floating point in kernel space 62 */ 63 li t0, SR_FS 64 csrc CSR_SSTATUS, t0 65 66#ifdef CONFIG_SMP 67 li t0, CONFIG_NR_CPUS 68 bgeu a0, t0, .Lsecondary_park 69#endif 70 71 /* Pick one hart to run the main boot sequence */ 72 la a3, hart_lottery 73 li a2, 1 74 amoadd.w a3, a2, (a3) 75 bnez a3, .Lsecondary_start 76 77 /* Clear BSS for flat non-ELF images */ 78 la a3, __bss_start 79 la a4, __bss_stop 80 ble a4, a3, clear_bss_done 81clear_bss: 82 REG_S zero, (a3) 83 add a3, a3, RISCV_SZPTR 84 blt a3, a4, clear_bss 85clear_bss_done: 86 87 /* Save hart ID and DTB physical address */ 88 mv s0, a0 89 mv s1, a1 90 la a2, boot_cpu_hartid 91 REG_S a0, (a2) 92 93 /* Initialize page tables and relocate to virtual addresses */ 94 la sp, init_thread_union + THREAD_SIZE 95 mv a0, s1 96 call setup_vm 97 la a0, early_pg_dir 98 call relocate 99 100 /* Restore C environment */ 101 la tp, init_task 102 sw zero, TASK_TI_CPU(tp) 103 la sp, init_thread_union + THREAD_SIZE 104 105 /* Start the kernel */ 106 call parse_dtb 107 tail start_kernel 108 109relocate: 110 /* Relocate return address */ 111 li a1, PAGE_OFFSET 112 la a2, _start 113 sub a1, a1, a2 114 add ra, ra, a1 115 116 /* Point stvec to virtual address of intruction after satp write */ 117 la a2, 1f 118 add a2, a2, a1 119 csrw CSR_STVEC, a2 120 121 /* Compute satp for kernel page tables, but don't load it yet */ 122 srl a2, a0, PAGE_SHIFT 123 li a1, SATP_MODE 124 or a2, a2, a1 125 126 /* 127 * Load trampoline page directory, which will cause us to trap to 128 * stvec if VA != PA, or simply fall through if VA == PA. We need a 129 * full fence here because setup_vm() just wrote these PTEs and we need 130 * to ensure the new translations are in use. 131 */ 132 la a0, trampoline_pg_dir 133 srl a0, a0, PAGE_SHIFT 134 or a0, a0, a1 135 sfence.vma 136 csrw CSR_SATP, a0 137.align 2 1381: 139 /* Set trap vector to spin forever to help debug */ 140 la a0, .Lsecondary_park 141 csrw CSR_STVEC, a0 142 143 /* Reload the global pointer */ 144.option push 145.option norelax 146 la gp, __global_pointer$ 147.option pop 148 149 /* 150 * Switch to kernel page tables. A full fence is necessary in order to 151 * avoid using the trampoline translations, which are only correct for 152 * the first superpage. Fetching the fence is guarnteed to work 153 * because that first superpage is translated the same way. 154 */ 155 csrw CSR_SATP, a2 156 sfence.vma 157 158 ret 159 160.Lsecondary_start: 161#ifdef CONFIG_SMP 162 /* Set trap vector to spin forever to help debug */ 163 la a3, .Lsecondary_park 164 csrw CSR_STVEC, a3 165 166 slli a3, a0, LGREG 167 la a1, __cpu_up_stack_pointer 168 la a2, __cpu_up_task_pointer 169 add a1, a3, a1 170 add a2, a3, a2 171 172 /* 173 * This hart didn't win the lottery, so we wait for the winning hart to 174 * get far enough along the boot process that it should continue. 175 */ 176.Lwait_for_cpu_up: 177 /* FIXME: We should WFI to save some energy here. */ 178 REG_L sp, (a1) 179 REG_L tp, (a2) 180 beqz sp, .Lwait_for_cpu_up 181 beqz tp, .Lwait_for_cpu_up 182 fence 183 184 /* Enable virtual memory and relocate to virtual address */ 185 la a0, swapper_pg_dir 186 call relocate 187 188 tail smp_callin 189#endif 190 191.align 2 192.Lsecondary_park: 193 /* We lack SMP support or have too many harts, so park this hart */ 194 wfi 195 j .Lsecondary_park 196END(_start) 197 198__PAGE_ALIGNED_BSS 199 /* Empty zero page */ 200 .balign PAGE_SIZE 201