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:01 UTC

[incubator-nuttx] branch master updated (6f0334140f -> feca57ffa9)

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


    from 6f0334140f sched: Convert DEBUGASSERT(false) into more intuitive DEBUGPANIC()
     new 76acfef5ec xtensa/esp32: Add support for Protected Mode
     new 27fc3c959d xtensa/esp32: Configure the PID controller for privilege separation
     new 60b7479f12 xtensa/esp32: Avoid ROM functions due to error with PIDs 2-7
     new 68c722c051 xtensa/esp32: Build patched IDFBoot for Protected Mode support
     new feca57ffa9 esp32-devkitc: Add knsh configuration to the Documentation page

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../xtensa/esp32/boards/esp32-devkitc/index.rst    |  22 ++
 arch/xtensa/Kconfig                                |  29 +-
 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/.gitignore                   |   1 -
 arch/xtensa/src/esp32/Bootloader.mk                |  22 +-
 arch/xtensa/src/esp32/Kconfig                      |  17 +
 arch/xtensa/src/esp32/Make.defs                    |  12 +-
 arch/xtensa/src/esp32/bootloader/.gitignore        |   2 +
 ...-Connect-Xtensa-Instruction-RAM1-to-Cache.patch | 112 ++++++
 arch/xtensa/src/esp32/chip_macros.h                | 131 +++++++
 arch/xtensa/src/esp32/esp32_allocateheap.c         |  86 ++++-
 arch/xtensa/src/esp32/esp32_start.c                |  39 +-
 arch/xtensa/src/esp32/esp32_userspace.c            | 428 +++++++++++++++++++++
 arch/xtensa/src/esp32/esp32_userspace.h            |  49 +++
 arch/xtensa/src/esp32/esp32_window_hooks.S         | 134 +++++++
 arch/xtensa/src/esp32/hardware/esp32_pid.h         | 127 ++++++
 boards/xtensa/esp32/common/kernel/Makefile         |  97 +++++
 .../xtensa/esp32/common/kernel/esp32_userspace.c   | 114 ++++++
 .../{esp32.template.ld => flat.template.ld}        |   2 +-
 boards/xtensa/esp32/common/scripts/kernel-space.ld | 313 +++++++++++++++
 .../esp32/common/scripts/protected.template.ld     |  97 +++++
 boards/xtensa/esp32/common/scripts/user-space.ld   | 217 +++++++++++
 .../esp32/esp32-devkitc/configs/knsh/defconfig     |  64 +++
 .../esp32/esp32-devkitc/include/board_memorymap.h  | 128 ++++++
 .../xtensa/esp32/esp32-devkitc/scripts/Make.defs   |  16 +-
 .../esp32-ethernet-kit/include/board_memorymap.h   | 128 ++++++
 .../esp32/esp32-ethernet-kit/scripts/Make.defs     |  16 +-
 .../esp32-wrover-kit/include/board_memorymap.h     | 128 ++++++
 .../esp32/esp32-wrover-kit/scripts/Make.defs       |  16 +-
 .../esp32/ttgo_eink5_v2/include/board_memorymap.h  | 128 ++++++
 .../xtensa/esp32/ttgo_eink5_v2/scripts/Make.defs   |  16 +-
 .../ttgo_lora_esp32/include/board_memorymap.h      | 128 ++++++
 .../xtensa/esp32/ttgo_lora_esp32/scripts/Make.defs |  16 +-
 tools/esp32/Config.mk                              |   4 +
 40 files changed, 2942 insertions(+), 105 deletions(-)
 create mode 100644 arch/xtensa/src/esp32/bootloader/.gitignore
 create mode 100644 arch/xtensa/src/esp32/bootloader/0001-esp32-Connect-Xtensa-Instruction-RAM1-to-Cache.patch
 create mode 100755 arch/xtensa/src/esp32/esp32_userspace.c
 create mode 100755 arch/xtensa/src/esp32/esp32_userspace.h
 create mode 100644 arch/xtensa/src/esp32/esp32_window_hooks.S
 create mode 100644 arch/xtensa/src/esp32/hardware/esp32_pid.h
 create mode 100755 boards/xtensa/esp32/common/kernel/Makefile
 create mode 100755 boards/xtensa/esp32/common/kernel/esp32_userspace.c
 rename boards/xtensa/esp32/common/scripts/{esp32.template.ld => flat.template.ld} (99%)
 create mode 100755 boards/xtensa/esp32/common/scripts/kernel-space.ld
 create mode 100644 boards/xtensa/esp32/common/scripts/protected.template.ld
 create mode 100755 boards/xtensa/esp32/common/scripts/user-space.ld
 create mode 100644 boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig
 create mode 100644 boards/xtensa/esp32/esp32-devkitc/include/board_memorymap.h
 create mode 100644 boards/xtensa/esp32/esp32-ethernet-kit/include/board_memorymap.h
 create mode 100644 boards/xtensa/esp32/esp32-wrover-kit/include/board_memorymap.h
 create mode 100644 boards/xtensa/esp32/ttgo_eink5_v2/include/board_memorymap.h
 create mode 100644 boards/xtensa/esp32/ttgo_lora_esp32/include/board_memorymap.h


[incubator-nuttx] 03/05: xtensa/esp32: Avoid ROM functions due to error with PIDs 2-7

Posted by xi...@apache.org.
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 60b7479f1250bb42522b7f3340211f9196e8cdf9
Author: Gustavo Henrique Nihei <gu...@espressif.com>
AuthorDate: Fri Jun 10 18:28:05 2022 -0300

    xtensa/esp32: Avoid ROM functions due to error with PIDs 2-7
    
    Signed-off-by: Gustavo Henrique Nihei <gu...@espressif.com>
---
 arch/xtensa/Kconfig | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 525f741a78..a4b0ec869d 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -22,18 +22,18 @@ config ARCH_CHIP_ESP32
 	select ARCH_HAVE_BOOTLOADER
 	select ARCH_HAVE_TESTSET
 	select ARCH_VECNOTIRQ
-	select LIBC_ARCH_MEMCPY
-	select LIBC_ARCH_MEMCHR
-	select LIBC_ARCH_MEMCMP
-	select LIBC_ARCH_MEMMOVE
-	select LIBC_ARCH_MEMSET
-	select LIBC_ARCH_STRCHR
-	select LIBC_ARCH_STRCMP
-	select LIBC_ARCH_STRCPY
-	select LIBC_ARCH_STRLCPY
-	select LIBC_ARCH_STRNCPY
-	select LIBC_ARCH_STRLEN
-	select LIBC_ARCH_STRNLEN
+	select LIBC_ARCH_MEMCPY if BUILD_FLAT
+	select LIBC_ARCH_MEMCHR if BUILD_FLAT
+	select LIBC_ARCH_MEMCMP if BUILD_FLAT
+	select LIBC_ARCH_MEMMOVE if BUILD_FLAT
+	select LIBC_ARCH_MEMSET if BUILD_FLAT
+	select LIBC_ARCH_STRCHR if BUILD_FLAT
+	select LIBC_ARCH_STRCMP if BUILD_FLAT
+	select LIBC_ARCH_STRCPY if BUILD_FLAT
+	select LIBC_ARCH_STRLCPY if BUILD_FLAT
+	select LIBC_ARCH_STRNCPY if BUILD_FLAT
+	select LIBC_ARCH_STRLEN if BUILD_FLAT
+	select LIBC_ARCH_STRNLEN if BUILD_FLAT
 	---help---
 		The ESP32 is a dual-core system from Espressif with two Harvard
 		architecture Xtensa LX6 CPUs. All embedded memory, external memory


[incubator-nuttx] 01/05: xtensa/esp32: Add support for Protected Mode

Posted by xi...@apache.org.
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 76acfef5ec585e8ba3fe48327ccf4305f69df3d8
Author: Gustavo Henrique Nihei <gu...@espressif.com>
AuthorDate: Wed May 11 18:59:27 2022 -0300

    xtensa/esp32: Add support for Protected Mode
    
    Signed-off-by: Gustavo Henrique Nihei <gu...@espressif.com>
---
 arch/xtensa/Kconfig                                |   1 +
 arch/xtensa/src/esp32/Kconfig                      |  10 +
 arch/xtensa/src/esp32/Make.defs                    |   6 +-
 arch/xtensa/src/esp32/esp32_allocateheap.c         |  86 +++++-
 arch/xtensa/src/esp32/esp32_start.c                |  18 +-
 arch/xtensa/src/esp32/esp32_userspace.c            | 344 +++++++++++++++++++++
 arch/xtensa/src/esp32/esp32_userspace.h            |  49 +++
 boards/xtensa/esp32/common/kernel/Makefile         |  97 ++++++
 .../xtensa/esp32/common/kernel/esp32_userspace.c   | 114 +++++++
 .../{esp32.template.ld => flat.template.ld}        |   2 +-
 boards/xtensa/esp32/common/scripts/kernel-space.ld | 313 +++++++++++++++++++
 .../esp32/common/scripts/protected.template.ld     |  97 ++++++
 boards/xtensa/esp32/common/scripts/user-space.ld   | 217 +++++++++++++
 .../esp32/esp32-devkitc/configs/knsh/defconfig     |  62 ++++
 .../esp32/esp32-devkitc/include/board_memorymap.h  | 128 ++++++++
 .../xtensa/esp32/esp32-devkitc/scripts/Make.defs   |  16 +-
 .../esp32-ethernet-kit/include/board_memorymap.h   | 128 ++++++++
 .../esp32/esp32-ethernet-kit/scripts/Make.defs     |  16 +-
 .../esp32-wrover-kit/include/board_memorymap.h     | 128 ++++++++
 .../esp32/esp32-wrover-kit/scripts/Make.defs       |  16 +-
 .../esp32/ttgo_eink5_v2/include/board_memorymap.h  | 128 ++++++++
 .../xtensa/esp32/ttgo_eink5_v2/scripts/Make.defs   |  16 +-
 .../ttgo_lora_esp32/include/board_memorymap.h      | 128 ++++++++
 .../xtensa/esp32/ttgo_lora_esp32/scripts/Make.defs |  16 +-
 tools/esp32/Config.mk                              |   4 +
 25 files changed, 2110 insertions(+), 30 deletions(-)

diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 0bd1bcc3bb..663276c727 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -14,6 +14,7 @@ config ARCH_CHIP_ESP32
 	select ARCH_FAMILY_LX6
 	select XTENSA_HAVE_INTERRUPTS
 	select ARCH_HAVE_FPU
+	select ARCH_HAVE_MPU
 	select ARCH_HAVE_MULTICPU
 	select ARCH_HAVE_TEXT_HEAP
 	select ARCH_HAVE_SDRAM
diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig
index b6032cae9f..98db1623bc 100644
--- a/arch/xtensa/src/esp32/Kconfig
+++ b/arch/xtensa/src/esp32/Kconfig
@@ -1601,6 +1601,16 @@ config ESP32_PARTITION_TABLE_OFFSET
 	default 0x8000
 	depends on ESP32_APP_FORMAT_LEGACY
 
+if BUILD_PROTECTED
+
+config ESP32_USER_IMAGE_OFFSET
+	hex "User image offset"
+	default 0x90000
+	---help---
+		Offset in SPI Flash for flashing the User application firmware image.
+
+endif
+
 source "arch/xtensa/src/esp32/Kconfig.security"
 
 endmenu # Application Image Configuration
diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs
index 2d6a50ae1c..7b8a1313dc 100644
--- a/arch/xtensa/src/esp32/Make.defs
+++ b/arch/xtensa/src/esp32/Make.defs
@@ -25,7 +25,7 @@ include common/Make.defs
 
 HEAD_CSRC = esp32_start.c esp32_wdt.c
 
-# Required ESP32 files (arch/xtensa/src/lx6)
+# Required ESP32 files (arch/xtensa/src/esp32)
 
 CHIP_CSRCS  = esp32_allocateheap.c esp32_clockconfig.c esp32_gpio.c
 CHIP_CSRCS += esp32_systemreset.c esp32_resetcause.c
@@ -37,6 +37,10 @@ ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y)
 CHIP_CSRCS += esp32_idle.c
 endif
 
+ifeq ($(CONFIG_BUILD_PROTECTED),y)
+CHIP_CSRCS += esp32_userspace.c
+endif
+
 ifeq ($(CONFIG_SCHED_TICKLESS),y)
 CHIP_CSRCS += esp32_tickless.c
 else
diff --git a/arch/xtensa/src/esp32/esp32_allocateheap.c b/arch/xtensa/src/esp32/esp32_allocateheap.c
index 5a7b32e42a..10fe37606d 100644
--- a/arch/xtensa/src/esp32/esp32_allocateheap.c
+++ b/arch/xtensa/src/esp32/esp32_allocateheap.c
@@ -29,9 +29,13 @@
 #include <debug.h>
 
 #include <nuttx/arch.h>
-#include <nuttx/mm/mm.h>
 #include <nuttx/board.h>
