xtensa/esp32: Configure the PID controller for privilege separation

Signed-off-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
This commit is contained in:
Gustavo Henrique Nihei
2022-05-20 12:40:04 -03:00
committed by Xiang Xiao
parent 76acfef5ec
commit 27fc3c959d
16 changed files with 679 additions and 68 deletions
+4
View File
@@ -129,6 +129,10 @@ config XTENSA_HAVE_DCACHE_LOCK
bool
default n
config XTENSA_HAVE_EXCEPTION_HOOKS
bool
default n
config XTENSA_ICACHE
bool "Use I-Cache"
default n
+15 -3
View File
@@ -113,10 +113,19 @@
#ifndef __XTENSA_CALL0_ABI__
/* Temporary space for saving stuff during window spill. */
# define REG_TMP0 (_REG_WINDOW_TMPS + 0)
# define _REG_OVLY_START (_REG_WINDOW_TMPS + 1)
# define REG_TMP0 (_REG_WINDOW_TMPS + 0)
# define _REG_INT_CTX_START (_REG_WINDOW_TMPS + 1)
#else
# define _REG_OVLY_START _REG_WINDOW_TMPS
# define _REG_INT_CTX_START _REG_WINDOW_TMPS
#endif
#ifndef CONFIG_BUILD_FLAT
/* Temporary space for saving Interrupt Context information */
# define REG_INT_CTX (_REG_INT_CTX_START + 0)
# define _REG_OVLY_START (_REG_INT_CTX_START + 1)
#else
# define _REG_OVLY_START _REG_INT_CTX_START
#endif
#ifdef CONFIG_XTENSA_USE_OVLY
@@ -155,6 +164,9 @@
struct xcpt_syscall_s
{
uintptr_t sysreturn; /* The return PC */
#ifndef CONFIG_BUILD_FLAT
uintptr_t int_ctx; /* Interrupt context */
#endif
};
#endif
@@ -517,6 +517,55 @@ _xtensa_level6_handler:
#endif /* XCHAL_EXCM_LEVEL >= 6 */
#if XCHAL_HAVE_NMI
.section HANDLER_SECTION, "ax"
.type _xtensa_nmi_handler, @function
.global _xtensa_nmi_handler
.align 4
_xtensa_nmi_handler:
/* For now, just panic */
exception_entry XCHAL_NMILEVEL
movi a2, XTENSA_NMI_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
.size _xtensa_nmi_handler, . -_xtensa_nmi_handler
#endif /* XCHAL_HAVE_NMI */
#if XCHAL_HAVE_DEBUG
.section HANDLER_SECTION, "ax"
.type _xtensa_debug_handler, @function
.global _xtensa_debug_handler
.align 4
_xtensa_debug_handler:
exception_entry XCHAL_DEBUGLEVEL
movi a2, XTENSA_DEBUG_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
.size _xtensa_debug_handler, . -_xtensa_debug_handler
#endif /* XCHAL_HAVE_DEBUG */
.section HANDLER_SECTION, "ax"
.type _xtensa_kernel_handler, @function
.global _xtensa_kernel_handler
.align 4
_xtensa_kernel_handler:
exception_entry 1
movi a2, XTENSA_KERNEL_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
.size _xtensa_kernel_handler, . -_xtensa_kernel_handler
/****************************************************************************
* HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) LOW-LEVEL HANDLERS
*
+14
View File
@@ -178,6 +178,13 @@
s32i a0, sp, (4 * REG_PS)
rsr a0, EPC_1 + \level - 1 /* Save interruptee's PC */
s32i a0, sp, (4 * REG_PC)
#ifdef CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS
/* Perform chip-specific exception entry operations */
exception_entry_hook \level sp a0
#endif
rsr a0, EXCSAVE_1 + \level - 1 /* Save interruptee's a0 */
s32i a0, sp, (4 * REG_A0)
s32i a2, sp, (4 * REG_A2)
@@ -199,6 +206,13 @@
ps_excp_write a0 \level
l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
wsr a0, EPC_1 + \level - 1
#ifdef CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS
/* Perform chip-specific exception exit operations */
exception_exit_hook \level a2 a0 a1
#endif
l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i sp, a2, (4 * REG_A1) /* Retrieve interrupt stack frame */
l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
+19 -3
View File
@@ -32,10 +32,11 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include "sched/sched.h"
#include "xtensa.h"
#include "irq/irq.h"
#include "sched/sched.h"
#include "chip.h"
#include "xtensa.h"
/****************************************************************************
* Public Functions
@@ -155,6 +156,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM |
PS_WOE | PS_CALLINC(1));
#endif
#ifndef CONFIG_BUILD_FLAT
xtensa_raiseprivilege(CURRENT_REGS);
#endif
CURRENT_REGS[REG_A1] = (uint32_t)CURRENT_REGS +
XCPTCONTEXT_SIZE;
@@ -200,6 +204,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_PS] = (uint32_t)
(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM |
PS_WOE | PS_CALLINC(1));
#endif
#ifndef CONFIG_BUILD_FLAT
xtensa_raiseprivilege(tcb->xcp.regs);
#endif
}
}
@@ -306,6 +313,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_PS] = (uint32_t)
(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM |
PS_WOE | PS_CALLINC(1));
#endif
#ifndef CONFIG_BUILD_FLAT
xtensa_raiseprivilege(tcb->xcp.regs);
#endif
}
else
@@ -348,6 +358,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
CURRENT_REGS[REG_PS] = (uint32_t)
(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM |
PS_WOE | PS_CALLINC(1));
#endif
#ifndef CONFIG_BUILD_FLAT
xtensa_raiseprivilege(CURRENT_REGS);
#endif
}
@@ -422,6 +435,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
tcb->xcp.regs[REG_PS] = (uint32_t)
(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM |
PS_WOE | PS_CALLINC(1));
#endif
#ifndef CONFIG_BUILD_FLAT
xtensa_raiseprivilege(tcb->xcp.regs);
#endif
}
}
+27 -16
View File
@@ -24,16 +24,16 @@
#include <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <debug.h>
#include <stdint.h>
#include <nuttx/arch.h>
#include <arch/xtensa/xtensa_specregs.h>
#include <nuttx/arch.h>
#include <sys/syscall.h>
#include "chip.h"
#include "signal/signal.h"
#include "syscall.h"
#include "xtensa.h"
/****************************************************************************
@@ -84,13 +84,8 @@ int xtensa_swint(int irq, void *context, void *arg)
*/
#ifdef CONFIG_DEBUG_SYSCALL_INFO
# ifndef CONFIG_DEBUG_SYSCALL
if (cmd > SYS_switch_context)
# endif
{
svcinfo("SYSCALL Entry: regs: %p cmd: %d\n", regs, cmd);
xtensa_registerdump(regs);
}
svcinfo("SYSCALL Entry: regs: %p cmd: %" PRIu32 "\n", regs, cmd);
xtensa_registerdump(regs);
#endif
/* Handle the syscall according to the command in A2 */
@@ -193,6 +188,9 @@ int xtensa_swint(int irq, void *context, void *arg)
*/
regs[REG_PC] = rtcb->xcp.syscall[index].sysreturn;
#ifndef CONFIG_BUILD_FLAT
xtensa_restoreprivilege(regs, rtcb->xcp.syscall[index].int_ctx);
#endif
/* The return value must be in A2-A5.
* xtensa_dispatch_syscall() temporarily moved the value into A3.
@@ -249,6 +247,10 @@ int xtensa_swint(int irq, void *context, void *arg)
regs[REG_A7] = regs[REG_A5]; /* argv */
#endif
/* Execute the task in User mode */
xtensa_lowerprivilege(regs); /* User mode */
/* User task rotates window, so pretend task was 'call4'd */
regs[REG_PS] = PS_UM | PS_WOE | PS_CALLINC(1);
@@ -285,6 +287,10 @@ int xtensa_swint(int irq, void *context, void *arg)
regs[REG_A6] = regs[REG_A4]; /* pthread entry */
regs[REG_A7] = regs[REG_A5]; /* arg */
/* Execute the pthread in User mode */
xtensa_lowerprivilege(regs); /* User mode */
/* Startup task rotates window, so pretend task was 'call4'd */
regs[REG_PS] = PS_UM | PS_WOE | PS_CALLINC(1);
@@ -322,6 +328,8 @@ int xtensa_swint(int irq, void *context, void *arg)
regs[REG_PC] = (uintptr_t)USERSPACE->signal_handler;
xtensa_lowerprivilege(regs); /* User mode */
/* Change the parameter ordering to match the expectation of struct
* userpace_s signal_handler.
*/
@@ -353,6 +361,8 @@ int xtensa_swint(int irq, void *context, void *arg)
DEBUGASSERT(rtcb->xcp.sigreturn != 0);
regs[REG_PC] = rtcb->xcp.sigreturn;
xtensa_raiseprivilege(regs); /* Privileged mode */
rtcb->xcp.sigreturn = 0;
}
break;
@@ -382,11 +392,18 @@ int xtensa_swint(int irq, void *context, void *arg)
/* Setup to return to xtensa_dispatch_syscall in privileged mode. */
rtcb->xcp.syscall[index].sysreturn = regs[REG_PC];
#ifndef CONFIG_BUILD_FLAT
xtensa_saveprivilege(regs, rtcb->xcp.syscall[index].int_ctx);
#endif
rtcb->xcp.nsyscalls = index + 1;
regs[REG_PC] = (uintptr_t)xtensa_dispatch_syscall;
#ifndef CONFIG_BUILD_FLAT
xtensa_raiseprivilege(regs); /* Privileged mode */
#endif
/* Offset A2 to account for the reserved values */
regs[REG_A2] -= CONFIG_SYS_RESERVED;
@@ -428,21 +445,15 @@ int xtensa_swint(int irq, void *context, void *arg)
*/
#ifdef CONFIG_DEBUG_SYSCALL_INFO
# ifndef CONFIG_DEBUG_SYSCALL
if (cmd > SYS_switch_context)
# else
if (regs != CURRENT_REGS)
# endif
{
svcinfo("SYSCALL Return: Context switch!\n");
xtensa_registerdump((const uintptr_t *)CURRENT_REGS);
}
# ifdef CONFIG_DEBUG_SYSCALL
else
{
svcinfo("SYSCALL Return: %" PRIu32 "\n", cmd);
}
# endif
#endif
return OK;
+14 -30
View File
@@ -183,30 +183,16 @@ _xtensa_level6_vector:
.begin literal_prefix .nmi_vector
.section .nmi_vector.text, "ax"
.global _xtensa_nmi_vector
.global _xtensa_nmi_handler
.type _xtensa_nmi_vector, @function
.align 4
_xtensa_nmi_vector:
wsr a0, EXCSAVE + XCHAL_NMILEVEL /* Preserve a0 */
call0 _xtensa_nmi_handler
#if 1
/* For now, just panic */
wsr a0, EXCSAVE + XCHAL_NMILEVEL /* Preserve a0 */
exception_entry XCHAL_NMILEVEL
movi a2, XTENSA_NMI_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
#else
/* Add high priority non-maskable interrupt (NMI) handler code here. */
rfi XCHAL_NMILEVEL
#endif
.size _xtensa_nmi_vector, . - _xtensa_nmi_vector
.end literal_prefix
.size _xtensa_nmi_vector, . - _xtensa_nmi_vector
.end literal_prefix
#endif /* XCHAL_HAVE_NMI */
@@ -222,16 +208,15 @@ _xtensa_nmi_vector:
.begin literal_prefix .debug_exception_vector
.section .debug_exception_vector.text, "ax"
.global _debug_exception_vector
.global _xtensa_debug_handler
.type _debug_exception_vector, @function
.align 4
_debug_exception_vector:
wsr a0, EXCSAVE + XCHAL_DEBUGLEVEL /* Preserve a0 */
exception_entry XCHAL_DEBUGLEVEL
movi a2, XTENSA_DEBUG_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
wsr a0, EXCSAVE + XCHAL_DEBUGLEVEL /* Preserve a0 */
call0 _xtensa_debug_handler
.size _debug_exception_vector, . - _debug_exception_vector
.end literal_prefix
#endif /* XCHAL_HAVE_DEBUG */
@@ -299,6 +284,8 @@ _double_exception_vector:
.begin literal_prefix .kernel_exception_vector
.section .kernel_exception_vector.text, "ax"
.global _kernel_exception_vector
.global _xtensa_kernel_handler
.type _kernel_exception_vector, @function
.align 4
_kernel_exception_vector:
@@ -308,12 +295,9 @@ _kernel_exception_vector:
#endif
wsr a0, EXCSAVE_1 /* Preserve a0 */
call0 _xtensa_kernel_handler
exception_entry 1
movi a2, XTENSA_KERNEL_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
.size _kernel_exception_vector, . - _kernel_exception_vector
.end literal_prefix
/****************************************************************************
+19 -1
View File
@@ -31,12 +31,14 @@
*
****************************************************************************/
.file "xtensa_vectors.S"
.file "xtensa_window_vector.S"
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <arch/xtensa/xtensa_specregs.h>
#include <arch/xtensa/core.h>
#include <arch/chip/core-isa.h>
@@ -96,7 +98,11 @@ _window_overflow4:
s32e a1, a5, -12 /* Save a1 to call[j+1]'s stack frame */
s32e a2, a5, -8 /* Save a2 to call[j+1]'s stack frame */
s32e a3, a5, -4 /* Save a3 to call[j+1]'s stack frame */
#ifdef CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS
j _overflow4_exit_hook
#else
rfwo /* Rotates back to call[i] position */
#endif
/* Window Underflow Exception for Call4
*
@@ -119,7 +125,11 @@ _window_underflow4:
l32e a1, a5, -12 /* Restore a1 from call[i+1]'s stack frame */
l32e a2, a5, -8 /* Restore a2 from call[i+1]'s stack frame */
l32e a3, a5, -4 /* Restore a3 from call[i+1]'s stack frame */
#ifdef CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS
j _underflow4_exit_hook
#else
rfwu
#endif
/* Handle alloca exception generated by interruptee executing 'movsp'.
* This uses space between the window vectors, so is essentially "free".
@@ -178,7 +188,11 @@ _window_overflow8:
s32e a5, a0, -28 /* Save a5 to call[j]'s stack frame */
s32e a6, a0, -24 /* Save a6 to call[j]'s stack frame */
s32e a7, a0, -20 /* Save a7 to call[j]'s stack frame */
#ifdef CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS
j _overflow8_exit_hook
#else
rfwo /* Rotates back to call[i] position */
#endif
/* Window Underflow Exception for Call8
*
@@ -207,7 +221,11 @@ _window_underflow8:
l32e a5, a7, -28 /* Restore a5 from call[i]'s stack frame */
l32e a6, a7, -24 /* Restore a6 from call[i]'s stack frame */
l32e a7, a7, -20 /* Restore a7 from call[i]'s stack frame */
#ifdef CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS
j _underflow8_exit_hook
#else
rfwu
#endif
/* Window Overflow Exception for Call12
*
+7
View File
@@ -541,6 +541,13 @@ config ESP32_AES_ACCELERATOR
bool "AES Accelerator"
default n
config ESP32_PID
bool "PID Controller"
default n
select ARCH_USE_MPU
select XTENSA_HAVE_EXCEPTION_HOOKS if BUILD_PROTECTED
depends on EXPERIMENTAL
endmenu # ESP32 Peripheral Selection
config ESP32_WIFI_BT_COEXIST
+5 -1
View File
@@ -23,7 +23,11 @@ include common/Make.defs
# The start-up, "head", file. May be either a .S or a .c file.
HEAD_CSRC = esp32_start.c esp32_wdt.c
HEAD_CSRC = esp32_start.c esp32_wdt.c
ifeq ($(CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS),y)
HEAD_ASRC += esp32_window_hooks.S
endif
# Required ESP32 files (arch/xtensa/src/esp32)
+131
View File
@@ -39,6 +39,10 @@
#include <nuttx/config.h>
#if defined(CONFIG_ESP32_PID) && defined(CONFIG_BUILD_PROTECTED)
#include "hardware/esp32_pid.h"
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -49,6 +53,23 @@
#define HANDLER_SECTION .iram1
#if defined(CONFIG_ESP32_PID) && defined(CONFIG_BUILD_PROTECTED)
/* Definitions for the PIDs reserved for Kernel and Userspace */
#define PIDCTRL_PID_KERNEL 0 /* Privileged */
#define PIDCTRL_PID_USER 5 /* Non-privileged */
/* Macros for privilege handling with the PID Controller peripheral */
#define xtensa_saveprivilege(regs,var) ((var) = (regs)[REG_INT_CTX])
#define xtensa_restoreprivilege(regs,var) ((regs)[REG_INT_CTX] = (var))
#define xtensa_lowerprivilege(regs) ((regs)[REG_INT_CTX] = PIDCTRL_PID_USER)
#define xtensa_raiseprivilege(regs) ((regs)[REG_INT_CTX] = PIDCTRL_PID_KERNEL)
#endif
/****************************************************************************
* Public Data
****************************************************************************/
@@ -95,6 +116,116 @@
l32i a1, \tmp2, 0 /* a1 = *tmp2 */
.endm
#endif
/****************************************************************************
* Name: get_prev_pid
*
* Description:
* Retrieve PID information from interruptee.
*
* Entry Conditions:
* level - Interrupt level
* out - Temporary and output register
*
* Exit Conditions:
* PID value to be returned will be written to "out" register.
*
****************************************************************************/
#ifdef CONFIG_ESP32_PID
.macro get_prev_pid level out
movi \out, PIDCTRL_FROM_1_REG + (\level - 1) * 0x4
l32i \out, \out, 0
extui \out, \out, 0, 3
.endm
#endif
/****************************************************************************
* Name: set_next_pid
*
* Description:
* Configure the PID Controller for the new execution context.
*
* Entry Conditions:
* in - PID to be set
* tmp - Temporary register
*
* Exit Conditions:
* Register "in" has been trashed.
*
****************************************************************************/
#ifdef CONFIG_ESP32_PID
.macro set_next_pid in tmp
movi \tmp, PIDCTRL_PID_NEW_REG
s32i \in, \tmp, 0 /* Set new PID */
movi \tmp, PIDCTRL_PID_DELAY_REG
movi \in, 0x0
s32i \in, \tmp, 0 /* Set delay (cycles) for PID change */
movi \tmp, PIDCTRL_PID_CONFIRM_REG
movi \in, 0x1
s32i \in, \tmp, 0 /* Confirm change to the new PID */
.endm
#endif
/****************************************************************************
* Name: exception_entry_hook
*
* Description:
* Perform chip-specific exception entry operations.
*
* Entry Conditions:
* level - Interrupt level
* reg_sp - Stack pointer
* tmp - Temporary register
*
****************************************************************************/
#ifdef CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS
.macro exception_entry_hook level reg_sp tmp
/* Save PID information from interruptee when handling User (Level 1) and
* Software-triggered interrupts (Level 3).
*/
.ifeq (\level - 1) & (\level - 3)
get_prev_pid \level \tmp
s32i \tmp, \reg_sp, (4 * REG_INT_CTX) /* Save PID into context area */
.endif
.endm
#endif
/****************************************************************************
* Name: exception_exit_hook
*
* Description:
* Perform chip-specific exception exit operations.
*
* Entry Conditions:
* level - Interrupt level
* reg_sp - Stack pointer
* tmp1 - Temporary register 1
* tmp2 - Temporary register 2
*
****************************************************************************/
#ifdef CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS
.macro exception_exit_hook level reg_sp tmp1 tmp2
/* Configure the PID Controller for the new execution context before
* returning from User (Level 1) and Software-triggered interrupts
* (Level 3).
*/
.ifeq (\level - 1) & (\level - 3)
l32i \tmp1, \reg_sp, (4 * REG_INT_CTX)
set_next_pid \tmp1 \tmp2
.endif
.endm
#endif
#endif /* __ASSEMBLY */
/****************************************************************************
+18 -3
View File
@@ -141,6 +141,7 @@ uint32_t g_idlestack[IDLETHREAD_STACKWORDS]
static noreturn_function void __esp32_start(void)
{
uint32_t sp;
uint32_t regval unused_data;
/* Make sure that normal interrupts are disabled. This is really only an
* issue when we are started in un-usual ways (such as from IRAM). In this
@@ -163,17 +164,31 @@ static noreturn_function void __esp32_start(void)
esp32_region_protection();
#if defined(CONFIG_ESP32_PID) && defined(CONFIG_BUILD_PROTECTED)
/* We have 2 VECBASE Addresses: one in CPU and one in DPORT peripheral.
* CPU has no knowledge of PID hence any PID can change the CPU VECBASE
* address thus jumping to malicious interrupt vectors with higher
* privilege.
* So we configure CPU to use the VECBASE address in DPORT peripheral.
*/
regval = ((uint32_t)&_init_start) >> 10;
putreg32(regval, DPORT_PRO_VECBASE_SET_REG);
regval = getreg32(DPORT_PRO_VECBASE_CTRL_REG);
regval |= BIT(0) | BIT(1);
putreg32(regval, DPORT_PRO_VECBASE_CTRL_REG);
#else
/* Move CPU0 exception vectors to IRAM */
__asm__ __volatile__ ("wsr %0, vecbase\n"::"r" (&_init_start));
__asm__ __volatile__ ("wsr %0, vecbase\n"::"r"(&_init_start));
#endif
/* Set .bss to zero */
memset(&_sbss, 0, (&_ebss - &_sbss) * sizeof(_sbss));
#ifndef CONFIG_SMP
uint32_t regval;
/* Make sure that the APP_CPU is disabled for now */
regval = getreg32(DPORT_APPCPU_CTRL_B_REG);
+94 -10
View File
@@ -33,9 +33,12 @@
#include <arch/board/board_memorymap.h>
#include "chip.h"
#include "xtensa.h"
#include "xtensa_attr.h"
#include "esp32_userspace.h"
#include "hardware/esp32_dport.h"
#include "hardware/esp32_pid.h"
#ifdef CONFIG_BUILD_PROTECTED
@@ -153,18 +156,34 @@ static noinline_function IRAM_ATTR void configure_flash_mmu(void)
drom_lma_aligned = app_drom_lma & MMU_FLASH_MASK;
drom_vma_aligned = app_drom_vma & MMU_FLASH_MASK;
drom_page_count = calc_mmu_pages(app_drom_size, app_drom_vma);
DEBUGVERIFY(cache_flash_mmu_set(0, 0, drom_vma_aligned, drom_lma_aligned,
64, (int)drom_page_count));
DEBUGVERIFY(cache_flash_mmu_set(1, 0, drom_vma_aligned, drom_lma_aligned,
64, (int)drom_page_count));
ASSERT(cache_flash_mmu_set(0, PIDCTRL_PID_KERNEL, drom_vma_aligned,
drom_lma_aligned, 64,
(int)drom_page_count) == 0);
ASSERT(cache_flash_mmu_set(1, PIDCTRL_PID_KERNEL, drom_vma_aligned,
drom_lma_aligned, 64,
(int)drom_page_count) == 0);
ASSERT(cache_flash_mmu_set(0, PIDCTRL_PID_USER, drom_vma_aligned,
drom_lma_aligned, 64,
(int)drom_page_count) == 0);
ASSERT(cache_flash_mmu_set(1, PIDCTRL_PID_USER, drom_vma_aligned,
drom_lma_aligned, 64,
(int)drom_page_count) == 0);
irom_lma_aligned = app_irom_lma & MMU_FLASH_MASK;
irom_vma_aligned = app_irom_vma & MMU_FLASH_MASK;
irom_page_count = calc_mmu_pages(app_irom_size, app_irom_vma);
DEBUGVERIFY(cache_flash_mmu_set(0, 0, irom_vma_aligned, irom_lma_aligned,
64, (int)irom_page_count));
DEBUGVERIFY(cache_flash_mmu_set(1, 0, irom_vma_aligned, irom_lma_aligned,
64, (int)irom_page_count));
ASSERT(cache_flash_mmu_set(0, PIDCTRL_PID_KERNEL, irom_vma_aligned,
irom_lma_aligned, 64,
(int)irom_page_count) == 0);
ASSERT(cache_flash_mmu_set(1, PIDCTRL_PID_KERNEL, irom_vma_aligned,
irom_lma_aligned, 64,
(int)irom_page_count) == 0);
ASSERT(cache_flash_mmu_set(0, PIDCTRL_PID_USER, irom_vma_aligned,
irom_lma_aligned, 64,
(int)irom_page_count) == 0);
ASSERT(cache_flash_mmu_set(1, PIDCTRL_PID_USER, irom_vma_aligned,
irom_lma_aligned, 64,
(int)irom_page_count) == 0);
cache_read_enable(0);
}
@@ -195,8 +214,8 @@ static noinline_function IRAM_ATTR const void *map_flash(uint32_t src_addr,
src_addr_aligned = src_addr & MMU_FLASH_MASK;
page_count = calc_mmu_pages(size, src_addr);
DEBUGVERIFY(cache_flash_mmu_set(0, 0, MMU_BLOCK50_VADDR, src_addr_aligned,
64, (int)page_count));
ASSERT(cache_flash_mmu_set(0, PIDCTRL_PID_KERNEL, MMU_BLOCK50_VADDR,
src_addr_aligned, 64, (int)page_count) == 0);
cache_read_enable(0);
@@ -279,6 +298,71 @@ static void initialize_data(void)
static void configure_mpu(void)
{
/* 8K page size for mappings both IRAM and DRAM */
REG_SET_FIELD(DPORT_IMMU_PAGE_MODE_REG, DPORT_IMMU_PAGE_MODE, 0);
REG_SET_FIELD(DPORT_DMMU_PAGE_MODE_REG, DPORT_DMMU_PAGE_MODE, 0);
/* 1:1 mapping for IRAM */
REG_SET_FIELD(DPORT_IMMU_TABLE0_REG, DPORT_IMMU_TABLE0, 0x00);
REG_SET_FIELD(DPORT_IMMU_TABLE1_REG, DPORT_IMMU_TABLE1, 0x51);
REG_SET_FIELD(DPORT_IMMU_TABLE2_REG, DPORT_IMMU_TABLE2, 0x52);
REG_SET_FIELD(DPORT_IMMU_TABLE3_REG, DPORT_IMMU_TABLE3, 0x53);
REG_SET_FIELD(DPORT_IMMU_TABLE4_REG, DPORT_IMMU_TABLE4, 0x54);
REG_SET_FIELD(DPORT_IMMU_TABLE5_REG, DPORT_IMMU_TABLE5, 0x55);
REG_SET_FIELD(DPORT_IMMU_TABLE6_REG, DPORT_IMMU_TABLE6, 0x56);
REG_SET_FIELD(DPORT_IMMU_TABLE7_REG, DPORT_IMMU_TABLE7, 0x57);
REG_SET_FIELD(DPORT_IMMU_TABLE8_REG, DPORT_IMMU_TABLE8, 0x08);
REG_SET_FIELD(DPORT_IMMU_TABLE9_REG, DPORT_IMMU_TABLE9, 0x09);
REG_SET_FIELD(DPORT_IMMU_TABLE10_REG, DPORT_IMMU_TABLE10, 0x0a);
REG_SET_FIELD(DPORT_IMMU_TABLE11_REG, DPORT_IMMU_TABLE11, 0x0b);
REG_SET_FIELD(DPORT_IMMU_TABLE12_REG, DPORT_IMMU_TABLE12, 0x0c);
REG_SET_FIELD(DPORT_IMMU_TABLE13_REG, DPORT_IMMU_TABLE13, 0x0d);
REG_SET_FIELD(DPORT_IMMU_TABLE14_REG, DPORT_IMMU_TABLE14, 0x0e);
REG_SET_FIELD(DPORT_IMMU_TABLE15_REG, DPORT_IMMU_TABLE15, 0x0f);
REG_SET_FIELD(DPORT_DMMU_TABLE0_REG, DPORT_DMMU_TABLE0, 0x00);
REG_SET_FIELD(DPORT_DMMU_TABLE1_REG, DPORT_DMMU_TABLE1, 0x01);
REG_SET_FIELD(DPORT_DMMU_TABLE2_REG, DPORT_DMMU_TABLE2, 0x02);
REG_SET_FIELD(DPORT_DMMU_TABLE3_REG, DPORT_DMMU_TABLE3, 0x03);
REG_SET_FIELD(DPORT_DMMU_TABLE4_REG, DPORT_DMMU_TABLE4, 0x54);
REG_SET_FIELD(DPORT_DMMU_TABLE5_REG, DPORT_DMMU_TABLE5, 0x55);
REG_SET_FIELD(DPORT_DMMU_TABLE6_REG, DPORT_DMMU_TABLE6, 0x56);
REG_SET_FIELD(DPORT_DMMU_TABLE7_REG, DPORT_DMMU_TABLE7, 0x57);
REG_SET_FIELD(DPORT_DMMU_TABLE8_REG, DPORT_DMMU_TABLE8, 0x58);
REG_SET_FIELD(DPORT_DMMU_TABLE9_REG, DPORT_DMMU_TABLE9, 0x59);
REG_SET_FIELD(DPORT_DMMU_TABLE10_REG, DPORT_DMMU_TABLE10, 0x5a);
REG_SET_FIELD(DPORT_DMMU_TABLE11_REG, DPORT_DMMU_TABLE11, 0x5b);
REG_SET_FIELD(DPORT_DMMU_TABLE12_REG, DPORT_DMMU_TABLE12, 0x5c);
REG_SET_FIELD(DPORT_DMMU_TABLE13_REG, DPORT_DMMU_TABLE13, 0x5d);
REG_SET_FIELD(DPORT_DMMU_TABLE14_REG, DPORT_DMMU_TABLE14, 0x5e);
REG_SET_FIELD(DPORT_DMMU_TABLE15_REG, DPORT_DMMU_TABLE15, 0x5f);
/* Configure interrupt vector addresses in PID Controller */
putreg32(PIDCTRL_INTERRUPT_ENABLE_M, PIDCTRL_INTERRUPT_ENABLE_REG);
/* Configure the PID Controller to switch to privileged mode (PID 0) when
* the CPU fetches instruction from the following interrupt vectors:
* 1) Level 1
* 2) Window Overflow 4
* 3) Level 3 (SWINT)
* 4) Window Underflow 4
* 5) Window Overflow 8
* 6) Window Underflow 8
* 7) NMI
*/
putreg32(VECTORS_START + 0x340, PIDCTRL_INTERRUPT_ADDR_1_REG);
putreg32(VECTORS_START + 0x000, PIDCTRL_INTERRUPT_ADDR_2_REG);
putreg32(VECTORS_START + 0x1c0, PIDCTRL_INTERRUPT_ADDR_3_REG);
putreg32(VECTORS_START + 0x040, PIDCTRL_INTERRUPT_ADDR_4_REG);
putreg32(VECTORS_START + 0x080, PIDCTRL_INTERRUPT_ADDR_5_REG);
putreg32(VECTORS_START + 0x0c0, PIDCTRL_INTERRUPT_ADDR_6_REG);
putreg32(VECTORS_START + 0x2c0, PIDCTRL_INTERRUPT_ADDR_7_REG);
putreg32(0, PIDCTRL_LEVEL_REG);
}
/****************************************************************************
+134
View File
@@ -0,0 +1,134 @@
/****************************************************************************
* arch/xtensa/src/esp32/esp32_window_hooks.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.
*
****************************************************************************/
.file "esp32_window_hooks.S"
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "chip_macros.h"
/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS
/* PID Controller is configured to switch to PID 0 when the CPU fetches
* instruction from the following window exception vectors:
* - Window Overflow 4: mapped as Level 2 vector entry address
* - Window Underflow 4: mapped as Level 4 vector entry address
* - Window Overflow 8: mapped as Level 5 vector entry address
* - Window Underflow 8: mapped as Level 6 vector entry address
*
* See arch/xtensa/src/esp32/esp32_userspace.c
*/
/****************************************************************************
* Name: _overflow4_exit_hook
****************************************************************************/
.section HANDLER_SECTION, "ax"
.global _overflow4_exit_hook
.type _overflow4_exit_hook, @function
.align 4
_overflow4_exit_hook:
wsr a0, misc0
wsr a1, misc1
/* Restore PID to the same value prior to the exception */
get_prev_pid 2 a0
set_next_pid a0 a1
rsr a0, misc0
rsr a1, misc1
rfwo /* rotates back to call[i] position */
/****************************************************************************
* Name: _underflow4_exit_hook
****************************************************************************/
.section HANDLER_SECTION, "ax"
.global _underflow4_exit_hook
.type _underflow4_exit_hook, @function
.align 4
_underflow4_exit_hook:
wsr a0, misc0
wsr a1, misc1
/* Restore PID to the same value prior to the exception */
get_prev_pid 4 a0
set_next_pid a0 a1
rsr a0, misc0
rsr a1, misc1
rfwu
/****************************************************************************
* Name: _overflow8_exit_hook
****************************************************************************/
.section HANDLER_SECTION, "ax"
.global _overflow8_exit_hook
.type _overflow8_exit_hook, @function
.align 4
_overflow8_exit_hook:
wsr a0, misc0
wsr a1, misc1
/* Restore PID to the same value prior to the exception */
get_prev_pid 5 a0
set_next_pid a0 a1
rsr a0, misc0
rsr a1, misc1
rfwo /* rotates back to call[i] position */
/****************************************************************************
* Name: _underflow8_exit_hook
****************************************************************************/
.section HANDLER_SECTION, "ax"
.global _underflow8_exit_hook
.type _underflow8_exit_hook, @function
.align 4
_underflow8_exit_hook:
wsr a0, misc0
wsr a1, misc1
/* Restore PID to the same value prior to the exception */
get_prev_pid 6 a0
set_next_pid a0 a1
rsr a0, misc0
rsr a1, misc1
rfwu
#endif /* CONFIG_XTENSA_HAVE_EXCEPTION_HOOKS */
+127
View File
@@ -0,0 +1,127 @@
/****************************************************************************
* arch/xtensa/src/esp32/hardware/esp32_pid.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_XTENSA_SRC_ESP32_HARDWARE_ESP32_PID_H_
#define __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_PID_H_
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define REG_PIDCTRL_BASE 0x3ff1f000
/* Bits 1..7: 1 if interrupt will be triggering PID change */
#define PIDCTRL_INTERRUPT_ENABLE_REG ((REG_PIDCTRL_BASE) + 0x000)
/* PIDCTRL_INTERRUPT_ENABLE : R/W; bitpos: [7:1]; default: 0;
* These bits are used to enable interrupt identification and processing.
*/
#define PIDCTRL_INTERRUPT_ENABLE 0x0000007f
#define PIDCTRL_INTERRUPT_ENABLE_M (PIDCTRL_INTERRUPT_ENABLE_V << PIDCTRL_INTERRUPT_ENABLE_S)
#define PIDCTRL_INTERRUPT_ENABLE_V 0x0000007f
#define PIDCTRL_INTERRUPT_ENABLE_S 1
/* Vectors for the various interrupt handlers */
#define PIDCTRL_INTERRUPT_ADDR_1_REG ((REG_PIDCTRL_BASE) + 0x004)
#define PIDCTRL_INTERRUPT_ADDR_2_REG ((REG_PIDCTRL_BASE) + 0x008)
#define PIDCTRL_INTERRUPT_ADDR_3_REG ((REG_PIDCTRL_BASE) + 0x00c)
#define PIDCTRL_INTERRUPT_ADDR_4_REG ((REG_PIDCTRL_BASE) + 0x010)
#define PIDCTRL_INTERRUPT_ADDR_5_REG ((REG_PIDCTRL_BASE) + 0x014)
#define PIDCTRL_INTERRUPT_ADDR_6_REG ((REG_PIDCTRL_BASE) + 0x018)
#define PIDCTRL_INTERRUPT_ADDR_7_REG ((REG_PIDCTRL_BASE) + 0x01c)
/* Delay, in CPU cycles, before switching to new PID */
#define PIDCTRL_PID_DELAY_REG ((REG_PIDCTRL_BASE) + 0x020)
/* PIDCTRL_PID_DELAY : R/W; bitpos: [11:0]; default: 20;
* Delay until newly assigned PID is valid.
*/
#define PIDCTRL_PID_DELAY 0x00001fff
#define PIDCTRL_PID_DELAY_M (PIDCTRL_PID_DELAY_V << PIDCTRL_PID_DELAY_S)
#define PIDCTRL_PID_DELAY_V 0x00001fff
#define PIDCTRL_PID_DELAY_S 0
#define PIDCTRL_NMI_DELAY_REG ((REG_PIDCTRL_BASE) + 0x024)
/* PIDCTRL_NMI_DELAY : R/W; bitpos: [11:0]; default: 16;
* Delay for disabling CPU NMI interrupt mask signal.
*/
#define PIDCTRL_NMI_DELAY 0x00001fff
#define PIDCTRL_NMI_DELAY_M (PIDCTRL_NMI_DELAY_V << PIDCTRL_NMI_DELAY_S)
#define PIDCTRL_NMI_DELAY_V 0x00001fff
#define PIDCTRL_NMI_DELAY_S 0
/* Last detected interrupt. Set by hw on int. */
#define PIDCTRL_LEVEL_REG ((REG_PIDCTRL_BASE) + 0x028)
/* PID/prev int data for each int */
#define PIDCTRL_FROM_REG(i) ((REG_PIDCTRL_BASE) + 0x028 + (0x4 * i))
#define PIDCTRL_FROM_1_REG ((REG_PIDCTRL_BASE) + 0x02c)
#define PIDCTRL_FROM_2_REG ((REG_PIDCTRL_BASE) + 0x030)
#define PIDCTRL_FROM_3_REG ((REG_PIDCTRL_BASE) + 0x034)
#define PIDCTRL_FROM_4_REG ((REG_PIDCTRL_BASE) + 0x038)
#define PIDCTRL_FROM_5_REG ((REG_PIDCTRL_BASE) + 0x03c)
#define PIDCTRL_FROM_6_REG ((REG_PIDCTRL_BASE) + 0x040)
#define PIDCTRL_FROM_7_REG ((REG_PIDCTRL_BASE) + 0x044)
/* PIDCTRL_FROM_INT : R/W; bitpos: [6:3]; default: 0;
* Interrupt status of the system before the interrupt occurs.
*/
#define PIDCTRL_FROM_INT 0x0000000f
#define PIDCTRL_FROM_INT_M (PIDCTRL_FROM_INT_V << PIDCTRL_FROM_INT_S)
#define PIDCTRL_FROM_INT_V 0x0000000f
#define PIDCTRL_FROM_INT_S 3
/* PIDCTRL_FROM_PID : R/W; bitpos: [2:0]; default: 0;
* Process running on the CPU before the interrupt occurs.
*/
#define PIDCTRL_FROM_PID 0x00000007
#define PIDCTRL_FROM_PID_M (PIDCTRL_FROM_PID_V << PIDCTRL_FROM_PID_S)
#define PIDCTRL_FROM_PID_V 0x00000007
#define PIDCTRL_FROM_PID_S 0
/* PID to be set after confirm routine */
#define PIDCTRL_PID_NEW_REG ((REG_PIDCTRL_BASE) + 0x048)
/* Write to kick off PID change */
#define PIDCTRL_PID_CONFIRM_REG ((REG_PIDCTRL_BASE) + 0x04c)
/* Write to mask NMI */
#define PIDCTRL_NMI_MASK_ENABLE_REG ((REG_PIDCTRL_BASE) + 0x054)
/* Write to unmask NMI */
#define PIDCTRL_NMI_MASK_DISABLE_REG ((REG_PIDCTRL_BASE) + 0x058)
#endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_PID_H_ */
@@ -18,7 +18,6 @@ CONFIG_ARCH_CHIP_ESP32=y
CONFIG_ARCH_CHIP_ESP32WROVER=y
CONFIG_ARCH_INTERRUPTSTACK=2048
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH_USE_MPU=y
CONFIG_ARCH_XTENSA=y
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BUILD_PROTECTED=y
@@ -30,7 +29,9 @@ CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEBUG_WARN=y
CONFIG_ESP32_PID=y
CONFIG_ESP32_UART0=y
CONFIG_EXPERIMENTAL=y
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y