blob: 52c8415e4c0264160db9b1f278c1fc308970363e [file] [log] [blame]
/****************************************************************************
* arch/risc-v/src/mpfs/mpfs_entrypoints.c
*
* 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>
#ifdef CONFIG_MPFS_BOOTLOADER
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/compiler.h>
#include <sys/types.h>
#include "riscv_internal.h"
/****************************************************************************
* Extern Function Declarations
****************************************************************************/
extern void mpfs_opensbi_prepare_hart(void);
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ENTRY_STACK 512
#define ENTRYPT_CNT sizeof(g_app_entrypoints) / sizeof(g_app_entrypoints[0])
/* Default PMP permissions */
#define PMP_DEFAULT_PERM (PMPCFG_A_NAPOT | PMPCFG_R | PMPCFG_W | PMPCFG_X)
/****************************************************************************
* Private Data
****************************************************************************/
/* The actual application entrypoints */
static uint64_t g_app_entrypoints[] =
{
CONFIG_MPFS_HART0_ENTRYPOINT,
CONFIG_MPFS_HART1_ENTRYPOINT,
CONFIG_MPFS_HART2_ENTRYPOINT,
CONFIG_MPFS_HART3_ENTRYPOINT,
CONFIG_MPFS_HART4_ENTRYPOINT
};
static uint64_t g_hart_use_sbi =
#ifdef CONFIG_MPFS_HART1_SBI
(1 << 1) |
#endif
#ifdef CONFIG_MPFS_HART2_SBI
(1 << 2) |
#endif
#ifdef CONFIG_MPFS_HART3_SBI
(1 << 3) |
#endif
#ifdef CONFIG_MPFS_HART4_SBI
(1 << 4) |
#endif
0;
#ifdef CONFIG_MPFS_BOARD_PMP
uint8_t g_mpfs_boot_stacks[ENTRY_STACK * ENTRYPT_CNT]
aligned_data(STACK_ALIGNMENT);
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
void mpfs_jump_to_app(void) naked_function;
void mpfs_jump_to_app(void)
{
__asm__ __volatile__
(
"csrr a0, mhartid\n" /* Hart ID */
#ifdef CONFIG_MPFS_BOARD_PMP
"li t1, %0\n" /* Size of hart's stack */
"mul t0, a0, t1\n" /* Hart stack base */
"add t0, t0, t1\n" /* Hart stack top */
"la sp, g_mpfs_boot_stacks\n" /* Stack area base */
"add sp, sp, t0\n" /* Set stack pointer */
"call mpfs_board_pmp_setup\n" /* Run PMP configuration */
"bne a0, x0, mpfs_board_pmp_error\n" /* If ret != 0, jump to errhan */
"csrr a0, mhartid\n" /* Restore hartid */
#else
"li t0, -1\n" /* Open the whole SoC */
"csrw pmpaddr0, t0\n"
"li t0, %0\n" /* Grant RWX permissions */
"csrw pmpcfg0, t0\n"
"csrw pmpcfg2, zero\n"
#endif
#ifdef CONFIG_MPFS_OPENSBI
"ld t0, g_hart_use_sbi\n" /* Load sbi usage bitmask */
"srl t0, t0, a0\n" /* Shift right by this hart */
"andi t0, t0, 1\n" /* Check the 0 bit */
"beqz t0, 1f\n" /* If bit was 1, jump to sbi */
"tail mpfs_opensbi_prepare_hart\n"
"1:\n"
#endif
"slli t1, a0, 3\n" /* To entrypoint offset */
"la t0, g_app_entrypoints\n" /* Entrypoint table base */
"add t0, t0, t1\n" /* Index in table */
"ld t0, 0(t0)\n" /* Load the address from table */
"jr t0\n" /* Jump to entrypoint */
:
#ifdef CONFIG_MPFS_BOARD_PMP
: "i" (ENTRY_STACK)
#else
: "i" (PMP_DEFAULT_PERM)
#endif
:
);
}
/****************************************************************************
* Name: mpfs_set_entrypt
*
* Description:
* Modify Hart entrypoint
*
* Input Parameters:
* hartid - Hart ID to modify
* entry - Entrypoint to set
*
* Returned value:
* OK on success, ERROR on failure
*
****************************************************************************/
int mpfs_set_entrypt(uint64_t hartid, uintptr_t entry)
{
if (hartid < ENTRYPT_CNT)
{
g_app_entrypoints[hartid] = entry;
return OK;
}
return ERROR;
}
/****************************************************************************
* Name: mpfs_get_entrypt
*
* Description:
* Obtain Hart entrypoint
*
* Input Parameters:
* hartid - Hart ID to read
*
* Returned value:
* Entrypoint on success; 0 on failure
*
****************************************************************************/
uintptr_t mpfs_get_entrypt(uint64_t hartid)
{
if (hartid < ENTRYPT_CNT)
{
return g_app_entrypoints[hartid];
}
return 0;
}
/****************************************************************************
* Name: mpfs_set_use_sbi
*
* Description:
* Set booting via SBI.
*
* Input Parameters:
* use_sbi - set to true if sbi is needed, false otherwise
*
* Returned value:
* OK on success, ERROR on failure
*
****************************************************************************/
int mpfs_set_use_sbi(uint64_t hartid, bool use_sbi)
{
if (hartid < ENTRYPT_CNT)
{
if (use_sbi)
{
g_hart_use_sbi |= (1 << hartid);
}
else
{
g_hart_use_sbi &= ~(1 << hartid);
}
return OK;
}
return ERROR;
}
#endif /* CONFIG_MPFS_BOOTLOADER */