forked from espressif/esp-idf
feat(esp_tee): Support for ESP-TEE - riscv
component
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
idf_build_get_property(target IDF_TARGET)
|
idf_build_get_property(target IDF_TARGET)
|
||||||
idf_build_get_property(arch IDF_TARGET_ARCH)
|
idf_build_get_property(arch IDF_TARGET_ARCH)
|
||||||
|
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
|
||||||
|
|
||||||
if(NOT "${arch}" STREQUAL "riscv")
|
if(NOT "${arch}" STREQUAL "riscv")
|
||||||
return()
|
return()
|
||||||
@@ -8,6 +9,11 @@ endif()
|
|||||||
|
|
||||||
if(BOOTLOADER_BUILD)
|
if(BOOTLOADER_BUILD)
|
||||||
set(priv_requires soc)
|
set(priv_requires soc)
|
||||||
|
elseif(esp_tee_build)
|
||||||
|
set(priv_requires soc)
|
||||||
|
if(CONFIG_SOC_INT_PLIC_SUPPORTED)
|
||||||
|
set(srcs "interrupt_plic.c")
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
set(priv_requires soc)
|
set(priv_requires soc)
|
||||||
set(srcs
|
set(srcs
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include "soc/interrupt_reg.h"
|
#include "soc/interrupt_reg.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "riscv/csr.h"
|
#include "riscv/csr.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#if SOC_INT_PLIC_SUPPORTED
|
#if SOC_INT_PLIC_SUPPORTED
|
||||||
|
|
||||||
@@ -84,12 +85,34 @@ FORCE_INLINE_ATTR void rv_utils_restore_intlevel_regval(uint32_t restoreval)
|
|||||||
*/
|
*/
|
||||||
FORCE_INLINE_ATTR uint32_t rv_utils_set_intlevel_regval(uint32_t intlevel)
|
FORCE_INLINE_ATTR uint32_t rv_utils_set_intlevel_regval(uint32_t intlevel)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
unsigned prv_mode = RV_READ_CSR(CSR_PRV_MODE);
|
||||||
|
|
||||||
|
unsigned old_xstatus;
|
||||||
|
if (prv_mode == PRV_M) {
|
||||||
|
old_xstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||||
|
} else {
|
||||||
|
old_xstatus = RV_CLEAR_CSR(ustatus, USTATUS_UIE);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t old_thresh = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG);
|
||||||
|
rv_utils_restore_intlevel_regval(intlevel);
|
||||||
|
|
||||||
|
if (prv_mode == PRV_M) {
|
||||||
|
RV_SET_CSR(mstatus, old_xstatus & MSTATUS_MIE);
|
||||||
|
} else {
|
||||||
|
RV_SET_CSR(ustatus, old_xstatus & USTATUS_UIE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return old_thresh;
|
||||||
|
#else
|
||||||
uint32_t old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
uint32_t old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||||
uint32_t old_thresh = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG);
|
uint32_t old_thresh = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG);
|
||||||
rv_utils_restore_intlevel_regval(intlevel);
|
rv_utils_restore_intlevel_regval(intlevel);
|
||||||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||||
|
|
||||||
return old_thresh;
|
return old_thresh;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -187,6 +187,13 @@ extern "C" {
|
|||||||
#define STPC1 0xBF1
|
#define STPC1 0xBF1
|
||||||
#define STPC2 0xBF2
|
#define STPC2 0xBF2
|
||||||
|
|
||||||
|
/* Espressif's custom CSR for the current privilege mode */
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#define CSR_PRV_MODE 0xC10
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61 || CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
#define CSR_PRV_MODE 0x810
|
||||||
|
#endif
|
||||||
|
|
||||||
/* RISC-V CSR macros
|
/* RISC-V CSR macros
|
||||||
* Adapted from https://github.com/michaeljclark/riscv-probe/blob/master/libfemto/include/arch/riscv/machine.h
|
* Adapted from https://github.com/michaeljclark/riscv-probe/blob/master/libfemto/include/arch/riscv/machine.h
|
||||||
*/
|
*/
|
||||||
|
@@ -146,6 +146,21 @@ bool esprv_int_is_vectored(int rv_int_num);
|
|||||||
*/
|
*/
|
||||||
void esprv_int_set_vectored(int rv_int_num, bool vectored);
|
void esprv_int_set_vectored(int rv_int_num, bool vectored);
|
||||||
|
|
||||||
|
/*************************** ESP-TEE specific ***************************/
|
||||||
|
|
||||||
|
/** Function prototype executing interrupt configuration APIs as service calls */
|
||||||
|
typedef void (*esprv_int_mgmt_t)(int argc, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Setup the callback function which executes the interrupt
|
||||||
|
* configuration APIs as TEE service calls
|
||||||
|
*
|
||||||
|
* @note This function should be called right after landing in the REE application,
|
||||||
|
* before any system initialization
|
||||||
|
*
|
||||||
|
* @param fptr Pointer to the function
|
||||||
|
*/
|
||||||
|
void esprv_int_setup_mgmt_cb(void *fptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include the deprecated functions last since they will alias the functions declared above
|
* Include the deprecated functions last since they will alias the functions declared above
|
||||||
|
@@ -15,16 +15,38 @@
|
|||||||
#include "riscv/csr.h"
|
#include "riscv/csr.h"
|
||||||
#include "riscv/interrupt.h"
|
#include "riscv/interrupt.h"
|
||||||
#include "riscv/csr_pie.h"
|
#include "riscv/csr_pie.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Check whether the current privilege level is Machine (M) mode */
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
#define IS_PRV_M_MODE() (RV_READ_CSR(CSR_PRV_MODE) == PRV_M)
|
||||||
|
#else
|
||||||
|
#define IS_PRV_M_MODE() (1UL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD
|
||||||
|
/* [ESP-TEE] Secure service call IDs for interrupt management */
|
||||||
|
#define TEE_INTR_ENABLE_SRV_ID (2)
|
||||||
|
#define TEE_INTR_DISABLE_SRV_ID (3)
|
||||||
|
#define TEE_INTR_SET_PRIORITY_SRV_ID (4)
|
||||||
|
#define TEE_INTR_SET_TYPE_SRV_ID (5)
|
||||||
|
#define TEE_INTR_SET_THRESHOLD_SRV_ID (6)
|
||||||
|
#define TEE_INTR_EDGE_ACK_SRV_ID (7)
|
||||||
|
#define TEE_INTR_GLOBAL_EN_SRV_ID (8)
|
||||||
|
/* [ESP-TEE] Callback function for accessing interrupt management services through REE */
|
||||||
|
extern esprv_int_mgmt_t esp_tee_intr_sec_srv_cb;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SOC_CPU_HAS_CSR_PC
|
#if SOC_CPU_HAS_CSR_PC
|
||||||
/*performance counter*/
|
/*performance counter*/
|
||||||
#define CSR_PCER_MACHINE 0x7e0
|
#define CSR_PCER_MACHINE 0x7e0
|
||||||
#define CSR_PCMR_MACHINE 0x7e1
|
#define CSR_PCMR_MACHINE 0x7e1
|
||||||
#define CSR_PCCR_MACHINE 0x7e2
|
#define CSR_PCCR_MACHINE 0x7e2
|
||||||
|
#define CSR_PCCR_USER 0x802
|
||||||
#endif /* SOC_CPU_HAS_CSR_PC */
|
#endif /* SOC_CPU_HAS_CSR_PC */
|
||||||
|
|
||||||
#if SOC_BRANCH_PREDICTOR_SUPPORTED
|
#if SOC_BRANCH_PREDICTOR_SUPPORTED
|
||||||
@@ -89,7 +111,11 @@ FORCE_INLINE_ATTR uint32_t __attribute__((always_inline)) rv_utils_get_cycle_cou
|
|||||||
#if !SOC_CPU_HAS_CSR_PC
|
#if !SOC_CPU_HAS_CSR_PC
|
||||||
return RV_READ_CSR(mcycle);
|
return RV_READ_CSR(mcycle);
|
||||||
#else
|
#else
|
||||||
|
if (IS_PRV_M_MODE()) {
|
||||||
return RV_READ_CSR(CSR_PCCR_MACHINE);
|
return RV_READ_CSR(CSR_PCCR_MACHINE);
|
||||||
|
} else {
|
||||||
|
return RV_READ_CSR(CSR_PCCR_USER);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +124,11 @@ FORCE_INLINE_ATTR void __attribute__((always_inline)) rv_utils_set_cycle_count(u
|
|||||||
#if !SOC_CPU_HAS_CSR_PC
|
#if !SOC_CPU_HAS_CSR_PC
|
||||||
RV_WRITE_CSR(mcycle, ccount);
|
RV_WRITE_CSR(mcycle, ccount);
|
||||||
#else
|
#else
|
||||||
|
if (IS_PRV_M_MODE()) {
|
||||||
RV_WRITE_CSR(CSR_PCCR_MACHINE, ccount);
|
RV_WRITE_CSR(CSR_PCCR_MACHINE, ccount);
|
||||||
|
} else {
|
||||||
|
RV_WRITE_CSR(CSR_PCCR_USER, ccount);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,32 +143,89 @@ FORCE_INLINE_ATTR void rv_utils_set_mtvec(uint32_t mtvec_val)
|
|||||||
RV_WRITE_CSR(mtvec, mtvec_val | MTVEC_MODE_CSR);
|
RV_WRITE_CSR(mtvec, mtvec_val | MTVEC_MODE_CSR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR void rv_utils_set_xtvec(uint32_t xtvec_val)
|
||||||
|
{
|
||||||
|
xtvec_val |= MTVEC_MODE_CSR; // Set MODE field to treat XTVEC as a vector base address
|
||||||
|
if (IS_PRV_M_MODE()) {
|
||||||
|
RV_WRITE_CSR(mtvec, xtvec_val);
|
||||||
|
} else {
|
||||||
|
RV_WRITE_CSR(utvec, xtvec_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------ Interrupt Control --------------------
|
// ------------------ Interrupt Control --------------------
|
||||||
|
|
||||||
FORCE_INLINE_ATTR void rv_utils_intr_enable(uint32_t intr_mask)
|
FORCE_INLINE_ATTR void rv_utils_intr_enable(uint32_t intr_mask)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD
|
||||||
|
esp_tee_intr_sec_srv_cb(2, TEE_INTR_ENABLE_SRV_ID, intr_mask);
|
||||||
|
#else
|
||||||
// Disable all interrupts to make updating of the interrupt mask atomic.
|
// Disable all interrupts to make updating of the interrupt mask atomic.
|
||||||
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||||
esprv_int_enable(intr_mask);
|
esprv_int_enable(intr_mask);
|
||||||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE_ATTR void rv_utils_intr_disable(uint32_t intr_mask)
|
FORCE_INLINE_ATTR void rv_utils_intr_disable(uint32_t intr_mask)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD
|
||||||
|
esp_tee_intr_sec_srv_cb(2, TEE_INTR_DISABLE_SRV_ID, intr_mask);
|
||||||
|
#else
|
||||||
// Disable all interrupts to make updating of the interrupt mask atomic.
|
// Disable all interrupts to make updating of the interrupt mask atomic.
|
||||||
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||||
esprv_int_disable(intr_mask);
|
esprv_int_disable(intr_mask);
|
||||||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE_ATTR void rv_utils_intr_global_enable(void)
|
FORCE_INLINE_ATTR void rv_utils_intr_global_enable(void)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD
|
||||||
|
esp_tee_intr_sec_srv_cb(1, TEE_INTR_GLOBAL_EN_SRV_ID);
|
||||||
|
#else
|
||||||
RV_SET_CSR(mstatus, MSTATUS_MIE);
|
RV_SET_CSR(mstatus, MSTATUS_MIE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE_ATTR void rv_utils_intr_global_disable(void)
|
FORCE_INLINE_ATTR void rv_utils_intr_global_disable(void)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
if (IS_PRV_M_MODE()) {
|
||||||
RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||||
|
} else {
|
||||||
|
RV_CLEAR_CSR(ustatus, USTATUS_UIE);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR void rv_utils_intr_set_type(int intr_num, enum intr_type type)
|
||||||
|
{
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD
|
||||||
|
esp_tee_intr_sec_srv_cb(3, TEE_INTR_SET_TYPE_SRV_ID, intr_num, type);
|
||||||
|
#else
|
||||||
|
esprv_int_set_type(intr_num, type);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR void rv_utils_intr_set_priority(int rv_int_num, int priority)
|
||||||
|
{
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD
|
||||||
|
esp_tee_intr_sec_srv_cb(3, TEE_INTR_SET_PRIORITY_SRV_ID, rv_int_num, priority);
|
||||||
|
#else
|
||||||
|
esprv_int_set_priority(rv_int_num, priority);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR void rv_utils_intr_set_threshold(int priority_threshold)
|
||||||
|
{
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD
|
||||||
|
esp_tee_intr_sec_srv_cb(2, TEE_INTR_SET_THRESHOLD_SRV_ID, priority_threshold);
|
||||||
|
#else
|
||||||
|
esprv_int_set_threshold(priority_threshold);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -352,8 +439,12 @@ FORCE_INLINE_ATTR bool rv_utils_compare_and_set(volatile uint32_t *addr, uint32_
|
|||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
// For a single core RV target has no atomic CAS instruction, we can achieve atomicity by disabling interrupts
|
// For a single core RV target has no atomic CAS instruction, we can achieve atomicity by disabling interrupts
|
||||||
unsigned old_mstatus;
|
unsigned old_xstatus;
|
||||||
old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
if (IS_PRV_M_MODE()) {
|
||||||
|
old_xstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||||
|
} else {
|
||||||
|
old_xstatus = RV_CLEAR_CSR(ustatus, USTATUS_UIE);
|
||||||
|
}
|
||||||
// Compare and set
|
// Compare and set
|
||||||
uint32_t old_value;
|
uint32_t old_value;
|
||||||
old_value = *addr;
|
old_value = *addr;
|
||||||
@@ -361,7 +452,11 @@ FORCE_INLINE_ATTR bool rv_utils_compare_and_set(volatile uint32_t *addr, uint32_
|
|||||||
*addr = new_value;
|
*addr = new_value;
|
||||||
}
|
}
|
||||||
// Restore interrupts
|
// Restore interrupts
|
||||||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
if (IS_PRV_M_MODE()) {
|
||||||
|
RV_SET_CSR(mstatus, old_xstatus & MSTATUS_MIE);
|
||||||
|
} else {
|
||||||
|
RV_SET_CSR(ustatus, old_xstatus & USTATUS_UIE);
|
||||||
|
}
|
||||||
|
|
||||||
#endif //__riscv_atomic
|
#endif //__riscv_atomic
|
||||||
return (old_value == compare_value);
|
return (old_value == compare_value);
|
||||||
|
@@ -4,7 +4,10 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
#include "riscv/csr.h"
|
||||||
#include "riscv/interrupt.h"
|
#include "riscv/interrupt.h"
|
||||||
|
#include "riscv/rv_utils.h"
|
||||||
#include "esp_private/interrupt_plic.h"
|
#include "esp_private/interrupt_plic.h"
|
||||||
#include "hal/interrupt_plic_ll.h"
|
#include "hal/interrupt_plic_ll.h"
|
||||||
|
|
||||||
@@ -18,19 +21,35 @@ void intr_matrix_route(int intr_src, int intr_num)
|
|||||||
|
|
||||||
uint32_t esprv_get_interrupt_unmask(void)
|
uint32_t esprv_get_interrupt_unmask(void)
|
||||||
{
|
{
|
||||||
return interrupt_plic_ll_get_unmask();
|
if (IS_PRV_M_MODE()) {
|
||||||
|
return REG_READ(PLIC_MXINT_ENABLE_REG);
|
||||||
|
} else {
|
||||||
|
return REG_READ(PLIC_UXINT_ENABLE_REG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum intr_type esprv_int_get_type(int rv_int_num)
|
enum intr_type esprv_int_get_type(int rv_int_num)
|
||||||
{
|
{
|
||||||
return interrupt_plic_ll_get_type(rv_int_num) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
|
uint32_t intr_type_reg;
|
||||||
|
|
||||||
|
if (IS_PRV_M_MODE()) {
|
||||||
|
intr_type_reg = REG_READ(PLIC_MXINT_TYPE_REG);
|
||||||
|
} else {
|
||||||
|
intr_type_reg = REG_READ(PLIC_UXINT_TYPE_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (intr_type_reg & (1 << rv_int_num)) ? INTR_TYPE_EDGE : INTR_TYPE_LEVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int esprv_int_get_priority(int rv_int_num)
|
int esprv_int_get_priority(int rv_int_num)
|
||||||
{
|
{
|
||||||
return interrupt_plic_ll_get_priority(rv_int_num);
|
if (IS_PRV_M_MODE()) {
|
||||||
|
return REG_READ(PLIC_MXINT0_PRI_REG + (rv_int_num) * 4);
|
||||||
|
} else {
|
||||||
|
return REG_READ(PLIC_UXINT0_PRI_REG + (rv_int_num) * 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -38,3 +57,44 @@ bool esprv_int_is_vectored(int rv_int_num)
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD
|
||||||
|
DRAM_ATTR esprv_int_mgmt_t esp_tee_intr_sec_srv_cb = NULL;
|
||||||
|
|
||||||
|
void esprv_int_setup_mgmt_cb(void *fptr)
|
||||||
|
{
|
||||||
|
esp_tee_intr_sec_srv_cb = (esprv_int_mgmt_t)fptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: Overriding ROM-based interrupt configuration symbols */
|
||||||
|
void esprv_int_enable(uint32_t unmask)
|
||||||
|
{
|
||||||
|
rv_utils_intr_enable(unmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void esprv_int_disable(uint32_t mask)
|
||||||
|
{
|
||||||
|
rv_utils_intr_disable(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void esprv_int_set_type(int intr_num, enum intr_type type)
|
||||||
|
{
|
||||||
|
rv_utils_intr_set_type(intr_num, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void esprv_int_set_priority(int rv_int_num, int priority)
|
||||||
|
{
|
||||||
|
rv_utils_intr_set_priority(rv_int_num, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void esprv_int_set_threshold(int priority_threshold)
|
||||||
|
{
|
||||||
|
rv_utils_intr_set_threshold(priority_threshold);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@@ -76,11 +76,39 @@
|
|||||||
sw t6, RV_STK_T6(sp)
|
sw t6, RV_STK_T6(sp)
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro save_mepc
|
/* Macro for saving special registers depending on the active execution
|
||||||
|
* environment - REE - U-mode / TEE - M-mode */
|
||||||
|
/* Save the XEPC register */
|
||||||
|
.macro save_xepc
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
csrr t0, uepc
|
||||||
|
#else
|
||||||
csrr t0, mepc
|
csrr t0, mepc
|
||||||
|
#endif
|
||||||
sw t0, RV_STK_MEPC(sp)
|
sw t0, RV_STK_MEPC(sp)
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
/* Save the required CSRs */
|
||||||
|
.macro save_xcsr
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
csrr t0, ustatus
|
||||||
|
sw t0, RV_STK_MSTATUS(sp)
|
||||||
|
csrr t0, utvec
|
||||||
|
sw t0, RV_STK_MTVEC(sp)
|
||||||
|
csrr t0, utval
|
||||||
|
sw t0, RV_STK_MTVAL(sp)
|
||||||
|
#else
|
||||||
|
csrr t0, mstatus
|
||||||
|
sw t0, RV_STK_MSTATUS(sp)
|
||||||
|
csrr t0, mtvec
|
||||||
|
sw t0, RV_STK_MTVEC(sp)
|
||||||
|
csrr t0, mhartid
|
||||||
|
sw t0, RV_STK_MHARTID(sp)
|
||||||
|
csrr t0, mtval
|
||||||
|
sw t0, RV_STK_MTVAL(sp)
|
||||||
|
#endif
|
||||||
|
.endm
|
||||||
|
|
||||||
/* Restore the general purpose registers (excluding gp) from the context on
|
/* Restore the general purpose registers (excluding gp) from the context on
|
||||||
* the stack. The context is then deallocated. The default size is CONTEXT_SIZE
|
* the stack. The context is then deallocated. The default size is CONTEXT_SIZE
|
||||||
* but it can be overridden. */
|
* but it can be overridden. */
|
||||||
@@ -117,11 +145,49 @@
|
|||||||
addi sp,sp, \cxt_size
|
addi sp,sp, \cxt_size
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro restore_mepc
|
/* Macro for restoring special registers depending on the active execution
|
||||||
|
* environment - REE - U-mode / TEE - M-mode */
|
||||||
|
|
||||||
|
/* Restore the XEPC register depending on the active execution
|
||||||
|
* environment - REE - U-mode / TEE - M-mode */
|
||||||
|
.macro restore_xepc
|
||||||
lw t0, RV_STK_MEPC(sp)
|
lw t0, RV_STK_MEPC(sp)
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
csrw uepc, t0
|
||||||
|
#else
|
||||||
csrw mepc, t0
|
csrw mepc, t0
|
||||||
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
/* Macros for enabling/disabling the global interrupts based on the
|
||||||
|
* active execution environment - REE - U-mode / TEE - M-mode */
|
||||||
|
.macro enable_intr
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
li t0, 0x1
|
||||||
|
csrs ustatus, t0
|
||||||
|
#else
|
||||||
|
li t0, 0x8
|
||||||
|
csrs mstatus, t0
|
||||||
|
#endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro disable_intr
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
li t0, 0x1
|
||||||
|
csrc ustatus, t0
|
||||||
|
#else
|
||||||
|
li t0, 0x8
|
||||||
|
csrc mstatus, t0
|
||||||
|
#endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro xret
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
uret
|
||||||
|
#else
|
||||||
|
mret
|
||||||
|
#endif
|
||||||
|
.endm
|
||||||
|
|
||||||
.global rtos_int_enter
|
.global rtos_int_enter
|
||||||
.global rtos_int_exit
|
.global rtos_int_exit
|
||||||
@@ -148,19 +214,15 @@ _panic_handler:
|
|||||||
|
|
||||||
/* Save CSRs */
|
/* Save CSRs */
|
||||||
sw t0, RV_STK_SP(sp)
|
sw t0, RV_STK_SP(sp)
|
||||||
csrr t0, mepc
|
save_xepc
|
||||||
sw t0, RV_STK_MEPC(sp)
|
save_xcsr
|
||||||
csrr t0, mstatus
|
|
||||||
sw t0, RV_STK_MSTATUS(sp)
|
|
||||||
csrr t0, mtvec
|
|
||||||
sw t0, RV_STK_MTVEC(sp)
|
|
||||||
csrr t0, mhartid
|
|
||||||
sw t0, RV_STK_MHARTID(sp)
|
|
||||||
csrr t0, mtval
|
|
||||||
sw t0, RV_STK_MTVAL(sp)
|
|
||||||
|
|
||||||
/* Keep mcause in s0, only the exception code and interrupt bit are relevant */
|
/* Keep mcause in s0, only the exception code and interrupt bit are relevant */
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
csrr s0, ucause
|
||||||
|
#else
|
||||||
csrr s0, mcause
|
csrr s0, mcause
|
||||||
|
#endif
|
||||||
li t1, VECTORS_MCAUSE_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK
|
li t1, VECTORS_MCAUSE_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK
|
||||||
and s0, s0, t1
|
and s0, s0, t1
|
||||||
|
|
||||||
@@ -274,7 +336,7 @@ _store_mcause:
|
|||||||
* Restore the registers and return from the exception.
|
* Restore the registers and return from the exception.
|
||||||
*/
|
*/
|
||||||
_return_from_exception:
|
_return_from_exception:
|
||||||
restore_mepc
|
restore_xepc
|
||||||
/* MTVEC and SP are assumed to be unmodified.
|
/* MTVEC and SP are assumed to be unmodified.
|
||||||
* MSTATUS, MHARTID, MTVAL are read-only and not restored.
|
* MSTATUS, MHARTID, MTVAL are read-only and not restored.
|
||||||
*/
|
*/
|
||||||
@@ -290,12 +352,14 @@ _return_from_exception:
|
|||||||
* from the stack.
|
* from the stack.
|
||||||
*/
|
*/
|
||||||
.global _interrupt_handler
|
.global _interrupt_handler
|
||||||
|
.global _tee_interrupt_handler
|
||||||
.type _interrupt_handler, @function
|
.type _interrupt_handler, @function
|
||||||
_interrupt_handler:
|
_interrupt_handler:
|
||||||
|
_tee_interrupt_handler:
|
||||||
/* Start by saving the general purpose registers and the PC value before
|
/* Start by saving the general purpose registers and the PC value before
|
||||||
* the interrupt happened. */
|
* the interrupt happened. */
|
||||||
save_general_regs
|
save_general_regs
|
||||||
save_mepc
|
save_xepc
|
||||||
|
|
||||||
/* Though it is not necessary we save GP and SP here.
|
/* Though it is not necessary we save GP and SP here.
|
||||||
* SP is necessary to help GDB to properly unwind
|
* SP is necessary to help GDB to properly unwind
|
||||||
@@ -317,8 +381,13 @@ _interrupt_handler:
|
|||||||
/* If this is a non-nested interrupt, SP now points to the interrupt stack */
|
/* If this is a non-nested interrupt, SP now points to the interrupt stack */
|
||||||
|
|
||||||
/* Before dispatch c handler, restore interrupt to enable nested intr */
|
/* Before dispatch c handler, restore interrupt to enable nested intr */
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
csrr s1, ucause
|
||||||
|
csrr s2, ustatus
|
||||||
|
#else
|
||||||
csrr s1, mcause
|
csrr s1, mcause
|
||||||
csrr s2, mstatus
|
csrr s2, mstatus
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !SOC_INT_HW_NESTED_SUPPORTED
|
#if !SOC_INT_HW_NESTED_SUPPORTED
|
||||||
/* Save the interrupt threshold level */
|
/* Save the interrupt threshold level */
|
||||||
@@ -337,7 +406,7 @@ _interrupt_handler:
|
|||||||
fence
|
fence
|
||||||
#endif // !SOC_INT_HW_NESTED_SUPPORTED
|
#endif // !SOC_INT_HW_NESTED_SUPPORTED
|
||||||
|
|
||||||
csrsi mstatus, 0x8
|
enable_intr
|
||||||
/* MIE set. Nested interrupts can now occur */
|
/* MIE set. Nested interrupts can now occur */
|
||||||
|
|
||||||
#ifdef CONFIG_PM_TRACE
|
#ifdef CONFIG_PM_TRACE
|
||||||
@@ -366,7 +435,7 @@ _interrupt_handler:
|
|||||||
|
|
||||||
/* After dispatch c handler, disable interrupt to make freertos make context switch */
|
/* After dispatch c handler, disable interrupt to make freertos make context switch */
|
||||||
|
|
||||||
csrci mstatus, 0x8
|
disable_intr
|
||||||
/* MIE cleared. Nested interrupts are disabled */
|
/* MIE cleared. Nested interrupts are disabled */
|
||||||
|
|
||||||
#if !SOC_INT_HW_NESTED_SUPPORTED
|
#if !SOC_INT_HW_NESTED_SUPPORTED
|
||||||
@@ -386,10 +455,15 @@ _interrupt_handler:
|
|||||||
* In case the target uses the CLIC, it is mandatory to restore `mcause` register since it contains
|
* In case the target uses the CLIC, it is mandatory to restore `mcause` register since it contains
|
||||||
* the former CPU priority. When executing `mret`, the hardware will restore the former threshold,
|
* the former CPU priority. When executing `mret`, the hardware will restore the former threshold,
|
||||||
* from `mcause` to `mintstatus` CSR */
|
* from `mcause` to `mintstatus` CSR */
|
||||||
|
#if CONFIG_SECURE_ENABLE_TEE
|
||||||
|
csrw ucause, s1
|
||||||
|
csrw ustatus, a0
|
||||||
|
#else
|
||||||
csrw mcause, s1
|
csrw mcause, s1
|
||||||
csrw mstatus, a0
|
csrw mstatus, a0
|
||||||
restore_mepc
|
#endif
|
||||||
|
restore_xepc
|
||||||
restore_general_regs
|
restore_general_regs
|
||||||
/* exit, this will also re-enable the interrupts */
|
/* exit, this will also re-enable the interrupts */
|
||||||
mret
|
xret
|
||||||
.size _interrupt_handler, .-_interrupt_handler
|
.size _interrupt_handler, .-_interrupt_handler
|
||||||
|
Reference in New Issue
Block a user