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-offsets.h> 8#include <asm/csr.h> 9 10#if __riscv_xlen == 64 11#define __REG_SEL(a, b) a 12#elif __riscv_xlen == 32 13#define __REG_SEL(a, b) b 14#else 15#error "Unexpected __riscv_xlen" 16#endif 17 18#define REG_L __REG_SEL(ld, lw) 19#define REG_S __REG_SEL(sd, sw) 20 21.macro zero_range, tmp1, tmp2 229998: beq \tmp1, \tmp2, 9997f 23 REG_S zero, 0(\tmp1) 24 addi \tmp1, \tmp1, 8 25 j 9998b 269997: 27.endm 28 29 .section .init 30 31/* 32 * The hartid of the current core is in a0 33 * The address of the devicetree is in a1 34 * 35 * See Linux kernel doc Documentation/riscv/boot.rst 36 */ 37.global start 38start: 39 /* 40 * Stash the hartid in scratch and shift the dtb address into a0. 41 * thread_info_init() will later promote scratch to point at thread 42 * local storage. 43 */ 44 csrw CSR_SSCRATCH, a0 45 mv a0, a1 46 47 /* 48 * Update all R_RISCV_RELATIVE relocations using the table 49 * of Elf32_Rela/Elf64_Rela entries between reloc_start/end. 50 * The build will not emit other relocation types. 51 */ 52 la a1, reloc_start 53 la a2, reloc_end 54 la a3, start // base 551: 56 bge a1, a2, 1f 57 REG_L a4, ELF_RELA_OFFSET(a1) // r_offset 58 REG_L a5, ELF_RELA_ADDEND(a1) // r_addend 59 add a4, a3, a4 // addr = base + r_offset 60 add a5, a3, a5 // val = base + r_addend 61 REG_S a5, 0(a4) // *addr = val 62 addi a1, a1, ELF_RELA_SIZE 63 j 1b 64 651: 66 /* zero BSS */ 67 la a1, bss 68 la a2, ebss 69 zero_range a1, a2 70 71 /* zero and set up stack */ 72 la sp, stacktop 73 li a1, -8192 74 add a1, sp, a1 75 zero_range a1, sp 76 77 /* set up exception handling */ 78 la a1, exception_vectors 79 csrw CSR_STVEC, a1 80 81 /* complete setup */ 82 la a1, stacktop // a1 is the base of free memory 83 mv a2, zero // clear a2 for xlen=32 84 call setup // a0 is the addr of the dtb 85 86 /* run the test */ 87 la a0, __argc 88 REG_L a0, 0(a0) 89 la a1, __argv 90 la a2, __environ 91 call main 92 call exit 93 j halt 94 95 .text 96 97.balign 4 98.global halt 99halt: 1001: wfi 101 j 1b 102 103/* 104 * Save context to address in a0. 105 * For a0, sets PT_A0(a0) to the contents of PT_ORIG_A0(a0). 106 * Clobbers a1. 107 */ 108.macro save_context 109 REG_S ra, PT_RA(a0) // x1 110 REG_S sp, PT_SP(a0) // x2 111 REG_S gp, PT_GP(a0) // x3 112 REG_S tp, PT_TP(a0) // x4 113 REG_S t0, PT_T0(a0) // x5 114 REG_S t1, PT_T1(a0) // x6 115 REG_S t2, PT_T2(a0) // x7 116 REG_S s0, PT_S0(a0) // x8 / fp 117 REG_S s1, PT_S1(a0) // x9 118 /* a0 */ // x10 119 REG_S a1, PT_A1(a0) // x11 120 REG_S a2, PT_A2(a0) // x12 121 REG_S a3, PT_A3(a0) // x13 122 REG_S a4, PT_A4(a0) // x14 123 REG_S a5, PT_A5(a0) // x15 124 REG_S a6, PT_A6(a0) // x16 125 REG_S a7, PT_A7(a0) // x17 126 REG_S s2, PT_S2(a0) // x18 127 REG_S s3, PT_S3(a0) // x19 128 REG_S s4, PT_S4(a0) // x20 129 REG_S s5, PT_S5(a0) // x21 130 REG_S s6, PT_S6(a0) // x22 131 REG_S s7, PT_S7(a0) // x23 132 REG_S s8, PT_S8(a0) // x24 133 REG_S s9, PT_S9(a0) // x25 134 REG_S s10, PT_S10(a0) // x26 135 REG_S s11, PT_S11(a0) // x27 136 REG_S t3, PT_T3(a0) // x28 137 REG_S t4, PT_T4(a0) // x29 138 REG_S t5, PT_T5(a0) // x30 139 REG_S t6, PT_T6(a0) // x31 140 csrr a1, CSR_SEPC 141 REG_S a1, PT_EPC(a0) 142 csrr a1, CSR_SSTATUS 143 REG_S a1, PT_STATUS(a0) 144 csrr a1, CSR_STVAL 145 REG_S a1, PT_BADADDR(a0) 146 csrr a1, CSR_SCAUSE 147 REG_S a1, PT_CAUSE(a0) 148 REG_L a1, PT_ORIG_A0(a0) 149 REG_S a1, PT_A0(a0) 150.endm 151 152/* 153 * Restore context from address in a0. 154 * Also restores a0. 155 */ 156.macro restore_context 157 REG_L ra, PT_RA(a0) // x1 158 REG_L sp, PT_SP(a0) // x2 159 REG_L gp, PT_GP(a0) // x3 160 REG_L tp, PT_TP(a0) // x4 161 REG_L t0, PT_T0(a0) // x5 162 REG_L t1, PT_T1(a0) // x6 163 REG_L t2, PT_T2(a0) // x7 164 REG_L s0, PT_S0(a0) // x8 / fp 165 REG_L s1, PT_S1(a0) // x9 166 /* a0 */ // x10 167 /* a1 */ // x11 168 REG_L a2, PT_A2(a0) // x12 169 REG_L a3, PT_A3(a0) // x13 170 REG_L a4, PT_A4(a0) // x14 171 REG_L a5, PT_A5(a0) // x15 172 REG_L a6, PT_A6(a0) // x16 173 REG_L a7, PT_A7(a0) // x17 174 REG_L s2, PT_S2(a0) // x18 175 REG_L s3, PT_S3(a0) // x19 176 REG_L s4, PT_S4(a0) // x20 177 REG_L s5, PT_S5(a0) // x21 178 REG_L s6, PT_S6(a0) // x22 179 REG_L s7, PT_S7(a0) // x23 180 REG_L s8, PT_S8(a0) // x24 181 REG_L s9, PT_S9(a0) // x25 182 REG_L s10, PT_S10(a0) // x26 183 REG_L s11, PT_S11(a0) // x27 184 REG_L t3, PT_T3(a0) // x28 185 REG_L t4, PT_T4(a0) // x29 186 REG_L t5, PT_T5(a0) // x30 187 REG_L t6, PT_T6(a0) // x31 188 REG_L a1, PT_EPC(a0) 189 csrw CSR_SEPC, a1 190 REG_L a1, PT_STATUS(a0) 191 csrw CSR_SSTATUS, a1 192 REG_L a1, PT_BADADDR(a0) 193 csrw CSR_STVAL, a1 194 REG_L a1, PT_CAUSE(a0) 195 csrw CSR_SCAUSE, a1 196 REG_L a1, PT_A1(a0) 197 REG_L a0, PT_A0(a0) 198.endm 199 200.balign 4 201.global exception_vectors 202exception_vectors: 203 REG_S a0, (-PT_SIZE + PT_ORIG_A0)(sp) 204 addi a0, sp, -PT_SIZE 205 save_context 206 mv sp, a0 207 call do_handle_exception 208 mv a0, sp 209 restore_context 210 sret 211