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