/*-
* Copyright (c) 2015-2016 Ruslan Bukin
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "assym.s"
#include
#include
#include
#include
#include
#include
#define HTIF_RING_NENTRIES (512)
#define HTIF_RING_ENTRY_SZ (24)
#define HTIF_RING_SIZE (HTIF_RING_ENTRY_SZ * HTIF_RING_NENTRIES)
#define HW_STACK_SIZE (96)
/*
* Event queue for each CPU core:
*
* struct htif_ring {
* uint64_t data;
* uint64_t used;
* uint64_t next;
* } htif_ring[HTIF_RING_NENTRIES];
* uint64_t htif_ring_cursor;
* uint64_t htif_ring_last;
*/
.macro build_ring
la t0, htif_ring
#ifdef SMP
csrr a0, mhartid
li s0, (HTIF_RING_SIZE + 16)
mulw s0, a0, s0
add t0, t0, s0
#endif
li t1, 0
sd t1, 0(t0) /* zero data */
sd t1, 8(t0) /* zero used */
mv t2, t0
mv t3, t0
li t5, (HTIF_RING_SIZE - HTIF_RING_ENTRY_SZ)
li t6, 0
add t4, t0, t5
1:
addi t3, t3, 24 /* pointer to next */
beq t3, t4, 2f /* finish */
sd t3, 16(t2) /* store pointer */
addi t2, t2, 24 /* next entry */
addi t6, t6, 1 /* counter */
j 1b
2:
sd t0, 16(t3) /* last -> first */
li t2, (HTIF_RING_SIZE)
add s0, t0, t2
sd t0, 0(s0) /* cursor */
sd t0, 8(s0) /* last */
/* finish building ring */
.endm
.globl kernbase
.set kernbase, KERNBASE
/* Trap entries */
.text
mentry:
/* User mode entry point (mtvec + 0x000) */
.align 6
j user_trap
/* Supervisor mode entry point (mtvec + 0x040) */
.align 6
j supervisor_trap
/* Hypervisor mode entry point (mtvec + 0x080) */
.align 6
j bad_trap
/* Machine mode entry point (mtvec + 0x0C0) */
.align 6
j bad_trap
/* Reset vector */
.text
.align 8
.globl _start
_start:
/* Direct secondary cores to mpentry */
csrr a0, mhartid
bnez a0, mpentry
/* Build event queue for current core */
build_ring
/* Setup machine-mode stack for CPU 0 */
la t0, hardstack_end
csrw mscratch, t0
la t0, mentry
csrw mtvec, t0
li t0, 0
csrw sscratch, t0
li s10, PAGE_SIZE
li s9, (PAGE_SIZE * KSTACK_PAGES)
/* Page tables */
/* Level 0 */
la s1, pagetable_l0
la s2, pagetable_l1 /* Link to next level PN */
srli s2, s2, PAGE_SHIFT
li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
or t6, t4, t5
/* Store single level0 PTE entry to position */
li a5, 0x1ff
li a6, PTE_SIZE
mulw a5, a5, a6
add t0, s1, a5
/* Store it to pagetable_l0 for each cpu */
li t1, MAXCPU
li t2, PAGE_SIZE
1:
sd t6, 0(t0)
add t0, t0, t2
addi t1, t1, -1
bnez t1, 1b
/* Level 1 */
la s1, pagetable_l1
la s2, pagetable_l2 /* Link to next level PN */
srli s2, s2, PAGE_SHIFT
li a5, KERNBASE
srli a5, a5, 0x1e /* >> 30 */
andi a5, a5, 0x1ff /* & 0x1ff */
li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
or t6, t4, t5
/* Store single level1 PTE entry to position */
li a6, PTE_SIZE
mulw a5, a5, a6
add t0, s1, a5
sd t6, (t0)
/* Level 2 superpages (512 x 2MiB) */
la s1, pagetable_l2
li t3, 512 /* Build 512 entries */
li t4, 0 /* Counter */
li t5, 0
2:
li t0, (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S))
slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */
or t5, t0, t2
sd t5, (s1) /* Store PTE entry to position */
addi s1, s1, PTE_SIZE
addi t4, t4, 1
bltu t4, t3, 2b
/* Set page tables base register */
la s1, pagetable_l0
csrw sptbr, s1
/* Page tables END */
/* Enter supervisor mode */
li s0, ((MSTATUS_VM_SV48 << MSTATUS_VM_SHIFT) | \
(MSTATUS_PRV_M << MSTATUS_PRV_SHIFT) | \
(MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \
(MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT));
csrw mstatus, s0
/*
* Enable machine-mode software interrupts
* so we can deliver IPI to this core.
*/
li t0, MIE_MSIE
csrs mie, t0
/* Exit from machine mode */
la t0, .Lmmu_on
li s11, KERNBASE
add t0, t0, s11
csrw mepc, t0
eret
.Lmmu_on:
/* Initialize stack pointer */
la s3, initstack_end
mv sp, s3
addi sp, sp, -PCB_SIZE
/* Clear BSS */
la a0, _C_LABEL(__bss_start)
la s1, _C_LABEL(_end)
1:
sd zero, 0(a0)
addi a0, a0, 8
bltu a0, s1, 1b
/* Fill riscv_bootparams */
addi sp, sp, -16
la t0, pagetable_l1
sd t0, 0(sp) /* kern_l1pt */
la t0, initstack_end
sd t0, 8(sp) /* kern_stack */
mv a0, sp
call _C_LABEL(initriscv) /* Off we go */
call _C_LABEL(mi_startup)
.align 4
initstack:
.space (PAGE_SIZE * KSTACK_PAGES)
initstack_end:
hardstack:
.space (HW_STACK_SIZE * MAXCPU)
hardstack_end:
.globl htif_ring
htif_ring:
.space ((HTIF_RING_SIZE + 16) * MAXCPU)
.globl console_intr
console_intr:
.space (8)
ENTRY(sigcode)
mv a0, sp
addi a0, a0, SF_UC
1:
li t0, SYS_sigreturn
ecall
/* sigreturn failed, exit */
li t0, SYS_exit
ecall
j 1b
END(sigcode)
/* This may be copied to the stack, keep it 16-byte aligned */
.align 3
esigcode:
.data
.align 3
.global szsigcode
szsigcode:
.quad esigcode - sigcode
.align 12
.globl pagetable_l0
pagetable_l0:
.space (PAGE_SIZE * MAXCPU)
pagetable_l1:
.space PAGE_SIZE
pagetable_l2:
.space PAGE_SIZE
pagetable_end:
.globl init_pt_va
init_pt_va:
.quad pagetable_l2 /* XXX: Keep page tables VA */
#ifndef SMP
ENTRY(mpentry)
1:
wfi
j 1b
END(mpentry)
#else
/*
* mpentry(unsigned long)
*
* Called by a core when it is being brought online.
* The data in x0 is passed straight to init_secondary.
*/
ENTRY(mpentry)
/*
* Calculate the offset to __riscv_boot_ap
* for current core, cpuid in a0.
*/
li t1, 4
mulw t1, t1, a0
/* Get pointer */
la t0, __riscv_boot_ap
add t0, t0, t1
1:
/* Wait the kernel to be ready */
lw t1, 0(t0)
beqz t1, 1b
/* Setup machine exception vector */
la t0, mentry
csrw mtvec, t0
/* Build event queue ring for this core */
build_ring
/* Set page tables base register */
la t0, pagetable_l0
li t1, PAGE_SIZE
mulw t1, t1, a0
add t0, t0, t1
csrw sptbr, t0
/* Page tables END */
/* Configure mstatus */
li s0, ((MSTATUS_VM_SV48 << MSTATUS_VM_SHIFT) | \
(MSTATUS_PRV_M << MSTATUS_PRV_SHIFT) | \
(MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \
(MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT));
csrw mstatus, s0
/* Setup stack for machine mode exceptions */
la t0, hardstack_end
li t1, HW_STACK_SIZE
mulw t1, t1, a0
sub t0, t0, t1
csrw mscratch, t0
li t0, 0
csrw sscratch, t0
/*
* Enable machine-mode software interrupts
* so we can deliver IPI to this core.
*/
li t0, MIE_MSIE
csrs mie, t0
/*
* Exit from machine mode and go to
* the virtual address space.
*/
la t0, mp_virtdone
li s11, KERNBASE
add t0, t0, s11
csrw mepc, t0
eret
mp_virtdone:
/* We are now in virtual address space */
/* Setup stack pointer */
la t0, secondary_stacks
li t1, (PAGE_SIZE * KSTACK_PAGES)
mulw t1, t1, a0
add sp, t0, t1
call init_secondary
END(mpentry)
#endif
#include "exception.S"