arch/risc-v: Improve the SBI function handle
To simplify processing, the existed SBI function code is just invoking the ecall and return the error value. This omits potential return value in "a1", which is defined in SBI doc. Add the "sbiret" struct so it can handle all the return value. In addition, there are some minor improvement: 1. move the SBI related interface to a separate file to make it clean. 2. add all necessary SBI ecall interface macro until version 2.0. 3. add an utilty function to convert sbi error numner to standard error number. Signed-off-by: Inochi Amaoto <inochiama@outlook.com>
This commit is contained in:
parent
dab55ef6e2
commit
caeb1757f6
@ -81,8 +81,10 @@ typedef int _wchar_t;
|
||||
/* Use uintreg_t for register-width integers */
|
||||
|
||||
#ifdef CONFIG_ARCH_RV32
|
||||
typedef _int32_t intreg_t;
|
||||
typedef _uint32_t uintreg_t;
|
||||
#else
|
||||
typedef _int64_t intreg_t;
|
||||
typedef _uint64_t uintreg_t;
|
||||
#endif
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "riscv_sbi.h"
|
||||
#include "riscv_common_memorymap.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -209,40 +210,6 @@ static inline void putreg64(uint64_t v, const volatile uintreg_t a)
|
||||
|
||||
#endif
|
||||
|
||||
/* SBI Extension IDs */
|
||||
|
||||
#define SBI_EXT_HSM 0x48534D
|
||||
#define SBI_EXT_IPI 0x735049
|
||||
#define SBI_EXT_TIME 0x54494D45
|
||||
#define SBI_EXT_SRST 0x53525354
|
||||
|
||||
/* SBI function IDs for TIME extension */
|
||||
|
||||
#define SBI_EXT_TIME_SET_TIMER 0x0
|
||||
|
||||
/* SBI function IDs for HSM extension */
|
||||
|
||||
#define SBI_EXT_HSM_HART_START 0x0
|
||||
|
||||
/* SBI function IDs for IPI extension */
|
||||
|
||||
#define SBI_EXT_IPI_SEND_IPI 0x0
|
||||
|
||||
/* SBI function IDs for SRST extension */
|
||||
|
||||
#define SBI_EXT_SRST_SYS_RESET 0x0
|
||||
|
||||
/* SBI system reset type */
|
||||
|
||||
#define SBI_SRST_TYPE_SHUTDOWN 0
|
||||
#define SBI_SRST_TYPE_REBOOT_COLD 1
|
||||
#define SBI_SRST_TYPE_REBOOT_WARM 1
|
||||
|
||||
/* SBI system reset reason */
|
||||
|
||||
#define SBI_SRST_REASON_NONE 0
|
||||
#define SBI_SRST_REASON_FAILURE 1
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
@ -372,17 +339,6 @@ int riscv_check_pmp_access(uintptr_t attr, uintptr_t base, uintptr_t size);
|
||||
int riscv_configured_pmp_regions(void);
|
||||
int riscv_next_free_pmp_region(void);
|
||||
|
||||
/* RISC-V SBI wrappers ******************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_USE_S_MODE
|
||||
uintptr_t riscv_sbi_send_ipi(uint32_t hmask, uintptr_t hbase);
|
||||
void riscv_sbi_set_timer(uint64_t stime_value);
|
||||
uint64_t riscv_sbi_get_time(void);
|
||||
uintptr_t riscv_sbi_boot_secondary(uint32_t hartid, uintptr_t addr,
|
||||
uintptr_t a1);
|
||||
uintptr_t riscv_sbi_system_reset(uint32_t type, uint32_t reason);
|
||||
#endif
|
||||
|
||||
/* Power management *********************************************************/
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
284
arch/risc-v/src/common/riscv_sbi.h
Normal file
284
arch/risc-v/src/common/riscv_sbi.h
Normal file
@ -0,0 +1,284 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/common/riscv_sbi.h
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_RISCV_SRC_COMMON_RISCV_SBI_H
|
||||
#define __ARCH_RISCV_SRC_COMMON_RISCV_SBI_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <arch/types.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* SBI Extension IDs */
|
||||
|
||||
#define SBI_EXT_BASE 0x00000010
|
||||
#define SBI_EXT_IPI 0x00735049
|
||||
#define SBI_EXT_TIME 0x54494D45
|
||||
#define SBI_EXT_RFENCE 0x52464E43
|
||||
#define SBI_EXT_HSM 0x0048534D
|
||||
#define SBI_EXT_SRST 0x53525354
|
||||
#define SBI_EXT_PMU 0x00504D55
|
||||
#define SBI_EXT_DBCN 0x4442434E
|
||||
#define SBI_EXT_SUSP 0x53555350
|
||||
|
||||
/* SBI function IDs for BASE extension */
|
||||
|
||||
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
|
||||
#define SBI_EXT_BASE_GET_IMP_ID 0x1
|
||||
#define SBI_EXT_BASE_GET_IMP_VERSION 0x2
|
||||
#define SBI_EXT_BASE_PROBE_EXT 0x3
|
||||
#define SBI_EXT_BASE_GET_MVENDORID 0x4
|
||||
#define SBI_EXT_BASE_GET_MARCHID 0x5
|
||||
#define SBI_EXT_BASE_GET_MIMPID 0x6
|
||||
|
||||
/* SBI function IDs for TIME extension */
|
||||
|
||||
#define SBI_EXT_TIME_SET_TIMER 0x0
|
||||
|
||||
/* SBI function IDs for IPI extension */
|
||||
|
||||
#define SBI_EXT_IPI_SEND_IPI 0x0
|
||||
|
||||
/* SBI function IDs for RFENCE extension */
|
||||
#define SBI_EXT_RFENCE_REMOTE_FENCE_I 0x0
|
||||
#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA 0x1
|
||||
#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID 0x2
|
||||
#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID 0x3
|
||||
#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA 0x4
|
||||
#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID 0x5
|
||||
#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA 0x6
|
||||
|
||||
/* SBI function IDs for HSM extension */
|
||||
|
||||
#define SBI_EXT_HSM_HART_START 0x0
|
||||
#define SBI_EXT_HSM_HART_STOP 0x1
|
||||
#define SBI_EXT_HSM_HART_GET_STATUS 0x2
|
||||
#define SBI_EXT_HSM_HART_SUSPEND 0x3
|
||||
|
||||
#define SBI_HSM_STATE_STARTED 0x0
|
||||
#define SBI_HSM_STATE_STOPPED 0x1
|
||||
#define SBI_HSM_STATE_START_PENDING 0x2
|
||||
#define SBI_HSM_STATE_STOP_PENDING 0x3
|
||||
#define SBI_HSM_STATE_SUSPENDED 0x4
|
||||
#define SBI_HSM_STATE_SUSPEND_PENDING 0x5
|
||||
#define SBI_HSM_STATE_RESUME_PENDING 0x6
|
||||
|
||||
/* SBI function IDs for SRST extension */
|
||||
|
||||
#define SBI_EXT_SRST_SYS_RESET 0x0
|
||||
|
||||
/* SBI system reset type */
|
||||
|
||||
#define SBI_SRST_TYPE_SHUTDOWN 0
|
||||
#define SBI_SRST_TYPE_REBOOT_COLD 1
|
||||
#define SBI_SRST_TYPE_REBOOT_WARM 1
|
||||
|
||||
/* SBI system reset reason */
|
||||
|
||||
#define SBI_SRST_REASON_NONE 0
|
||||
#define SBI_SRST_REASON_FAILURE 1
|
||||
|
||||
/* SBI function IDs for PMU extension */
|
||||
|
||||
#define SBI_EXT_PMU_NUM_COUNTERS 0x0
|
||||
#define SBI_EXT_PMU_COUNTER_GET_INFO 0x1
|
||||
#define SBI_EXT_PMU_COUNTER_CFG_MATCH 0x2
|
||||
#define SBI_EXT_PMU_COUNTER_START 0x3
|
||||
#define SBI_EXT_PMU_COUNTER_STOP 0x4
|
||||
#define SBI_EXT_PMU_COUNTER_FW_READ 0x5
|
||||
#define SBI_EXT_PMU_COUNTER_FW_READ_HI 0x6
|
||||
#define SBI_EXT_PMU_SNAPSHOT_SET_SHMEM 0x7
|
||||
|
||||
/* SBI PMU counter config match flags */
|
||||
|
||||
#define SBI_PMU_CFG_FLAG_SKIP_MATCH (1 << 0)
|
||||
#define SBI_PMU_CFG_FLAG_CLEAR_VALUE (1 << 1)
|
||||
#define SBI_PMU_CFG_FLAG_AUTO_START (1 << 2)
|
||||
#define SBI_PMU_CFG_FLAG_SET_VUINH (1 << 3)
|
||||
#define SBI_PMU_CFG_FLAG_SET_VSINH (1 << 4)
|
||||
#define SBI_PMU_CFG_FLAG_SET_UINH (1 << 5)
|
||||
#define SBI_PMU_CFG_FLAG_SET_SINH (1 << 6)
|
||||
#define SBI_PMU_CFG_FLAG_SET_MINH (1 << 7)
|
||||
|
||||
/* SBI PMU counter start flags */
|
||||
|
||||
#define SBI_PMU_START_FLAG_SET_INIT_VALUE (1 << 0)
|
||||
#define SBI_PMU_START_FLAG_INIT_FROM_SNAPSHOT (1 << 1)
|
||||
|
||||
/* SBI PMU counter stop flags */
|
||||
|
||||
#define SBI_PMU_STOP_FLAG_RESET (1 << 0)
|
||||
#define SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT (1 << 1)
|
||||
|
||||
/* SBI function IDs for DBCN extension */
|
||||
|
||||
#define SBI_EXT_DBCN_CONSOLE_WRITE 0x0
|
||||
#define SBI_EXT_DBCN_CONSOLE_READ 0x1
|
||||
#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2
|
||||
|
||||
/* SBI function IDs for SUSP extension */
|
||||
|
||||
#define SBI_EXT_SUSP_SUSPEND 0x0
|
||||
|
||||
/* SBI system suspend type */
|
||||
|
||||
#define SBI_SUSP_SLEEP_TYPE_SUSPEND 0x0
|
||||
|
||||
/* SBI return error codes */
|
||||
|
||||
#define SBI_SUCCESS 0
|
||||
#define SBI_ERR_FAILED -1
|
||||
#define SBI_ERR_NOT_SUPPORTED -2
|
||||
#define SBI_ERR_INVALID_PARAM -3
|
||||
#define SBI_ERR_DENIED -4
|
||||
#define SBI_ERR_INVALID_ADDRESS -5
|
||||
#define SBI_ERR_ALREADY_AVAILABLE -6
|
||||
#define SBI_ERR_ALREADY_STARTED -7
|
||||
#define SBI_ERR_ALREADY_STOPPED -8
|
||||
#define SBI_ERR_NO_SHMEM -9
|
||||
#define SBI_ERR_INVALID_STATE -10
|
||||
#define SBI_ERR_BAD_RANGE -11
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct sbiret_s
|
||||
{
|
||||
intreg_t error;
|
||||
uintreg_t value;
|
||||
};
|
||||
typedef struct sbiret_s sbiret_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* RISC-V SBI wrappers ******************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_USE_S_MODE
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sbi_err_map_errno
|
||||
*
|
||||
* Description:
|
||||
* Convert SBI error value to posix error value
|
||||
*
|
||||
* Input Parameters:
|
||||
* err - error value of SBI function
|
||||
*
|
||||
* Return:
|
||||
* Posix error value representing the input
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int sbi_err_map_errno(intreg_t err);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_sbi_send_ipi
|
||||
*
|
||||
* Description:
|
||||
* Send a ipi to the target harts
|
||||
*
|
||||
* Input Parameters:
|
||||
* hmask - bit mask for target harts
|
||||
* hbase - the start hart id to send
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void riscv_sbi_send_ipi(uintreg_t hmask, uintreg_t hbase);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_sbi_set_timer
|
||||
*
|
||||
* Description:
|
||||
* Set new compare match value for timer
|
||||
*
|
||||
* Input Parameters:
|
||||
* stime_value - Value to set
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void riscv_sbi_set_timer(uint64_t stime_value);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_sbi_get_time
|
||||
*
|
||||
* Description:
|
||||
* Get value of mtime
|
||||
*
|
||||
* Return:
|
||||
* Value of mtime
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint64_t riscv_sbi_get_time(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_sbi_boot_secondary
|
||||
*
|
||||
* Description:
|
||||
* Start the target hart
|
||||
*
|
||||
* Input Parameters:
|
||||
* hartid - hart id to start
|
||||
* addr - start address for the hart
|
||||
* a1 - opaque parameter for the hart
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int riscv_sbi_boot_secondary(uintreg_t hartid, uintreg_t addr,
|
||||
uintreg_t a1);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_sbi_system_reset
|
||||
*
|
||||
* Description:
|
||||
* Reset the system with specific type and reason.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int riscv_sbi_system_reset(uint32_t type, uint32_t reason);
|
||||
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_COMMON_RISCV_SBI_H */
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "riscv_sbi.h"
|
||||
#include "riscv_internal.h"
|
||||
|
||||
#ifdef CONFIG_NUTTSBI
|
||||
@ -41,10 +42,10 @@
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline uintptr_t sbi_ecall(unsigned int extid, unsigned int fid,
|
||||
uintptr_t parm0, uintptr_t parm1,
|
||||
uintptr_t parm2, uintptr_t parm3,
|
||||
uintptr_t parm4, uintptr_t parm5)
|
||||
static inline sbiret_t sbi_ecall(unsigned int extid, unsigned int fid,
|
||||
uintreg_t parm0, uintreg_t parm1,
|
||||
uintreg_t parm2, uintreg_t parm3,
|
||||
uintreg_t parm4, uintreg_t parm5)
|
||||
{
|
||||
register long r0 asm("a0") = (long)(parm0);
|
||||
register long r1 asm("a1") = (long)(parm1);
|
||||
@ -54,6 +55,7 @@ static inline uintptr_t sbi_ecall(unsigned int extid, unsigned int fid,
|
||||
register long r5 asm("a5") = (long)(parm5);
|
||||
register long r6 asm("a6") = (long)(fid);
|
||||
register long r7 asm("a7") = (long)(extid);
|
||||
sbiret_t ret;
|
||||
|
||||
asm volatile
|
||||
(
|
||||
@ -63,23 +65,34 @@ static inline uintptr_t sbi_ecall(unsigned int extid, unsigned int fid,
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return r1;
|
||||
ret.error = r0;
|
||||
ret.value = (uintreg_t)r1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_sbi_set_timer
|
||||
*
|
||||
* Description:
|
||||
* Set new compare match value for timer
|
||||
*
|
||||
* Input Parameters:
|
||||
* stime_value - Value to set
|
||||
*
|
||||
****************************************************************************/
|
||||
int sbi_err_map_errno(intreg_t err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case SBI_SUCCESS:
|
||||
return 0;
|
||||
case SBI_ERR_DENIED:
|
||||
return -EPERM;
|
||||
case SBI_ERR_INVALID_PARAM:
|
||||
return -EINVAL;
|
||||
case SBI_ERR_INVALID_ADDRESS:
|
||||
return -EFAULT;
|
||||
case SBI_ERR_NOT_SUPPORTED:
|
||||
case SBI_ERR_FAILED:
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
};
|
||||
}
|
||||
|
||||
void riscv_sbi_set_timer(uint64_t stime_value)
|
||||
{
|
||||
@ -92,22 +105,13 @@ void riscv_sbi_set_timer(uint64_t stime_value)
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_sbi_get_time
|
||||
*
|
||||
* Description:
|
||||
* Get value of mtime
|
||||
*
|
||||
* Return:
|
||||
* Value of mtime
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint64_t riscv_sbi_get_time(void)
|
||||
{
|
||||
#ifdef CONFIG_NUTTSBI
|
||||
return sbi_ecall(SBI_EXT_FIRMWARE, SBI_EXT_FIRMWARE_GET_MTIME, 0, 0,
|
||||
0, 0, 0, 0);
|
||||
sbiret_t ret = sbi_ecall(SBI_EXT_FIRMWARE, SBI_EXT_FIRMWARE_GET_MTIME,
|
||||
0, 0, 0, 0, 0, 0);
|
||||
|
||||
return ret.value;
|
||||
#elif defined(CONFIG_ARCH_RV64)
|
||||
return READ_CSR(CSR_TIME);
|
||||
#else
|
||||
@ -125,23 +129,37 @@ uint64_t riscv_sbi_get_time(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
uintptr_t riscv_sbi_send_ipi(uint32_t hmask, uintptr_t hbase)
|
||||
void riscv_sbi_send_ipi(uintreg_t hmask, uintreg_t hbase)
|
||||
{
|
||||
return sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
|
||||
hmask, hbase, 0, 0, 0, 0);
|
||||
sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
|
||||
hmask, hbase, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NUTTSBI
|
||||
uintptr_t riscv_sbi_system_reset(uint32_t type, uint32_t reason)
|
||||
int riscv_sbi_boot_secondary(uintreg_t hartid, uintreg_t addr,
|
||||
uintreg_t a1)
|
||||
{
|
||||
return sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_SYS_RESET,
|
||||
type, reason, 0, 0, 0, 0);
|
||||
sbiret_t ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START,
|
||||
hartid, addr, a1, 0, 0, 0);
|
||||
|
||||
if (ret.error < 0)
|
||||
{
|
||||
return sbi_err_map_errno(ret.error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintptr_t riscv_sbi_boot_secondary(uint32_t hartid, uintptr_t addr,
|
||||
uintptr_t a1)
|
||||
int riscv_sbi_system_reset(uint32_t type, uint32_t reason)
|
||||
{
|
||||
return sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START,
|
||||
hartid, addr, a1, 0, 0, 0);
|
||||
sbiret_t ret = sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_SYS_RESET,
|
||||
type, reason, 0, 0, 0, 0);
|
||||
|
||||
if (ret.error < 0)
|
||||
{
|
||||
return sbi_err_map_errno(ret.error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NUTTSBI */
|
||||
|
Loading…
Reference in New Issue
Block a user