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