summaryrefslogtreecommitdiff
path: root/arch/riscv/cpu/start.S
blob: c313477ae072d82251025c87a581a9745b1591a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Startup Code for RISC-V Core
 *
 * Copyright (c) 2017 Microsemi Corporation.
 * Copyright (c) 2017 Padmarao Begari <Padmarao.Begari@microsemi.com>
 *
 * Copyright (C) 2017 Andes Technology Corporation
 * Rick Chen, Andes Technology Corporation <rick@andestech.com>
 */

#include <asm-offsets.h>
#include <config.h>
#include <common.h>
#include <elf.h>
#include <asm/encoding.h>

#ifdef CONFIG_32BIT
#define LREG			lw
#define SREG			sw
#define REGBYTES		4
#define RELOC_TYPE		R_RISCV_32
#define SYM_INDEX		0x8
#define SYM_SIZE		0x10
#else
#define LREG			ld
#define SREG			sd
#define REGBYTES		8
#define RELOC_TYPE		R_RISCV_64
#define SYM_INDEX		0x20
#define SYM_SIZE		0x18
#endif

.section .text
.globl _start
_start:
	li	t0, CONFIG_SYS_SDRAM_BASE
	SREG	a2, 0(t0)
	la	t0, trap_entry
	csrw	mtvec, t0
	csrwi	mstatus, 0
	csrwi	mie, 0

/*
 * Set stackpointer in internal/ex RAM to call board_init_f
 */
call_board_init_f:
	li	t0, -16
	li	t1, CONFIG_SYS_INIT_SP_ADDR
	and	sp, t1, t0		/* force 16 byte alignment */

#ifdef CONFIG_DEBUG_UART
	jal	debug_uart_init
#endif

call_board_init_f_0:
	mv	a0, sp
	jal	board_init_f_alloc_reserve
	mv	sp, a0
	jal	board_init_f_init_reserve

	mv	a0, zero		/* a0 <-- boot_flags = 0 */
	la	t5, board_init_f
	jr	t5			/* jump to board_init_f() */

/*
 * void relocate_code (addr_sp, gd, addr_moni)
 *
 * This "function" does not return, instead it continues in RAM
 * after relocating the monitor code.
 *
 */
.globl relocate_code
relocate_code:
	mv	s2, a0			/* save addr_sp */
	mv	s3, a1			/* save addr of gd */
	mv	s4, a2			/* save addr of destination */

/*
 *Set up the stack
 */
stack_setup:
	mv	sp, s2
	la	t0, _start
	sub	t6, s4, t0		/* t6 <- relocation offset */
	beq	t0, s4, clear_bss	/* skip relocation */

	mv	t1, s4			/* t1 <- scratch for copy_loop */
	la	t3, __bss_start
	sub	t3, t3, t0		/* t3 <- __bss_start_ofs */
	add	t2, t0, t3		/* t2 <- source end address */

copy_loop:
	LREG	t5, 0(t0)
	addi	t0, t0, REGBYTES
	SREG	t5, 0(t1)
	addi	t1, t1, REGBYTES
	blt	t0, t2, copy_loop

/*
 * Update dynamic relocations after board_init_f
 */
fix_rela_dyn:
	la	t1, __rel_dyn_start
	la	t2, __rel_dyn_end
	beq	t1, t2, clear_bss
	add	t1, t1, t6		/* t1 <- rela_dyn_start in RAM */
	add	t2, t2, t6		/* t2 <- rela_dyn_end in RAM */

/*
 * skip first reserved entry: address, type, addend
 */
	bne	t1, t2, 7f

6:
	LREG	t5, -(REGBYTES*2)(t1)	/* t5 <-- relocation info:type */
	li	t3, R_RISCV_RELATIVE	/* reloc type R_RISCV_RELATIVE */
	bne	t5, t3, 8f		/* skip non-RISCV_RELOC entries */
	LREG	t3, -(REGBYTES*3)(t1)
	LREG	t5, -(REGBYTES)(t1)	/* t5 <-- addend */
	add	t5, t5, t6		/* t5 <-- location to fix up in RAM */
	add	t3, t3, t6		/* t3 <-- location to fix up in RAM */
	SREG	t5, 0(t3)
7:
	addi	t1, t1, (REGBYTES*3)
	ble	t1, t2, 6b

8:
	la	t4, __dyn_sym_start
	add	t4, t4, t6

9:
	LREG	t5, -(REGBYTES*2)(t1)	/* t5 <-- relocation info:type */
	srli	t0, t5, SYM_INDEX	/* t0 <--- sym table index */
	andi	t5, t5, 0xFF		/* t5 <--- relocation type */
	li	t3, RELOC_TYPE
	bne	t5, t3, 10f		/* skip non-addned entries */

	LREG	t3, -(REGBYTES*3)(t1)
	li	t5, SYM_SIZE
	mul	t0, t0, t5
	add	s1, t4, t0
	LREG	t5, REGBYTES(s1)
	add	t5, t5, t6		/* t5 <-- location to fix up in RAM */
	add	t3, t3, t6		/* t3 <-- location to fix up in RAM */
	SREG	t5, 0(t3)