+#include <nuttx/mm/mm.h>
+#include <nuttx/userspace.h>
 #include <arch/board/board.h>
+#ifdef CONFIG_MM_KERNEL_HEAP
+#include <arch/board/board_memorymap.h>
+#endif
 #include <arch/esp32/memory_layout.h>
 
 #ifdef CONFIG_ESP32_SPIRAM_BANKSWITCH_ENABLE
@@ -55,29 +59,83 @@
  * Description:
  *   This function will be called to dynamically set aside the heap region.
  *
- *   For the kernel build (CONFIG_BUILD_KERNEL=y) with both kernel- and
- *   user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
- *   size of the unprotected, user-space heap.
+ *   For the kernel build (CONFIG_BUILD_KERNEL=y) with both kernel and
+ *   userspace heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
+ *   size of the unprotected, userspace heap.
  *
- *   If a protected kernel-space heap is provided, the kernel heap must be
+ *   If a protected kernel space heap is provided, the kernel heap must be
  *   allocated (and protected) by an analogous up_allocate_kheap().
  *
  ****************************************************************************/
 
 void up_allocate_heap(void **heap_start, size_t *heap_size)
 {
+#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP)
+  uintptr_t ubase = USERSPACE->us_dataend;
+  uintptr_t utop  = USERSPACE->us_heapend;
+  size_t    usize = utop - ubase;
+
+  minfo("Heap: start=%" PRIxPTR " end=%" PRIxPTR " size=%zu\n",
+        ubase, utop, usize);
+
+  board_autoled_on(LED_HEAPALLOCATE);
+
+  /* Return the userspace heap settings */
+
+  *heap_start = (void *)ubase;
+  *heap_size  = usize;
+
+  /* Allow user-mode access to the user heap memory */
+
+#else
   board_autoled_on(LED_HEAPALLOCATE);
 
   *heap_start = (void *)&_sheap;
   DEBUGASSERT(HEAP_REGION1_END > (uintptr_t)*heap_start);
   *heap_size = (size_t)(HEAP_REGION1_END - (uintptr_t)*heap_start);
+#endif /* CONFIG_BUILD_PROTECTED && CONFIG_MM_KERNEL_HEAP */
 }
 
+/****************************************************************************
+ * Name: up_allocate_kheap
+ *
+ * Description:
+ *   This function will be called to dynamically set aside the heap region.
+ *
+ *   For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel and
+ *   userspace heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates
+ *   (and protects) the kernel space heap.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) && \
+    defined(__KERNEL__)
+void up_allocate_kheap(void **heap_start, size_t *heap_size)
+{
+  /* These values come from the linker scripts (kernel-space.ld and
+   * protected.template.ld).
+   * Check boards/xtensa/esp32.
+   */
+
+  uintptr_t kbase = (uintptr_t)&_sheap;
+  uintptr_t ktop  = KDRAM_0_END;
+  size_t    ksize = ktop - kbase;
+
+  minfo("Heap: start=%" PRIxPTR " end=%" PRIxPTR " size=%zu\n",
+        kbase, ktop, ksize);
+
+  board_autoled_on(LED_HEAPALLOCATE);
+
+  *heap_start = (void *)kbase;
+  *heap_size  = ksize;
+}
+#endif /* CONFIG_BUILD_PROTECTED && CONFIG_MM_KERNEL_HEAP */
+
 /****************************************************************************
  * Name: xtensa_add_region
  *
  * Description:
- *   Memory may be added in non-contiguous chunks.  Additional chunks are
+ *   Memory may be added in non-contiguous chunks. Additional chunks are
  *   added by calling this function.
  *
  ****************************************************************************/
@@ -115,22 +173,38 @@ void xtensa_add_region(void)
 #ifndef CONFIG_SMP
   start = (void *)(HEAP_REGION2_START + XTENSA_IMEM_REGION_SIZE);
   size  = (size_t)(uintptr_t)&_eheap - (size_t)start;
+#ifdef CONFIG_BUILD_PROTECTED
+  kmm_addregion(start, size);
+#else
   umm_addregion(start, size);
+#endif
 #else
   start = (void *)HEAP_REGION2_START;
   size  = (size_t)(HEAP_REGION2_END - HEAP_REGION2_START);
+#ifdef CONFIG_BUILD_PROTECTED
+  kmm_addregion(start, size);
+#else
   umm_addregion(start, size);
+#endif
 
   start = (void *)HEAP_REGION3_START + XTENSA_IMEM_REGION_SIZE;
   size  = (size_t)(uintptr_t)&_eheap - (size_t)start;
+#ifdef CONFIG_BUILD_PROTECTED
+  kmm_addregion(start, size);
+#else
   umm_addregion(start, size);
 #endif
+#endif
 
 #ifndef CONFIG_ESP32_BLE
   start = (void *)HEAP_REGION0_START;
   size  = (size_t)(HEAP_REGION0_END - HEAP_REGION0_START);
+#ifdef CONFIG_BUILD_PROTECTED
+  kmm_addregion(start, size);
+#else
   umm_addregion(start, size);
 #endif
+#endif
 
 #ifdef CONFIG_ESP32_SPIRAM
 #  if defined(CONFIG_HEAP2_BASE) && defined(CONFIG_HEAP2_SIZE)
diff --git a/arch/xtensa/src/esp32/esp32_start.c b/arch/xtensa/src/esp32/esp32_start.c
index fab28e26a6..420ac161c3 100644
--- a/arch/xtensa/src/esp32/esp32_start.c
+++ b/arch/xtensa/src/esp32/esp32_start.c
@@ -34,13 +34,16 @@
 #include "xtensa.h"
 #include "xtensa_attr.h"
 
-#include "hardware/esp32_dport.h"
-#include "hardware/esp32_rtccntl.h"
 #include "esp32_clockconfig.h"
 #include "esp32_region.h"
 #include "esp32_start.h"
 #include "esp32_spiram.h"
 #include "esp32_wdt.h"
+#ifdef CONFIG_BUILD_PROTECTED
+#  include "esp32_userspace.h"
+#endif
+#include "hardware/esp32_dport.h"
+#include "hardware/esp32_rtccntl.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -232,6 +235,17 @@ static noreturn_function void __esp32_start(void)
 
   showprogress("B");
 
+  /* For the case of the separate user-/kernel-space build, perform whatever
+   * platform specific initialization of the user memory is required.
+   * Normally this just means initializing the user space .data and .bss
+   * segments.
+   */
+
+#ifdef CONFIG_BUILD_PROTECTED
+  esp32_userspace();
+  showprogress("C");
+#endif
+
   /* Bring up NuttX */
 
   nx_start();
