]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/riscv/riscv/locore.S
zfs: merge openzfs/zfs@e25f9131d (zfs-2.1-release) into stable/13
[FreeBSD/FreeBSD.git] / sys / riscv / riscv / locore.S
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