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