diff --git a/arch/xtensa/src/esp32/esp32_userspace.c b/arch/xtensa/src/esp32/esp32_userspace.c
new file mode 100755
index 0000000000..812bbc84ca
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_userspace.c
@@ -0,0 +1,344 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_userspace.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <nuttx/userspace.h>
+
+#include <arch/board/board_memorymap.h>
+
+#include "xtensa_attr.h"
+#include "esp32_userspace.h"
+#include "hardware/esp32_dport.h"
+
+#ifdef CONFIG_BUILD_PROTECTED
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define USER_IMAGE_OFFSET   CONFIG_ESP32_USER_IMAGE_OFFSET
+
+#define MMU_BLOCK0_VADDR    SOC_DROM_LOW
+#define MMU_SIZE            0x320000
+#define MMU_BLOCK50_VADDR   (MMU_BLOCK0_VADDR + MMU_SIZE)
+
+/* Cache MMU block size */
+
+#define MMU_BLOCK_SIZE      0x00010000  /* 64 KB */
+
+/* Cache MMU address mask (MMU tables ignore bits which are zero) */
+
+#define MMU_FLASH_MASK      (~(MMU_BLOCK_SIZE - 1))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct user_image_load_header_s
+{
+  uintptr_t drom_vma;      /* Destination address (VMA) for DROM region */
+  uintptr_t drom_lma;      /* Flash offset (LMA) for start of DROM region */
+  uintptr_t drom_size;     /* Size of DROM region */
+  uintptr_t irom_vma;      /* Destination address (VMA) for IROM region */
+  uintptr_t irom_lma;      /* Flash offset (LMA) for start of IROM region */
+  uintptr_t irom_size;     /* Size of IROM region */
+};
+
+/****************************************************************************
+ * ROM Function Prototypes
+ ****************************************************************************/
+
+extern void cache_read_enable(int cpu);
+extern void cache_read_disable(int cpu);
+extern void cache_flush(int cpu);
+extern unsigned int cache_flash_mmu_set(int cpu_no, int pid,
+                                        unsigned int vaddr,
+                                        unsigned int paddr,
+                                        int psize, int num);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct user_image_load_header_s g_header;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: calc_mmu_pages
+ *
+ * Description:
+ *   Calculate the required number of MMU pages for mapping a given region
+ *   from External Flash into Internal RAM.
+ *
+ * Input Parameters:
+ *   size          - Length of the region to map
+ *   vaddr         - Starting External Flash offset to map to Internal RAM
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static inline uint32_t calc_mmu_pages(uint32_t size, uint32_t vaddr)
+{
+  return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_BLOCK_SIZE - 1) /
+    MMU_BLOCK_SIZE;
+}
+
+/****************************************************************************
+ * Name: configure_flash_mmu
+ *
+ * Description:
+ *   Configure the External Flash MMU and Cache for enabling access to code
+ *   and read-only data of the userspace image.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static noinline_function IRAM_ATTR void configure_flash_mmu(void)
+{
+  uint32_t drom_lma_aligned;
+  uint32_t drom_vma_aligned;
+  uint32_t drom_page_count;
+  uint32_t irom_lma_aligned;
+  uint32_t irom_vma_aligned;
+  uint32_t irom_page_count;
+
+  size_t partition_offset = USER_IMAGE_OFFSET;
+  uint32_t app_drom_lma = partition_offset + g_header.drom_lma;
+  uint32_t app_drom_size = g_header.drom_size;
+  uint32_t app_drom_vma = g_header.drom_vma;
+  uint32_t app_irom_lma = partition_offset + g_header.irom_lma;
+  uint32_t app_irom_size = g_header.irom_size;
+  uint32_t app_irom_vma = g_header.irom_vma;
+
+  cache_read_disable(0);
+  cache_flush(0);
+
+  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));
+
+  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));
+
+  cache_read_enable(0);
+}
+
+/****************************************************************************
+ * Name: map_flash
+ *
+ * Description:
+ *   Map a region of the External Flash memory to Internal RAM.
+ *
+ * Input Parameters:
+ *   src_addr      - Starting External Flash offset to map to Internal RAM
+ *   size          - Length of the region to map
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static noinline_function IRAM_ATTR const void *map_flash(uint32_t src_addr,
+                                                         uint32_t size)
+{
+  uint32_t src_addr_aligned;
+  uint32_t page_count;
+
+  cache_read_disable(0);
+  cache_flush(0);
+
+  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));
+
+  cache_read_enable(0);
+
+  return (void *)(MMU_BLOCK50_VADDR + (src_addr - src_addr_aligned));
+}
+
+/****************************************************************************
+ * Name: load_header
+ *
+ * Description:
+ *   Load IROM and DROM information from image header to enable the correct
+ *   configuration of the Flash MMU and Cache.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void load_header(void)
+{
+  size_t length = sizeof(struct user_image_load_header_s);
+  const uint8_t *data =
+    (const uint8_t *)map_flash(USER_IMAGE_OFFSET, length);
+
+  DEBUGASSERT(data != NULL);
+
+  memcpy(&g_header, data, length);
+}
+
+/****************************************************************************
+ * Name: initialize_data
+ *
+ * Description:
+ *   Initialize data sections of the userspace image.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void initialize_data(void)
+{
+  uint8_t *dest;
+  uint8_t *end;
+  size_t length = USERSPACE->us_dataend - USERSPACE->us_datastart;
+  const uint8_t *src =
+    (const uint8_t *)map_flash(USER_IMAGE_OFFSET + USERSPACE->us_datasource,
+                               length);
+
+  DEBUGASSERT(src != NULL);
+
+  dest = (uint8_t *)USERSPACE->us_datastart;
+  end  = (uint8_t *)USERSPACE->us_dataend;
+
+  while (dest != end)
+    {
+      *dest++ = *src++;
+    }
+}
+
+/****************************************************************************
+ * Name: configure_mpu
+ *
+ * Description:
+ *   Configure the MPU for kernel/userspace separation.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void configure_mpu(void)
+{
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_userspace
+ *
+ * Description:
+ *   For the case of the separate user/kernel space build, perform whatever
+ *   platform specific initialization of the user memory is required.
+ *   Normally this just means initializing the userspace .data and .bss
+ *   segments.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp32_userspace(void)
+{
+  uint8_t *dest;
+  uint8_t *end;
+
+  /* Load IROM and DROM information from image header */
+
+  load_header();
+
+  /* Configure the Flash MMU for enabling access to the userspace image */
+
+  configure_flash_mmu();
+
+  /* Clear all of userspace .bss */
+
+  DEBUGASSERT(USERSPACE->us_bssstart != 0 && USERSPACE->us_bssend != 0 &&
+              USERSPACE->us_bssstart <= USERSPACE->us_bssend);
+
+  dest = (uint8_t *)USERSPACE->us_bssstart;
+  end  = (uint8_t *)USERSPACE->us_bssend;
+
+  while (dest != end)
+    {
+      *dest++ = 0;
+    }
+
+  /* Initialize all of userspace .data */
+
+  DEBUGASSERT(USERSPACE->us_datasource != 0 &&
+              USERSPACE->us_datastart != 0 && USERSPACE->us_dataend != 0 &&
+              USERSPACE->us_datastart <= USERSPACE->us_dataend);
+
+  initialize_data();
+
+  /* Configure MPU to grant access to the userspace */
+
+  configure_mpu();
+}
+
+#endif /* CONFIG_BUILD_PROTECTED */
diff --git a/arch/xtensa/src/esp32/esp32_userspace.h b/arch/xtensa/src/esp32/esp32_userspace.h
new file mode 100755
index 0000000000..4271177dc7
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_userspace.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_userspace.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_ESP32_USERSPACE_H
+#define __ARCH_XTENSA_SRC_ESP32_ESP32_USERSPACE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_userspace
+ *
+ * Description:
+ *   For the case of the separate user-/kernel-space build, perform whatever
+ *   platform specific initialization of the user memory is required.
+ *   Normally this just means initializing the user space .data and .bss
+ *   segments.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BUILD_PROTECTED
+void esp32_userspace(void);
+#endif
+
+#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_USERSPACE_H */
diff --git a/boards/xtensa/esp32/common/kernel/Makefile b/boards/xtensa/esp32/common/kernel/Makefile
new file mode 100755
index 0000000000..c29e3c5f71
--- /dev/null
+++ b/boards/xtensa/esp32/common/kernel/Makefile
@@ -0,0 +1,97 @@
+############################################################################
+# boards/xtensa/esp32/common/kernel/Makefile
+#
+# 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.
+#
+############################################################################
+
+include $(TOPDIR)/Make.defs
+
+# The entry point name (if none is provided in the .config file)
+
+CONFIG_INIT_ENTRYPOINT ?= user_start
+ENTRYPT = $(patsubst "%",%,$(CONFIG_INIT_ENTRYPOINT))
+
+# Get the paths to the libraries and the links script path in format that
+# is appropriate for the host OS
+
+USER_LIBPATHS = $(addprefix -L,$(call CONVERT_PATH,$(addprefix $(TOPDIR)$(DELIM),$(dir $(USERLIBS)))))
+USER_LDSCRIPT = -T $(call CONVERT_PATH,$(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32_out.ld)
+USER_LDSCRIPT += -T $(call CONVERT_PATH,$(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)user-space.ld)
+USER_HEXFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.hex)
+USER_BINFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.bin)
+
+USER_LDFLAGS = --undefined=$(ENTRYPT) --entry=$(ENTRYPT) $(USER_LDSCRIPT)
+
+ifeq ($(CONFIG_DEBUG_LINK_MAP),y)
+USER_LDFLAGS += --cref -Map="$(TOPDIR)$(DELIM)User.map"
+endif
+
+USER_LDLIBS = $(patsubst lib%,-l%,$(basename $(notdir $(USERLIBS))))
+USER_LIBGCC = "${shell "$(CC)" $(ARCHCPUFLAGS) -print-libgcc-file-name}"
+
+# Source files
+
+CSRCS = esp32_userspace.c
+COBJS = $(CSRCS:.c=$(OBJEXT))
+OBJS  = $(COBJS)
+
+ifeq ($(LD),$(CC))
+  LDSTARTGROUP ?= -Wl,--start-group
+  LDENDGROUP   ?= -Wl,--end-group
+  USER_LDFLAGS := $(addprefix -Xlinker ,$(USER_LDFLAGS))
+  USER_LDFLAGS += $(CFLAGS)
+else
+  LDSTARTGROUP ?= --start-group
+  LDENDGROUP   ?= --end-group
+endif
+
+# Targets:
+
+all: $(TOPDIR)$(DELIM)nuttx_user.elf
+.PHONY: nuttx_user.elf depend clean distclean
+
+$(COBJS): %$(OBJEXT): %.c
+	$(call COMPILE, $<, $@)
+
+# Create the nuttx_user.elf file containing all of the user-mode code
+
+nuttx_user.elf: $(OBJS)
+	$(Q) $(LD) -o $@ $(USER_LDFLAGS) $(USER_LIBPATHS) $(OBJS) $(LDSTARTGROUP) $(USER_LDLIBS) $(LDENDGROUP) $(USER_LIBGCC)
+
+$(TOPDIR)$(DELIM)nuttx_user.elf: nuttx_user.elf
+	$(Q) echo "LD: nuttx_user.elf"
+	$(Q) cp -a nuttx_user.elf $(TOPDIR)$(DELIM)nuttx_user.elf
+ifeq ($(CONFIG_INTELHEX_BINARY),y)
+	$(Q) echo "CP: nuttx_user.hex"
+	$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O ihex nuttx_user.elf $(USER_HEXFILE)
+endif
+ifeq ($(CONFIG_RAW_BINARY),y)
+	$(Q) echo "CP: nuttx_user.bin"
+	$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary nuttx_user.elf $(USER_BINFILE)
+endif
+
+.depend:
+
+depend: .depend
+
+clean:
+	$(call DELFILE, nuttx_user.elf)
+	$(call DELFILE, "$(TOPDIR)$(DELIM)nuttx_user.*")
+	$(call DELFILE, "$(TOPDIR)$(DELIM)User.map")
+	$(call CLEAN)
+
+distclean: clean
diff --git a/boards/xtensa/esp32/common/kernel/esp32_userspace.c b/boards/xtensa/esp32/common/kernel/esp32_userspace.c
new file mode 100755
index 0000000000..6e292769fa
--- /dev/null
+++ b/boards/xtensa/esp32/common/kernel/esp32_userspace.c
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * boards/xtensa/esp32/common/kernel/esp32_userspace.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/mm/mm.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/userspace.h>
+
+#if defined(CONFIG_BUILD_PROTECTED) && !defined(__KERNEL__)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_NUTTX_USERSPACE
+#  error "CONFIG_NUTTX_USERSPACE not defined"
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* These 'addresses' of these values are setup by the linker script.
+ * They are not actual uint32_t storage locations!
+ * They are only used meaningfully in the following way:
+ *
+ *  - The linker script defines, for example, the symbol_sdata.
+ *  - The declaration extern uint32_t _sdata; makes C happy.  C will believe
+ *    that the value _sdata is the address of a uint32_t variable _data
+ *    (it is not!).
+ *  - We can recover the linker value then by simply taking the address of
+ *    of _data.  like:  uint32_t *pdata = &_sdata;
+ */
+
+extern uint32_t _stext;           /* Start of .text */
+extern uint32_t _etext;           /* End+1 of .text + .rodata */
+extern const uint32_t _eronly;    /* End+1 of read only section */
+extern uint32_t _sdata;           /* Start of .data */
+extern uint32_t _edata;           /* End+1 of .data */
+extern uint32_t _sbss;            /* Start of .bss */
+extern uint32_t _ebss;            /* End+1 of .bss */
+
+extern uintptr_t *__ld_udram_end; /* End+1 of user ram section */
+
+/* This is the user space entry point */
+
+int CONFIG_INIT_ENTRYPOINT(int argc, char *argv[]);
+
+const struct userspace_s userspace locate_data(".userspace") =
+{
+  /* General memory map */
+
+  .us_entrypoint    = (main_t)CONFIG_INIT_ENTRYPOINT,
+  .us_textstart     = (uintptr_t)&_stext,
+  .us_textend       = (uintptr_t)&_etext,
+  .us_datasource    = (uintptr_t)&_eronly,
+  .us_datastart     = (uintptr_t)&_sdata,
+  .us_dataend       = (uintptr_t)&_edata,
+  .us_bssstart      = (uintptr_t)&_sbss,
+  .us_bssend        = (uintptr_t)&_ebss,
+
+  .us_heapend       = (uintptr_t)&__ld_udram_end,
+
+  /* Memory manager heap structure */
+
+  .us_heap          = &g_mmheap,
+
+  /* Task/thread startup routines */
+
+  .task_startup     = nxtask_startup,
+
+  /* Signal handler trampoline */
+
+  .signal_handler   = up_signal_handler,
+
+  /* Userspace work queue support (declared in include/nuttx/wqueue.h) */
+
+#ifdef CONFIG_LIBC_USRWORK
+  .work_usrstart    = work_usrstart,
+#endif
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#endif /* CONFIG_BUILD_PROTECTED && !__KERNEL__ */
diff --git a/boards/xtensa/esp32/common/scripts/esp32.template.ld b/boards/xtensa/esp32/common/scripts/flat.template.ld
similarity index 99%
rename from boards/xtensa/esp32/common/scripts/esp32.template.ld
rename to boards/xtensa/esp32/common/scripts/flat.template.ld
index 36aa1ed689..826dd21ba0 100644
--- a/boards/xtensa/esp32/common/scripts/esp32.template.ld
+++ b/boards/xtensa/esp32/common/scripts/flat.template.ld
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/xtensa/esp32/common/scripts/esp32.template.ld
+ * boards/xtensa/esp32/common/scripts/flat.template.ld
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
diff --git a/boards/xtensa/esp32/common/scripts/kernel-space.ld b/boards/xtensa/esp32/common/scripts/kernel-space.ld
new file mode 100755
index 0000000000..5e0013fd55
--- /dev/null
+++ b/boards/xtensa/esp32/common/scripts/kernel-space.ld
@@ -0,0 +1,313 @@
+/****************************************************************************
+ * boards/xtensa/esp32/common/scripts/kernel-space.ld
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/* Provide these so there is no need for using config files for this */
+
+__uirom_start = ORIGIN(UIROM);
+__uirom_size = LENGTH(UIROM);
+__uirom_end = ORIGIN(UIROM) + LENGTH(UIROM);
+__udrom_start = ORIGIN(UDROM);
+__udrom_size = LENGTH(UDROM);
+__udrom_end = ORIGIN(UDROM) + LENGTH(UDROM);
+__uiram_start = ORIGIN(UIRAM);
+__uiram_size = LENGTH(UIRAM);
+__uiram_end = ORIGIN(UIRAM) + LENGTH(UIRAM);
+__udram_start = ORIGIN(UDRAM);
+__udram_size = LENGTH(UDRAM);
+__udram_end = ORIGIN(UDRAM) + LENGTH(UDRAM);
+
+/* Provide the kernel boundaries as well */
+
+__kirom_start = ORIGIN(KIROM);
+__kirom_size = LENGTH(KIROM);
+__kdrom_start = ORIGIN(KDROM);
+__kdrom_size = LENGTH(KDROM);
+__kdrom_start = ORIGIN(KDROM);
+__kdrom_size = LENGTH(KDROM);
+__kiram_0_start = ORIGIN(KIRAM_0);
+__kiram_0_size = LENGTH(KIRAM_0);
+__kiram_0_end = ORIGIN(KIRAM_0) + LENGTH(KIRAM_0);
+__kiram_1_start = ORIGIN(KIRAM_1);
+__kiram_1_size = LENGTH(KIRAM_1);
+__kiram_1_end = ORIGIN(KIRAM_1) + LENGTH(KIRAM_1);
+__kdram_0_start = ORIGIN(KDRAM_0);
+__kdram_0_size = LENGTH(KDRAM_0);
+__kdram_0_end = ORIGIN(KDRAM_0) + LENGTH(KDRAM_0);
+__kdram_1_start = ORIGIN(KDRAM_1);
+__kdram_1_size = LENGTH(KDRAM_1);
+__kdram_1_end = ORIGIN(KDRAM_1) + LENGTH(KDRAM_1);
+
+/* Heap ends at top of dram0_0_seg */
+
+_eheap = 0x40000000;
+
+ENTRY(_stext)
+
+SECTIONS
+{
+  /* Send .iram0 code to iram */
+
+  .iram0.vectors :
+  {
+    /* Vectors go to IRAM */
+
+    _init_start = ABSOLUTE(.);
+
+    __vectors_start = ABSOLUTE(.);
+
+    /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
+
+    . = 0x0;
+    KEEP (*(.window_vectors.text));
+    . = 0x180;
+    KEEP (*(.xtensa_level2_vector.text));
+    . = 0x1c0;
+    KEEP (*(.xtensa_level3_vector.text));
+    . = 0x200;
+    KEEP (*(.xtensa_level4_vector.text));
+    . = 0x240;
+    KEEP (*(.xtensa_level5_vector.text));
+    . = 0x280;
+    KEEP (*(.debug_exception_vector.text));
+    . = 0x2c0;
+    KEEP (*(.nmi_vector.text));
+    . = 0x300;
+    KEEP (*(.kernel_exception_vector.text));
+    . = 0x340;
+    KEEP (*(.user_exception_vector.text));
+    . = 0x3c0;
+    KEEP (*(.double_exception_vector.text));
+    . = 0x400;
+    *(.*_vector.literal)
+
+    . = ALIGN (16);
+
+    __vectors_end = ABSOLUTE(.);
+
+    *(.entry.text)
+    *(.init.literal)
+    *(.init)
+
+    _init_end = ABSOLUTE(.);
+  } >KIRAM_0
+
+  .iram0.text :
+  {
+    /* Code marked as running out of IRAM */
+
+    _iram_text_start = ABSOLUTE(.);
+    *(.iram1 .iram1.*)
+    *librtc.a:(.literal .text .literal.* .text.*)
+    *libkarch.a:esp32_spiflash.*(.literal .text .literal.* .text.*)
+    *libkarch.a:xtensa_cpupause.*(.literal .text .literal.* .text.*)
+    *libkarch.a:xtensa_copystate.*(.literal .text .literal.* .text.*)
+    *libkarch.a:xtensa_interruptcontext.*(.literal .text .literal.* .text.*)
+    *libkarch.a:xtensa_testset.*(.literal .text .literal.* .text.*)
+
+    *libsched.a:sched_suspendscheduler.*(.literal .text .literal.* .text.*)
+    *libsched.a:sched_note.*(.literal .text .literal.* .text.*)
+    *libsched.a:sched_thistask.*(.literal .text .literal.* .text.*)
+    *libsched.a:spinlock.*(.literal .text .literal.* .text.*)
+    *libsched.a:irq_csection.*(.literal .text .literal.* .text.*)
+    *libsched.a:irq_dispatch.*(.literal .text .literal.* .text.*)
+
+    *(.wifirxiram .wifirxiram.*)
+    *(.wifi0iram  .wifi0iram.*)
+    *(.wifislpiram .wifislpiram.*)
+    *(.wifislprxiram .wifislprxiram.*)
+    *(.phyiram .phyiram.*)
+    _iram_text_end = ABSOLUTE(.);
+
+    /* IRAM heap starts at the end of iram0_0_seg */
+
+    . = ALIGN (4);
+    _siramheap = ABSOLUTE(.);
+  } >KIRAM_1
+
+  /* Shared RAM */
+
+  .dram0.bss (NOLOAD) :
+  {
+    /* .bss initialized on power-up */
+
+    . = ALIGN (8);
+    _sbss = ABSOLUTE(.);
+    _bss_start = ABSOLUTE(.);
+    *(.ext_ram.bss*)
+    _bt_bss_start = ABSOLUTE(.);
+    *libbt.a:(.bss .bss.* COMMON)
+    . = ALIGN (4);
+    _bt_bss_end = ABSOLUTE(.);
+    _btdm_bss_start = ABSOLUTE(.);
+    *libbtdm_app.a:(.bss .bss.* COMMON)
+    . = ALIGN (4);
+    _btdm_bss_end = ABSOLUTE(.);
+    . = ALIGN (8);
+    *(.dynsbss)
+    *(.sbss)
+    *(.sbss.*)
+    *(.gnu.linkonce.sb.*)
+    *(.scommon)
+    *(.sbss2)
+    *(.sbss2.*)
+    *(.gnu.linkonce.sb2.*)
+    *(.dynbss)
+    KEEP (*(.bss))
+    *(.bss.*)
+    *(.share.mem)
+    *(.gnu.linkonce.b.*)
+    *(COMMON)
+    *libkarch.a:esp32_spiflash.*(.bss  .bss.*  COMMON)
+    *libkarch.a:xtensa_cpupause.*(.bss  .bss.*  COMMON)
+    *libkarch.a:xtensa_copystate.*(.bss  .bss.*  COMMON)
+    *libkarch.a:xtensa_interruptcontext.*(.bss  .bss.*  COMMON)
+    *libkarch.a:xtensa_testset.*(.bss  .bss.*  COMMON)
+
+    *libsched.a:sched_suspendscheduler.*(.bss  .bss.*  COMMON)
+    *libsched.a:sched_thistask.*(.bss  .bss.*  COMMON)
+    *libsched.a:sched_note.*(.bss  .bss.*  COMMON)
+    *libsched.a:spinlock.*(.bss  .bss.*  COMMON)
+    *libsched.a:irq_csection.*(.bss  .bss.*  COMMON)
+    *libsched.a:irq_dispatch.*(.bss  .bss.*  COMMON)
+
+    . = ALIGN(8);
+    _bss_end = ABSOLUTE(.);
+    _ebss = ABSOLUTE(.);
+  } >KDRAM_0
+
+  .noinit (NOLOAD):
+  {
+    /* This section contains data that is not initialized during load,
+     * or during the application's initialization sequence.
+     */
+
+    *(.noinit)
+  } >KDRAM_0
+
+  .dram0.data :
+  {
+    /* .data initialized on power-up in ROMed configurations. */
+
+    _sdata = ABSOLUTE(.);
+    _bt_data_start = ABSOLUTE(.);
+    *libbt.a:(.data .data.*)
+    . = ALIGN (4);
+    _bt_data_end = ABSOLUTE(.);
+    _btdm_data_start = ABSOLUTE(.);
+    *libbtdm_app.a:(.data .data.*)
+    . = ALIGN (4);
+    _btdm_data_end = ABSOLUTE(.);
+    KEEP (*(.data))
+    KEEP (*(.data.*))
+    KEEP (*(.gnu.linkonce.d.*))
+    KEEP (*(.data1))
+    KEEP (*(.sdata))
+    KEEP (*(.sdata.*))
+    KEEP (*(.gnu.linkonce.s.*))
+    KEEP (*(.sdata2))
+    KEEP (*(.sdata2.*))
+    KEEP (*(.gnu.linkonce.s2.*))
+    KEEP (*(.jcr))
+    *(.dram1 .dram1.*)
+    *libphy.a:(.rodata  .rodata.*)
+    *libkarch.a:esp32_spiflash.*(.rodata  .rodata.*)
+    *libkarch.a:xtensa_cpupause.*(.rodata  .rodata.*)
+    *libkarch.a:xtensa_copystate.*(.rodata  .rodata.*)
+    *libkarch.a:xtensa_interruptcontext.*(.rodata  .rodata.*)
+    *libkarch.a:xtensa_testset.*(.rodata  .rodata.*)
+
+    *libsched.a:sched_suspendscheduler.*(.rodata  .rodata.*)
+    *libsched.a:sched_thistask.*(.rodata  .rodata.*)
+    *libsched.a:sched_note.*(.rodata  .rodata.*)
+    *libsched.a:spinlock.*(.rodata  .rodata.*)
+    *libsched.a:irq_csection.*(.rodata  .rodata.*)
+    *libsched.a:irq_dispatch.*(.rodata  .rodata.*)
+
+    . = ALIGN(4);
+    _edata = ABSOLUTE(.);
+
+    /* Heap starts at the end of .data */
+
+    _sheap = ABSOLUTE(.);
+  } >KDRAM_0
+
+  .flash.rodata :
+  {
+    _srodata = ABSOLUTE(.);
+    *(.rodata)
+    *(.rodata.*)
+    *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
+    *(.gnu.linkonce.r.*)
+    *(.rodata1)
+    __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
+    *(.xt_except_table)
+    *(.gcc_except_table)
+    *(.gcc_except_table.*)
+    *(.gnu.linkonce.e.*)
+    *(.gnu.version_r)
+    *(.eh_frame)
+
+    . = (. + 3) & ~ 3;
+
+    /* C++ constructor and destructor tables, properly ordered: */
+
+    _sinit = ABSOLUTE(.);
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+    _einit = ABSOLUTE(.);
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+
+    /* C++ exception handlers table: */
+
+    __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
+    *(.xt_except_desc)
+    *(.gnu.linkonce.h.*)
+    __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
+    *(.xt_except_desc_end)
+    *(.dynamic)
+    *(.gnu.version_d)
+    _erodata = ABSOLUTE(.);
+    /* Literals are also RO data. */
+    _lit4_start = ABSOLUTE(.);
+    *(*.lit4)
+    *(.lit4.*)
+    *(.gnu.linkonce.lit4.*)
+    _lit4_end = ABSOLUTE(.);
+    . = ALIGN(4);
+  } >KDROM
+
+  .flash.text :
+  {
+    _stext = .;
+    _text_start = ABSOLUTE(.);
+    *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+    *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
+    *(.fini.literal)
+    *(.fini)
+    *(.gnu.version)
+    _text_end = ABSOLUTE(.);
+    _etext = .;
+  } >KIROM
+}
diff --git a/boards/xtensa/esp32/common/scripts/protected.template.ld b/boards/xtensa/esp32/common/scripts/protected.template.ld
new file mode 100644
index 0000000000..80ebe214db
--- /dev/null
+++ b/boards/xtensa/esp32/common/scripts/protected.template.ld
@@ -0,0 +1,97 @@
+/****************************************************************************
+ * boards/xtensa/esp32/common/scripts/protected.template.ld
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * ESP32 Linker Script Memory Layout
+ *
+ * This file describes the memory layout (memory blocks) as virtual
+ * memory addresses.
+ *
+ * kernel-space.ld and user-space.ld contain output sections to link compiler
+ * output into these memory blocks for the Kernel and User images,
+ * respectively.
+ *
+ * NOTE: That this is not the actual linker script but rather a "template"
+ * for the esp32_out.ld script. This template script is passed through
+ * the C preprocessor to include selected configuration options.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "esp32_aliases.ld"
+
+MEMORY
+{
+
+  metadata (RX) :   org = 0x0, len = 0x18
+  ROM (RX) :        org = 0x18, len = 0x100000
+
+  /* Below values assume the flash cache is on, and have the blocks this
+   * uses subtracted from the length of the various regions. The 'data access
+   * port' dram/drom regions map to the same iram/irom regions but are
+   * connected to the data port of the CPU and e.g. allow bytewise access.
+   */
+
+  /* Physically located in SRAM0 */
+  KIRAM_0 (RWX) : org = 0x40080000, len = 0x2000
+  UIRAM (RWX)   : org = 0x40082000, len = 0xe000
+  KIRAM_1 (RWX) : org = 0x40090000, len = 0x10000
+
+  /* Flash mapped instruction data. */
+
+  /* The 0x20 offset for the KIROM region is a convenience for the Kernel
+   * binary image generation in Espressif Application Image format.
+   * Flash cache has 64KB pages. The .bin file which is flashed to the chip
+   * has a 0x18 byte file header, and each segment has a 0x08 byte segment
+   * header. Setting this offset makes it simple to meet the flash cache MMU's
+   * constraint that (paddr % 64KB == vaddr % 64KB).
+   */
+
+  KIROM (RX) : org = 0x400d0020, len = 0x330000 - 0x20
+  UIROM (RX) : org = 0x40400000, len = 0x400000
+
+  /* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
+   * Enabling Bluetooth & Trace Memory features in menuconfig will decrease
+   * the amount of RAM available to the NuttX Kernel.
+   */
+
+  /* Physically located in SRAM2 */
+  KDRAM_0 (RW) : org = 0x3ffb0000 + CONFIG_ESP32_BT_RESERVE_DRAM,
+                 len = 0x18000 - CONFIG_ESP32_BT_RESERVE_DRAM
+  UDRAM (RW)   : org = 0x3ffc8000, len = 0x18000
+
+  /* Physically located in SRAM1 */
+  KDRAM_1 (RW) : org = 0x3ffe0000, len = 0x20000
+
+  /* Flash mapped constant data */
+
+  /* See KIROM region documentation above for the meaning of the 0x20 offset.
+   *
+   * The 0x18 offset for the UDROM region is a convenience for the User
+   * binary image generation following a custom image format, which defines
+   * a "metadata" output section containing some information that the Kernel
+   * needs for properly configuring the External Flash MMU when loading the
+   * User application image.
+   */
+
+  KDROM (R) : org = 0x3f400020, len = 0x80000 - 0x20
+  UDROM (R) : org = 0x3f480018, len = 0x80000 - 0x18
+}
diff --git a/boards/xtensa/esp32/common/scripts/user-space.ld b/boards/xtensa/esp32/common/scripts/user-space.ld
new file mode 100755
index 0000000000..4977cc6751
--- /dev/null
+++ b/boards/xtensa/esp32/common/scripts/user-space.ld
@@ -0,0 +1,217 @@
+/****************************************************************************
+ * boards/xtensa/esp32/common/scripts/user-space.ld
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+SECTIONS
+{
+  .metadata :
+  {
+    /* DROM metadata:
+     * - Destination address (VMA) for DROM region
+     * - Flash offset (LMA) for start of DROM region
+     * - Size of DROM region
+     */
+
+    LONG(ADDR(.userspace))
+    LONG(LOADADDR(.userspace))
+    LONG(SIZEOF(.userspace) + SIZEOF(.rodata))
+
+    /* IROM metadata:
+     * - Destination address (VMA) for IROM region
+     * - Flash offset (LMA) for start of IROM region
+     * - Size of IROM region
+     */
+
+    LONG(ADDR(.text))
+    LONG(LOADADDR(.text))
+    LONG(SIZEOF(.text))
+  } >metadata
+
+  /* section info */
+
+  __ld_uirom_start = ORIGIN(UIROM);
+  __ld_uirom_size = LENGTH(UIROM);
+  __ld_uirom_end = ORIGIN(UIROM) + LENGTH(UIROM);
+  __ld_udrom_start = ORIGIN(UDROM);
+  __ld_udrom_size = LENGTH(UDROM);
+  __ld_udrom_end = ORIGIN(UDROM) + LENGTH(UDROM);
+  __ld_uiram_start = ORIGIN(UIRAM);
+  __ld_uiram_size = LENGTH(UIRAM);
+  __ld_uiram_end = ORIGIN(UIRAM) + LENGTH(UIRAM);
+  __ld_udram_start = ORIGIN(UDRAM);
+  __ld_udram_size = LENGTH(UDRAM);
+  __ld_udram_end = ORIGIN(UDRAM) + LENGTH(UDRAM);
+
+  _eronly = LOADADDR(.data);
+
+  .userspace :
+  {
+    *(.userspace)
+  } >UDROM AT>ROM
+
+  /* Output sections for the Userspace image are given standard names, so
+   * instead of the Espressif-usual ".flash.text" we name it as ".text".
+   * The motivation is to ease debugging with GDB when loading symbols from
+   * both Kernel and User images since GDB's "add-symbol-file" command
+   * expects to find a .text section at the provided offset.
+   */
+
+  .rodata :
+  {
+    . = ALIGN(4);
+    _srodata = ABSOLUTE(.);
+
+    *(.rodata)
+    *(.rodata.*)
+
+    *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
+    *(.gnu.linkonce.r.*)
+    *(.rodata1)
+    __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
+    *(.xt_except_table)
+    *(.gcc_except_table)
+    *(.gcc_except_table.*)
+    *(.gnu.linkonce.e.*)
+    *(.gnu.version_r)
+    *(.eh_frame)
+
+    . = (. + 3) & ~ 3;
+
+    /* C++ constructor and destructor tables, properly ordered: */
+
+    _sinit = ABSOLUTE(.);
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+    _einit = ABSOLUTE(.);
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+
+    /* C++ exception handlers table: */
+
+    __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
+    *(.xt_except_desc)
+    *(.gnu.linkonce.h.*)
+    __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
+    *(.xt_except_desc_end)
+    *(.dynamic)
+    *(.gnu.version_d)
+    . = ALIGN(4);               /* This table MUST be 4-byte aligned */
+
+    _erodata = ABSOLUTE(.);
+
+    /* Literals are also RO data. */
+    _lit4_start = ABSOLUTE(.);
+    *(*.lit4)
+    *(.lit4.*)
+    *(.gnu.linkonce.lit4.*)
+    _lit4_end = ABSOLUTE(.);
+    . = ALIGN(4);
+  } >UDROM AT>ROM
+
+  .iram0.text :
+  {
+    _iram_text_start = ABSOLUTE(.);
+
+    *(.iram1)
+    *(.iram1.*)
+
+    _iram_text_end = ABSOLUTE(.);
+  } >UIRAM AT>ROM
+
+  /* Shared RAM */
+
+  .bss (NOLOAD) :
+  {
+    /* .bss initialized on power-up */
+
+    . = ALIGN (8);
+    _sbss = ABSOLUTE(.);
+
+    *(.dynsbss)
+    *(.sbss)
+    *(.sbss.*)
+    *(.gnu.linkonce.sb.*)
+    *(.scommon)
+    *(.sbss2)
+    *(.sbss2.*)
+    *(.gnu.linkonce.sb2.*)
+    *(.dynbss)
+    KEEP (*(.bss))
+    *(.bss.*)
+    *(.share.mem)
+    *(.gnu.linkonce.b.*)
+    *(COMMON)
+    . = ALIGN(8);
+
+    _ebss = ABSOLUTE(.);
+  } >UDRAM
+
+  .noinit (NOLOAD):
+  {
+    /* This section contains data that is not initialized during load,
+     * or during the application's initialization sequence.
+     */
+
+    . = ALIGN(8);
+    *(.noinit)
+    *(.noinit.*)
+    . = ALIGN(8);
+  } >UDRAM
+
+  .data :
+  {
+    _sdata = ABSOLUTE(.);
+    KEEP (*(.data))
+    KEEP (*(.data.*))
+    KEEP (*(.gnu.linkonce.d.*))
+    KEEP (*(.data1))
+    KEEP (*(.sdata))
+    KEEP (*(.sdata.*))
+    KEEP (*(.gnu.linkonce.s.*))
+    KEEP (*(.sdata2))
+    KEEP (*(.sdata2.*))
+    KEEP (*(.gnu.linkonce.s2.*))
+    KEEP (*(.jcr))
+    *(.dram1 .dram1.*)
+    _edata = ABSOLUTE(.);
+    . = ALIGN(4);
+
+    /* Heap starts at the end of .data */
+
+    _sheap = ABSOLUTE(.);
+  } >UDRAM AT>ROM
+
+  .text : ALIGN(0x00010000)
+  {
+    _stext = .;
+
+    *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+    *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
+    *(.fini.literal)
+    *(.fini)
+    *(.gnu.version)
+    . = ALIGN(4);
+
+    _etext = .;
+  } >UIROM AT>ROM
+}
diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig
new file mode 100644
index 0000000000..e85a601fb0
--- /dev/null
+++ b/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig
@@ -0,0 +1,62 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_ARCH_LEDS is not set
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+# CONFIG_NSH_CMDPARMS is not set
+CONFIG_ARCH="xtensa"
+CONFIG_ARCH_BOARD="esp32-devkitc"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_ESP32_DEVKITC=y
+CONFIG_ARCH_CHIP="esp32"
+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
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_ASSERTIONS=y
+CONFIG_DEBUG_ERROR=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEBUG_WARN=y
+CONFIG_ESP32_UART0=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=3072
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_MM_REGIONS=3
+CONFIG_NDEBUG=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_NUTTX_USERSPACE=0x3f480018
+CONFIG_PASS1_BUILDIR="boards/xtensa/esp32/common/kernel"
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=114688
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_DAY=6
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_UART0_SERIAL_CONSOLE=y
diff --git a/boards/xtensa/esp32/esp32-devkitc/include/board_memorymap.h b/boards/xtensa/esp32/esp32-devkitc/include/board_memorymap.h
new file mode 100644
index 0000000000..3a78a915d3
--- /dev/null
+++ b/boards/xtensa/esp32/esp32-devkitc/include/board_memorymap.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+ * boards/xtensa/esp32/esp32-devkitc/include/board_memorymap.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 __BOARDS_XTENSA_ESP32_ESP32_DEVKITC_INCLUDE_BOARD_MEMORYMAP_H
+#define __BOARDS_XTENSA_ESP32_ESP32_DEVKITC_INCLUDE_BOARD_MEMORYMAP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Kernel ROM */
+
+#define KIROM_START     (uintptr_t)&__kirom_start
+#define KIROM_SIZE      (uintptr_t)&__kirom_size
+#define KDROM_START     (uintptr_t)&__kdrom_start
+#define KDROM_SIZE      (uintptr_t)&__kdrom_size
+
+/* Kernel RAM */
+
+#define KIRAM_0_START   (uintptr_t)&__kiram_0_start
+#define KIRAM_0_SIZE    (uintptr_t)&__kiram_0_size
+#define KIRAM_0_END     (uintptr_t)&__kiram_0_end
+#define KIRAM_1_START   (uintptr_t)&__kiram_1_start
+#define KIRAM_1_SIZE    (uintptr_t)&__kiram_1_size
+#define KIRAM_1_END     (uintptr_t)&__kiram_1_end
+#define KDRAM_0_START   (uintptr_t)&__kdram_0_start
+#define KDRAM_0_SIZE    (uintptr_t)&__kdram_0_size
+#define KDRAM_0_END     (uintptr_t)&__kdram_0_end
+#define KDRAM_1_START   (uintptr_t)&__kdram_1_start
+#define KDRAM_1_SIZE    (uintptr_t)&__kdram_1_size
+#define KDRAM_1_END     (uintptr_t)&__kdram_1_end
+
+/* Exception vectors */
+
+#define VECTORS_START   (uintptr_t)&__vectors_start
+#define VECTORS_END     (uintptr_t)&__vectors_end
+
+/* User ROM */
+
+#define UIROM_START     (uintptr_t)&__uirom_start
+#define UIROM_SIZE      (uintptr_t)&__uirom_size
+#define UIROM_END       (uintptr_t)&__uirom_end
+#define UDROM_START     (uintptr_t)&__udrom_start
+#define UDROM_SIZE      (uintptr_t)&__udrom_size
+#define UDROM_END       (uintptr_t)&__udrom_end
+
+/* User RAM */
+
+#define UIRAM_START     (uintptr_t)&__uiram_start
+#define UIRAM_SIZE      (uintptr_t)&__uiram_size
+#define UIRAM_END       (uintptr_t)&__uiram_end
+#define UDRAM_START     (uintptr_t)&__udram_start
+#define UDRAM_SIZE      (uintptr_t)&__udram_size
+#define UDRAM_END       (uintptr_t)&__udram_end
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Kernel ROM (RX)  */
+
+extern uintptr_t        __kirom_start;
+extern uintptr_t        __kirom_size;
+extern uintptr_t        __kdrom_start;
+extern uintptr_t        __kdrom_size;
+
+/* Kernel RAM (RW) */
+
+extern uintptr_t        __kiram_0_start;
+extern uintptr_t        __kiram_0_size;
+extern uintptr_t        __kiram_0_end;
+extern uintptr_t        __kiram_1_start;
+extern uintptr_t        __kiram_1_size;
+extern uintptr_t        __kiram_1_end;
+extern uintptr_t        __kdram_0_start;
+extern uintptr_t        __kdram_0_size;
+extern uintptr_t        __kdram_0_end;
+extern uintptr_t        __kdram_1_start;
+extern uintptr_t        __kdram_1_size;
+extern uintptr_t        __kdram_1_end;
+
+/* Exception vectors */
+
+extern uintptr_t        __vectors_start;
+extern uintptr_t        __vectors_end;
+
+/* User ROM (RX) */
+
+extern uintptr_t        __uirom_start;
+extern uintptr_t        __uirom_size;
+extern uintptr_t        __uirom_end;
+extern uintptr_t        __udrom_start;
+extern uintptr_t        __udrom_size;
+extern uintptr_t        __udrom_end;
+
+/* User RAM (RW) */
+
+extern uintptr_t        __uiram_start;
+extern uintptr_t        __uiram_size;
+extern uintptr_t        __uiram_end;
+extern uintptr_t        __udram_start;
+extern uintptr_t        __udram_size;
+extern uintptr_t        __udram_end;
+
+#endif /* __BOARDS_XTENSA_ESP32_ESP32_DEVKITC_INCLUDE_BOARD_MEMORYMAP_H */
diff --git a/boards/xtensa/esp32/esp32-devkitc/scripts/Make.defs b/boards/xtensa/esp32/esp32-devkitc/scripts/Make.defs
index 18d8ad0229..9425f18ac6 100644
--- a/boards/xtensa/esp32/esp32-devkitc/scripts/Make.defs
+++ b/boards/xtensa/esp32/esp32-devkitc/scripts/Make.defs
@@ -34,10 +34,14 @@ ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32_out.ld
 ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld),)
 	ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld
 else
