xref: /freebsd-src/sys/riscv/riscv/locore.S (revision da327cd22e88f26f6cab9d4c45805b512139aa11)
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	/* Get the physical address kernel loaded to */
57	la	t0, virt_map
58	ld	t1, 0(t0)
59	sub	t1, t1, t0
60	li	t2, KERNBASE
61	sub	s9, t2, t1	/* s9 = physmem base */
62
63	/*
64	 * a0 = hart id
65	 * a1 = dtbp
66	 */
67
68	/* Pick a hart to run the boot process. */
69	la	t0, hart_lottery
70	li	t1, 1
71	amoadd.w t0, t1, 0(t0)
72
73	/*
74	 * We must jump to mpentry in the non-BSP case because the offset is
75	 * too large to fit in a 12-bit branch immediate.
76	 */
77	beqz	t0, 1f
78	j	mpentry
79
80	/*
81	 * Page tables
82	 */
831:
84	/* Add L1 entry for kernel */
85	la	s1, pagetable_l1
86	la	s2, pagetable_l2	/* Link to next level PN */
87	srli	s2, s2, PAGE_SHIFT
88
89	li	a5, KERNBASE
90	srli	a5, a5, L1_SHIFT	/* >> L1_SHIFT */
91	andi	a5, a5, 0x1ff		/* & 0x1ff */
92	li	t4, PTE_V
93	slli	t5, s2, PTE_PPN0_S	/* (s2 << PTE_PPN0_S) */
94	or	t6, t4, t5
95
96	/* Store L1 PTE entry to position */
97	li	a6, PTE_SIZE
98	mulw	a5, a5, a6
99	add	t0, s1, a5
100	sd	t6, (t0)
101
102	/* Level 2 superpages (512 x 2MiB) */
103	la	s1, pagetable_l2
104	srli	t4, s9, 21		/* Div physmem base by 2 MiB */
105	li	t2, 512			/* Build 512 entries */
106	add	t3, t4, t2
107	li	t5, 0
1082:
109	li	t0, (PTE_KERN | PTE_X)
110	slli	t2, t4, PTE_PPN1_S	/* << PTE_PPN1_S */
111	or	t5, t0, t2
112	sd	t5, (s1)		/* Store PTE entry to position */
113	addi	s1, s1, PTE_SIZE
114
115	addi	t4, t4, 1
116	bltu	t4, t3, 2b
117
118	/* Create an L1 page for early devmap */
119	la	s1, pagetable_l1
120	la	s2, pagetable_l2_devmap	/* Link to next level PN */
121	srli	s2, s2, PAGE_SHIFT
122
123	li	a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE)
124	srli	a5, a5, L1_SHIFT	/* >> L1_SHIFT */
125	andi	a5, a5, 0x1ff		/* & 0x1ff */
126	li	t4, PTE_V
127	slli	t5, s2, PTE_PPN0_S	/* (s2 << PTE_PPN0_S) */
128	or	t6, t4, t5
129
130	/* Store single level1 PTE entry to position */
131	li	a6, PTE_SIZE
132	mulw	a5, a5, a6
133	add	t0, s1, a5
134	sd	t6, (t0)
135
136	/* Create an L2 page superpage for DTB */
137	la	s1, pagetable_l2_devmap
138	mv	s2, a1
139	srli	s2, s2, PAGE_SHIFT
140
141	li	t0, (PTE_KERN)
142	slli	t2, s2, PTE_PPN0_S	/* << PTE_PPN0_S */
143	or	t0, t0, t2
144
145	/* Store PTE entry to position */
146	li	a6, PTE_SIZE
147	li	a5, 510
148	mulw	a5, a5, a6
149	add	t1, s1, a5
150	sd	t0, (t1)
151
152	/* Page tables END */
153
154	/* Setup supervisor trap vector */
155	la	t0, va
156	sub	t0, t0, s9
157	li	t1, KERNBASE
158	add	t0, t0, t1
159	csrw	stvec, t0
160
161	/* Set page tables base register */
162	la	s2, pagetable_l1
163	srli	s2, s2, PAGE_SHIFT
164	li	t0, SATP_MODE_SV39
165	or	s2, s2, t0
166	sfence.vma
167	csrw	satp, s2
168
169	.align 2
170va:
171
172	/* Setup supervisor trap vector */
173	la	t0, cpu_exception_handler
174	csrw	stvec, t0
175
176	/* Ensure sscratch is zero */
177	li	t0, 0
178	csrw	sscratch, t0
179
180	/* Set the global pointer */
181.option push
182.option norelax
183	la	gp, __global_pointer$
184.option pop
185
186	/* Initialize stack pointer */
187	la	s3, initstack_end
188	mv	sp, s3
189	addi	sp, sp, -PCB_SIZE
190
191	/* Clear BSS */
192	la	s0, _C_LABEL(__bss_start)
193	la	s1, _C_LABEL(_end)
1941:
195	sd	zero, 0(s0)
196	addi	s0, s0, 8
197	bltu	s0, s1, 1b
198
199#ifdef SMP
200	/* Store boot hart id. */
201	la	t0, boot_hart
202	sw	a0, 0(t0)
203#endif
204
205	/* Fill riscv_bootparams */
206	addi	sp, sp, -40
207
208	la	t0, pagetable_l1
209	sd	t0, 0(sp) /* kern_l1pt */
210	sd	s9, 8(sp) /* kern_phys */
211
212	la	t0, initstack_end
213	sd	t0, 16(sp) /* kern_stack */
214
215	li	t0, (VM_MAX_KERNEL_ADDRESS - 2 * L2_SIZE)
216	sd	t0, 24(sp) /* dtbp_virt */
217	sd	a1, 32(sp) /* dtbp_phys */
218
219	mv	a0, sp
220	call	_C_LABEL(initriscv)	/* Off we go */
221	call	_C_LABEL(mi_startup)
222
223	.align  4
224initstack:
225	.space  (PAGE_SIZE * KSTACK_PAGES)
226initstack_end:
227
228ENTRY(sigcode)
229	mv	a0, sp
230	addi	a0, a0, SF_UC
231
2321:
233	li	t0, SYS_sigreturn
234	ecall
235
236	/* sigreturn failed, exit */
237	li	t0, SYS_exit
238	ecall
239
240	j	1b
241END(sigcode)
242	/* This may be copied to the stack, keep it 16-byte aligned */
243	.align	3
244esigcode:
245
246	.data
247	.align	3
248	.global	szsigcode
249szsigcode:
250	.quad	esigcode - sigcode
251
252	.align	12
253pagetable_l1:
254	.space	PAGE_SIZE
255pagetable_l2:
256	.space	PAGE_SIZE
257pagetable_l2_devmap:
258	.space	PAGE_SIZE
259
260	.align 3
261virt_map:
262	.quad   virt_map
263hart_lottery:
264	.space	4
265
266	.globl init_pt_va
267init_pt_va:
268	.quad pagetable_l2	/* XXX: Keep page tables VA */
269
270#ifndef SMP
271ENTRY(mpentry)
2721:
273	wfi
274	j	1b
275END(mpentry)
276#else
277/*
278 * mpentry(unsigned long)
279 *
280 * Called by a core when it is being brought online.
281 */
282ENTRY(mpentry)
283	/*
284	 * Calculate the offset to __riscv_boot_ap
285	 * for the current core, cpuid is in a0.
286	 */
287	li	t1, 4
288	mulw	t1, t1, a0
289	/* Get the pointer */
290	la	t0, __riscv_boot_ap
291	add	t0, t0, t1
292
2931:
294	/* Wait the kernel to be ready */
295	lw	t1, 0(t0)
296	beqz	t1, 1b
297
298	/* Setup stack pointer */
299	la	t0, secondary_stacks
300	li	t1, (PAGE_SIZE * KSTACK_PAGES)
301	mulw	t2, t1, a0
302	add	t0, t0, t2
303	add	t0, t0, t1
304	sub	t0, t0, s9
305	li	t1, KERNBASE
306	add	sp, t0, t1
307
308	/* Setup supervisor trap vector */
309	la	t0, mpva
310	sub	t0, t0, s9
311	li	t1, KERNBASE
312	add	t0, t0, t1
313	csrw	stvec, t0
314
315	/* Set page tables base register */
316	la	s2, pagetable_l1
317	srli	s2, s2, PAGE_SHIFT
318	li	t0, SATP_MODE_SV39
319	or	s2, s2, t0
320	sfence.vma
321	csrw	satp, s2
322
323	.align 2
324mpva:
325	/* Setup supervisor trap vector */
326	la	t0, cpu_exception_handler
327	csrw	stvec, t0
328
329	/* Ensure sscratch is zero */
330	li	t0, 0
331	csrw	sscratch, t0
332
333	/* Set the global pointer */
334.option push
335.option norelax
336	la	gp, __global_pointer$
337.option pop
338
339	call	init_secondary
340END(mpentry)
341#endif
342