xref: /freebsd/sys/riscv/riscv/locore.S (revision 4f52dfbb)
1/*-
2 * Copyright (c) 2015-2017 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	mv	s10, a0		/* s10 = hart id */
63	mv	s11, a1		/* s11 = dtbp */
64
65	li	t0, SSTATUS_SUM
66	csrs	sstatus, t0
67
68	/* Direct secondary cores to mpentry */
69	bnez	s10, mpentry
70
71	/*
72	 * Page tables
73	 */
74
75	/* Add L1 entry for kernel */
76	la	s1, pagetable_l1
77	la	s2, pagetable_l2	/* Link to next level PN */
78	srli	s2, s2, PAGE_SHIFT
79
80	li	a5, KERNBASE
81	srli	a5, a5, L1_SHIFT	/* >> L1_SHIFT */
82	andi	a5, a5, 0x1ff		/* & 0x1ff */
83	li	t4, PTE_V
84	slli	t5, s2, PTE_PPN0_S	/* (s2 << PTE_PPN0_S) */
85	or	t6, t4, t5
86
87	/* Store L1 PTE entry to position */
88	li	a6, PTE_SIZE
89	mulw	a5, a5, a6
90	add	t0, s1, a5
91	sd	t6, (t0)
92
93	/* Level 2 superpages (512 x 2MiB) */
94	la	s1, pagetable_l2
95	srli	t4, s9, 21		/* Div physmem base by 2 MiB */
96	li	t2, 512			/* Build 512 entries */
97	add	t3, t4, t2
98	li	t5, 0
992:
100	li	t0, (PTE_V | PTE_RWX | PTE_D)
101	slli	t2, t4, PTE_PPN1_S	/* << PTE_PPN1_S */
102	or	t5, t0, t2
103	sd	t5, (s1)		/* Store PTE entry to position */
104	addi	s1, s1, PTE_SIZE
105
106	addi	t4, t4, 1
107	bltu	t4, t3, 2b
108
109	/* Create an L1 page for early devmap */
110	la	s1, pagetable_l1
111	la	s2, pagetable_l2_devmap	/* Link to next level PN */
112	srli	s2, s2, PAGE_SHIFT
113
114	li	a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE)
115	srli	a5, a5, L1_SHIFT	/* >> L1_SHIFT */
116	andi	a5, a5, 0x1ff		/* & 0x1ff */
117	li	t4, PTE_V
118	slli	t5, s2, PTE_PPN0_S	/* (s2 << PTE_PPN0_S) */
119	or	t6, t4, t5
120
121	/* Store single level1 PTE entry to position */
122	li	a6, PTE_SIZE
123	mulw	a5, a5, a6
124	add	t0, s1, a5
125	sd	t6, (t0)
126
127	/* Create an L2 page superpage for DTB */
128	la	s1, pagetable_l2_devmap
129	mv	s2, s11
130	srli	s2, s2, PAGE_SHIFT
131
132	li	t0, (PTE_V | PTE_RWX | PTE_D)
133	slli	t2, s2, PTE_PPN0_S	/* << PTE_PPN0_S */
134	or	t0, t0, t2
135
136	/* Store PTE entry to position */
137	li	a6, PTE_SIZE
138	li	a5, 510
139	mulw	a5, a5, a6
140	add	t1, s1, a5
141	sd	t0, (t1)
142
143	/* Page tables END */
144
145	/* Setup supervisor trap vector */
146	la	t0, va
147	sub	t0, t0, s9
148	li	t1, KERNBASE
149	add	t0, t0, t1
150	csrw	stvec, t0
151
152	/* Set page tables base register */
153	la	s2, pagetable_l1
154	srli	s2, s2, PAGE_SHIFT
155	li	t0, SATP_MODE_SV39
156	or	s2, s2, t0
157	sfence.vma
158	csrw	sptbr, s2
159va:
160
161	/* Setup supervisor trap vector */
162	la	t0, cpu_exception_handler
163	csrw	stvec, t0
164
165	/* Ensure sscratch is zero */
166	li	t0, 0
167	csrw	sscratch, t0
168
169	/* Initialize stack pointer */
170	la	s3, initstack_end
171	mv	sp, s3
172	addi	sp, sp, -PCB_SIZE
173
174	/* Clear BSS  */
175	la	a0, _C_LABEL(__bss_start)
176	la	s1, _C_LABEL(_end)
1771:
178	sd	zero, 0(a0)
179	addi	a0, a0, 8
180	bltu	a0, s1, 1b
181
182	/* Fill riscv_bootparams */
183	addi	sp, sp, -40
184
185	la	t0, pagetable_l1
186	sd	t0, 0(sp) /* kern_l1pt */
187	sd	s9, 8(sp) /* kern_phys */
188
189	la	t0, initstack_end
190	sd	t0, 16(sp) /* kern_stack */
191
192	li	t0, (VM_MAX_KERNEL_ADDRESS - 2 * L2_SIZE)
193	sd	t0, 24(sp) /* dtbp_virt */
194	sd	s11, 32(sp) /* dtbp_phys */
195
196	mv	a0, sp
197	call	_C_LABEL(initriscv)	/* Off we go */
198	call	_C_LABEL(mi_startup)
199
200	.align  4
201initstack:
202	.space  (PAGE_SIZE * KSTACK_PAGES)
203initstack_end:
204
205ENTRY(sigcode)
206	mv	a0, sp
207	addi	a0, a0, SF_UC
208
2091:
210	li	t0, SYS_sigreturn
211	ecall
212
213	/* sigreturn failed, exit */
214	li	t0, SYS_exit
215	ecall
216
217	j	1b
218END(sigcode)
219	/* This may be copied to the stack, keep it 16-byte aligned */
220	.align	3
221esigcode:
222
223	.data
224	.align	3
225	.global	szsigcode
226szsigcode:
227	.quad	esigcode - sigcode
228
229	.align	12
230pagetable_l1:
231	.space	PAGE_SIZE
232pagetable_l2:
233	.space	PAGE_SIZE
234pagetable_l2_devmap:
235	.space	PAGE_SIZE
236
237        .align 3
238virt_map:
239        .quad   virt_map
240
241	/* Not in use, but required for linking. */
242	.align 3
243	.globl __global_pointer$
244__global_pointer$:
245	.space	8
246
247	.globl init_pt_va
248init_pt_va:
249	.quad pagetable_l2	/* XXX: Keep page tables VA */
250
251#ifndef SMP
252ENTRY(mpentry)
2531:
254	wfi
255	j	1b
256END(mpentry)
257#else
258/*
259 * mpentry(unsigned long)
260 *
261 * Called by a core when it is being brought online.
262 */
263ENTRY(mpentry)
264	/* Setup stack pointer */
265	la	t0, secondary_stacks
266	li	t1, (PAGE_SIZE * KSTACK_PAGES)
267	mulw	t1, t1, s10
268	add	t0, t0, t1
269	sub	t0, t0, s9
270	li	t1, KERNBASE
271	add	sp, t0, t1
272
273	/* Setup supervisor trap vector */
274	la	t0, mpva
275	sub	t0, t0, s9
276	li	t1, KERNBASE
277	add	t0, t0, t1
278	csrw	stvec, t0
279
280	/* Set page tables base register */
281	la	s2, pagetable_l1
282	srli	s2, s2, PAGE_SHIFT
283	li	t0, SATP_MODE_SV39
284	or	s2, s2, t0
285	sfence.vma
286	csrw	sptbr, s2
287mpva:
288	/* Setup supervisor trap vector */
289	la	t0, cpu_exception_handler
290	csrw	stvec, t0
291
292	/* Ensure sscratch is zero */
293	li	t0, 0
294	csrw	sscratch, t0
295	/*
296	 * Calculate the offset to __riscv_boot_ap
297	 * for current core, cpuid in a0.
298	 */
299	li	t1, 4
300	mulw	t1, t1, a0
301	/* Get pointer */
302	la	t0, __riscv_boot_ap
303	add	t0, t0, t1
304
3051:
306	/* Wait the kernel to be ready */
307	lw	t1, 0(t0)
308	beqz	t1, 1b
309
310	call	init_secondary
311END(mpentry)
312#endif
313