-	ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
-		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld
+	ifeq ($(CONFIG_BUILD_PROTECTED),y)
+		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)kernel-space.ld
 	else
-		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld
+		ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
+			ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld
+		else
+			ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld
+		endif
 	endif
 endif
 
@@ -50,7 +54,11 @@ endif
 ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld),)
 	LDSCRIPT_TEMPLATE = $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld
 else
-	LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld
+	ifeq ($(CONFIG_BUILD_PROTECTED),y)
+		LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)protected.template.ld
+	else
+		LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)flat.template.ld
+	endif
 endif
 
 ARCHPICFLAGS = -fpic
diff --git a/boards/xtensa/esp32/esp32-ethernet-kit/include/board_memorymap.h b/boards/xtensa/esp32/esp32-ethernet-kit/include/board_memorymap.h
new file mode 100644
index 0000000000..dbc4f20c06
--- /dev/null
+++ b/boards/xtensa/esp32/esp32-ethernet-kit/include/board_memorymap.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+ * boards/xtensa/esp32/esp32-ethernet-kit/include/board_memorymap.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 __BOARDS_XTENSA_ESP32_ESP32_ETHERNET_KIT_INCLUDE_BOARD_MEMORYMAP_H
+#define __BOARDS_XTENSA_ESP32_ESP32_ETHERNET_KIT_INCLUDE_BOARD_MEMORYMAP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Kernel ROM */
+
+#define KIROM_START     (uintptr_t)&__kirom_start
+#define KIROM_SIZE      (uintptr_t)&__kirom_size
+#define KDROM_START     (uintptr_t)&__kdrom_start
+#define KDROM_SIZE      (uintptr_t)&__kdrom_size
+
+/* Kernel RAM */
+
+#define KIRAM_0_START   (uintptr_t)&__kiram_0_start
+#define KIRAM_0_SIZE    (uintptr_t)&__kiram_0_size
+#define KIRAM_0_END     (uintptr_t)&__kiram_0_end
+#define KIRAM_1_START   (uintptr_t)&__kiram_1_start
+#define KIRAM_1_SIZE    (uintptr_t)&__kiram_1_size
+#define KIRAM_1_END     (uintptr_t)&__kiram_1_end
+#define KDRAM_0_START   (uintptr_t)&__kdram_0_start
+#define KDRAM_0_SIZE    (uintptr_t)&__kdram_0_size
+#define KDRAM_0_END     (uintptr_t)&__kdram_0_end
+#define KDRAM_1_START   (uintptr_t)&__kdram_1_start
+#define KDRAM_1_SIZE    (uintptr_t)&__kdram_1_size
+#define KDRAM_1_END     (uintptr_t)&__kdram_1_end
+
+/* Exception vectors */
+
+#define VECTORS_START   (uintptr_t)&__vectors_start
+#define VECTORS_END     (uintptr_t)&__vectors_end
+
+/* User ROM */
+
+#define UIROM_START     (uintptr_t)&__uirom_start
+#define UIROM_SIZE      (uintptr_t)&__uirom_size
+#define UIROM_END       (uintptr_t)&__uirom_end
+#define UDROM_START     (uintptr_t)&__udrom_start
+#define UDROM_SIZE      (uintptr_t)&__udrom_size
+#define UDROM_END       (uintptr_t)&__udrom_end
+
+/* User RAM */
+
+#define UIRAM_START     (uintptr_t)&__uiram_start
+#define UIRAM_SIZE      (uintptr_t)&__uiram_size
+#define UIRAM_END       (uintptr_t)&__uiram_end
+#define UDRAM_START     (uintptr_t)&__udram_start
+#define UDRAM_SIZE      (uintptr_t)&__udram_size
+#define UDRAM_END       (uintptr_t)&__udram_end
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Kernel ROM (RX)  */
+
+extern uintptr_t        __kirom_start;
+extern uintptr_t        __kirom_size;
+extern uintptr_t        __kdrom_start;
+extern uintptr_t        __kdrom_size;
+
+/* Kernel RAM (RW) */
+
+extern uintptr_t        __kiram_0_start;
+extern uintptr_t        __kiram_0_size;
+extern uintptr_t        __kiram_0_end;
+extern uintptr_t        __kiram_1_start;
+extern uintptr_t        __kiram_1_size;
+extern uintptr_t        __kiram_1_end;
+extern uintptr_t        __kdram_0_start;
+extern uintptr_t        __kdram_0_size;
+extern uintptr_t        __kdram_0_end;
+extern uintptr_t        __kdram_1_start;
+extern uintptr_t        __kdram_1_size;
+extern uintptr_t        __kdram_1_end;
+
+/* Exception vectors */
+
+extern uintptr_t        __vectors_start;
+extern uintptr_t        __vectors_end;
+
+/* User ROM (RX) */
+
+extern uintptr_t        __uirom_start;
+extern uintptr_t        __uirom_size;
+extern uintptr_t        __uirom_end;
+extern uintptr_t        __udrom_start;
+extern uintptr_t        __udrom_size;
+extern uintptr_t        __udrom_end;
+
+/* User RAM (RW) */
+
+extern uintptr_t        __uiram_start;
+extern uintptr_t        __uiram_size;
+extern uintptr_t        __uiram_end;
+extern uintptr_t        __udram_start;
+extern uintptr_t        __udram_size;
+extern uintptr_t        __udram_end;
+
+#endif /* __BOARDS_XTENSA_ESP32_ESP32_ETHERNET_KIT_INCLUDE_BOARD_MEMORYMAP_H */
diff --git a/boards/xtensa/esp32/esp32-ethernet-kit/scripts/Make.defs b/boards/xtensa/esp32/esp32-ethernet-kit/scripts/Make.defs
index e3af7dac13..1e3a48629c 100644
--- a/boards/xtensa/esp32/esp32-ethernet-kit/scripts/Make.defs
+++ b/boards/xtensa/esp32/esp32-ethernet-kit/scripts/Make.defs
@@ -34,10 +34,14 @@ ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32_out.ld
 ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld),)
 	ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld
 else
