From 437e299d1060c0da4324993b9878611601ed9212 Mon Sep 17 00:00:00 2001 From: Yi-Hsuan Deng Date: Thu, 21 Nov 2024 14:39:23 +0000 Subject: [PATCH] [imm_rom_ext] Add immutable ROM_EXT ePMP reconfiguration Reconfigure ePMP in immutable ROM_EXT to remove executable permission on the immutable data segment. Now, ePMP will be reconfigured to the following layout before jumping to the mutable ROM_EXT: ``` * 6: MU_EXT ----- ---- * 7: MU_EXT TOR LX-R * 8: IM_EXT ----- ---- * 9: IM_EXT TOR LX-R * 10: VIRTUAL NAPOT L--R * 11: STACK NA4 L--- ``` MU_EXT stands for mutable part of rom_ext, and IM_EXT is the immutable part. Slot 10 will be empty if address translation is not enabled, and stack guard is added back to slot 11. Before jumping to Owner SW, all lock bits will be cleared, so all entries can be recycled by Owner SW. Owner SW will be placed at the same entries as before (2, 3, 4). Change-Id: Id9b6cd68cc24a5816d3e3dc8374b5533a7c6eb75 Signed-off-by: Yi-Hsuan Deng --- sw/device/silicon_creator/imm_rom_ext/BUILD | 17 +++ .../silicon_creator/imm_rom_ext/imm_rom_ext.c | 6 + .../imm_rom_ext/imm_rom_ext_epmp.c | 115 ++++++++++++++++++ .../imm_rom_ext/imm_rom_ext_epmp.h | 66 ++++++++++ sw/device/silicon_creator/lib/drivers/BUILD | 10 ++ sw/device/silicon_creator/lib/drivers/epmp.c | 35 +++++- sw/device/silicon_creator/lib/drivers/epmp.h | 25 ++++ .../lib/drivers/epmp_unittest.cc | 64 ++++++++++ sw/device/silicon_creator/rom_ext/rom_ext.c | 76 +----------- 9 files changed, 339 insertions(+), 75 deletions(-) create mode 100644 sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_epmp.c create mode 100644 sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_epmp.h create mode 100644 sw/device/silicon_creator/lib/drivers/epmp_unittest.cc diff --git a/sw/device/silicon_creator/imm_rom_ext/BUILD b/sw/device/silicon_creator/imm_rom_ext/BUILD index faa572d3b35fa..537baf64ed969 100644 --- a/sw/device/silicon_creator/imm_rom_ext/BUILD +++ b/sw/device/silicon_creator/imm_rom_ext/BUILD @@ -14,6 +14,7 @@ cc_library( srcs = ["imm_rom_ext.c"], hdrs = ["imm_rom_ext.h"], deps = [ + ":imm_rom_ext_epmp", "//hw/top_earlgrey/ip_autogen/flash_ctrl:flash_ctrl_c_regs", "//sw/device/lib/arch:device", "//sw/device/lib/base:macros", @@ -34,6 +35,22 @@ cc_library( ], ) +cc_library( + name = "imm_rom_ext_epmp", + srcs = ["imm_rom_ext_epmp.c"], + hdrs = ["imm_rom_ext_epmp.h"], + deps = [ + "//hw/top_earlgrey/sw/autogen:top_earlgrey", + "//sw/device/lib/base:csr", + "//sw/device/lib/base:macros", + "//sw/device/silicon_creator/lib:epmp_state", + "//sw/device/silicon_creator/lib:error", + "//sw/device/silicon_creator/lib:manifest", + "//sw/device/silicon_creator/lib/drivers:epmp", + "//sw/device/silicon_creator/lib/drivers:lifecycle", + ], +) + ld_library( name = "ld_hello_world", script = "hello_world.ld", diff --git a/sw/device/silicon_creator/imm_rom_ext/imm_rom_ext.c b/sw/device/silicon_creator/imm_rom_ext/imm_rom_ext.c index fb6b32dd8279a..de4e896f067f4 100644 --- a/sw/device/silicon_creator/imm_rom_ext/imm_rom_ext.c +++ b/sw/device/silicon_creator/imm_rom_ext/imm_rom_ext.c @@ -6,6 +6,7 @@ #include "sw/device/lib/arch/device.h" #include "sw/device/lib/base/macros.h" +#include "sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_epmp.h" #include "sw/device/silicon_creator/lib/base/boot_measurements.h" #include "sw/device/silicon_creator/lib/base/sec_mmio.h" #include "sw/device/silicon_creator/lib/cert/dice_chain.h" @@ -31,6 +32,8 @@ static rom_error_t imm_rom_ext_start(void) { // Initialize Immutable ROM EXT. sec_mmio_next_stage_init(); + HARDENED_RETURN_IF_ERROR(imm_rom_ext_epmp_reconfigure()); + // Configure UART0 as stdout. pinmux_init_uart0_tx(); uart_init(kUartNCOValue); @@ -52,6 +55,9 @@ static rom_error_t imm_rom_ext_start(void) { // Write the DICE certs to flash if they have been updated. HARDENED_RETURN_IF_ERROR(dice_chain_flush_flash()); + // Make mutable part executable. + HARDENED_RETURN_IF_ERROR(imm_rom_ext_epmp_mutable_rx(rom_ext)); + return kErrorOk; } diff --git a/sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_epmp.c b/sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_epmp.c new file mode 100644 index 0000000000000..4f25738e0c684 --- /dev/null +++ b/sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_epmp.c @@ -0,0 +1,115 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_epmp.h" + +#include "sw/device/lib/base/csr.h" +#include "sw/device/lib/base/macros.h" +#include "sw/device/silicon_creator/lib/drivers/epmp.h" +#include "sw/device/silicon_creator/lib/drivers/lifecycle.h" +#include "sw/device/silicon_creator/lib/epmp_state.h" +#include "sw/device/silicon_creator/lib/error.h" +#include "sw/device/silicon_creator/lib/manifest.h" + +#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated. + +// Address populated by the linker. +extern char _rom_ext_immutable_start[]; +extern char _rom_ext_immutable_end[]; +extern char _text_end[]; +extern char _stack_start[]; // Lowest stack address. + +static const epmp_region_t kMmioRegion = { + .start = TOP_EARLGREY_MMIO_BASE_ADDR, + .end = TOP_EARLGREY_MMIO_BASE_ADDR + TOP_EARLGREY_MMIO_SIZE_BYTES, +}; + +static const epmp_region_t kFlashRegion = { + .start = TOP_EARLGREY_EFLASH_BASE_ADDR, + .end = TOP_EARLGREY_EFLASH_BASE_ADDR + TOP_EARLGREY_EFLASH_SIZE_BYTES, +}; + +static const epmp_region_t kRvDmRegion = { + .start = TOP_EARLGREY_RV_DM_MEM_BASE_ADDR, + .end = TOP_EARLGREY_RV_DM_MEM_BASE_ADDR + TOP_EARLGREY_RV_DM_MEM_SIZE_BYTES, +}; + +static const epmp_region_t kStackGuard = {.start = (uintptr_t)_stack_start, + .end = (uintptr_t)_stack_start + 4}; + +static const epmp_region_t kImmTextRegion = { + .start = (uintptr_t)_rom_ext_immutable_start, + .end = (uintptr_t)_text_end, +}; + +rom_error_t imm_rom_ext_epmp_reconfigure(void) { + lifecycle_state_t lc_state = lifecycle_state_get(); + + // ePMP region 15 gives read/write access to RAM. + // Leave it unchanged. + + // Reconfigure the ePMP MMIO region to be NAPOT region 14, thus freeing + // up an ePMP entry for use elsewhere. + epmp_set_napot(14, kMmioRegion, kEpmpPermLockedReadWrite); + + // ePMP region 11 protects the stack from overflow. + // This stack guard was in ePMP region 14. + epmp_set_napot(11, kStackGuard, kEpmpPermLockedNoAccess); + + // ePMP region 12 allows RvDM access. + // This RvDM region was in ePMP region 13. + if (lc_state == kLcStateProd || lc_state == kLcStateProdEnd) { + // No RvDM access in Prod states, so we can clear the entry. + epmp_clear(12); + } else { + epmp_set_napot(12, kRvDmRegion, kEpmpPermLockedReadWriteExecute); + } + + // ePMP region 13 gives read access to all of flash for both M and U modes. + // This flash region was in ePMP region 5. + epmp_set_napot(13, kFlashRegion, kEpmpPermLockedReadOnly); + + // Move the ROM_EXT virtual region from entry 6 to 10. + uint32_t virtual_napot; + CSR_READ(CSR_REG_PMPADDR6, &virtual_napot); + epmp_clear(10); + if (virtual_napot) { + epmp_set_napot(10, epmp_decode_napot(virtual_napot), + kEpmpPermLockedReadOnly); + } + + // Clear mutable ROM_EXT entries (8 & 9). + epmp_clear(9); + epmp_clear(8); + + // Immutable ROM_EXT TOR (6 & 7). + epmp_set_tor(6, kImmTextRegion, kEpmpPermLockedReadExecute); + + // Clear entries from 5 ~ 3. + epmp_clear(5); + epmp_clear(4); + epmp_clear(3); + + // 3 ~ 0 are ROM ePMP entries. + // Leave them unchanged. + + HARDENED_RETURN_IF_ERROR(epmp_state_check()); + + return kErrorOk; +} + +rom_error_t imm_rom_ext_epmp_mutable_rx(const manifest_t *manifest) { + // Immutable ROM_EXT TOR (8 & 9). + epmp_region_t mutable_code_region = manifest_code_region_get(manifest); + + // Manifest code_region includes immutable data segment. Move the start + // address to exclude. + mutable_code_region.start = (uintptr_t)_rom_ext_immutable_end; + + epmp_set_tor(8, mutable_code_region, kEpmpPermLockedReadExecute); + + HARDENED_RETURN_IF_ERROR(epmp_state_check()); + + return kErrorOk; +} diff --git a/sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_epmp.h b/sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_epmp.h new file mode 100644 index 0000000000000..974f5be59fed0 --- /dev/null +++ b/sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_epmp.h @@ -0,0 +1,66 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_IMM_ROM_EXT_IMM_ROM_EXT_EPMP_H_ +#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_IMM_ROM_EXT_IMM_ROM_EXT_EPMP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sw/device/silicon_creator/lib/error.h" +#include "sw/device/silicon_creator/lib/manifest.h" + +/** + * Reconfigure ePMP entries to lower priority. + * + * ePMP will be reconfigured to: + * 0: ROM ----- ---- + * 1: ROM TOR LX-R + * 2: ROM NAPOT L--R + * 3: ------- ----- ---- + * 4: ------- ----- ---- + * 5: ------- ----- ---- + * 6: IM_EXT ----- ---- + * 7: IM_EXT TOR LX-R + * 8:[MU_EXT ----- ----] + * 9:[MU_EXT TOR LX-R] + * 10: VIRTUAL NAPOT L--R + * 11: STACK NA4 L--- + * 12: RvDM NAPOT LXWR + * 13: FLASH NAPOT L--R + * 14: MMIO NAPOT L-WR + * 15: RAM NAPOT L-WR + * + * Mutable ROM_EXT segment (8 & 9) won't be configured by this function. + * `imm_rom_ext_epmp_mutable_rx` will configure them when we are ready to + * jump back to ROM. + * + * Entries 6~12 can be recycled in Owner SW stage. + * + * @return The result of the operation. + */ +OT_WARN_UNUSED_RESULT +rom_error_t imm_rom_ext_epmp_reconfigure(void); + +/** + * Configure the Mutable ROM_EXT text segment with read-execute permissions. + * + * 8: MU_EXT ----- ---- + * 9: MU_EXT TOR LX-R + * + * Note: When address translation is enabled, the manifest argument should + * point to the one in the virtual space. + * + * @param manifest Pointer to the rom_ext manifest. + * @return The result of the operation. + */ +OT_WARN_UNUSED_RESULT +rom_error_t imm_rom_ext_epmp_mutable_rx(const manifest_t *manifest); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_IMM_ROM_EXT_IMM_ROM_EXT_EPMP_H_ diff --git a/sw/device/silicon_creator/lib/drivers/BUILD b/sw/device/silicon_creator/lib/drivers/BUILD index a55827a9d21d9..02599aee58315 100644 --- a/sw/device/silicon_creator/lib/drivers/BUILD +++ b/sw/device/silicon_creator/lib/drivers/BUILD @@ -893,3 +893,13 @@ cc_library( "//sw/device/silicon_creator/lib:epmp_state", ], ) + +cc_test( + name = "epmp_unittest", + srcs = ["epmp_unittest.cc"], + deps = [ + ":epmp", + "//sw/device/silicon_creator/testing:rom_test", + "@googletest//:gtest_main", + ], +) diff --git a/sw/device/silicon_creator/lib/drivers/epmp.c b/sw/device/silicon_creator/lib/drivers/epmp.c index a11f9fb1bb6c1..306df514ad608 100644 --- a/sw/device/silicon_creator/lib/drivers/epmp.c +++ b/sw/device/silicon_creator/lib/drivers/epmp.c @@ -16,7 +16,7 @@ CSR_WRITE(CSR_REG_PMPADDR##addr_reg, pmpaddr); \ CSR_SET_BITS(CSR_REG_PMPCFG##cfg_reg, cfg); -static void epmp_set(uint8_t entry, uint32_t pmpcfg, uint32_t pmpaddr) { +void epmp_set(uint8_t entry, uint32_t pmpcfg, uint32_t pmpaddr) { uint32_t shift = 8 * (entry % 4); uint32_t mask = 0xFFu << shift; uint32_t cfg = (pmpcfg & 0xFFu) << shift; @@ -51,16 +51,41 @@ static void epmp_set(uint8_t entry, uint32_t pmpcfg, uint32_t pmpaddr) { void epmp_clear(uint8_t entry) { epmp_set(entry, kEpmpModeOff, 0); } -void epmp_set_napot(uint8_t entry, epmp_region_t region, epmp_perm_t perm) { - uint32_t length = region.end - region.start; +void epmp_clear_lock_bits(void) { + const uint32_t mask = + ((uint32_t)EPMP_CFG_L << 0 * 8) | ((uint32_t)EPMP_CFG_L << 1 * 8) | + ((uint32_t)EPMP_CFG_L << 2 * 8) | ((uint32_t)EPMP_CFG_L << 3 * 8); + CSR_CLEAR_BITS(CSR_REG_PMPCFG0, mask); + CSR_CLEAR_BITS(CSR_REG_PMPCFG1, mask); + CSR_CLEAR_BITS(CSR_REG_PMPCFG2, mask); + CSR_CLEAR_BITS(CSR_REG_PMPCFG3, mask); + for (int cfgent = 0; cfgent < 4; ++cfgent) { + epmp_state.pmpcfg[cfgent] &= ~mask; + } +} + +uint32_t epmp_encode_napot(epmp_region_t region) { + const uint32_t length = region.end - region.start; // The length must be 4 or more. HARDENED_CHECK_GE(length, 4); // The length must be a power of 2. HARDENED_CHECK_EQ(bitfield_popcount32(length), 1); // The start address must be naturally aligned with length. HARDENED_CHECK_EQ(region.start & (length - 1), 0); - epmp_mode_t mode = length == 4 ? kEpmpModeNa4 : kEpmpModeNapot; - uint32_t addr = (region.start >> 2) | ((length - 1) >> 3); + return (region.start >> 2) | ((length - 1) >> 3); +} + +epmp_region_t epmp_decode_napot(uint32_t pmpaddr) { + uint32_t size = 1 << bitfield_count_trailing_zeroes32(~pmpaddr); + pmpaddr = (pmpaddr & ~(size - 1)) << 2; + size <<= 3; + return (epmp_region_t){.start = pmpaddr, .end = pmpaddr + size}; +} + +void epmp_set_napot(uint8_t entry, epmp_region_t region, epmp_perm_t perm) { + uint32_t addr = epmp_encode_napot(region); + epmp_mode_t mode = + region.end - region.start == 4 ? kEpmpModeNa4 : kEpmpModeNapot; epmp_set(entry, (uint32_t)mode | (uint32_t)perm, addr); } diff --git a/sw/device/silicon_creator/lib/drivers/epmp.h b/sw/device/silicon_creator/lib/drivers/epmp.h index bdabb32ac85d1..25cc3a35eca65 100644 --- a/sw/device/silicon_creator/lib/drivers/epmp.h +++ b/sw/device/silicon_creator/lib/drivers/epmp.h @@ -43,6 +43,31 @@ extern "C" { */ void epmp_clear(uint8_t entry); +/** + * Clear the lock bit in all ePMP entries. + */ +void epmp_clear_lock_bits(void); + +/** + * Encode a start/end address pair to NAPOT address. + * + * The region start must have an alignment consistend with the region size. The + * region size must be a power of two. If either of these conditions is not + * met, this function will fault. + * + * @param region The address region to configure. + * @return The encoded NAPOT address. + */ +uint32_t epmp_encode_napot(epmp_region_t region); + +/** + * Decode a NAPOT address back to start/end address pair. + * + * @param pmpaddr The encoded NAPOT address. + * @return region The decoded start/end address pair. + */ +epmp_region_t epmp_decode_napot(uint32_t pmpaddr); + /** * Configures an ePMP entry for a NAPOT or NA4 region. * diff --git a/sw/device/silicon_creator/lib/drivers/epmp_unittest.cc b/sw/device/silicon_creator/lib/drivers/epmp_unittest.cc new file mode 100644 index 0000000000000..9f6989c8ae04d --- /dev/null +++ b/sw/device/silicon_creator/lib/drivers/epmp_unittest.cc @@ -0,0 +1,64 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "sw/device/silicon_creator/lib/drivers/epmp.h" + +#include "gtest/gtest.h" +#include "sw/device/silicon_creator/testing/rom_test.h" + +namespace epmp_unittest { +namespace { + +struct NapotCase { + /** + * Start / end of the NAPOT region. + */ + uint32_t start; + uint32_t end; + /** + * Encoded NAPOT address. + */ + uint32_t encoded; +}; + +class NapotTest : public rom_test::RomTest, + public testing::WithParamInterface {}; + +TEST_P(NapotTest, Codec) { + epmp_region_t region = { + .start = (uintptr_t)GetParam().start, + .end = (uintptr_t)GetParam().end, + }; + EXPECT_EQ(epmp_encode_napot(region), GetParam().encoded); + + epmp_region_t decoded = epmp_decode_napot(GetParam().encoded); + EXPECT_EQ(decoded.start, GetParam().start); + EXPECT_EQ(decoded.end, GetParam().end); +} + +INSTANTIATE_TEST_SUITE_P(AllCases, NapotTest, + testing::Values( + NapotCase{ + .start = 0b1000010100100100101010100000, + .end = 0b1000010100100100101011000000, + .encoded = 0b10000101001001001010101011, + }, + NapotCase{ + .start = 0b101000001101000011100000000000, + .end = 0b101000001101000011100100000000, + .encoded = 0b1010000011010000111000011111, + }, + NapotCase{ + .start = 0b10111111111111111111111111111000, + .end = 0b11000000000000000000000000000000, + .encoded = 0b101111111111111111111111111110, + }, + NapotCase{ + .start = 0b00000000000000000000000000000000, + .end = 0b10000000000000000000000000000000, + .encoded = 0b001111111111111111111111111111, + })); + +} // namespace +} // namespace epmp_unittest diff --git a/sw/device/silicon_creator/rom_ext/rom_ext.c b/sw/device/silicon_creator/rom_ext/rom_ext.c index b50ba4ff08b88..212fe2a797e6f 100644 --- a/sw/device/silicon_creator/rom_ext/rom_ext.c +++ b/sw/device/silicon_creator/rom_ext/rom_ext.c @@ -67,27 +67,6 @@ owner_config_t owner_config; // Owner application keys. owner_application_keyring_t keyring; -// ePMP regions for important address spaces. -const epmp_region_t kRamRegion = { - .start = TOP_EARLGREY_RAM_MAIN_BASE_ADDR, - .end = TOP_EARLGREY_RAM_MAIN_BASE_ADDR + TOP_EARLGREY_RAM_MAIN_SIZE_BYTES, -}; - -const epmp_region_t kMmioRegion = { - .start = TOP_EARLGREY_MMIO_BASE_ADDR, - .end = TOP_EARLGREY_MMIO_BASE_ADDR + TOP_EARLGREY_MMIO_SIZE_BYTES, -}; - -const epmp_region_t kRvDmRegion = { - .start = TOP_EARLGREY_RV_DM_MEM_BASE_ADDR, - .end = TOP_EARLGREY_RV_DM_MEM_BASE_ADDR + TOP_EARLGREY_RV_DM_MEM_SIZE_BYTES, -}; - -const epmp_region_t kFlashRegion = { - .start = TOP_EARLGREY_EFLASH_BASE_ADDR, - .end = TOP_EARLGREY_EFLASH_BASE_ADDR + TOP_EARLGREY_EFLASH_SIZE_BYTES, -}; - OT_WARN_UNUSED_RESULT static rom_error_t rom_ext_irq_error(void) { uint32_t mcause; @@ -158,7 +137,11 @@ static rom_error_t rom_ext_init(boot_data_t *boot_data) { // Configure UART0 as stdout. uart_init(kUartNCOValue); - // TODO: Verify ePMP expectations from ROM. + // Reclaim entries 0 ~ 7 from ROM and IMM_ROM_EXT. + for (int8_t i = 7; i >= 0; --i) { + epmp_clear((uint8_t)i); + } + HARDENED_RETURN_IF_ERROR(epmp_state_check()); // Conditionally patch AST and check that it is in the expected state. HARDENED_RETURN_IF_ERROR(ast_patch(lc_state)); @@ -292,55 +275,8 @@ static rom_error_t rom_ext_boot(const manifest_t *manifest) { SEC_MMIO_WRITE_INCREMENT(kFlashCtrlSecMmioCreatorInfoPagesLockdown + kOtpSecMmioCreatorSwCfgLockDown); - // ePMP region 15 gives read/write access to RAM. - epmp_set_napot(15, kRamRegion, kEpmpPermReadWrite); + epmp_clear_lock_bits(); - // Reconfigure the ePMP MMIO region to be NAPOT region 14, thus freeing - // up an ePMP entry for use elsewhere. - epmp_set_napot(14, kMmioRegion, kEpmpPermReadWrite); - - // ePMP region 13 allows RvDM access. - if (lc_state == kLcStateProd || lc_state == kLcStateProdEnd) { - // No RvDM access in Prod states, so we can clear the entry. - epmp_clear(13); - } else { - epmp_set_napot(13, kRvDmRegion, kEpmpPermReadWriteExecute); - } - - // ePMP region 12 gives read access to all of flash for both M and U modes. - // The flash access was in ePMP region 5. Clear it so it doesn't take - // priority over 12. - epmp_set_napot(12, kFlashRegion, kEpmpPermReadOnly); - epmp_clear(5); - - // Move the ROM_EXT TOR region from entries 3/4/6 to 9/10/11. - // If the ROM_EXT is located in the virtual window, the ROM will have - // configured ePMP entry 6 as the read-only region over the entire - // window. - // - // If not using the virtual window, we move the ROM_EXT TOR region to - // ePMP entries 10/11. - // If using the virtual window, we move the ROM_EXT read-only region to - // ePMP entry 11 and move the TOR region to 9/10. - uint32_t start, end, vwindow; - CSR_READ(CSR_REG_PMPADDR3, &start); - CSR_READ(CSR_REG_PMPADDR4, &end); - CSR_READ(CSR_REG_PMPADDR6, &vwindow); - uint8_t rxindex = 10; - if (vwindow) { - rxindex = 9; - uint32_t size = 1 << bitfield_count_trailing_zeroes32(~vwindow); - vwindow = (vwindow & ~(size - 1)) << 2; - size <<= 3; - - epmp_set_napot(11, (epmp_region_t){.start = vwindow, .end = vwindow + size}, - kEpmpPermReadOnly); - } - epmp_set_tor(rxindex, (epmp_region_t){.start = start << 2, .end = end << 2}, - kEpmpPermReadExecute); - for (int8_t i = (int8_t)rxindex - 1; i >= 0; --i) { - epmp_clear((uint8_t)i); - } HARDENED_RETURN_IF_ERROR(epmp_state_check()); // Configure address translation, compute the epmp regions and the entry