mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
feat(esp_psram): add option to carve unencrypted PSRAM region
Adds CONFIG_SPIRAM_ENC_EXEMPT, available on chips that support per-page PSRAM encryption configuration (esp32c5, esp32c61, esp32p4). When enabled, esp_psram carves CONFIG_SPIRAM_ENC_EXEMPT_SIZE off the top of PSRAM and maps it via the new mmu_hal_map_region_no_enc() helper, which writes MMU entries without the SENSITIVE bit. The region is registered as a separate heap pool reachable only through the new MALLOC_CAP_SPIRAM_NO_ENC capability bit, so default SPIRAM allocations cannot accidentally land there. PSRAM encryption imposes alignment constraints that some DMA engines (e.g. 2D-DMA) cannot satisfy. This option lets such workloads place their buffers in unencrypted PSRAM while keeping the rest of PSRAM (and flash) encrypted. Default disabled; security implications are documented in the Kconfig help text.
This commit is contained in:
@@ -49,13 +49,19 @@
|
||||
#define BYTES_TO_MMU_PAGE(bytes) ((bytes) / MMU_PAGE_SIZE)
|
||||
|
||||
/**
|
||||
* Two types of PSRAM memory regions for now:
|
||||
* PSRAM memory regions:
|
||||
* - 8bit aligned
|
||||
* - 32bit aligned
|
||||
* - Optional: encryption-exempt carve-out (top of PSRAM)
|
||||
*/
|
||||
#define PSRAM_MEM_TYPE_NUM 2
|
||||
#define PSRAM_MEM_8BIT_ALIGNED 0
|
||||
#define PSRAM_MEM_32BIT_ALIGNED 1
|
||||
#if CONFIG_SPIRAM_ENC_EXEMPT
|
||||
#define PSRAM_MEM_ENC_EXEMPT 2
|
||||
#define PSRAM_MEM_TYPE_NUM 3
|
||||
#else
|
||||
#define PSRAM_MEM_TYPE_NUM 2
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM
|
||||
#define PSRAM_EARLY_LOGI ESP_DRAM_LOGI
|
||||
@@ -283,6 +289,16 @@ static void s_xip_psram_placement(uint32_t *psram_available_size, uint32_t *out_
|
||||
static void s_psram_mapping(uint32_t psram_available_size, uint32_t start_page)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
#if CONFIG_SPIRAM_ENC_EXEMPT
|
||||
size_t enc_exempt_size = ALIGN_UP_BY((size_t)CONFIG_SPIRAM_ENC_EXEMPT_SIZE * 1024, MMU_PAGE_SIZE);
|
||||
if (enc_exempt_size >= psram_available_size) {
|
||||
ESP_EARLY_LOGE(TAG, "SPIRAM_ENC_EXEMPT_SIZE (%dKB) >= available PSRAM (%dKB); disabling carve-out",
|
||||
(int)(enc_exempt_size / 1024), (int)(psram_available_size / 1024));
|
||||
enc_exempt_size = 0;
|
||||
} else {
|
||||
psram_available_size -= enc_exempt_size;
|
||||
}
|
||||
#endif
|
||||
//----------------------------------Map the PSRAM physical range to MMU-----------------------------//
|
||||
/**
|
||||
* @note 2
|
||||
@@ -372,6 +388,33 @@ static void s_psram_mapping(uint32_t psram_available_size, uint32_t start_page)
|
||||
ESP_EARLY_LOGW(TAG, "Virtual address not enough for PSRAM, map as much as we can. %dMB is mapped", total_mapped_size / 1024 / 1024);
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM_ENC_EXEMPT
|
||||
if (enc_exempt_size) {
|
||||
const void *v_start_no_enc = NULL;
|
||||
ret = esp_mmu_map_reserve_block_with_caps(enc_exempt_size,
|
||||
MMU_MEM_CAP_READ | MMU_MEM_CAP_WRITE | MMU_MEM_CAP_8BIT | MMU_MEM_CAP_32BIT,
|
||||
MMU_TARGET_PSRAM0, &v_start_no_enc);
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
mmu_hal_map_region_no_enc((uint32_t)v_start_no_enc, MMU_PAGE_TO_BYTES(start_page), enc_exempt_size);
|
||||
|
||||
cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, (uint32_t)v_start_no_enc, enc_exempt_size);
|
||||
cache_ll_l1_enable_bus(0, bus_mask);
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
bus_mask = cache_ll_l1_get_bus(1, (uint32_t)v_start_no_enc, enc_exempt_size);
|
||||
cache_ll_l1_enable_bus(1, bus_mask);
|
||||
#endif
|
||||
|
||||
s_psram_ctx.mapped_regions[PSRAM_MEM_ENC_EXEMPT].size = enc_exempt_size;
|
||||
s_psram_ctx.mapped_regions[PSRAM_MEM_ENC_EXEMPT].vaddr_start = (intptr_t)v_start_no_enc;
|
||||
s_psram_ctx.mapped_regions[PSRAM_MEM_ENC_EXEMPT].vaddr_end = (intptr_t)v_start_no_enc + enc_exempt_size;
|
||||
s_psram_ctx.regions_to_heap[PSRAM_MEM_ENC_EXEMPT].size = enc_exempt_size;
|
||||
s_psram_ctx.regions_to_heap[PSRAM_MEM_ENC_EXEMPT].vaddr_start = (intptr_t)v_start_no_enc;
|
||||
s_psram_ctx.regions_to_heap[PSRAM_MEM_ENC_EXEMPT].vaddr_end = (intptr_t)v_start_no_enc + enc_exempt_size;
|
||||
ESP_EARLY_LOGI(TAG, "PSRAM unencrypted region: 0x%x B at %p", (unsigned)enc_exempt_size, v_start_no_enc);
|
||||
}
|
||||
#endif /* CONFIG_SPIRAM_ENC_EXEMPT */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* After mapping, we DON'T care about the PSRAM PHYSICAL ADDRESS ANYMORE!
|
||||
*----------------------------------------------------------------------------*/
|
||||
@@ -500,6 +543,22 @@ esp_err_t esp_psram_extram_add_to_heap_allocator(void)
|
||||
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of PSRAM memory to heap allocator",
|
||||
(s_psram_ctx.regions_to_heap[PSRAM_MEM_8BIT_ALIGNED].size + s_psram_ctx.regions_to_heap[PSRAM_MEM_32BIT_ALIGNED].size) / 1024);
|
||||
|
||||
#if CONFIG_SPIRAM_ENC_EXEMPT
|
||||
if (s_psram_ctx.regions_to_heap[PSRAM_MEM_ENC_EXEMPT].size) {
|
||||
// Only MALLOC_CAP_SPIRAM_NO_ENC: any other bit here would let generic 8BIT/32BIT
|
||||
// allocations fall through to this region as a low-priority match.
|
||||
uint32_t no_enc_caps[] = {MALLOC_CAP_SPIRAM_NO_ENC, 0, 0};
|
||||
ret = heap_caps_add_region_with_caps(no_enc_caps,
|
||||
s_psram_ctx.regions_to_heap[PSRAM_MEM_ENC_EXEMPT].vaddr_start,
|
||||
s_psram_ctx.regions_to_heap[PSRAM_MEM_ENC_EXEMPT].vaddr_end);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of unencrypted PSRAM memory to heap allocator",
|
||||
(int)(s_psram_ctx.regions_to_heap[PSRAM_MEM_ENC_EXEMPT].size / 1024));
|
||||
}
|
||||
#endif
|
||||
|
||||
// To allow using the page alignment gaps created while mapping the flash segments,
|
||||
// the alignment gaps must be configured with correct memory protection configurations.
|
||||
#if CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION
|
||||
@@ -544,6 +603,13 @@ bool IRAM_ATTR esp_psram_check_ptr_addr(const void *p)
|
||||
return true;
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM_ENC_EXEMPT
|
||||
if ((intptr_t)p >= s_psram_ctx.mapped_regions[PSRAM_MEM_ENC_EXEMPT].vaddr_start &&
|
||||
(intptr_t)p < s_psram_ctx.mapped_regions[PSRAM_MEM_ENC_EXEMPT].vaddr_end) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_RODATA
|
||||
if (mmu_psram_check_ptr_addr_in_xip_psram_rodata_region(p)) {
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user