riscv/riscv_pmp.c: Improve NAPOT area validity checks

Check that the base address and region size are properly aligned with
relation to each other.

With NAPOT encoding the area base and size are not arbitrary, as when
the size increases the amount of bits available for encoding the base
address decreases.
This commit is contained in:
Ville Juven 2023-08-30 16:13:40 +03:00 committed by Petro Karashchenko
parent 7d1763a57c
commit 779741d1d9

View File

@ -100,6 +100,32 @@ typedef struct pmp_entry_s pmp_entry_t;
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: log2ceil
*
* Description:
* Calculate the up-rounded power-of-two for input.
*
* Input Parameters:
* size - The size of the PMP region.
*
* Returned Value:
* Power-of-two for argument, rounded up.
*
****************************************************************************/
static uintptr_t log2ceil(uintptr_t size)
{
uintptr_t pot = 0;
for (size = size - 1; size > 1; size >>= 1)
{
pot++;
}
return pot;
}
/****************************************************************************
* Name: pmp_check_addrmatch_type
*
@ -160,7 +186,8 @@ static bool pmp_check_addrmatch_type(uintptr_t type)
*
****************************************************************************/
static bool pmp_check_region_attrs(uintptr_t base, uintptr_t size)
static bool pmp_check_region_attrs(uintptr_t base, uintptr_t size,
uintptr_t type)
{
/* Check that the size is not too small */
@ -183,7 +210,23 @@ static bool pmp_check_region_attrs(uintptr_t base, uintptr_t size)
return false;
}
return OK;
/* Perform additional checks on base and size for NAPOT area */
if (type == PMPCFG_A_NAPOT)
{
/* Get the power-of-two for size, rounded up */
uintptr_t pot = log2ceil(size);
if ((base & ((UINT64_C(1) << pot) - 1)) != 0)
{
/* The start address is not properly aligned with size */
return false;
}
}
return true;
}
/****************************************************************************
@ -455,7 +498,7 @@ int riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
/* Check the region attributes */
if (pmp_check_region_attrs(base, size))
if (pmp_check_region_attrs(base, size, type) == false)
{
return -EINVAL;
}
@ -463,7 +506,7 @@ int riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
/* Calculate new base address from type */
addr = base >> 2;
if (PMPCFG_A_NAPOT == (attr & PMPCFG_A_MASK))
if (type == PMPCFG_A_NAPOT)
{
addr |= (size - 1) >> 3;
}