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 /* Pick one hart to run the main boot sequence */ 67 la a3, hart_lottery 68 li a2, 1 69 amoadd.w a3, a2, (a3) 70 bnez a3, .Lsecondary_start 71 72 /* Clear BSS for flat non-ELF images */ 73 la a3, __bss_start 74 la a4, __bss_stop 75 ble a4, a3, clear_bss_done 76clear_bss: 77 REG_S zero, (a3) 78 add a3, a3, RISCV_SZPTR 79 blt a3, a4, clear_bss 80clear_bss_done: 81 82 /* Save hart ID and DTB physical address */ 83 mv s0, a0 84 mv s1, a1 85 la a2, boot_cpu_hartid 86 REG_S a0, (a2) 87 88 /* Initialize page tables and relocate to virtual addresses */ 89 la sp, init_thread_union + THREAD_SIZE 90 mv a0, s1 91 call setup_vm 92 la a0, early_pg_dir 93 call relocate 94 95 /* Restore C environment */ 96 la tp, init_task 97 sw zero, TASK_TI_CPU(tp) 98 la sp, init_thread_union + THREAD_SIZE 99 100 /* Start the kernel */ 101 call parse_dtb 102 tail start_kernel 103 104relocate: 105 /* Relocate return address */ 106 li a1, PAGE_OFFSET 107 la a2, _start 108 sub a1, a1, a2 109 add ra, ra, a1 110 111 /* Point stvec to virtual address of intruction after satp write */ 112 la a2, 1f 113 add a2, a2, a1 114 csrw CSR_STVEC, a2 115 116 /* Compute satp for kernel page tables, but don't load it yet */ 117 srl a2, a0, PAGE_SHIFT 118 li a1, SATP_MODE 119 or a2, a2, a1 120 121 /* 122 * Load trampoline page directory, which will cause us to trap to 123 * stvec if VA != PA, or simply fall through if VA == PA. We need a 124 * full fence here because setup_vm() just wrote these PTEs and we need 125 * to ensure the new translations are in use. 126 */ 127 la a0, trampoline_pg_dir 128 srl a0, a0, PAGE_SHIFT 129 or a0, a0, a1 130 sfence.vma 131 csrw CSR_SATP, a0 132.align 2 1331: 134 /* Set trap vector to spin forever to help debug */ 135 la a0, .Lsecondary_park 136 csrw CSR_STVEC, a0 137 138 /* Reload the global pointer */ 139.option push 140.option norelax 141 la gp, __global_pointer$ 142.option pop 143 144 /* 145 * Switch to kernel page tables. A full fence is necessary in order to 146 * avoid using the trampoline translations, which are only correct for 147 * the first superpage. Fetching the fence is guarnteed to work 148 * because that first superpage is translated the same way. 149 */ 150 csrw CSR_SATP, a2 151 sfence.vma 152 153 ret 154 155.Lsecondary_start: 156#ifdef CONFIG_SMP 157 li a1, CONFIG_NR_CPUS 158 bgeu a0, a1, .Lsecondary_park 159 160 /* Set trap vector to spin forever to help debug */ 161 la a3, .Lsecondary_park 162 csrw CSR_STVEC, a3 163 164 slli a3, a0, LGREG 165 la a1, __cpu_up_stack_pointer 166 la a2, __cpu_up_task_pointer 167 add a1, a3, a1 168 add a2, a3, a2 169 170 /* 171 * This hart didn't win the lottery, so we wait for the winning hart to 172 * get far enough along the boot process that it should continue. 173 */ 174.Lwait_for_cpu_up: 175 /* FIXME: We should WFI to save some energy here. */ 176 REG_L sp, (a1) 177 REG_L tp, (a2) 178 beqz sp, .Lwait_for_cpu_up 179 beqz tp, .Lwait_for_cpu_up 180 fence 181 182 /* Enable virtual memory and relocate to virtual address */ 183 la a0, swapper_pg_dir 184 call relocate 185 186 tail smp_callin 187#endif 188 189.align 2 190.Lsecondary_park: 191 /* We lack SMP support or have too many harts, so park this hart */ 192 wfi 193 j .Lsecondary_park 194END(_start) 195 196__PAGE_ALIGNED_BSS 197 /* Empty zero page */ 198 .balign PAGE_SIZE 199