-	ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
-		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld
+	ifeq ($(CONFIG_BUILD_PROTECTED),y)
+		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)kernel-space.ld
 	else
-		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld
+		ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
+			ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld
+		else
+			ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld
+		endif
 	endif
 endif
 
@@ -50,7 +54,11 @@ endif
 ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld),)
 	LDSCRIPT_TEMPLATE = $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld
 else
-	LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld
+	ifeq ($(CONFIG_BUILD_PROTECTED),y)
+		LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)protected.template.ld
+	else
+		LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)flat.template.ld
+	endif
 endif
 
 ARCHPICFLAGS = -fpic
diff --git a/boards/xtensa/esp32/esp32-wrover-kit/include/board_memorymap.h b/boards/xtensa/esp32/esp32-wrover-kit/include/board_memorymap.h
new file mode 100644
index 0000000000..566dbeb5d7
--- /dev/null
+++ b/boards/xtensa/esp32/esp32-wrover-kit/include/board_memorymap.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+ * boards/xtensa/esp32/esp32-wrover-kit/include/board_memorymap.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 __BOARDS_XTENSA_ESP32_ESP32_WROVER_KIT_INCLUDE_BOARD_MEMORYMAP_H
+#define __BOARDS_XTENSA_ESP32_ESP32_WROVER_KIT_INCLUDE_BOARD_MEMORYMAP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Kernel ROM */
+
+#define KIROM_START     (uintptr_t)&__kirom_start
+#define KIROM_SIZE      (uintptr_t)&__kirom_size
+#define KDROM_START     (uintptr_t)&__kdrom_start
+#define KDROM_SIZE      (uintptr_t)&__kdrom_size
+
+/* Kernel RAM */
+
+#define KIRAM_0_START   (uintptr_t)&__kiram_0_start
+#define KIRAM_0_SIZE    (uintptr_t)&__kiram_0_size
+#define KIRAM_0_END     (uintptr_t)&__kiram_0_end
+#define KIRAM_1_START   (uintptr_t)&__kiram_1_start
+#define KIRAM_1_SIZE    (uintptr_t)&__kiram_1_size
+#define KIRAM_1_END     (uintptr_t)&__kiram_1_end
+#define KDRAM_0_START   (uintptr_t)&__kdram_0_start
+#define KDRAM_0_SIZE    (uintptr_t)&__kdram_0_size
+#define KDRAM_0_END     (uintptr_t)&__kdram_0_end
+#define KDRAM_1_START   (uintptr_t)&__kdram_1_start
+#define KDRAM_1_SIZE    (uintptr_t)&__kdram_1_size
+#define KDRAM_1_END     (uintptr_t)&__kdram_1_end
+
+/* Exception vectors */
+
+#define VECTORS_START   (uintptr_t)&__vectors_start
+#define VECTORS_END     (uintptr_t)&__vectors_end
+
+/* User ROM */
+
+#define UIROM_START     (uintptr_t)&__uirom_start
+#define UIROM_SIZE      (uintptr_t)&__uirom_size
+#define UIROM_END       (uintptr_t)&__uirom_end
+#define UDROM_START     (uintptr_t)&__udrom_start
+#define UDROM_SIZE      (uintptr_t)&__udrom_size
+#define UDROM_END       (uintptr_t)&__udrom_end
+
+/* User RAM */
+
+#define UIRAM_START     (uintptr_t)&__uiram_start
+#define UIRAM_SIZE      (uintptr_t)&__uiram_size
+#define UIRAM_END       (uintptr_t)&__uiram_end
+#define UDRAM_START     (uintptr_t)&__udram_start
+#define UDRAM_SIZE      (uintptr_t)&__udram_size
+#define UDRAM_END       (uintptr_t)&__udram_end
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Kernel ROM (RX)  */
+
+extern uintptr_t        __kirom_start;
+extern uintptr_t        __kirom_size;
+extern uintptr_t        __kdrom_start;
+extern uintptr_t        __kdrom_size;
+
+/* Kernel RAM (RW) */
+
+extern uintptr_t        __kiram_0_start;
+extern uintptr_t        __kiram_0_size;
+extern uintptr_t        __kiram_0_end;
+extern uintptr_t        __kiram_1_start;
+extern uintptr_t        __kiram_1_size;
+extern uintptr_t        __kiram_1_end;
+extern uintptr_t        __kdram_0_start;
+extern uintptr_t        __kdram_0_size;
+extern uintptr_t        __kdram_0_end;
+extern uintptr_t        __kdram_1_start;
+extern uintptr_t        __kdram_1_size;
+extern uintptr_t        __kdram_1_end;
+
+/* Exception vectors */
+
+extern uintptr_t        __vectors_start;
+extern uintptr_t        __vectors_end;
+
+/* User ROM (RX) */
+
+extern uintptr_t        __uirom_start;
+extern uintptr_t        __uirom_size;
+extern uintptr_t        __uirom_end;
+extern uintptr_t        __udrom_start;
+extern uintptr_t        __udrom_size;
+extern uintptr_t        __udrom_end;
+
+/* User RAM (RW) */
+
+extern uintptr_t        __uiram_start;
+extern uintptr_t        __uiram_size;
+extern uintptr_t        __uiram_end;
+extern uintptr_t        __udram_start;
+extern uintptr_t        __udram_size;
+extern uintptr_t        __udram_end;
+
+#endif /* __BOARDS_XTENSA_ESP32_ESP32_WROVER_KIT_INCLUDE_BOARD_MEMORYMAP_H */
diff --git a/boards/xtensa/esp32/esp32-wrover-kit/scripts/Make.defs b/boards/xtensa/esp32/esp32-wrover-kit/scripts/Make.defs
index ad65da140d..026f791c23 100644
--- a/boards/xtensa/esp32/esp32-wrover-kit/scripts/Make.defs
+++ b/boards/xtensa/esp32/esp32-wrover-kit/scripts/Make.defs
@@ -34,10 +34,14 @@ ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32_out.ld
 ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld),)
 	ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld
 else
