]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/riscv/riscv/locore.S
riscv: catch up with EARLY_PRINTF changes
[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
35 #include "assym.inc"
36
37 #include <sys/syscall.h>
38 #include <machine/asm.h>
39 #include <machine/param.h>
40 #include <machine/trap.h>
41 #include <machine/riscvreg.h>
42 #include <machine/pte.h>
43
44         .globl  kernbase
45         .set    kernbase, KERNBASE
46
47         .text
48 /*
49  * Alternate entry point. Used when booting via SBI firmware. It must be placed
50  * at the beginning of the .text section. Arguments are as follows:
51  *  - a0 = hart ID
52  *  - a1 = dtbp
53  *
54  * Multiple CPUs might enter from this point, so we perform a hart lottery and
55  * send the losers to mpentry.
56  */
57         .globl _alt_start
58 _alt_start:
59         /* Set the global pointer */
60 .option push
61 .option norelax
62         lla     gp, __global_pointer$
63 .option pop
64
65         /* Pick a hart to run the boot process. */
66         lla     t0, hart_lottery
67         li      t1, 1
68         amoadd.w t0, t1, 0(t0)
69
70         /*
71          * We must jump to mpentry in the non-BSP case because the offset is
72          * too large to fit in a 12-bit branch immediate.
73          */
74         beqz    t0, 1f
75         j       mpentry
76 1:
77         /* Store the boot hart */
78         lla     t0, boot_hart
79         sw      a0, 0(t0)
80
81         /* Load zero as modulep */
82         mv      a0, zero
83         j       pagetables
84
85 /*
86  * Main entry point. This routine is marked as the ELF entry, and is where
87  * loader(8) will enter the kernel. Arguments are as follows:
88  *  - a0 = modulep
89  *  - a1 = ???
90  *
91  * It is expected that only a single CPU will enter here.
92  */
93         .globl _start
94 _start:
95         /* Set the global pointer */
96 .option push
97 .option norelax
98         lla     gp, __global_pointer$
99 .option pop
100
101         /*
102          * Zero a1 to indicate that we have no DTB pointer. It is already
103          * included in the loader(8) metadata.
104          */
105         mv      a1, zero
106
107         /*
108          * Set up page tables: map a 1GB region starting at KERNBASE using 2MB
109          * superpages, starting from the first 2MB physical page into which the
110          * kernel was loaded.  Also reserve an L2 page for the early device map
111          * and map the DTB, if any, using the second-last entry of that L2
112          * page.  This is hopefully enough to get us to pmap_bootstrap().
113          *
114          * Implementations are required to provide SV39 mode, so we use that
115          * initially and will optionally enable SV48 mode during kernel pmap
116          * initialization.
117          *
118          *  a0 - modulep or zero
119          *  a1 - zero or dtbp
120          */
121 pagetables:
122         /* Get the kernel's load address */
123         jal     get_physmem
124
125         /* Add L1 entry for kernel */
126         lla     s1, pagetable_l1
127         lla     s2, pagetable_l2        /* Link to next level PN */
128         srli    s2, s2, PAGE_SHIFT
129
130         li      a5, KERNBASE
131         srli    a5, a5, L1_SHIFT        /* >> L1_SHIFT */
132         andi    a5, a5, Ln_ADDR_MASK    /* & Ln_ADDR_MASK */
133         li      t4, PTE_V
134         slli    t5, s2, PTE_PPN0_S      /* (s2 << PTE_PPN0_S) */
135         or      t6, t4, t5
136
137         /* Store L1 PTE entry to position */
138         li      a6, PTE_SIZE
139         mulw    a5, a5, a6
140         add     t0, s1, a5
141         sd      t6, (t0)
142
143         /* Level 2 superpages (512 x 2MiB) */
144         lla     s1, pagetable_l2
145         srli    t4, s9, L2_SHIFT        /* Div physmem base by 2 MiB */
146         li      t2, 512                 /* Build 512 entries */
147         add     t3, t4, t2
148         li      t0, (PTE_KERN | PTE_X)
149 1:
150         slli    t2, t4, PTE_PPN1_S      /* << PTE_PPN1_S */
151         or      t5, t0, t2
152         sd      t5, (s1)                /* Store PTE entry to position */
153         addi    s1, s1, PTE_SIZE
154
155         addi    t4, t4, 1
156         bltu    t4, t3, 1b
157
158         /* Create an L1 table entry for early devmap */
159         lla     s1, pagetable_l1
160         lla     s2, pagetable_l2_devmap /* Link to next level PN */
161         srli    s2, s2, PAGE_SHIFT
162
163         li      a5, (VM_MAX_KERNEL_ADDRESS - PMAP_MAPDEV_EARLY_SIZE)
164         srli    a5, a5, L1_SHIFT        /* >> L1_SHIFT */
165         andi    a5, a5, Ln_ADDR_MASK    /* & Ln_ADDR_MASK */
166         li      t4, PTE_V
167         slli    t5, s2, PTE_PPN0_S      /* (s2 << PTE_PPN0_S) */
168         or      t6, t4, t5
169
170         /* Store the L1 table entry */
171         li      a6, PTE_SIZE
172         mulw    a5, a5, a6
173         add     t0, s1, a5
174         sd      t6, (t0)
175
176         /* Check if we have a DTB that needs to be mapped */
177         beqz    a1, 2f
178
179         /* Create an L2 mapping for the DTB */
180         lla     s1, pagetable_l2_devmap
181         mv      s2, a1
182         srli    s2, s2, PAGE_SHIFT
183         /* Mask off any bits that aren't aligned */
184         andi    s2, s2, ~((1 << (PTE_PPN1_S - PTE_PPN0_S)) - 1)
185
186         li      t0, (PTE_KERN)
187         slli    t2, s2, PTE_PPN0_S      /* << PTE_PPN0_S */
188         or      t0, t0, t2
189
190         /* Store the L2 table entry for the DTB */
191         li      a6, PTE_SIZE
192         li      a5, VM_EARLY_DTB_ADDRESS
193         srli    a5, a5, L2_SHIFT    /* >> L2_SHIFT */
194         andi    a5, a5, Ln_ADDR_MASK    /* & Ln_ADDR_MASK */
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