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