-	ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
-		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld
+	ifeq ($(CONFIG_BUILD_PROTECTED),y)
+		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)kernel-space.ld
 	else
-		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld
+		ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
+			ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld
+		else
+			ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld
+		endif
 	endif
 endif
 
@@ -50,7 +54,11 @@ endif
 ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld),)
 	LDSCRIPT_TEMPLATE = $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld
 else
-	LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld
+	ifeq ($(CONFIG_BUILD_PROTECTED),y)
+		LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)protected.template.ld
+	else
+		LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)flat.template.ld
+	endif
 endif
 
 ARCHPICFLAGS = -fpic
diff --git a/boards/xtensa/esp32/ttgo_eink5_v2/include/board_memorymap.h b/boards/xtensa/esp32/ttgo_eink5_v2/include/board_memorymap.h
new file mode 100644
index 0000000000..bfd74185b7
--- /dev/null
+++ b/boards/xtensa/esp32/ttgo_eink5_v2/include/board_memorymap.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+ * boards/xtensa/esp32/ttgo_eink5_v2/include/board_memorymap.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 __BOARDS_XTENSA_ESP32_TTGO_EINK_5_V2_INCLUDE_BOARD_MEMORYMAP_H
+#define __BOARDS_XTENSA_ESP32_TTGO_EINK_5_V2_INCLUDE_BOARD_MEMORYMAP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Kernel ROM */
+
+#define KIROM_START     (uintptr_t)&__kirom_start
+#define KIROM_SIZE      (uintptr_t)&__kirom_size
+#define KDROM_START     (uintptr_t)&__kdrom_start
+#define KDROM_SIZE      (uintptr_t)&__kdrom_size
+
+/* Kernel RAM */
+
+#define KIRAM_0_START   (uintptr_t)&__kiram_0_start
+#define KIRAM_0_SIZE    (uintptr_t)&__kiram_0_size
+#define KIRAM_0_END     (uintptr_t)&__kiram_0_end
+#define KIRAM_1_START   (uintptr_t)&__kiram_1_start
+#define KIRAM_1_SIZE    (uintptr_t)&__kiram_1_size
+#define KIRAM_1_END     (uintptr_t)&__kiram_1_end
+#define KDRAM_0_START   (uintptr_t)&__kdram_0_start
+#define KDRAM_0_SIZE    (uintptr_t)&__kdram_0_size
+#define KDRAM_0_END     (uintptr_t)&__kdram_0_end
+#define KDRAM_1_START   (uintptr_t)&__kdram_1_start
+#define KDRAM_1_SIZE    (uintptr_t)&__kdram_1_size
+#define KDRAM_1_END     (uintptr_t)&__kdram_1_end
+
+/* Exception vectors */
+
+#define VECTORS_START   (uintptr_t)&__vectors_start
+#define VECTORS_END     (uintptr_t)&__vectors_end
+
+/* User ROM */
+
+#define UIROM_START     (uintptr_t)&__uirom_start
+#define UIROM_SIZE      (uintptr_t)&__uirom_size
+#define UIROM_END       (uintptr_t)&__uirom_end
+#define UDROM_START     (uintptr_t)&__udrom_start
+#define UDROM_SIZE      (uintptr_t)&__udrom_size
+#define UDROM_END       (uintptr_t)&__udrom_end
+
+/* User RAM */
+
+#define UIRAM_START     (uintptr_t)&__uiram_start
+#define UIRAM_SIZE      (uintptr_t)&__uiram_size
+#define UIRAM_END       (uintptr_t)&__uiram_end
+#define UDRAM_START     (uintptr_t)&__udram_start
+#define UDRAM_SIZE      (uintptr_t)&__udram_size
+#define UDRAM_END       (uintptr_t)&__udram_end
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Kernel ROM (RX)  */
+
+extern uintptr_t        __kirom_start;
+extern uintptr_t        __kirom_size;
+extern uintptr_t        __kdrom_start;
+extern uintptr_t        __kdrom_size;
+
+/* Kernel RAM (RW) */
+
+extern uintptr_t        __kiram_0_start;
+extern uintptr_t        __kiram_0_size;
+extern uintptr_t        __kiram_0_end;
+extern uintptr_t        __kiram_1_start;
+extern uintptr_t        __kiram_1_size;
+extern uintptr_t        __kiram_1_end;
+extern uintptr_t        __kdram_0_start;
+extern uintptr_t        __kdram_0_size;
+extern uintptr_t        __kdram_0_end;
+extern uintptr_t        __kdram_1_start;
+extern uintptr_t        __kdram_1_size;
+extern uintptr_t        __kdram_1_end;
+
+/* Exception vectors */
+
+extern uintptr_t        __vectors_start;
+extern uintptr_t        __vectors_end;
+
+/* User ROM (RX) */
+
+extern uintptr_t        __uirom_start;
+extern uintptr_t        __uirom_size;
+extern uintptr_t        __uirom_end;
+extern uintptr_t        __udrom_start;
+extern uintptr_t        __udrom_size;
+extern uintptr_t        __udrom_end;
+
+/* User RAM (RW) */
+
+extern uintptr_t        __uiram_start;
+extern uintptr_t        __uiram_size;
+extern uintptr_t        __uiram_end;
+extern uintptr_t        __udram_start;
+extern uintptr_t        __udram_size;
+extern uintptr_t        __udram_end;
+
+#endif /* __BOARDS_XTENSA_ESP32_TTGO_EINK_5_V2_INCLUDE_BOARD_MEMORYMAP_H */
diff --git a/boards/xtensa/esp32/ttgo_eink5_v2/scripts/Make.defs b/boards/xtensa/esp32/ttgo_eink5_v2/scripts/Make.defs
index d15706ea6e..c83fdebbc8 100644
--- a/boards/xtensa/esp32/ttgo_eink5_v2/scripts/Make.defs
+++ b/boards/xtensa/esp32/ttgo_eink5_v2/scripts/Make.defs
@@ -34,10 +34,14 @@ ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32_out.ld
 ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld),)
 	ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld
 else
