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 .text
50 /*
51 * Alternate entry point. Used when booting via SBI firmware. It must be placed
52 * at the beginning of the .text section. Arguments are as follows:
53 * - a0 = hart ID
54 * - a1 = dtbp
55 *
56 * Multiple CPUs might enter from this point, so we perform a hart lottery and
57 * send the losers to mpentry.
58 */
59 .globl _alt_start
60 _alt_start:
61 /* Set the global pointer */
62 .option push
63 .option norelax
64 lla gp, __global_pointer$
65 .option pop
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 1:
79 /* Store the boot hart */
80 lla t0, boot_hart
81 sw a0, 0(t0)
82
83 /* Load zero as modulep */
84 mv a0, zero
85 j pagetables
86
87 /*
88 * Main entry point. This routine is marked as the ELF entry, and is where
89 * loader(8) will enter the kernel. Arguments are as follows:
90 * - a0 = modulep
91 * - a1 = ???
92 *
93 * It is expected that only a single CPU will enter here.
94 */
95 .globl _start
96 _start:
97 /* Set the global pointer */
98 .option push
99 .option norelax
100 lla gp, __global_pointer$
101 .option pop
102
103 /*
104 * Zero a1 to indicate that we have no DTB pointer. It is already
105 * included in the loader(8) metadata.
106 */
107 mv a1, zero
108
109 /*
110 * Set up page tables: map a 1GB region starting at KERNBASE using 2MB
111 * superpages, starting from the first 2MB physical page into which the
112 * kernel was loaded. Also reserve an L2 page for the early device map
113 * and map the DTB, if any, using the second-last entry of that L2
114 * page. This is hopefully enough to get us to pmap_bootstrap().
115 *
116 * Implementations are required to provide SV39 mode, so we use that
117 * initially and will optionally enable SV48 mode during kernel pmap
118 * initialization.
119 *
120 * a0 - modulep or zero
121 * a1 - zero or dtbp
122 */
123 pagetables:
124 /* Get the kernel's load address */
125 jal get_physmem
126
127 /* Add L1 entry for kernel */
128 lla s1, pagetable_l1
129 lla s2, pagetable_l2 /* Link to next level PN */
130 srli s2, s2, PAGE_SHIFT
131
132 li a5, KERNBASE
133 srli a5, a5, L1_SHIFT /* >> L1_SHIFT */
134 andi a5, a5, Ln_ADDR_MASK /* & Ln_ADDR_MASK */
135 li t4, PTE_V
136 slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
137 or t6, t4, t5
138
139 /* Store L1 PTE entry to position */
140 li a6, PTE_SIZE
141 mulw a5, a5, a6
142 add t0, s1, a5
143 sd t6, (t0)
144
145 /* Level 2 superpages (512 x 2MiB) */
146 lla s1, pagetable_l2
147 srli t4, s9, L2_SHIFT /* Div physmem base by 2 MiB */
148 li t2, 512 /* Build 512 entries */
149 add t3, t4, t2
150 li t0, (PTE_KERN | PTE_X)
151 1:
152 slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */
153 or t5, t0, t2
154 sd t5, (s1) /* Store PTE entry to position */
155 addi s1, s1, PTE_SIZE
156
157 addi t4, t4, 1
158 bltu t4, t3, 1b
159
160 /* Create an L1 table entry for early devmap */
161 lla s1, pagetable_l1
162 lla s2, pagetable_l2_devmap /* Link to next level PN */
163 srli s2, s2, PAGE_SHIFT
164
165 li a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE)
166 srli a5, a5, L1_SHIFT /* >> L1_SHIFT */
167 andi a5, a5, Ln_ADDR_MASK /* & Ln_ADDR_MASK */
168 li t4, PTE_V
169 slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
170 or t6, t4, t5
171
172 /* Store the L1 table entry */
173 li a6, PTE_SIZE
174 mulw a5, a5, a6
175 add t0, s1, a5
176 sd t6, (t0)
177
178 /* Check if we have a DTB that needs to be mapped */
179 beqz a1, 2f
180
181 /* Create an L2 mapping for the DTB */
182 lla s1, pagetable_l2_devmap
183 mv s2, a1
184 srli s2, s2, PAGE_SHIFT
185 /* Mask off any bits that aren't aligned */
186 andi s2, s2, ~((1 << (PTE_PPN1_S - PTE_PPN0_S)) - 1)
187
188 li t0, (PTE_KERN)
189 slli t2, s2, PTE_PPN0_S /* << PTE_PPN0_S */
190 or t0, t0, t2
191
192 /* Store the L2 table entry for the DTB */
193 li a6, PTE_SIZE
194 li a5, 510
195 mulw a5, a5, a6
196 add t1, s1, a5
197 sd t0, (t1)
198
199 /* Page tables END */
200
201 /* Setup supervisor trap vector */
202 2:
203 lla t0, va
204 sub t0, t0, s9
205 li t1, KERNBASE
206 add t0, t0, t1
207 csrw stvec, t0
208
209 /* Set page tables base register */
210 lla s2, pagetable_l1
211 srli s2, s2, PAGE_SHIFT
212 li t0, SATP_MODE_SV39
213 or s2, s2, t0
214 sfence.vma
215 csrw satp, s2
216
217 .align 2
218 va:
219 /* Set the global pointer again, this time with the virtual address. */
220 .option push
221 .option norelax
222 lla gp, __global_pointer$
223 .option pop
224
225 /* Setup supervisor trap vector */
226 la t0, cpu_exception_handler
227 csrw stvec, t0
228
229 /* Ensure sscratch is zero */
230 li t0, 0
231 csrw sscratch, t0
232
233 /* Initialize stack pointer */
234 la sp, initstack_end
235
236 /* Clear frame pointer */
237 mv s0, zero
238
239 /* Allocate space for thread0 PCB and riscv_bootparams */
240 addi sp, sp, -(PCB_SIZE + RISCV_BOOTPARAMS_SIZE) & ~STACKALIGNBYTES
241
242 /* Clear BSS */
243 la t0, _C_LABEL(__bss_start)
244 la t1, _C_LABEL(_end)
245 1:
246 sd zero, 0(t0)
247 addi t0, t0, 8
248 bltu t0, t1, 1b
249
250 /* Fill riscv_bootparams */
251 la t0, pagetable_l1
252 sd t0, RISCV_BOOTPARAMS_KERN_L1PT(sp)
253 sd s9, RISCV_BOOTPARAMS_KERN_PHYS(sp)
254
255 la t0, initstack
256 sd t0, RISCV_BOOTPARAMS_KERN_STACK(sp)
257
258 li t0, (VM_EARLY_DTB_ADDRESS)
259 /* Add offset of DTB within superpage */
260 li t1, (L2_OFFSET)
261 and t1, a1, t1
262 add t0, t0, t1
263 sd t0, RISCV_BOOTPARAMS_DTBP_VIRT(sp)
264 sd a1, RISCV_BOOTPARAMS_DTBP_PHYS(sp)
265
266 sd a0, RISCV_BOOTPARAMS_MODULEP(sp)
267
268 mv a0, sp
269 call _C_LABEL(initriscv) /* Off we go */
270 call _C_LABEL(mi_startup)
271
272 /* We should never reach here, but if so just hang. */
273 2:
274 wfi
275 j 2b
276
277 /*
278 * Get the physical address the kernel is loaded to. Returned in s9.
279 */
280 get_physmem:
281 lla t0, virt_map /* physical address of virt_map */
282 ld t1, 0(t0) /* virtual address of virt_map */
283 sub t1, t1, t0 /* calculate phys->virt delta */
284 li t2, KERNBASE
285 sub s9, t2, t1 /* s9 = physmem base */
286 ret
287
288 .align 4
289 initstack:
290 .space (PAGE_SIZE * KSTACK_PAGES)
291 initstack_end:
292
293 ENTRY(sigcode)
294 mv a0, sp
295 addi a0, a0, SF_UC
296
297 1:
298 li t0, SYS_sigreturn
299 ecall
300
301 /* sigreturn failed, exit */
302 li t0, SYS_exit
303 ecall
304
305 j 1b
306 END(sigcode)
307 /* This may be copied to the stack, keep it 16-byte aligned */
308 .align 3
309 esigcode:
310
311 .data
312 .align 3
313 .global szsigcode
314 szsigcode:
315 .quad esigcode - sigcode
316
317 .align 12
318 pagetable_l1:
319 .space PAGE_SIZE
320 pagetable_l2:
321 .space PAGE_SIZE
322 pagetable_l2_devmap:
323 .space PAGE_SIZE
324
325 .align 3
326 virt_map:
327 .quad virt_map
328 hart_lottery:
329 .space 4
330
331 .globl init_pt_va
332 init_pt_va:
333 .quad pagetable_l2 /* XXX: Keep page tables VA */
334
335 #ifndef SMP
336 ENTRY(mpentry)
337 1:
338 wfi
339 j 1b
340 END(mpentry)
341 #else
342 /*
343 * mpentry(unsigned long)
344 *
345 * Called by a core when it is being brought online.
346 */
347 ENTRY(mpentry)
348 /*
349 * Calculate the offset to __riscv_boot_ap
350 * for the current core, cpuid is in a0.
351 */
352 li t1, 4
353 mulw t1, t1, a0
354 /* Get the pointer */
355 lla t0, __riscv_boot_ap
356 add t0, t0, t1
357
358 1:
359 /* Wait the kernel to be ready */
360 lw t1, 0(t0)
361 beqz t1, 1b
362
363 /* Setup stack pointer */
364 lla t0, bootstack
365 ld sp, 0(t0)
366
367 /* Get the kernel's load address */
368 jal get_physmem
369
370 /* Setup supervisor trap vector */
371 lla t0, mpva
372 sub t0, t0, s9
373 li t1, KERNBASE
374 add t0, t0, t1
375 csrw stvec, t0
376
377 /* Set page tables base register */
378 lla s2, pagetable_l1
379 srli s2, s2, PAGE_SHIFT
380 li t0, SATP_MODE_SV39
381 or s2, s2, t0
382 sfence.vma
383 csrw satp, s2
384
385 .align 2
386 mpva:
387 /* Set the global pointer again, this time with the virtual address. */
388 .option push
389 .option norelax
390 lla gp, __global_pointer$
391 .option pop
392
393 /* Setup supervisor trap vector */
394 la t0, cpu_exception_handler
395 csrw stvec, t0
396
397 /* Ensure sscratch is zero */
398 li t0, 0
399 csrw sscratch, t0
400
401 call init_secondary
402 END(mpentry)
403 #endif
Cache object: bc7bb94896192bd3c1ccb6443f1e84a6
|