Skip to content

Commit

Permalink
riscv/riscv_pmp.c: Improve NAPOT area validity checks
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pussuw authored and pkarashchenko committed Aug 30, 2023
1 parent 7d1763a commit 779741d
Showing 1 changed file with 47 additions and 4 deletions.
51 changes: 47 additions & 4 deletions arch/risc-v/src/common/riscv_pmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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 */

Expand All @@ -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;
}

/****************************************************************************
Expand Down Expand Up @@ -455,15 +498,15 @@ 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;
}

/* 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;
}
Expand Down

0 comments on commit 779741d

Please sign in to comment.