1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Boot entry point and assembler functions for riscv. 4 * 5 * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com> 6 */ 7#include <asm/asm.h> 8#include <asm/asm-offsets.h> 9#include <asm/csr.h> 10 11 12.macro push_fp, ra=ra 13 addi sp, sp, -FP_SIZE 14 REG_S \ra, (FP_SIZE - SZREG)(sp) 15 REG_S fp, (FP_SIZE - 2*SZREG)(sp) 16 addi fp, sp, FP_SIZE 17.endm 18 19.macro pop_fp 20 REG_L ra, (FP_SIZE - SZREG)(sp) 21 REG_L fp, (FP_SIZE - 2*SZREG)(sp) 22 addi sp, sp, FP_SIZE 23.endm 24 25.macro zero_range, tmp1, tmp2 269998: beq \tmp1, \tmp2, 9997f 27 REG_S zero, 0(\tmp1) 28 addi \tmp1, \tmp1, 8 29 j 9998b 309997: 31.endm 32 33#ifdef CONFIG_EFI 34#include "efi/crt0-efi-riscv64.S" 35#else 36 .section .init 37 38/* 39 * The hartid of the current core is in a0 40 * The address of the devicetree is in a1 41 * 42 * See Linux kernel doc Documentation/riscv/boot.rst 43 */ 44.global start 45start: 46 /* 47 * Stash the hartid in scratch and shift the dtb address into a0. 48 * thread_info_init() will later promote scratch to point at thread 49 * local storage. 50 */ 51 csrw CSR_SSCRATCH, a0 52 mv a0, a1 53 54 /* 55 * Update all R_RISCV_RELATIVE relocations using the table 56 * of Elf32_Rela/Elf64_Rela entries between reloc_start/end. 57 * The build will not emit other relocation types. 58 */ 59 la a1, reloc_start 60 la a2, reloc_end 61 la a3, start // base 621: 63 bge a1, a2, 1f 64 REG_L a4, ELF_RELA_OFFSET(a1) // r_offset 65 REG_L a5, ELF_RELA_ADDEND(a1) // r_addend 66 add a4, a3, a4 // addr = base + r_offset 67 add a5, a3, a5 // val = base + r_addend 68 REG_S a5, 0(a4) // *addr = val 69 addi a1, a1, ELF_RELA_SIZE 70 j 1b 71 721: 73 /* zero BSS */ 74 la a1, bss 75 la a2, ebss 76 zero_range a1, a2 77 78 /* zero and set up stack */ 79 la sp, stacktop 80 li a1, -8192 81 add a1, sp, a1 82 zero_range a1, sp 83 mv fp, zero // Ensure fp starts out as zero 84 85 /* set up exception handling */ 86 la a1, exception_vectors 87 csrw CSR_STVEC, a1 88 89 /* complete setup */ 90 la a1, stacktop // a1 is the base of free memory 91 mv a2, zero // clear a2 for xlen=32 92 call setup // a0 is the addr of the dtb 93 94 /* run the test */ 95 la a0, __argc 96 REG_L a0, 0(a0) 97 la a1, __argv 98 la a2, __environ 99 call main 100 call exit 101 j halt 102 103#endif /* !CONFIG_EFI */ 104 .text 105 106.balign 4 107.global halt 108halt: 1091: wfi 110 j 1b 111 112.balign 4 113.global secondary_entry 114secondary_entry: 115 /* 116 * From the "HSM Hart Start Register State" table of the SBI spec: 117 * satp 0 118 * sstatus.SIE 0 119 * a0 hartid 120 * a1 opaque parameter 121 * 122 * __smp_boot_secondary() sets the opaque parameter (a1) to the physical 123 * address of the stack and the stack contains the secondary data. 124 */ 125 csrw CSR_SSCRATCH, a0 126 mv sp, a1 127 mv fp, zero 128 REG_L a0, SECONDARY_STVEC(sp) 129 csrw CSR_STVEC, a0 130 mv a0, sp 131 call secondary_cinit 132 addi sp, sp, SECONDARY_DATA_SIZE 133 jr a0 134 la a0, do_idle 135 jr a0 136 137/* 138 * Save context to address in a0. 139 * For a0, sets PT_A0(a0) to the contents of PT_ORIG_A0(a0). 140 * Clobbers a1. 141 */ 142.macro save_context 143 REG_S ra, PT_RA(a0) // x1 144 REG_S sp, PT_SP(a0) // x2 145 REG_S gp, PT_GP(a0) // x3 146 REG_S tp, PT_TP(a0) // x4 147 REG_S t0, PT_T0(a0) // x5 148 REG_S t1, PT_T1(a0) // x6 149 REG_S t2, PT_T2(a0) // x7 150 REG_S s0, PT_S0(a0) // x8 / fp 151 REG_S s1, PT_S1(a0) // x9 152 /* a0 */ // x10 153 REG_S a1, PT_A1(a0) // x11 154 REG_S a2, PT_A2(a0) // x12 155 REG_S a3, PT_A3(a0) // x13 156 REG_S a4, PT_A4(a0) // x14 157 REG_S a5, PT_A5(a0) // x15 158 REG_S a6, PT_A6(a0) // x16 159 REG_S a7, PT_A7(a0) // x17 160 REG_S s2, PT_S2(a0) // x18 161 REG_S s3, PT_S3(a0) // x19 162 REG_S s4, PT_S4(a0) // x20 163 REG_S s5, PT_S5(a0) // x21 164 REG_S s6, PT_S6(a0) // x22 165 REG_S s7, PT_S7(a0) // x23 166 REG_S s8, PT_S8(a0) // x24 167 REG_S s9, PT_S9(a0) // x25 168 REG_S s10, PT_S10(a0) // x26 169 REG_S s11, PT_S11(a0) // x27 170 REG_S t3, PT_T3(a0) // x28 171 REG_S t4, PT_T4(a0) // x29 172 REG_S t5, PT_T5(a0) // x30 173 REG_S t6, PT_T6(a0) // x31 174 csrr a1, CSR_SEPC 175 REG_S a1, PT_EPC(a0) 176 csrr a1, CSR_SSTATUS 177 REG_S a1, PT_STATUS(a0) 178 csrr a1, CSR_STVAL 179 REG_S a1, PT_BADADDR(a0) 180 csrr a1, CSR_SCAUSE 181 REG_S a1, PT_CAUSE(a0) 182 REG_L a1, PT_ORIG_A0(a0) 183 REG_S a1, PT_A0(a0) 184.endm 185 186/* 187 * Restore context from address in a0. 188 * Also restores a0. 189 */ 190.macro restore_context 191 REG_L ra, PT_RA(a0) // x1 192 REG_L sp, PT_SP(a0) // x2 193 REG_L gp, PT_GP(a0) // x3 194 REG_L tp, PT_TP(a0) // x4 195 REG_L t0, PT_T0(a0) // x5 196 REG_L t1, PT_T1(a0) // x6 197 REG_L t2, PT_T2(a0) // x7 198 REG_L s0, PT_S0(a0) // x8 / fp 199 REG_L s1, PT_S1(a0) // x9 200 /* a0 */ // x10 201 /* a1 */ // x11 202 REG_L a2, PT_A2(a0) // x12 203 REG_L a3, PT_A3(a0) // x13 204 REG_L a4, PT_A4(a0) // x14 205 REG_L a5, PT_A5(a0) // x15 206 REG_L a6, PT_A6(a0) // x16 207 REG_L a7, PT_A7(a0) // x17 208 REG_L s2, PT_S2(a0) // x18 209 REG_L s3, PT_S3(a0) // x19 210 REG_L s4, PT_S4(a0) // x20 211 REG_L s5, PT_S5(a0) // x21 212 REG_L s6, PT_S6(a0) // x22 213 REG_L s7, PT_S7(a0) // x23 214 REG_L s8, PT_S8(a0) // x24 215 REG_L s9, PT_S9(a0) // x25 216 REG_L s10, PT_S10(a0) // x26 217 REG_L s11, PT_S11(a0) // x27 218 REG_L t3, PT_T3(a0) // x28 219 REG_L t4, PT_T4(a0) // x29 220 REG_L t5, PT_T5(a0) // x30 221 REG_L t6, PT_T6(a0) // x31 222 REG_L a1, PT_EPC(a0) 223 csrw CSR_SEPC, a1 224 REG_L a1, PT_STATUS(a0) 225 csrw CSR_SSTATUS, a1 226 REG_L a1, PT_BADADDR(a0) 227 csrw CSR_STVAL, a1 228 REG_L a1, PT_CAUSE(a0) 229 csrw CSR_SCAUSE, a1 230 REG_L a1, PT_A1(a0) 231 REG_L a0, PT_A0(a0) 232.endm 233 234.balign 4 235.global exception_vectors 236exception_vectors: 237 REG_S a0, (-PT_SIZE - FP_SIZE + PT_ORIG_A0)(sp) 238 addi a0, sp, -PT_SIZE - FP_SIZE 239 save_context 240 /* 241 * Set a frame pointer "ra" which points to the last instruction. 242 * Add 1 to it, because pretty_print_stacks.py subtracts 1. 243 */ 244 REG_L a1, PT_EPC(a0) 245 addi a1, a1, 1 246 push_fp a1 247 mv sp, a0 248 call do_handle_exception 249 mv a0, sp 250 restore_context 251 sret 252