You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/07/14 06:58:03 UTC
[incubator-nuttx] 02/05: xtensa/esp32: Configure the PID controller for privilege separation
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 27fc3c959d5bfd047d96cae8d9de835b04f24654
Author: Gustavo Henrique Nihei <gu...@espressif.com>
AuthorDate: Fri May 20 12:40:04 2022 -0300
xtensa/esp32: Configure the PID controller for privilege separation
Signed-off-by: Gustavo Henrique Nihei <gu...@espressif.com>
---
arch/xtensa/Kconfig | 4 +
arch/xtensa/include/irq.h | 18 ++-
arch/xtensa/src/common/xtensa_int_handlers.S | 49 ++++++++
arch/xtensa/src/common/xtensa_macros.S | 14 +++
arch/xtensa/src/common/xtensa_schedsigaction.c | 20 ++-
arch/xtensa/src/common/xtensa_swint.c | 43 ++++---
arch/xtensa/src/common/xtensa_vectors.S | 44 +++----
arch/xtensa/src/common/xtensa_window_vector.S | 20 ++-
arch/xtensa/src/esp32/Kconfig | 7 ++
arch/xtensa/src/esp32/Make.defs | 6 +-
arch/xtensa/src/esp32/chip_macros.h | 131 ++++++++++++++++++++
arch/xtensa/src/esp32/esp32_start.c | 21 +++-
arch/xtensa/src/esp32/esp32_userspace.c | 104 ++++++++++++++--
arch/xtensa/src/esp32/esp32_window_hooks.S | 134 +++++++++++++++++++++
arch/xtensa/src/esp32/hardware/esp32_pid.h | 127 +++++++++++++++++++
.../esp32/esp32-devkitc/configs/knsh/defconfig | 3 +-
16 files changed, 678 insertions(+), 67 deletions(-)
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 663276c727..525f741a78 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -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
diff --git a/arch/xtensa/include/irq.h b/arch/xtensa/include/irq.h
index fdad3b8211..3f5afa43f9 100644
--- a/arch/xtensa/include/irq.h
+++ b/arch/xtensa/include/irq.h
@@ -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
diff --git a/arch/xtensa/src/common/xtensa_int_handlers.S b/arch/xtensa/src/common/xtensa_int_handlers.S
index e4f40f7551..bc61bfe193 100644
--- a/arch/xtensa/src/common/xtensa_int_handlers.S
+++ b/arch/xtensa/src/common/xtensa_int_handlers.S
@@ -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
*
diff --git a/arch/xtensa/src/common/xtensa_macros.S b/arch/xtensa/src/common/xtensa_macros.S
index b101c8b843..5519a60ad6 100644
--- a/arch/xtensa/src/common/xtensa_macros.S
+++ b/arch/xtensa/src/common/xtensa_macros.S
@@ -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 */
diff --git a/arch/xtensa/src/common/xtensa_schedsigaction.c b/arch/xtensa/src/common/xtensa_schedsigaction.c
index 41c8dfcf72..fcfb906eda 100644
--- a/arch/xtensa/src/common/xtensa_schedsigaction.c
+++ b/arch/xtensa/src/common/xtensa_schedsigaction.c
@@ -32,10 +32,11 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
+#include "irq/irq.h"
#include "sched/sched.h"
-#include "xtensa.h"
-#include "irq/irq.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
}
}
diff --git a/arch/xtensa/src/common/xtensa_swint.c b/arch/xtensa/src/common/xtensa_swint.c
index 731bf804c3..682f65c6be 100644
--- a/arch/xtensa/src/common/xtensa_swint.c
+++ b/arch/xtensa/src/common/xtensa_swint.c
@@ -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;
diff --git a/arch/xtensa/src/common/xtensa_vectors.S b/arch/xtensa/src/common/xtensa_vectors.S
index 2b4ae27004..46a24ab47a 100644
--- a/arch/xtensa/src/common/xtensa_vectors.S
+++ b/arch/xtensa/src/common/xtensa_vectors.S
@@ -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
/****************************************************************************
diff --git a/arch/xtensa/src/common/xtensa_window_vector.S b/arch/xtensa/src/common/xtensa_window_vector.S
index 5be6c079e3..997c203bea 100644
--- a/arch/xtensa/src/common/xtensa_window_vector.S
+++ b/arch/xtensa/src/common/xtensa_window_vector.S
@@ -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
*
diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig
index 98db1623bc..4883ccf11b 100644
--- a/arch/xtensa/src/esp32/Kconfig
+++ b/arch/xtensa/src/esp32/Kconfig
@@ -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
diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs
index 7b8a1313dc..9de3789104 100644
--- a/arch/xtensa/src/esp32/Make.defs
+++ b/arch/xtensa/src/esp32/Make.defs
@@ -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)
diff --git a/arch/xtensa/src/esp32/chip_macros.h b/arch/xtensa/src/esp32/chip_macros.h
index 8613b33674..e5fe6a7c89 100644
--- a/arch/xtensa/src/esp32/chip_macros.h
+++ b/arch/xtensa/src/esp32/chip_macros.h
@@ -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 */
/****************************************************************************
diff --git a/arch/xtensa/src/esp32/esp32_start.c b/arch/xtensa/src/esp32/esp32_start.c
index 420ac161c3..cbcb858ebe 100644
--- a/arch/xtensa/src/esp32/esp32_start.c
+++ b/arch/xtensa/src/esp32/esp32_start.c
@@ -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);
diff --git a/arch/xtensa/src/esp32/esp32_userspace.c b/arch/xtensa/src/esp32/esp32_userspace.c
index 812bbc84ca..fdf9e30d19 100755
--- a/arch/xtensa/src/esp32/esp32_userspace.c
+++ b/arch/xtensa/src/esp32/esp32_userspace.c
@@ -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);
}
/****************************************************************************
diff --git a/arch/xtensa/src/esp32/esp32_window_hooks.S b/arch/xtensa/src/esp32/esp32_window_hooks.S
new file mode 100644
index 0000000000..bebb85cfe1
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_window_hooks.S
@@ -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 */
diff --git a/arch/xtensa/src/esp32/hardware/esp32_pid.h b/arch/xtensa/src/esp32/hardware/esp32_pid.h
new file mode 100644
index 0000000000..193070ad2a
--- /dev/null
+++ b/arch/xtensa/src/esp32/hardware/esp32_pid.h
@@ -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_ */
diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig
index e85a601fb0..6058b287bb 100644
--- a/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig
+++ b/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig
@@ -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