10:
	addi	t1, t1, (REGBYTES*3)
	ble	t1, t2, 9b

/*
 * trap update
*/
	la	t0, trap_entry
	add	t0, t0, t6
	csrw	mtvec, t0

clear_bss:
	la	t0, __bss_start		/* t0 <- rel __bss_start in FLASH */
	add	t0, t0, t6		/* t0 <- rel __bss_start in RAM */
	la	t1, __bss_end		/* t1 <- rel __bss_end in FLASH */
	add	t1, t1, t6		/* t1 <- rel __bss_end in RAM */
	li	t2, 0x00000000		/* clear */
	beq	t0, t1, call_board_init_r

clbss_l:
	SREG	t2, 0(t0)		/* clear loop... */
	addi	t0, t0, REGBYTES
	bne	t0, t1, clbss_l

/*
 * We are done. Do not return, instead branch to second part of board
 * initialization, now running from RAM.
 */
call_board_init_r:
	la	t0, board_init_r
	mv	t4, t0			/* offset of board_init_r() */
	add	t4, t4, t6		/* real address of board_init_r() */
/*
 * setup parameters for board_init_r
 */
	mv	a0, s3			/* gd_t */
	mv	a1, s4			/* dest_addr */

/*
 * jump to it ...
 */
	jr	t4			/* jump to board_init_r() */

/*
 * trap entry
 */
.align 2
trap_entry:
	addi	sp, sp, -32*REGBYTES
	SREG	x1, 1*REGBYTES(sp)
	SREG	x2, 2*REGBYTES(sp)
	SREG	x3, 3*REGBYTES(sp)
	SREG	x4, 4*REGBYTES(sp)
	SREG	x5, 5*REGBYTES(sp)
	SREG	x6, 6*REGBYTES(sp)
	SREG	x7, 7*REGBYTES(sp)
	SREG	x8, 8*REGBYTES(sp)
	SREG	x9, 9*REGBYTES(sp)
	SREG	x10, 10*REGBYTES(sp)
	SREG	x11, 11*REGBYTES(sp)
	SREG	x12, 12*REGBYTES(sp)
	SREG	x13, 13*REGBYTES(sp)
	SREG	x14, 14*REGBYTES(sp)
	SREG	x15, 15*REGBYTES(sp)
	SREG	x16, 16*REGBYTES(sp)
	SREG	x17, 17*REGBYTES(sp)
	SREG	x18, 18*REGBYTES(sp)
	SREG	x19, 19*REGBYTES(sp)
	SREG	x20, 20*REGBYTES(sp)
	SREG	x21, 21*REGBYTES(sp)
	SREG	x22, 22*REGBYTES(sp)
	SREG	x23, 23*REGBYTES(sp)
	SREG	x24, 24*REGBYTES(sp)
	SREG	x25, 25*REGBYTES(sp)
	SREG	x26, 26*REGBYTES(sp)
	SREG	x27, 27*REGBYTES(sp)
	SREG	x28, 28*REGBYTES(sp)
	SREG	x29, 29*REGBYTES(sp)
	SREG	x30, 30*REGBYTES(sp)
	SREG	x31, 31*REGBYTES(sp)
	csrr	a0, mcause
	csrr	a1, mepc
	mv	a2, sp
	jal	handle_trap
	csrw	mepc, a0

/*
 * Remain in M-mode after mret
 */
	li	t0, MSTATUS_MPP
	csrs	mstatus, t0
	LREG	x1, 1*REGBYTES(sp)
	LREG	x2, 2*REGBYTES(sp)
	LREG	x3, 3*REGBYTES(sp)
	LREG	x4, 4*REGBYTES(sp)
	LREG	x5, 5*REGBYTES(sp)
	LREG	x6, 6*REGBYTES(sp)
	LREG	x7, 7*REGBYTES(sp)
	LREG	x8, 8*REGBYTES(sp)
	LREG	x9, 9*REGBYTES(sp)
	LREG	x10, 10*REGBYTES(sp)
	LREG	x11, 11*REGBYTES(sp)
	LREG	x12, 12*REGBYTES(sp)
	LREG	x13, 13*REGBYTES(sp)
	LREG	x14, 14*REGBYTES(sp)
	LREG	x15, 15*REGBYTES(sp)
	LREG	x16, 16*REGBYTES(sp)
	LREG	x17, 17*REGBYTES(sp)
	LREG	x18, 18*REGBYTES(sp)
	LREG	x19, 19*REGBYTES(sp)
	LREG	x20, 20*REGBYTES(sp)
	LREG	x21, 21*REGBYTES(sp)
	LREG	x22, 22*REGBYTES(sp)
	LREG	x23, 23*REGBYTES(sp)
	LREG	x24, 24*REGBYTES(sp)
	LREG	x25, 25*REGBYTES(sp)
	LREG	x26, 26*REGBYTES(sp)
	LREG	x27, 27*REGBYTES(sp)
	LREG	x28, 28*REGBYTES(sp)
	LREG	x29, 29*REGBYTES(sp)
	LREG	x30, 30*REGBYTES(sp)
	LREG	x31, 31*REGBYTES(sp)
	addi	sp, sp, 32*REGBYTES
	mret