xref: /freebsd/sys/riscv/riscv/locore.S (revision a3557ef0)
1/*-
2 * Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com>
3 * All rights reserved.
4 *
5 * Portions of this software were developed by SRI International and the
6 * University of Cambridge Computer Laboratory under DARPA/AFRL contract
7 * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
8 *
9 * Portions of this software were developed by the University of Cambridge
10 * Computer Laboratory as part of the CTSRD Project, with support from the
11 * UK Higher Education Innovation Fund (HEIF).
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $FreeBSD$
35 */
36
37#include "assym.inc"
38
39#include <sys/syscall.h>
40#include <machine/asm.h>
41#include <machine/param.h>
42#include <machine/trap.h>
43#include <machine/riscvreg.h>
44#include <machine/pte.h>
45
46	.globl	kernbase
47	.set	kernbase, KERNBASE
48
49	/* Trap entries */
50	.text
51
52	/* Reset vector */
53	.text
54	.globl _start
55_start:
56	/* Set the global pointer */
57.option push
58.option norelax
59	lla	gp, __global_pointer$
60.option pop
61
62	/*
63	 * a0 = hart id
64	 * a1 = dtbp
65	 */
66
67	/* Pick a hart to run the boot process. */
68	lla	t0, hart_lottery
69	li	t1, 1
70	amoadd.w t0, t1, 0(t0)
71
72	/*
73	 * We must jump to mpentry in the non-BSP case because the offset is
74	 * too large to fit in a 12-bit branch immediate.
75	 */
76	beqz	t0, 1f
77	j	mpentry
78
79	/*
80	 * Page tables
81	 */
821:
83	/* Get the kernel's load address */
84	jal	get_physmem
85
86	/* Add L1 entry for kernel */
87	lla	s1, pagetable_l1
88	lla	s2, pagetable_l2	/* Link to next level PN */
89	srli	s2, s2, PAGE_SHIFT
90
91	li	a5, KERNBASE
92	srli	a5, a5, L1_SHIFT	/* >> L1_SHIFT */
93	andi	a5, a5, 0x1ff		/* & 0x1ff */
94	li	t4, PTE_V
95	slli	t5, s2, PTE_PPN0_S	/* (s2 << PTE_PPN0_S) */
96	or	t6, t4, t5
97
98	/* Store L1 PTE entry to position */
99	li	a6, PTE_SIZE
100	mulw	a5, a5, a6
101	add	t0, s1, a5
102	sd	t6, (t0)
103
104	/* Level 2 superpages (512 x 2MiB) */
105	lla	s1, pagetable_l2
106	srli	t4, s9, 21		/* Div physmem base by 2 MiB */
107	li	t2, 512			/* Build 512 entries */
108	add	t3, t4, t2
109	li	t5, 0
1102:
111	li	t0, (PTE_KERN | PTE_X)
112	slli	t2, t4, PTE_PPN1_S	/* << PTE_PPN1_S */
113	or	t5, t0, t2
114	sd	t5, (s1)		/* Store PTE entry to position */
115	addi	s1, s1, PTE_SIZE
116
117	addi	t4, t4, 1
118	bltu	t4, t3, 2b
119
120	/* Create an L1 page for early devmap */
121	lla	s1, pagetable_l1
122	lla	s2, pagetable_l2_devmap	/* Link to next level PN */
123	srli	s2, s2, PAGE_SHIFT
124
125	li	a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE)
126	srli	a5, a5, L1_SHIFT	/* >> L1_SHIFT */
127	andi	a5, a5, 0x1ff		/* & 0x1ff */
128	li	t4, PTE_V
129	slli	t5, s2, PTE_PPN0_S	/* (s2 << PTE_PPN0_S) */
130	or	t6, t4, t5
131
132	/* Store single level1 PTE entry to position */
133	li	a6, PTE_SIZE
134	mulw	a5, a5, a6
135	add	t0, s1, a5
136	sd	t6, (t0)
137
138	/* Create an L2 page superpage for DTB */
139	lla	s1, pagetable_l2_devmap
140	mv	s2, a1
141	srli	s2, s2, PAGE_SHIFT
142	/* Mask off any bits that aren't aligned */
143	andi	s2, s2, ~((1 << (PTE_PPN1_S - PTE_PPN0_S)) - 1)
144
145	li	t0, (PTE_KERN)
146	slli	t2, s2, PTE_PPN0_S	/* << PTE_PPN0_S */
147	or	t0, t0, t2
148
149	/* Store PTE entry to position */
150	li	a6, PTE_SIZE
151	li	a5, 510
152	mulw	a5, a5, a6
153	add	t1, s1, a5
154	sd	t0, (t1)
155
156	/* Page tables END */
157
158	/* Setup supervisor trap vector */
159	lla	t0, va
160	sub	t0, t0, s9
161	li	t1, KERNBASE
162	add	t0, t0, t1
163	csrw	stvec, t0
164
165	/* Set page tables base register */
166	lla	s2, pagetable_l1
167	srli	s2, s2, PAGE_SHIFT
168	li	t0, SATP_MODE_SV39
169	or	s2, s2, t0
170	sfence.vma
171	csrw	satp, s2
172
173	.align 2
174va:
175	/* Set the global pointer again, this time with the virtual address. */
176.option push
177.option norelax
178	lla	gp, __global_pointer$
179.option pop
180
181	/* Setup supervisor trap vector */
182	la	t0, cpu_exception_handler
183	csrw	stvec, t0
184
185	/* Ensure sscratch is zero */
186	li	t0, 0
187	csrw	sscratch, t0
188
189	/* Initialize stack pointer */
190	la	s3, initstack_end
191	mv	sp, s3
192
193	/* Allocate space for thread0 PCB and riscv_bootparams */
194	addi	sp, sp, -(PCB_SIZE + RISCV_BOOTPARAMS_SIZE) & ~STACKALIGNBYTES
195
196	/* Clear BSS */
197	la	s0, _C_LABEL(__bss_start)
198	la	s1, _C_LABEL(_end)
1991:
200	sd	zero, 0(s0)
201	addi	s0, s0, 8
202	bltu	s0, s1, 1b
203
204#ifdef SMP
205	/* Store boot hart id. */
206	la	t0, boot_hart
207	sw	a0, 0(t0)
208#endif
209
210	/* Fill riscv_bootparams */
211	la	t0, pagetable_l1
212	sd	t0, RISCV_BOOTPARAMS_KERN_L1PT(sp)
213	sd	s9, RISCV_BOOTPARAMS_KERN_PHYS(sp)
214
215	la	t0, initstack
216	sd	t0, RISCV_BOOTPARAMS_KERN_STACK(sp)
217
218	li	t0, (VM_EARLY_DTB_ADDRESS)
219	/* Add offset of DTB within superpage */
220	li	t1, (L2_OFFSET)
221	and	t1, a1, t1
222	add	t0, t0, t1
223	sd	t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp)
224	sd	a1, RISCV_BOOTPARAMS_DTBP_PHYS(sp)
225
226	mv	a0, sp
227	call	_C_LABEL(initriscv)	/* Off we go */
228	call	_C_LABEL(mi_startup)
229
230/*
231 * Get the physical address the kernel is loaded to. Returned in s9.
232 */
233get_physmem:
234	lla	t0, virt_map	/* physical address of virt_map */
235	ld	t1, 0(t0)	/* virtual address of virt_map */
236	sub	t1, t1, t0	/* calculate phys->virt delta */
237	li	t2, KERNBASE
238	sub	s9, t2, t1	/* s9 = physmem base */
239	ret
240
241	.align  4
242initstack:
243	.space  (PAGE_SIZE * KSTACK_PAGES)
244initstack_end:
245
246ENTRY(sigcode)
247	mv	a0, sp
248	addi	a0, a0, SF_UC
249
2501:
251	li	t0, SYS_sigreturn
252	ecall
253
254	/* sigreturn failed, exit */
255	li	t0, SYS_exit
256	ecall
257
258	j	1b
259END(sigcode)
260	/* This may be copied to the stack, keep it 16-byte aligned */
261	.align	3
262esigcode:
263
264	.data
265	.align	3
266	.global	szsigcode
267szsigcode:
268	.quad	esigcode - sigcode
269
270	.align	12
271pagetable_l1:
272	.space	PAGE_SIZE
273pagetable_l2:
274	.space	PAGE_SIZE
275pagetable_l2_devmap:
276	.space	PAGE_SIZE
277
278	.align 3
279virt_map:
280	.quad   virt_map
281hart_lottery:
282	.space	4
283
284	.globl init_pt_va
285init_pt_va:
286	.quad pagetable_l2	/* XXX: Keep page tables VA */
287
288#ifndef SMP
289ENTRY(mpentry)
2901:
291	wfi
292	j	1b
293END(mpentry)
294#else
295/*
296 * mpentry(unsigned long)
297 *
298 * Called by a core when it is being brought online.
299 */
300ENTRY(mpentry)
301	/*
302	 * Calculate the offset to __riscv_boot_ap
303	 * for the current core, cpuid is in a0.
304	 */
305	li	t1, 4
306	mulw	t1, t1, a0
307	/* Get the pointer */
308	lla	t0, __riscv_boot_ap
309	add	t0, t0, t1
310
3111:
312	/* Wait the kernel to be ready */
313	lw	t1, 0(t0)
314	beqz	t1, 1b
315
316	/* Setup stack pointer */
317	lla	t0, bootstack
318	ld	sp, 0(t0)
319
320	/* Get the kernel's load address */
321	jal get_physmem
322
323	/* Setup supervisor trap vector */
324	lla	t0, mpva
325	sub	t0, t0, s9
326	li	t1, KERNBASE
327	add	t0, t0, t1
328	csrw	stvec, t0
329
330	/* Set page tables base register */
331	lla	s2, pagetable_l1
332	srli	s2, s2, PAGE_SHIFT
333	li	t0, SATP_MODE_SV39
334	or	s2, s2, t0
335	sfence.vma
336	csrw	satp, s2
337
338	.align 2
339mpva:
340	/* Set the global pointer again, this time with the virtual address. */
341.option push
342.option norelax
343	lla	gp, __global_pointer$
344.option pop
345
346	/* Setup supervisor trap vector */
347	la	t0, cpu_exception_handler
348	csrw	stvec, t0
349
350	/* Ensure sscratch is zero */
351	li	t0, 0
352	csrw	sscratch, t0
353
354	call	init_secondary
355END(mpentry)
356#endif
357