locore.S revision 295972
1295041Sbr/*-
2295972Sbr * Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
3295041Sbr * All rights reserved.
4295041Sbr *
5295041Sbr * Portions of this software were developed by SRI International and the
6295041Sbr * University of Cambridge Computer Laboratory under DARPA/AFRL contract
7295041Sbr * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
8295041Sbr *
9295041Sbr * Portions of this software were developed by the University of Cambridge
10295041Sbr * Computer Laboratory as part of the CTSRD Project, with support from the
11295041Sbr * UK Higher Education Innovation Fund (HEIF).
12295041Sbr *
13295041Sbr * Redistribution and use in source and binary forms, with or without
14295041Sbr * modification, are permitted provided that the following conditions
15295041Sbr * are met:
16295041Sbr * 1. Redistributions of source code must retain the above copyright
17295041Sbr *    notice, this list of conditions and the following disclaimer.
18295041Sbr * 2. Redistributions in binary form must reproduce the above copyright
19295041Sbr *    notice, this list of conditions and the following disclaimer in the
20295041Sbr *    documentation and/or other materials provided with the distribution.
21295041Sbr *
22295041Sbr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23295041Sbr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24295041Sbr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25295041Sbr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26295041Sbr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27295041Sbr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28295041Sbr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29295041Sbr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30295041Sbr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31295041Sbr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32295041Sbr * SUCH DAMAGE.
33295041Sbr *
34295041Sbr * $FreeBSD: head/sys/riscv/riscv/locore.S 295972 2016-02-24 16:50:34Z br $
35295041Sbr */
36295041Sbr
37295041Sbr#include "assym.s"
38295041Sbr
39295041Sbr#include <sys/syscall.h>
40295041Sbr#include <machine/asm.h>
41295041Sbr#include <machine/param.h>
42295041Sbr#include <machine/trap.h>
43295041Sbr#include <machine/riscvreg.h>
44295041Sbr#include <machine/pte.h>
45295041Sbr
46295972Sbr#define	HTIF_RING_NENTRIES	(512)
47295972Sbr#define	HTIF_RING_ENTRY_SZ	(24)
48295972Sbr#define	HTIF_RING_SIZE		(HTIF_RING_ENTRY_SZ * HTIF_RING_NENTRIES)
49295972Sbr#define	HW_STACK_SIZE		(96)
50295041Sbr
51295972Sbr/*
52295972Sbr * Event queue for each CPU core:
53295972Sbr *
54295972Sbr * struct htif_ring {
55295972Sbr *     uint64_t data;
56295972Sbr *     uint64_t used;
57295972Sbr *     uint64_t next;
58295972Sbr * } htif_ring[HTIF_RING_NENTRIES];
59295972Sbr * uint64_t htif_ring_cursor;
60295972Sbr * uint64_t htif_ring_last;
61295972Sbr */
62295972Sbr
63295972Sbr.macro build_ring
64295972Sbr	la	t0, htif_ring
65295972Sbr#ifdef SMP
66295972Sbr	csrr	a0, mhartid
67295972Sbr	li	s0, (HTIF_RING_SIZE + 16)
68295972Sbr	mulw	s0, a0, s0
69295972Sbr	add	t0, t0, s0
70295972Sbr#endif
71295972Sbr	li	t1, 0
72295972Sbr	sd	t1, 0(t0)	/* zero data */
73295972Sbr	sd	t1, 8(t0)	/* zero used */
74295972Sbr	mv	t2, t0
75295972Sbr	mv	t3, t0
76295972Sbr	li	t5, (HTIF_RING_SIZE - HTIF_RING_ENTRY_SZ)
77295972Sbr	li	t6, 0
78295972Sbr	add	t4, t0, t5
79295972Sbr1:
80295972Sbr	addi	t3, t3, 24	/* pointer to next */
81295972Sbr	beq	t3, t4, 2f	/* finish */
82295972Sbr	sd	t3, 16(t2)	/* store pointer */
83295972Sbr	addi	t2, t2, 24	/* next entry */
84295972Sbr	addi	t6, t6, 1	/* counter */
85295972Sbr	j	1b
86295972Sbr2:
87295972Sbr	sd	t0, 16(t3)	/* last -> first */
88295972Sbr
89295972Sbr	li	t2, (HTIF_RING_SIZE)
90295972Sbr	add	s0, t0, t2
91295972Sbr	sd	t0, 0(s0)	/* cursor */
92295972Sbr	sd	t0, 8(s0)	/* last */
93295972Sbr	/* finish building ring */
94295972Sbr.endm
95295972Sbr
96295041Sbr	.globl	kernbase
97295041Sbr	.set	kernbase, KERNBASE
98295041Sbr
99295041Sbr	/* Trap entries */
100295041Sbr	.text
101295041Sbr
102295041Sbrmentry:
103295041Sbr	/* User mode entry point (mtvec + 0x000) */
104295041Sbr	.align 6
105295041Sbr	j	user_trap
106295041Sbr
107295041Sbr	/* Supervisor mode entry point (mtvec + 0x040) */
108295041Sbr	.align 6
109295041Sbr	j	supervisor_trap
110295041Sbr
111295041Sbr	/* Hypervisor mode entry point (mtvec + 0x080) */
112295041Sbr	.align 6
113295041Sbr	j	bad_trap
114295041Sbr
115295041Sbr	/* Machine mode entry point (mtvec + 0x0C0) */
116295041Sbr	.align 6
117295041Sbr	j	bad_trap
118295041Sbr
119295041Sbr	/* Reset vector */
120295041Sbr	.text
121295041Sbr	.align 8
122295041Sbr	.globl _start
123295041Sbr_start:
124295972Sbr	/* Direct secondary cores to mpentry */
125295972Sbr	csrr	a0, mhartid
126295972Sbr	bnez	a0, mpentry
127295041Sbr
128295972Sbr	/* Build event queue for current core */
129295972Sbr	build_ring
130295041Sbr
131295972Sbr	/* Setup machine-mode stack for CPU 0 */
132295041Sbr	la	t0, hardstack_end
133295041Sbr	csrw	mscratch, t0
134295041Sbr
135295041Sbr	la	t0, mentry
136295041Sbr	csrw	mtvec, t0
137295041Sbr
138295041Sbr	li	t0, 0
139295041Sbr	csrw	sscratch, t0
140295041Sbr
141295041Sbr	li	s10, PAGE_SIZE
142295041Sbr	li	s9, (PAGE_SIZE * KSTACK_PAGES)
143295041Sbr
144295041Sbr	/* Page tables */
145295041Sbr
146295041Sbr	/* Level 0 */
147295041Sbr	la	s1, pagetable_l0
148295041Sbr	la	s2, pagetable_l1	/* Link to next level PN */
149295041Sbr	srli	s2, s2, PAGE_SHIFT
150295041Sbr
151295041Sbr	li	t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
152295041Sbr	slli	t5, s2, PTE_PPN0_S	/* (s2 << PTE_PPN0_S) */
153295041Sbr	or	t6, t4, t5
154295041Sbr
155295041Sbr	/* Store single level0 PTE entry to position */
156295041Sbr	li	a5, 0x1ff
157295041Sbr	li	a6, PTE_SIZE
158295041Sbr	mulw	a5, a5, a6
159295041Sbr	add	t0, s1, a5
160295972Sbr	/* Store it to pagetable_l0 for each cpu */
161295972Sbr	li	t1, MAXCPU
162295972Sbr	li	t2, PAGE_SIZE
163295972Sbr1:
164295041Sbr	sd	t6, 0(t0)
165295972Sbr	add	t0, t0, t2
166295972Sbr	addi	t1, t1, -1
167295972Sbr	bnez	t1, 1b
168295041Sbr
169295041Sbr	/* Level 1 */
170295041Sbr	la	s1, pagetable_l1
171295041Sbr	la	s2, pagetable_l2	/* Link to next level PN */
172295041Sbr	srli	s2, s2, PAGE_SHIFT
173295041Sbr
174295041Sbr	li	a5, KERNBASE
175295041Sbr	srli	a5, a5, 0x1e		/* >> 30 */
176295041Sbr	andi	a5, a5, 0x1ff		/* & 0x1ff */
177295041Sbr	li	t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
178295041Sbr	slli	t5, s2, PTE_PPN0_S	/* (s2 << PTE_PPN0_S) */
179295041Sbr	or	t6, t4, t5
180295041Sbr
181295041Sbr	/* Store single level1 PTE entry to position */
182295041Sbr	li	a6, PTE_SIZE
183295041Sbr	mulw	a5, a5, a6
184295041Sbr	add	t0, s1, a5
185295041Sbr	sd	t6, (t0)
186295041Sbr
187295041Sbr	/* Level 2 superpages (512 x 2MiB) */
188295041Sbr	la	s1, pagetable_l2
189295041Sbr	li	t3, 512			/* Build 512 entries */
190295041Sbr	li	t4, 0			/* Counter */
191295041Sbr	li	t5, 0
192295041Sbr2:
193295041Sbr	li	t0, (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S))
194295041Sbr	slli	t2, t4, PTE_PPN1_S	/* << PTE_PPN1_S */
195295041Sbr	or	t5, t0, t2
196295041Sbr	sd	t5, (s1)		/* Store PTE entry to position */
197295041Sbr	addi	s1, s1, PTE_SIZE
198295041Sbr
199295041Sbr	addi	t4, t4, 1
200295041Sbr	bltu	t4, t3, 2b
201295041Sbr
202295041Sbr	/* Set page tables base register */
203295041Sbr	la	s1, pagetable_l0
204295041Sbr	csrw	sptbr, s1
205295041Sbr
206295041Sbr	/* Page tables END */
207295041Sbr
208295041Sbr	/* Enter supervisor mode */
209295041Sbr	li	s0, ((MSTATUS_VM_SV48 << MSTATUS_VM_SHIFT) | \
210295041Sbr		     (MSTATUS_PRV_M << MSTATUS_PRV_SHIFT) | \
211295041Sbr		     (MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \
212295041Sbr		     (MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT));
213295041Sbr	csrw	mstatus, s0
214295041Sbr
215295972Sbr	/*
216295972Sbr	 * Enable machine-mode software interrupts
217295972Sbr	 * so we can deliver IPI to this core.
218295972Sbr	 */
219295972Sbr	li	t0, MIE_MSIE
220295972Sbr	csrs	mie, t0
221295972Sbr
222295041Sbr	/* Exit from machine mode */
223295041Sbr	la	t0, .Lmmu_on
224295972Sbr	li	s11, KERNBASE
225295041Sbr	add	t0, t0, s11
226295041Sbr	csrw	mepc, t0
227295041Sbr	eret
228295041Sbr
229295041Sbr.Lmmu_on:
230295041Sbr	/* Initialize stack pointer */
231295041Sbr	la	s3, initstack_end
232295041Sbr	mv	sp, s3
233295041Sbr	addi	sp, sp, -PCB_SIZE
234295041Sbr
235295041Sbr	/* Clear BSS  */
236295041Sbr	la	a0, _C_LABEL(__bss_start)
237295041Sbr	la	s1, _C_LABEL(_end)
238295041Sbr1:
239295041Sbr	sd	zero, 0(a0)
240295041Sbr	addi	a0, a0, 8
241295041Sbr	bltu	a0, s1, 1b
242295041Sbr
243295041Sbr	/* Fill riscv_bootparams */
244295041Sbr	addi	sp, sp, -16
245295041Sbr	la	t0, pagetable_l1
246295041Sbr	sd	t0, 0(sp) /* kern_l1pt */
247295041Sbr	la	t0, initstack_end
248295041Sbr	sd	t0, 8(sp) /* kern_stack */
249295041Sbr
250295041Sbr	mv	a0, sp
251295041Sbr	call	_C_LABEL(initriscv)	/* Off we go */
252295041Sbr	call	_C_LABEL(mi_startup)
253295041Sbr
254295041Sbr	.align  4
255295041Sbrinitstack:
256295041Sbr	.space  (PAGE_SIZE * KSTACK_PAGES)
257295041Sbrinitstack_end:
258295041Sbrhardstack:
259295972Sbr	.space  (HW_STACK_SIZE * MAXCPU)
260295041Sbrhardstack_end:
261295041Sbr
262295041Sbr	.globl htif_ring
263295041Sbrhtif_ring:
264295972Sbr	.space ((HTIF_RING_SIZE + 16) * MAXCPU)
265295041Sbr
266295041Sbr	.globl console_intr
267295041Sbrconsole_intr:
268295972Sbr	.space (8)
269295041Sbr
270295041SbrENTRY(sigcode)
271295041Sbr	mv	a0, sp
272295041Sbr	addi	a0, a0, SF_UC
273295041Sbr
274295041Sbr1:
275295041Sbr	li	t0, SYS_sigreturn
276295041Sbr	ecall
277295041Sbr
278295041Sbr	/* sigreturn failed, exit */
279295041Sbr	li	t0, SYS_exit
280295041Sbr	ecall
281295041Sbr
282295041Sbr	j	1b
283295041SbrEND(sigcode)
284295041Sbr	/* This may be copied to the stack, keep it 16-byte aligned */
285295041Sbr	.align	3
286295041Sbresigcode:
287295041Sbr
288295041Sbr	.data
289295041Sbr	.align	3
290295041Sbr	.global	szsigcode
291295041Sbrszsigcode:
292295041Sbr	.quad	esigcode - sigcode
293295041Sbr
294295041Sbr	.align	12
295295041Sbr	.globl pagetable_l0
296295041Sbrpagetable_l0:
297295972Sbr	.space (PAGE_SIZE * MAXCPU)
298295041Sbrpagetable_l1:
299295041Sbr	.space	PAGE_SIZE
300295041Sbrpagetable_l2:
301295041Sbr	.space	PAGE_SIZE
302295041Sbrpagetable_end:
303295041Sbr
304295041Sbr	.globl init_pt_va
305295041Sbrinit_pt_va:
306295041Sbr	.quad pagetable_l2	/* XXX: Keep page tables VA */
307295041Sbr
308295972Sbr#ifndef SMP
309295972SbrENTRY(mpentry)
310295972Sbr1:
311295972Sbr	wfi
312295972Sbr	j	1b
313295972SbrEND(mpentry)
314295972Sbr#else
315295972Sbr/*
316295972Sbr * mpentry(unsigned long)
317295972Sbr *
318295972Sbr * Called by a core when it is being brought online.
319295972Sbr * The data in x0 is passed straight to init_secondary.
320295972Sbr */
321295972SbrENTRY(mpentry)
322295972Sbr	/*
323295972Sbr	 * Calculate the offset to __riscv_boot_ap
324295972Sbr	 * for current core, cpuid in a0.
325295972Sbr	 */
326295972Sbr	li	t1, 4
327295972Sbr	mulw	t1, t1, a0
328295972Sbr	/* Get pointer */
329295972Sbr	la	t0, __riscv_boot_ap
330295972Sbr	add	t0, t0, t1
331295972Sbr
332295972Sbr1:
333295972Sbr	/* Wait the kernel to be ready */
334295972Sbr	lw	t1, 0(t0)
335295972Sbr	beqz	t1, 1b
336295972Sbr
337295972Sbr	/* Setup machine exception vector */
338295972Sbr	la	t0, mentry
339295972Sbr	csrw	mtvec, t0
340295972Sbr
341295972Sbr	/* Build event queue ring for this core */
342295972Sbr	build_ring
343295972Sbr
344295972Sbr	/* Set page tables base register */
345295972Sbr	la	t0, pagetable_l0
346295972Sbr	li	t1, PAGE_SIZE
347295972Sbr	mulw	t1, t1, a0
348295972Sbr	add	t0, t0, t1
349295972Sbr	csrw	sptbr, t0
350295972Sbr	/* Page tables END */
351295972Sbr
352295972Sbr	/* Configure mstatus */
353295972Sbr	li	s0, ((MSTATUS_VM_SV48 << MSTATUS_VM_SHIFT) | \
354295972Sbr		     (MSTATUS_PRV_M << MSTATUS_PRV_SHIFT) | \
355295972Sbr		     (MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \
356295972Sbr		     (MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT));
357295972Sbr	csrw	mstatus, s0
358295972Sbr
359295972Sbr	/* Setup stack for machine mode exceptions */
360295972Sbr	la	t0, hardstack_end
361295972Sbr	li	t1, HW_STACK_SIZE
362295972Sbr	mulw	t1, t1, a0
363295972Sbr	sub	t0, t0, t1
364295972Sbr	csrw	mscratch, t0
365295972Sbr
366295972Sbr	li	t0, 0
367295972Sbr	csrw	sscratch, t0
368295972Sbr
369295972Sbr	/*
370295972Sbr	 * Enable machine-mode software interrupts
371295972Sbr	 * so we can deliver IPI to this core.
372295972Sbr	 */
373295972Sbr	li	t0, MIE_MSIE
374295972Sbr	csrs	mie, t0
375295972Sbr
376295972Sbr	/*
377295972Sbr	 * Exit from machine mode and go to
378295972Sbr	 * the virtual address space.
379295972Sbr	 */
380295972Sbr	la	t0, mp_virtdone
381295972Sbr	li	s11, KERNBASE
382295972Sbr	add	t0, t0, s11
383295972Sbr	csrw	mepc, t0
384295972Sbr	eret
385295972Sbr
386295972Sbrmp_virtdone:
387295972Sbr	/* We are now in virtual address space */
388295972Sbr
389295972Sbr	/* Setup stack pointer */
390295972Sbr	la	t0, secondary_stacks
391295972Sbr	li	t1, (PAGE_SIZE * KSTACK_PAGES)
392295972Sbr	mulw	t1, t1, a0
393295972Sbr	add	sp, t0, t1
394295972Sbr
395295972Sbr	call	init_secondary
396295972SbrEND(mpentry)
397295972Sbr#endif
398295972Sbr
399295041Sbr#include "exception.S"
400