Skip to content

Commit 3ec255e

Browse files
committed
Disable and lock regions for protection
Implements region disabling which clears configuration to remove protection, and region locking which sets the lock bit to prevent further modification without hardware reset. Both operations preserve other regions in their respective configuration registers.
1 parent f912cd0 commit 3ec255e

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

arch/riscv/pmp.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,72 @@ int32_t pmp_set_region(pmp_config_t *config, const pmp_region_t *region)
251251

252252
return ERR_OK;
253253
}
254+
255+
int32_t pmp_disable_region(pmp_config_t *config, uint8_t region_idx)
256+
{
257+
if (!config)
258+
return ERR_PMP_INVALID_REGION;
259+
260+
/* Validate region index is within bounds */
261+
if (region_idx >= PMP_MAX_REGIONS)
262+
return ERR_PMP_INVALID_REGION;
263+
264+
/* Check if region is already locked */
265+
if (config->regions[region_idx].locked)
266+
return ERR_PMP_LOCKED;
267+
268+
uint8_t pmpcfg_idx, pmpcfg_offset;
269+
pmp_get_cfg_indices(region_idx, &pmpcfg_idx, &pmpcfg_offset);
270+
271+
/* Read current pmpcfg register to preserve other regions */
272+
uint32_t pmpcfg_val = read_pmpcfg(pmpcfg_idx);
273+
274+
/* Clear the configuration byte for this region (disables it) */
275+
pmpcfg_val &= ~(0xFFU << pmpcfg_offset);
276+
277+
/* Write pmpcfg register with updated configuration */
278+
write_pmpcfg(pmpcfg_idx, pmpcfg_val);
279+
280+
/* Update shadow configuration */
281+
config->regions[region_idx].addr_start = 0;
282+
config->regions[region_idx].addr_end = 0;
283+
config->regions[region_idx].permissions = 0;
284+
285+
return ERR_OK;
286+
}
287+
288+
int32_t pmp_lock_region(pmp_config_t *config, uint8_t region_idx)
289+
{
290+
if (!config)
291+
return ERR_PMP_INVALID_REGION;
292+
293+
/* Validate region index is within bounds */
294+
if (region_idx >= PMP_MAX_REGIONS)
295+
return ERR_PMP_INVALID_REGION;
296+
297+
uint8_t pmpcfg_idx, pmpcfg_offset;
298+
pmp_get_cfg_indices(region_idx, &pmpcfg_idx, &pmpcfg_offset);
299+
300+
/* Read current pmpcfg register to preserve other regions */
301+
uint32_t pmpcfg_val = read_pmpcfg(pmpcfg_idx);
302+
303+
/* Get current configuration byte for this region */
304+
uint8_t pmpcfg_byte = (pmpcfg_val >> pmpcfg_offset) & 0xFFU;
305+
306+
/* Set lock bit */
307+
pmpcfg_byte |= PMPCFG_L;
308+
309+
/* Clear the configuration byte for this region */
310+
pmpcfg_val &= ~(0xFFU << pmpcfg_offset);
311+
312+
/* Write new configuration byte with lock bit set */
313+
pmpcfg_val |= (pmpcfg_byte << pmpcfg_offset);
314+
315+
/* Write pmpcfg register with updated configuration */
316+
write_pmpcfg(pmpcfg_idx, pmpcfg_val);
317+
318+
/* Update shadow configuration */
319+
config->regions[region_idx].locked = 1;
320+
321+
return ERR_OK;
322+
}

0 commit comments

Comments
 (0)