Skip to content

Commit

Permalink
riscv: pmp: provision for implementations with partial PMP support
Browse files Browse the repository at this point in the history
Looks like some implementors decided not to implement the full set of
PMP range matching modes. Let's rearrange the code so that any of those
modes can be disabled.

Signed-off-by: Nicolas Pitre <[email protected]>
  • Loading branch information
Nicolas Pitre authored and carlescufi committed Feb 20, 2023
1 parent ea34acb commit 3c440af
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 10 deletions.
19 changes: 17 additions & 2 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,26 @@ config PMP_SLOTS
This is the number of PMP entries implemented by the hardware.
Typical values are 8 or 16.

config PMP_NO_TOR
bool
help
Set this if TOR (Top Of Range) mode is not supported.

config PMP_NO_NA4
bool
help
Set this if NA4 (Naturally Aligned 4-byte) mode is not supported.

config PMP_NO_NAPOT
bool
help
Set this if NAPOT (Naturally Aligned Power Of Two) is not supported.

config PMP_POWER_OF_TWO_ALIGNMENT
bool "Enforce power-of-two alignment on PMP memory areas"
depends on USERSPACE
bool "Enforce power-of-two alignment on PMP memory areas" if !PMP_NO_TOR
default y if TEST_USERSPACE
default y if (PMP_SLOTS = 8)
default y if PMP_NO_TOR
select MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT
select GEN_PRIV_STACKS
help
Expand Down
28 changes: 21 additions & 7 deletions arch/riscv/core/pmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ LOG_MODULE_REGISTER(mpu);
# define PR_ADDR "0x%08lx"
#endif

#define PMP_TOR_SUPPORTED !IS_ENABLED(CONFIG_PMP_NO_TOR)
#define PMP_NA4_SUPPORTED !IS_ENABLED(CONFIG_PMP_NO_NA4)
#define PMP_NAPOT_SUPPORTED !IS_ENABLED(CONFIG_PMP_NO_NAPOT)

#define PMPCFG_STRIDE sizeof(unsigned long)

#define PMP_ADDR(addr) ((addr) >> 2)
Expand Down Expand Up @@ -163,27 +167,37 @@ static bool set_pmp_entry(unsigned int *index_p, uint8_t perm,
if (index >= index_limit) {
LOG_ERR("out of PMP slots");
ok = false;
} else if ((index == 0 && start == 0) ||
(index != 0 && pmp_addr[index - 1] == PMP_ADDR(start))) {
} else if (PMP_TOR_SUPPORTED &&
((index == 0 && start == 0) ||
(index != 0 && pmp_addr[index - 1] == PMP_ADDR(start)))) {
/* We can use TOR using only one additional slot */
pmp_addr[index] = PMP_ADDR(start + size);
pmp_n_cfg[index] = perm | PMP_TOR;
index += 1;
} else if (((size & (size - 1)) == 0) /* power of 2 */ &&
((start & (size - 1)) == 0) /* naturally aligned */) {
} else if (PMP_NA4_SUPPORTED && size == 4) {
pmp_addr[index] = PMP_ADDR(start);
pmp_n_cfg[index] = perm | PMP_NA4;
index += 1;
} else if (PMP_NAPOT_SUPPORTED &&
((size & (size - 1)) == 0) /* power of 2 */ &&
((start & (size - 1)) == 0) /* naturally aligned */ &&
(PMP_NA4_SUPPORTED || (size != 4))) {
pmp_addr[index] = PMP_ADDR_NAPOT(start, size);
pmp_n_cfg[index] = perm | (size == 4 ? PMP_NA4 : PMP_NAPOT);
pmp_n_cfg[index] = perm | PMP_NAPOT;
index += 1;
} else if (index + 1 >= index_limit) {
} else if (PMP_TOR_SUPPORTED && index + 1 >= index_limit) {
LOG_ERR("out of PMP slots");
ok = false;
} else {
} else if (PMP_TOR_SUPPORTED) {
pmp_addr[index] = PMP_ADDR(start);
pmp_n_cfg[index] = 0;
index += 1;
pmp_addr[index] = PMP_ADDR(start + size);
pmp_n_cfg[index] = perm | PMP_TOR;
index += 1;
} else {
LOG_ERR("inappropriate PMP range (start=%#lx size=%#zx)", start, size);
ok = false;
}

*index_p = index;
Expand Down
6 changes: 5 additions & 1 deletion include/zephyr/arch/riscv/common/linker.ld
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@
#define RAM_SIZE KB(CONFIG_SRAM_SIZE)

#ifdef CONFIG_RISCV_PMP
#define MPU_MIN_SIZE 4
#if defined(CONFIG_PMP_NO_TOR) && defined(CONFIG_PMP_NO_NA4)
#define MPU_MIN_SIZE 8
#else
#define MPU_MIN_SIZE 4
#endif
#define MPU_MIN_SIZE_ALIGN . = ALIGN(MPU_MIN_SIZE);
#if defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT)
#define MPU_ALIGN(region_size) \
Expand Down
4 changes: 4 additions & 0 deletions tests/kernel/mem_protect/mem_protect/src/mem_protect.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ static inline void set_fault_valid(bool valid)
#elif defined(CONFIG_ARM)
#define MEM_REGION_ALLOC (Z_THREAD_MIN_STACK_ALIGN)
#elif defined(CONFIG_RISCV)
#if defined(CONFIG_PMP_NO_TOR) && defined(CONFIG_PMP_NO_NA4)
#define MEM_REGION_ALLOC (8)
#else
#define MEM_REGION_ALLOC (4)
#endif
#else
#error "Test suite not compatible for the given architecture"
#endif
Expand Down

0 comments on commit 3c440af

Please sign in to comment.