From 68c722c05178ee351b1b0c11faf1419bd060107b Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Nihei Date: Wed, 6 Jul 2022 15:46:25 -0300 Subject: [PATCH] xtensa/esp32: Build patched IDFBoot for Protected Mode support Signed-off-by: Gustavo Henrique Nihei --- arch/xtensa/src/esp32/.gitignore | 1 - arch/xtensa/src/esp32/Bootloader.mk | 22 +++- arch/xtensa/src/esp32/bootloader/.gitignore | 2 + ...ect-Xtensa-Instruction-RAM1-to-Cache.patch | 112 ++++++++++++++++++ .../esp32-devkitc/configs/knsh/defconfig | 1 + 5 files changed, 131 insertions(+), 7 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 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 +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 +--- + .../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