-	ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
-		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld
+	ifeq ($(CONFIG_BUILD_PROTECTED),y)
+		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)kernel-space.ld
 	else
-		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld
+		ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
+			ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld
+		else
+			ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld
+		endif
 	endif
 endif
 
@@ -50,7 +54,11 @@ endif
 ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld),)
 	LDSCRIPT_TEMPLATE = $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld
 else
-	LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld
+	ifeq ($(CONFIG_BUILD_PROTECTED),y)
+		LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)protected.template.ld
+	else
+		LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)flat.template.ld
+	endif
 endif
 
 ARCHPICFLAGS = -fpic
diff --git a/boards/xtensa/esp32/ttgo_lora_esp32/include/board_memorymap.h b/boards/xtensa/esp32/ttgo_lora_esp32/include/board_memorymap.h
new file mode 100644
index 0000000000..98b95f772e
--- /dev/null
+++ b/boards/xtensa/esp32/ttgo_lora_esp32/include/board_memorymap.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+ * boards/xtensa/esp32/ttgo_lora_esp32/include/board_memorymap.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 __BOARDS_XTENSA_ESP32_TTGO_LORA_ESP32_INCLUDE_BOARD_MEMORYMAP_H
+#define __BOARDS_XTENSA_ESP32_TTGO_LORA_ESP32_INCLUDE_BOARD_MEMORYMAP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Kernel ROM */
+
+#define KIROM_START     (uintptr_t)&__kirom_start
+#define KIROM_SIZE      (uintptr_t)&__kirom_size
+#define KDROM_START     (uintptr_t)&__kdrom_start
+#define KDROM_SIZE      (uintptr_t)&__kdrom_size
+
+/* Kernel RAM */
+
+#define KIRAM_0_START   (uintptr_t)&__kiram_0_start
+#define KIRAM_0_SIZE    (uintptr_t)&__kiram_0_size
+#define KIRAM_0_END     (uintptr_t)&__kiram_0_end
+#define KIRAM_1_START   (uintptr_t)&__kiram_1_start
+#define KIRAM_1_SIZE    (uintptr_t)&__kiram_1_size
+#define KIRAM_1_END     (uintptr_t)&__kiram_1_end
+#define KDRAM_0_START   (uintptr_t)&__kdram_0_start
+#define KDRAM_0_SIZE    (uintptr_t)&__kdram_0_size
+#define KDRAM_0_END     (uintptr_t)&__kdram_0_end
+#define KDRAM_1_START   (uintptr_t)&__kdram_1_start
+#define KDRAM_1_SIZE    (uintptr_t)&__kdram_1_size
+#define KDRAM_1_END     (uintptr_t)&__kdram_1_end
+
+/* Exception vectors */
+
+#define VECTORS_START   (uintptr_t)&__vectors_start
+#define VECTORS_END     (uintptr_t)&__vectors_end
+
+/* User ROM */
+
+#define UIROM_START     (uintptr_t)&__uirom_start
+#define UIROM_SIZE      (uintptr_t)&__uirom_size
+#define UIROM_END       (uintptr_t)&__uirom_end
+#define UDROM_START     (uintptr_t)&__udrom_start
+#define UDROM_SIZE      (uintptr_t)&__udrom_size
+#define UDROM_END       (uintptr_t)&__udrom_end
+
+/* User RAM */
+
+#define UIRAM_START     (uintptr_t)&__uiram_start
+#define UIRAM_SIZE      (uintptr_t)&__uiram_size
+#define UIRAM_END       (uintptr_t)&__uiram_end
+#define UDRAM_START     (uintptr_t)&__udram_start
+#define UDRAM_SIZE      (uintptr_t)&__udram_size
+#define UDRAM_END       (uintptr_t)&__udram_end
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Kernel ROM (RX)  */
+
+extern uintptr_t        __kirom_start;
+extern uintptr_t        __kirom_size;
+extern uintptr_t        __kdrom_start;
+extern uintptr_t        __kdrom_size;
+
+/* Kernel RAM (RW) */
+
+extern uintptr_t        __kiram_0_start;
+extern uintptr_t        __kiram_0_size;
+extern uintptr_t        __kiram_0_end;
+extern uintptr_t        __kiram_1_start;
+extern uintptr_t        __kiram_1_size;
+extern uintptr_t        __kiram_1_end;
+extern uintptr_t        __kdram_0_start;
+extern uintptr_t        __kdram_0_size;
+extern uintptr_t        __kdram_0_end;
+extern uintptr_t        __kdram_1_start;
+extern uintptr_t        __kdram_1_size;
+extern uintptr_t        __kdram_1_end;
+
+/* Exception vectors */
+
+extern uintptr_t        __vectors_start;
+extern uintptr_t        __vectors_end;
+
+/* User ROM (RX) */
+
+extern uintptr_t        __uirom_start;
+extern uintptr_t        __uirom_size;
+extern uintptr_t        __uirom_end;
+extern uintptr_t        __udrom_start;
+extern uintptr_t        __udrom_size;
+extern uintptr_t        __udrom_end;
+
+/* User RAM (RW) */
+
+extern uintptr_t        __uiram_start;
+extern uintptr_t        __uiram_size;
+extern uintptr_t        __uiram_end;
+extern uintptr_t        __udram_start;
+extern uintptr_t        __udram_size;
+extern uintptr_t        __udram_end;
+
+#endif /* __BOARDS_XTENSA_ESP32_TTGO_LORA_ESP32_INCLUDE_BOARD_MEMORYMAP_H */
diff --git a/boards/xtensa/esp32/ttgo_lora_esp32/scripts/Make.defs b/boards/xtensa/esp32/ttgo_lora_esp32/scripts/Make.defs
index cbb40767c1..89fe0afde0 100644
--- a/boards/xtensa/esp32/ttgo_lora_esp32/scripts/Make.defs
+++ b/boards/xtensa/esp32/ttgo_lora_esp32/scripts/Make.defs
@@ -34,10 +34,14 @@ ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32_out.ld
 ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld),)
 	ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.ld
 else
-	ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
-		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld
+	ifeq ($(CONFIG_BUILD_PROTECTED),y)
+		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)kernel-space.ld
 	else
-		ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld
+		ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
+			ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32_mcuboot.ld
+		else
+			ARCHSCRIPT += $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.ld
+		endif
 	endif
 endif
 
@@ -50,7 +54,11 @@ endif
 ifneq ($(wildcard $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld),)
 	LDSCRIPT_TEMPLATE = $(BOARD_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld
 else
-	LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)esp32.template.ld
+	ifeq ($(CONFIG_BUILD_PROTECTED),y)
+		LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)protected.template.ld
+	else
+		LDSCRIPT_TEMPLATE = $(BOARD_COMMON_DIR)$(DELIM)scripts$(DELIM)flat.template.ld
+	endif
 endif
 
 ARCHPICFLAGS = -fpic
diff --git a/tools/esp32/Config.mk b/tools/esp32/Config.mk
index f1a6ecffc1..fc8b18a71c 100644
--- a/tools/esp32/Config.mk
+++ b/tools/esp32/Config.mk
@@ -128,6 +128,10 @@ endif
 
 ESPTOOL_BINS += $(FLASH_APP)
 
