Sv39 is the only mode supported for now. However, it should be trivial to extend the driver to support the other modes (including Sv32) as well. The driver is tested with mpfs only, but it should work with any riscv implementation.
220 lines
5 KiB
ArmAsm
Executable file
220 lines
5 KiB
ArmAsm
Executable file
/****************************************************************************
|
|
* arch/risc-v/src/mpfs/mpfs_head.S
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
#include <arch/csr.h>
|
|
#include <arch/irq.h>
|
|
|
|
#include "chip.h"
|
|
#include "mpfs_memorymap.h"
|
|
#include "riscv_internal.h"
|
|
|
|
/****************************************************************************
|
|
* Public Symbols
|
|
****************************************************************************/
|
|
|
|
/* Imported symbols */
|
|
|
|
.extern __trap_vec
|
|
|
|
.section .text
|
|
.global __start
|
|
|
|
__start:
|
|
|
|
|
|
/* Disable all interrupts (i.e. timer, external) in mie */
|
|
|
|
csrw mie, zero
|
|
csrw mip, zero
|
|
|
|
/* Initialize the Machine Trap Vector */
|
|
|
|
la t0, __trap_vec
|
|
csrw mtvec, t0
|
|
|
|
/* Make sure that mtvec is updated before continuing */
|
|
|
|
1:
|
|
csrr t1, mtvec
|
|
bne t0, t1, 1b
|
|
|
|
/* mscratch must be init to zero- we are not using scratch memory */
|
|
|
|
csrw mscratch, zero
|
|
csrw mcause, zero
|
|
csrw mepc, zero
|
|
li x1, 0
|
|
li x2, 0
|
|
li x3, 0
|
|
li x4, 0
|
|
li x5, 0
|
|
li x6, 0
|
|
li x7, 0
|
|
li x8, 0
|
|
li x9, 0
|
|
li x10, 0
|
|
li x11, 0
|
|
li x12, 0
|
|
li x13, 0
|
|
li x14, 0
|
|
li x15, 0
|
|
li x16, 0
|
|
li x17, 0
|
|
li x18, 0
|
|
li x19, 0
|
|
li x20, 0
|
|
li x21, 0
|
|
li x22, 0
|
|
li x23, 0
|
|
li x24, 0
|
|
li x25, 0
|
|
li x26, 0
|
|
li x27, 0
|
|
li x28, 0
|
|
li x29, 0
|
|
li x30, 0
|
|
li x31, 0
|
|
|
|
/* Skip delegation register, mmu and floating point initializations if E51 */
|
|
csrr a0, mhartid
|
|
beqz a0, .skip_e51
|
|
|
|
/* Init delegation registers, mideleg, medeleg, if a U54
|
|
* These are not initialised by the hardware and come up in a random state
|
|
*/
|
|
|
|
csrw mideleg, 0
|
|
csrw medeleg, 0
|
|
|
|
/* Disable MMU if not done already */
|
|
|
|
csrw satp, zero
|
|
fence
|
|
|
|
/* invalid all MMU TLB Entry */
|
|
|
|
sfence.vma x0, x0
|
|
|
|
/* enable FPU and accelerator if present, setting ignored on E51
|
|
* 15,16 = MSTATUS_XS, 17,18 = MSTATUS_MPRV
|
|
* not defined on riscv-v/include/csr.h
|
|
*/
|
|
|
|
/* li t0, MSTATUS_FS_DIRTY | (1 << 15) | (1 << 16) | (1 << 17) | (1 << 18) */
|
|
li t0, 0x00006000 | 0x00018000 /* MSTATUS_FS | MSTATUS_XS */
|
|
csrs mstatus, t0
|
|
|
|
/* Init floating point control register to zero */
|
|
#ifdef __riscv_flen
|
|
fscsr x0
|
|
#endif
|
|
|
|
.skip_e51:
|
|
|
|
#ifdef CONFIG_MPFS_BOOTLOADER
|
|
|
|
/* Set all but the boot hart into wfi */
|
|
|
|
li a1, CONFIG_MPFS_BOOT_HART
|
|
beq a0, a1, .continue_boot
|
|
|
|
/* Enable IRQ_M_SOFT */
|
|
|
|
li a2, (1U << 3)
|
|
csrw mie, a2 /* Set MSIE bit to receive IPI */
|
|
|
|
/* flush the instruction cache */
|
|
fence.i
|
|
|
|
.wait_boot:
|
|
wfi
|
|
|
|
/* Only start if MIP_MSIP is set. Breakpoints in the debugger (halt)
|
|
* will wakeup wfi, so we will check again that we actually got the soft
|
|
* interrupt
|
|
*/
|
|
|
|
csrr a2, mip
|
|
andi a2, a2, (1U << 3) /* MIP_MSIP */
|
|
beqz a2, .wait_boot
|
|
|
|
/* Disable and clear all interrupts (the sw interrupt) */
|
|
li a2, 0x00000008 /* MSTATUS_MIE */
|
|
csrc mstatus, a2
|
|
csrw mie, zero
|
|
csrw mip, zero
|
|
|
|
#ifdef CONFIG_MPFS_OPENSBI
|
|
jal mpfs_opensbi_prepare_hart
|
|
#else
|
|
/* Jump to app (TODO: remove fixed address) */
|
|
li a1, 0x80000000
|
|
jr a1
|
|
#endif
|
|
|
|
.continue_boot:
|
|
|
|
#endif
|
|
|
|
/* Set stack pointer to the idle thread stack */
|
|
|
|
la sp, MPFS_IDLESTACK_TOP
|
|
|
|
|
|
/* initialize global pointer, global data
|
|
* The __global_pointer is allocated in the linker script.
|
|
* It points to a location between _sdata and _edata as the offsets used in the gp are +/- 2k
|
|
* See https://www.sifive.com/blog/2017/08/28/all-aboard-part-3-linker-relaxation-in-riscv-toolchain/
|
|
* see: http://www.rowleydownload.co.uk/arm/documentation/gnu/as/RISC_002dV_002dDirectives.html
|
|
*/
|
|
|
|
.option push
|
|
.option norelax
|
|
la gp, __global_pointer$
|
|
.option pop
|
|
|
|
|
|
/* Jump to __mpfs_start with mhartid in a0 */
|
|
|
|
jal __mpfs_start
|
|
|
|
/* We shouldn't return from __mpfs_start
|
|
* in case of return, loop forever. nop's added so can be seen in debugger
|
|
*/
|
|
|
|
1:
|
|
nop
|
|
nop
|
|
j 1b
|
|
|
|
.global _init
|
|
.global _fini
|
|
|
|
_init:
|
|
_fini:
|
|
|
|
/* These don't have to do anything since we use init_array/fini_array. */
|
|
|
|
ret
|