Skip to content

Commit acd3cfd

Browse files
committed
Verify memory access permissions in PMP regions
Checks if a memory access falls within a configured region by comparing the requested address and size against the region boundaries. When a matching region is found, validates that the region's permissions match the requested operation type. Address register read helpers are marked unused as the current implementation maintains shadow state in memory rather than reading hardware registers. They remain available for potential future use cases requiring hardware state verification.
1 parent 920d586 commit acd3cfd

File tree

1 file changed

+45
-2
lines changed

1 file changed

+45
-2
lines changed

arch/riscv/pmp.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,13 @@ static void write_pmpcfg(uint8_t idx, uint32_t val)
4242
}
4343
}
4444

45-
/* Read PMP address register by index (0-15) */
46-
static uint32_t read_pmpaddr(uint8_t idx)
45+
/* Read PMP address register by index (0-15)
46+
*
47+
* Currently unused as the implementation maintains shadow state in memory
48+
* rather than reading hardware registers. Provided for API completeness
49+
* and potential future use cases requiring hardware state verification.
50+
*/
51+
static uint32_t __attribute__((unused)) read_pmpaddr(uint8_t idx)
4752
{
4853
switch (idx) {
4954
case 0: return read_csr_num(CSR_PMPADDR0);
@@ -344,3 +349,41 @@ int32_t pmp_get_region(const pmp_config_t *config, uint8_t region_idx,
344349

345350
return ERR_OK;
346351
}
352+
353+
int32_t pmp_check_access(const pmp_config_t *config, uint32_t addr,
354+
uint32_t size, uint8_t is_write, uint8_t is_execute)
355+
{
356+
if (!config)
357+
return ERR_PMP_INVALID_REGION;
358+
359+
uint32_t access_end = addr + size;
360+
361+
/* In TOR mode, check all regions in priority order */
362+
for (uint8_t i = 0; i < config->region_count; i++) {
363+
const pmp_region_t *region = &config->regions[i];
364+
365+
/* Skip disabled regions */
366+
if (region->addr_start == 0 && region->addr_end == 0)
367+
continue;
368+
369+
/* Check if access falls within this region */
370+
if (addr >= region->addr_start && access_end <= region->addr_end) {
371+
/* Verify permissions match access type */
372+
uint8_t required_perm = 0;
373+
if (is_write)
374+
required_perm |= PMPCFG_W;
375+
if (is_execute)
376+
required_perm |= PMPCFG_X;
377+
if (!is_write && !is_execute)
378+
required_perm = PMPCFG_R;
379+
380+
if ((region->permissions & required_perm) == required_perm)
381+
return 1; /* Access allowed */
382+
else
383+
return 0; /* Access denied */
384+
}
385+
}
386+
387+
/* Access not covered by any region */
388+
return 0;
389+
}

0 commit comments

Comments
 (0)