From 73678c4839285f4af6a4a920757085cb73fc0d69 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Nihei Date: Mon, 6 Jun 2022 17:34:51 -0300 Subject: [PATCH] xtensa/esp32: Allow allocation of user data in SPI RAM Signed-off-by: Gustavo Henrique Nihei --- arch/xtensa/src/esp32/Kconfig | 20 ++++- arch/xtensa/src/esp32/chip_macros.h | 14 +++- arch/xtensa/src/esp32/esp32_allocateheap.c | 78 ++++++++----------- arch/xtensa/src/esp32/esp32_psram.c | 4 + arch/xtensa/src/esp32/esp32_userspace.c | 78 +++++++++++++++++++ .../common/scripts/protected.template.ld | 12 +++ 6 files changed, 158 insertions(+), 48 deletions(-) diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index dd34818a57..94869aedde 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -624,7 +624,7 @@ config ESP32_SPI3 config ESP32_SPIRAM bool "SPI RAM Support" default n - select ARCH_HAVE_HEAP2 + select ARCH_HAVE_HEAP2 if !ESP32_USER_DATA_EXTMEM select XTENSA_IMEM_USE_SEPARATE_HEAP if ESP32_SPIRAM && SMP @@ -1362,7 +1362,7 @@ endchoice # ESP32_SPIRAM_SPEED config ESP32_SPIRAM_BOOT_INIT bool "Initialize SPI RAM during startup" - depends on ESP32_SPIRAM + depends on ESP32_SPIRAM && !ESP32_USER_DATA_EXTMEM default y ---help--- If this is enabled, the SPI RAM will be enabled during initial @@ -1894,6 +1894,22 @@ config ESP32_USER_IMAGE_OFFSET ---help--- Offset in SPI Flash for flashing the User application firmware image. +config ESP32_USER_DATA_EXTMEM + bool "Allocate user data in SPI RAM (READ HELP FIRST)" + default n + depends on ESP32_SPIRAM && EXPERIMENTAL + ---help--- + Allocate all data from User application firmware image in the external + SPI RAM. + + Enabling this configuration comes with the restriction of running the Userspace + with high privilege (same as Kernel space), which in turn makes the execution + under Protected Mode not really protected. + + This feature is intended to allow experimentation of Protected Mode on ESP32 and + should not be used in production. Protected mode on ESP32 is only supported with + PSRAM disabled. + endif source "arch/xtensa/src/esp32/Kconfig.security" diff --git a/arch/xtensa/src/esp32/chip_macros.h b/arch/xtensa/src/esp32/chip_macros.h index e5fe6a7c89..b42c098121 100644 --- a/arch/xtensa/src/esp32/chip_macros.h +++ b/arch/xtensa/src/esp32/chip_macros.h @@ -57,8 +57,18 @@ /* Definitions for the PIDs reserved for Kernel and Userspace */ -#define PIDCTRL_PID_KERNEL 0 /* Privileged */ -#define PIDCTRL_PID_USER 5 /* Non-privileged */ +# define PIDCTRL_PID_KERNEL 0 /* Privileged */ + +#ifdef CONFIG_ESP32_USER_DATA_EXTMEM + +/* Allocating user data in External RAM is currently limited to only using + * privileged PIDs (0 and 1). + */ + +# define PIDCTRL_PID_USER 1 /* Privileged */ +#else +# define PIDCTRL_PID_USER 5 /* Non-privileged */ +#endif /* Macros for privilege handling with the PID Controller peripheral */ diff --git a/arch/xtensa/src/esp32/esp32_allocateheap.c b/arch/xtensa/src/esp32/esp32_allocateheap.c index 6146f55cb0..484340affa 100644 --- a/arch/xtensa/src/esp32/esp32_allocateheap.c +++ b/arch/xtensa/src/esp32/esp32_allocateheap.c @@ -49,6 +49,12 @@ * Pre-processor Definitions ****************************************************************************/ +#ifdef CONFIG_BUILD_PROTECTED +# define MM_ADDREGION kmm_addregion +#else +# define MM_ADDREGION umm_addregion +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -75,6 +81,11 @@ void up_allocate_heap(void **heap_start, size_t *heap_size) uintptr_t utop = USERSPACE->us_heapend; size_t usize = utop - ubase; +#if defined(CONFIG_ESP32_USER_DATA_EXTMEM) && \ + defined(CONFIG_ESP32_SPIRAM_BANKSWITCH_ENABLE) + usize -= esp_himem_reserved_area_size(); +#endif + minfo("Heap: start=%" PRIxPTR " end=%" PRIxPTR " size=%zu\n", ubase, utop, usize); @@ -84,9 +95,6 @@ void up_allocate_heap(void **heap_start, size_t *heap_size) *heap_start = (void *)ubase; *heap_size = usize; - - /* Allow user-mode access to the user heap memory */ - #else board_autoled_on(LED_HEAPALLOCATE); @@ -160,66 +168,48 @@ void xtensa_add_region(void) availregions = 2; #endif -#ifdef CONFIG_ESP32_SPIRAM +#if defined(CONFIG_ESP32_SPIRAM) && !defined(CONFIG_BUILD_PROTECTED) availregions++; #endif if (nregions < availregions) { mwarn("Some memory regions are left unused!\n"); - mwarn("Increase CONFIG_MM_NREGIONS to add them to the heap\n"); + mwarn("Increase CONFIG_MM_REGIONS to add them to the heap\n"); } -#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 +#ifdef CONFIG_SMP 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); + MM_ADDREGION(start, size); #endif - start = (void *)HEAP_REGION3_START + XTENSA_IMEM_REGION_SIZE; + /* Skip internal heap region if CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP is + * enabled. + */ + + start = (void *)ESP32_IMEM_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 + MM_ADDREGION(start, size); #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 + MM_ADDREGION(start, size); #endif -#ifdef CONFIG_ESP32_SPIRAM -# if defined(CONFIG_HEAP2_BASE) && defined(CONFIG_HEAP2_SIZE) -# ifdef CONFIG_XTENSA_EXTMEM_BSS - start = _ebss_extmem; - size = CONFIG_HEAP2_SIZE - (_ebss_extmem - _sbss_extmem); -# else - start = (void *)CONFIG_HEAP2_BASE; - size = CONFIG_HEAP2_SIZE; -# endif -# ifdef CONFIG_ESP32_SPIRAM_BANKSWITCH_ENABLE - size -= esp_himem_reserved_area_size(); -# endif - umm_addregion(start, size); -# endif +#if defined(CONFIG_ESP32_SPIRAM) && defined(CONFIG_ARCH_HAVE_HEAP2) +#ifdef CONFIG_XTENSA_EXTMEM_BSS + start = (void *)(_ebss_extmem); + size = CONFIG_HEAP2_SIZE - (size_t)(_ebss_extmem - _sbss_extmem); +#else + start = (void *)CONFIG_HEAP2_BASE; + size = CONFIG_HEAP2_SIZE; +#endif +#ifdef CONFIG_ESP32_SPIRAM_BANKSWITCH_ENABLE + size -= esp_himem_reserved_area_size(); +#endif + MM_ADDREGION(start, size); #endif } #endif diff --git a/arch/xtensa/src/esp32/esp32_psram.c b/arch/xtensa/src/esp32/esp32_psram.c index 7ecda4981f..16e42b01aa 100644 --- a/arch/xtensa/src/esp32/esp32_psram.c +++ b/arch/xtensa/src/esp32/esp32_psram.c @@ -715,7 +715,9 @@ psram_cmd_recv_start(psram_spi_num_t spi_num, while (getreg32(SPI_EXT2_REG(0)) != 0); +#ifndef CONFIG_ESP32_USER_DATA_EXTMEM modifyreg32(DPORT_HOST_INF_SEL_REG, 0, 1 << 14); +#endif /* Start send data */ @@ -723,7 +725,9 @@ psram_cmd_recv_start(psram_spi_num_t spi_num, while ((getreg32(SPI_CMD_REG(spi_num)) & SPI_USR)); +#ifndef CONFIG_ESP32_USER_DATA_EXTMEM modifyreg32(DPORT_HOST_INF_SEL_REG, 1 << 14, 0); +#endif /* recover spi mode */ diff --git a/arch/xtensa/src/esp32/esp32_userspace.c b/arch/xtensa/src/esp32/esp32_userspace.c index fdf9e30d19..a30555c6e4 100644 --- a/arch/xtensa/src/esp32/esp32_userspace.c +++ b/arch/xtensa/src/esp32/esp32_userspace.c @@ -36,6 +36,9 @@ #include "chip.h" #include "xtensa.h" #include "xtensa_attr.h" +#ifdef CONFIG_ESP32_USER_DATA_EXTMEM +#include "esp32_spiram.h" +#endif #include "esp32_userspace.h" #include "hardware/esp32_dport.h" #include "hardware/esp32_pid.h" @@ -188,6 +191,49 @@ static noinline_function IRAM_ATTR void configure_flash_mmu(void) cache_read_enable(0); } +/**************************************************************************** + * Name: configure_sram_mmu + * + * Description: + * Configure the External SRAM MMU and Cache for enabling access to the + * data of the userspace image. + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32_USER_DATA_EXTMEM +static noinline_function IRAM_ATTR void configure_sram_mmu(void) +{ +#ifdef CONFIG_SMP + uint32_t regval; +#endif + + /* Enable external RAM in MMU */ + + ASSERT(cache_sram_mmu_set(0, PIDCTRL_PID_KERNEL, SOC_EXTRAM_DATA_LOW, 0, + 32, 128) == 0); + ASSERT(cache_sram_mmu_set(0, PIDCTRL_PID_USER, SOC_EXTRAM_DATA_LOW, 0, + 32, 128) == 0); + + /* Flush and enable icache for APP CPU */ + +#ifdef CONFIG_SMP + regval = getreg32(DPORT_APP_CACHE_CTRL1_REG); + regval &= ~(1 << DPORT_APP_CACHE_MASK_DRAM1); + putreg32(regval, DPORT_APP_CACHE_CTRL1_REG); + ASSERT(cache_sram_mmu_set(1, PIDCTRL_PID_KERNEL, SOC_EXTRAM_DATA_LOW, 0, + 32, 128) == 0); + ASSERT(cache_sram_mmu_set(1, PIDCTRL_PID_USER, SOC_EXTRAM_DATA_LOW, 0, + 32, 128) == 0); +#endif +} +#endif + /**************************************************************************** * Name: map_flash * @@ -322,6 +368,24 @@ static void configure_mpu(void) REG_SET_FIELD(DPORT_IMMU_TABLE14_REG, DPORT_IMMU_TABLE14, 0x0e); REG_SET_FIELD(DPORT_IMMU_TABLE15_REG, DPORT_IMMU_TABLE15, 0x0f); +#ifdef CONFIG_ESP32_USER_DATA_EXTMEM + 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, 0x04); + REG_SET_FIELD(DPORT_DMMU_TABLE5_REG, DPORT_DMMU_TABLE5, 0x05); + REG_SET_FIELD(DPORT_DMMU_TABLE6_REG, DPORT_DMMU_TABLE6, 0x06); + REG_SET_FIELD(DPORT_DMMU_TABLE7_REG, DPORT_DMMU_TABLE7, 0x07); + REG_SET_FIELD(DPORT_DMMU_TABLE8_REG, DPORT_DMMU_TABLE8, 0x08); + REG_SET_FIELD(DPORT_DMMU_TABLE9_REG, DPORT_DMMU_TABLE9, 0x09); + REG_SET_FIELD(DPORT_DMMU_TABLE10_REG, DPORT_DMMU_TABLE10, 0x0a); + REG_SET_FIELD(DPORT_DMMU_TABLE11_REG, DPORT_DMMU_TABLE11, 0x0b); + REG_SET_FIELD(DPORT_DMMU_TABLE12_REG, DPORT_DMMU_TABLE12, 0x0c); + REG_SET_FIELD(DPORT_DMMU_TABLE13_REG, DPORT_DMMU_TABLE13, 0x0d); + REG_SET_FIELD(DPORT_DMMU_TABLE14_REG, DPORT_DMMU_TABLE14, 0x0e); + REG_SET_FIELD(DPORT_DMMU_TABLE15_REG, DPORT_DMMU_TABLE15, 0x0f); +#else 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); @@ -338,6 +402,7 @@ static void configure_mpu(void) 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); +#endif /* Configure interrupt vector addresses in PID Controller */ @@ -399,6 +464,19 @@ void esp32_userspace(void) configure_flash_mmu(); +#ifdef CONFIG_ESP32_USER_DATA_EXTMEM + if (esp_spiram_init() != OK) + { + mwarn("SPI RAM initialization failed!\n"); + + PANIC(); + } + + /* Configure the SRAM MMU for enabling access to the userspace image */ + + configure_sram_mmu(); +#endif + /* Clear all of userspace .bss */ DEBUGASSERT(USERSPACE->us_bssstart != 0 && USERSPACE->us_bssend != 0 && diff --git a/boards/xtensa/esp32/common/scripts/protected.template.ld b/boards/xtensa/esp32/common/scripts/protected.template.ld index 80ebe214db..5862de63b7 100644 --- a/boards/xtensa/esp32/common/scripts/protected.template.ld +++ b/boards/xtensa/esp32/common/scripts/protected.template.ld @@ -73,6 +73,17 @@ MEMORY * the amount of RAM available to the NuttX Kernel. */ +#ifdef CONFIG_ESP32_USER_DATA_EXTMEM + /* Physically located in External RAM */ + UDRAM (RW) : org = 0x3f800000, len = 0x400000 + + /* Physically located in SRAM2 */ + KDRAM_0 (RW) : org = 0x3ffb0000 + CONFIG_ESP32_BT_RESERVE_DRAM, + len = 0x30000 - CONFIG_ESP32_BT_RESERVE_DRAM + + /* Physically located in SRAM1 */ + KDRAM_1 (RW) : org = 0x3ffe0000, len = 0x20000 +#else /* Physically located in SRAM2 */ KDRAM_0 (RW) : org = 0x3ffb0000 + CONFIG_ESP32_BT_RESERVE_DRAM, len = 0x18000 - CONFIG_ESP32_BT_RESERVE_DRAM @@ -80,6 +91,7 @@ MEMORY /* Physically located in SRAM1 */ KDRAM_1 (RW) : org = 0x3ffe0000, len = 0x20000 +#endif /* Flash mapped constant data */