+ifeq ($(CONFIG_BUILD_PROTECTED),y)
+	ESPTOOL_BINS += $(CONFIG_ESP32_USER_IMAGE_OFFSET) nuttx_user.bin
+endif
+
 # Commands for colored and formatted output
 
 RED    = \033[1;31m


[incubator-nuttx] 02/05: xtensa/esp32: Configure the PID controller for privilege separation

Posted by xi...@apache.org.
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


[incubator-nuttx] 04/05: xtensa/esp32: Build patched IDFBoot for Protected Mode support

Posted by xi...@apache.org.
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 68c722c05178ee351b1b0c11faf1419bd060107b
Author: Gustavo Henrique Nihei <gu...@espressif.com>
AuthorDate: Wed Jul 6 15:46:25 2022 -0300

    xtensa/esp32: Build patched IDFBoot for Protected Mode support
    
    Signed-off-by: Gustavo Henrique Nihei <gu...@espressif.com>
---
 arch/xtensa/src/esp32/.gitignore                   |   1 -
 arch/xtensa/src/esp32/Bootloader.mk                |  22 ++--
 arch/xtensa/src/esp32/bootloader/.gitignore        |   2 +
 ...-Connect-Xtensa-Instruction-RAM1-to-Cache.patch | 112 +++++++++++++++++++++
 .../esp32/esp32-devkitc/configs/knsh/defconfig     |   1 +
 5 files changed, 131 insertions(+), 7 deletions(-)

diff --git a/arch/xtensa/src/esp32/.gitignore b/arch/xtensa/src/esp32/.gitignore
index 9adccd80ae..cdf3df5616 100644
--- a/arch/xtensa/src/esp32/.gitignore
+++ b/arch/xtensa/src/esp32/.gitignore
@@ -1,3 +1,2 @@
 /esp-wireless-drivers-3rdparty
-/esp-nuttx-bootloader
 /*.zip
diff --git a/arch/xtensa/src/esp32/Bootloader.mk b/arch/xtensa/src/esp32/Bootloader.mk
index 6044f1e59d..85505eacd8 100644
--- a/arch/xtensa/src/esp32/Bootloader.mk
+++ b/arch/xtensa/src/esp32/Bootloader.mk
@@ -18,18 +18,18 @@
 #
 ############################################################################
 
+.PHONY: bootloader clean_bootloader
+
 ifeq ($(CONFIG_ESP32_BOOTLOADER_BUILD_FROM_SOURCE),y)
 
 CHIPDIR            = $(TOPDIR)/arch/xtensa/src/chip
 
-BOOTLOADER_SRCDIR  = $(CHIPDIR)/esp-nuttx-bootloader
+BOOTLOADER_DIR     = $(CHIPDIR)/bootloader
+BOOTLOADER_SRCDIR  = $(BOOTLOADER_DIR)/esp-nuttx-bootloader
 BOOTLOADER_VERSION = main
 BOOTLOADER_URL     = https://github.com/espressif/esp-nuttx-bootloader
 BOOTLOADER_OUTDIR  = out
-BOOTLOADER_CONFIG  = $(CHIPDIR)/bootloader.conf
-
-$(BOOTLOADER_SRCDIR):
-	$(Q) git clone $(BOOTLOADER_URL) $(BOOTLOADER_SRCDIR) -b $(BOOTLOADER_VERSION)
+BOOTLOADER_CONFIG  = $(BOOTLOADER_DIR)/bootloader.conf
 
 # Helpers for creating the configuration file
 
@@ -108,6 +108,9 @@ ifeq ($(CONFIG_ESP32_APP_FORMAT_MCUBOOT),y)
 BOOTLOADER_BIN        = $(TOPDIR)/mcuboot-esp32.bin
 BOOTLOADER_SIGNED_BIN = $(TOPDIR)/mcuboot-esp32.signed.bin
 
+$(BOOTLOADER_SRCDIR):
+	$(Q) git clone $(BOOTLOADER_URL) $(BOOTLOADER_SRCDIR) -b $(BOOTLOADER_VERSION)
+
 $(BOOTLOADER_BIN): $(BOOTLOADER_CONFIG)
 	$(Q) echo "Building Bootloader"
 	$(Q) $(BOOTLOADER_SRCDIR)/build_mcuboot.sh -c esp32 -s -f $(BOOTLOADER_CONFIG)
@@ -145,9 +148,16 @@ clean_bootloader:
 
 else ifeq ($(CONFIG_ESP32_APP_FORMAT_LEGACY),y)
 
+$(BOOTLOADER_SRCDIR):
+	$(Q) git clone $(BOOTLOADER_URL) $(BOOTLOADER_SRCDIR) -b $(BOOTLOADER_VERSION)
+	$(Q) git -C $(BOOTLOADER_SRCDIR) submodule update --init esp-idf
+ifeq ($(CONFIG_BUILD_PROTECTED),y)
+	$(Q) git -C $(BOOTLOADER_SRCDIR)/esp-idf apply -v $(BOOTLOADER_DIR)/0001-esp32-Connect-Xtensa-Instruction-RAM1-to-Cache.patch
+endif
+
 bootloader: $(BOOTLOADER_SRCDIR) $(BOOTLOADER_CONFIG)
 	$(Q) echo "Building Bootloader binaries"
-	$(Q) $(BOOTLOADER_SRCDIR)/build_idfboot.sh -c esp32 -s -f $(BOOTLOADER_CONFIG)
+	$(Q) $(BOOTLOADER_SRCDIR)/build_idfboot.sh -c esp32 -f $(BOOTLOADER_CONFIG)
 	$(call COPYFILE,$(BOOTLOADER_SRCDIR)/$(BOOTLOADER_OUTDIR)/bootloader-esp32.bin,$(TOPDIR))
 	$(call COPYFILE,$(BOOTLOADER_SRCDIR)/$(BOOTLOADER_OUTDIR)/partition-table-esp32.bin,$(TOPDIR))
 
diff --git a/arch/xtensa/src/esp32/bootloader/.gitignore b/arch/xtensa/src/esp32/bootloader/.gitignore
new file mode 100644
index 0000000000..1921db116c
--- /dev/null
+++ b/arch/xtensa/src/esp32/bootloader/.gitignore
@@ -0,0 +1,2 @@
+/esp-nuttx-bootloader
+/bootloader.conf
diff --git a/arch/xtensa/src/esp32/bootloader/0001-esp32-Connect-Xtensa-Instruction-RAM1-to-Cache.patch b/arch/xtensa/src/esp32/bootloader/0001-esp32-Connect-Xtensa-Instruction-RAM1-to-Cache.patch
new file mode 100644
index 0000000000..03d2c6e9e2
--- /dev/null
+++ b/arch/xtensa/src/esp32/bootloader/0001-esp32-Connect-Xtensa-Instruction-RAM1-to-Cache.patch
@@ -0,0 +1,112 @@
+From 3ee21d64a48018b33c1db485b5fbfb08145e4f67 Mon Sep 17 00:00:00 2001
+From: Gustavo Henrique Nihei <gu...@espressif.com>
+Date: Wed, 6 Jul 2022 10:03:09 -0300
+Subject: [PATCH] esp32: Connect Xtensa Instruction RAM1 to Cache
+
+User application image is executed with PID 5, so it accesses the
+External Flash via virtual address starting from 0x40400000 (Vaddr2).
+
+See:
+https://github.com/espressif/esp-idf/blob/v4.4.1/components/xtensa/esp32/include/xtensa/config/core-isa.h#L301-L305
+
+Signed-off-by: Gustavo Henrique Nihei <gu...@espressif.com>
+---
+ .../bootloader_support/src/bootloader_utility.c | 17 ++++++++++++++---
+ components/soc/esp32/include/soc/mmu.h          |  1 +
+ components/spi_flash/cache_utils.c              |  2 ++
+ components/spi_flash/flash_mmap.c               |  8 ++++++++
+ 4 files changed, 25 insertions(+), 3 deletions(-)
+
+diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c
+index ad56335253..7e343a551b 100644
+--- a/components/bootloader_support/src/bootloader_utility.c
++++ b/components/bootloader_support/src/bootloader_utility.c
+@@ -737,6 +737,14 @@ static void set_cache_and_start_app(
+     for (int i = 0; i < DPORT_FLASH_MMU_TABLE_SIZE; i++) {
+         DPORT_PRO_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL;
+     }
++
++    /* Xtensa CPU does speculative load/store on VAddr1/2/3 when connected to cache.
++     * Hence it requires all the pages of VAddr2/3 to be set valid to any physical page.
++     * Marking any page invalid would stall the CPU
++     */
++    for (int i = 64; i < 256; i++) {
++        DPORT_PRO_FLASH_MMU_TABLE[i] = 0;
++    }
+ #else
+     for (size_t i = 0; i < FLASH_MMU_TABLE_SIZE; i++) {
+         FLASH_MMU_TABLE[i] = MMU_TABLE_INVALID_VAL;
+@@ -793,11 +801,11 @@ static void set_cache_and_start_app(
+     rc = cache_flash_mmu_set(1, 0, irom_load_addr_aligned, irom_addr_aligned, 64, irom_page_count);
+     ESP_LOGV(TAG, "rc=%d", rc);
+     DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG,
+-                       (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) |
++                       (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1) |
+                        (DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 |
+                        DPORT_PRO_CACHE_MASK_DRAM1 );
+     DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG,
+-                       (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) |
++                       (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1) |
+                        (DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 |
+                        DPORT_APP_CACHE_MASK_DRAM1 );
+ #elif CONFIG_IDF_TARGET_ESP32S2
+@@ -815,7 +823,10 @@ static void set_cache_and_start_app(
+     REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
+ #endif
+ #if CONFIG_IDF_TARGET_ESP32
+-    Cache_Read_Enable(0);
++    DPORT_REG_SET_BIT(0x3ff43050, 1);
++    DPORT_REG_SET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE);
++
++    asm("memw");
+ #elif CONFIG_IDF_TARGET_ESP32S2
+     Cache_Resume_ICache(autoload);
+ #elif CONFIG_IDF_TARGET_ESP32S3
+diff --git a/components/soc/esp32/include/soc/mmu.h b/components/soc/esp32/include/soc/mmu.h
+index bde6995516..9fff17ddba 100644
+--- a/components/soc/esp32/include/soc/mmu.h
++++ b/components/soc/esp32/include/soc/mmu.h
+@@ -32,6 +32,7 @@ extern "C" {
+ #define SOC_MMU_ADDR_MASK                       DPORT_MMU_ADDRESS_MASK
+ #define SOC_MMU_PAGE_IN_FLASH(page)             (page)
+ #define SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE       ((volatile uint32_t*) 0x3FF10000)
++#define SOC_MMU_DPORT_APP_FLASH_MMU_TABLE       ((volatile uint32_t*) 0x3FF12000)
+ #define SOC_MMU_VADDR1_START_ADDR               SOC_IROM_MASK_LOW
+ #define SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE     ((SOC_MMU_VADDR1_FIRST_USABLE_ADDR - SOC_MMU_VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + SOC_MMU_IROM0_PAGES_START)
+ #define SOC_MMU_VADDR0_START_ADDR               SOC_DROM_LOW
+diff --git a/components/spi_flash/cache_utils.c b/components/spi_flash/cache_utils.c
+index 7715900055..b29aed2953 100644
+--- a/components/spi_flash/cache_utils.c
++++ b/components/spi_flash/cache_utils.c
+@@ -308,6 +308,8 @@ static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_st
+         while (DPORT_GET_PERI_REG_BITS2(DPORT_PRO_DCACHE_DBUG0_REG, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) {
+             ;
+         }
++        /* Disconnect from cache */
++        DPORT_REG_WRITE(DPORT_PRO_CACHE_CTRL1_REG, 0xff);
+         DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
+     }
+ #if !CONFIG_FREERTOS_UNICORE
+diff --git a/components/spi_flash/flash_mmap.c b/components/spi_flash/flash_mmap.c
+index 9523bc7959..c17a9903ef 100644
+--- a/components/spi_flash/flash_mmap.c
++++ b/components/spi_flash/flash_mmap.c
+@@ -108,7 +108,15 @@ static void IRAM_ATTR spi_flash_mmap_init(void)
+         if ((entry_pro & SOC_MMU_INVALID_ENTRY_VAL) == 0 && (i == SOC_MMU_DROM0_PAGES_START || i == SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE || entry_pro != 0)) {
+             s_mmap_page_refcnt[i] = 1;
+         } else {
++#if CONFIG_IDF_TARGET_ESP32
++            /* Due to Xtensa speculative load/store, pages need to be marked valid if VAddr2/VAddr3
++             * are connected to cache. If marked invalid, CPU will halt
++             */
++            SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i] = 0x00;
++            SOC_MMU_DPORT_APP_FLASH_MMU_TABLE[i] = 0x00;
++#else
+             SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i] = SOC_MMU_INVALID_ENTRY_VAL;
++#endif
+ #if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
+             DPORT_APP_FLASH_MMU_TABLE[i] = SOC_MMU_INVALID_ENTRY_VAL;
+ #endif
+-- 
+2.34.1
+
diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig
index 6058b287bb..ae24f7dcbb 100644
--- a/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig
+++ b/boards/xtensa/esp32/esp32-devkitc/configs/knsh/defconfig
@@ -29,6 +29,7 @@ CONFIG_DEBUG_FULLOPT=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_SYMBOLS=y
 CONFIG_DEBUG_WARN=y
+CONFIG_ESP32_BOOTLOADER_BUILD_FROM_SOURCE=y
 CONFIG_ESP32_PID=y
 CONFIG_ESP32_UART0=y
 CONFIG_EXPERIMENTAL=y


[incubator-nuttx] 05/05: esp32-devkitc: Add knsh configuration to the Documentation page

Posted by xi...@apache.org.
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 feca57ffa9c5a92186409569f849c246319047f4
Author: Gustavo Henrique Nihei <gu...@espressif.com>
AuthorDate: Wed Jul 13 10:08:16 2022 -0300

    esp32-devkitc: Add knsh configuration to the Documentation page
    
    Signed-off-by: Gustavo Henrique Nihei <gu...@espressif.com>
---
 .../xtensa/esp32/boards/esp32-devkitc/index.rst    | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst b/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst
index a5d09ef0ff..db01f6e0b2 100644
--- a/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst
+++ b/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst
@@ -115,6 +115,28 @@ nsh
 Basic NuttShell configuration (console enabled in UART0, exposed via
 USB connection by means of CP2102 converter, at 115200 bps).
 
+knsh
+----
+
+This is identical to the nsh configuration except that (1) NuttX
+is built as PROTECTED mode, monolithic module and the user applications
+are built separately and, as a consequence, (2) some features that are
+only available in the FLAT build are disabled.
+
+Protected Mode support for ESP32 relies on the PID Controller peripheral
+for implementing isolation between Kernel and Userspace.
+
+By working together with the MMU and Static MPUs of the ESP32, the PID
+Controller is able to restrict the application access to peripherals, on-chip
+memories (Internal ROM and Internal SRAM) and off-chip memories (External
+Flash and PSRAM).
+
+.. warning::
+    * The PID Controller driver is in **EXPERIMENTAL** state, so please
+      consider the Protected Mode feature for ESP32 a **Proof-of-Concept**.
+    * The PID Controller **does not** prevent the application from accessing
+      CPU System Registers.
+
 wapi
 ----