@@ -1488,9 +1488,32 @@ def parkOtherHarts(self, symbol=None):
14881488 self .gdb .select_hart (self .hart )
14891489 self .gdb .command (f"monitor targets { self .hart .id } " )
14901490
1491- def set_pmp_deny (self , address , size = 4 * 1024 ):
1491+ def ctz (self , i ):
1492+ # count trailing zeros
1493+ return (i & - i ).bit_length () - 1
1494+
1495+ def get_minimum_pmp_granularity (self ):
1496+ # Determine the minimum PMP granularity supported by this hart.
1497+ # cf. RISC-V Privileged Architecture, 3.7.1.1. Address Matching
1498+ self .gdb .p ("$pmpcfg0=0" ) # Null region
1499+ self .gdb .p ("$pmpaddr0=-1" ) # All ones
1500+ readback = self .gdb .p ("$pmpaddr0" )
1501+ return 2 ** (self .ctz (readback ) + 2 )
1502+
1503+ def set_pmp_deny (self , address , size ):
14921504 # Enable physical memory protection, no permission to access specific
1493- # address range (default 4KB).
1505+ # address range. The size must be a power of two and the address must be
1506+ # naturally aligned to the size.
1507+
1508+ # PMP requires size to be at least the minimum granularity.
1509+ # The minimum granularity for NAPOT mode is 8 bytes.
1510+ size = max (size , self .get_minimum_pmp_granularity (), 8 )
1511+
1512+ if 2 ** self .ctz (address ) < size :
1513+ raise TestNotApplicable (
1514+ f"address 0x{ address :x} should be naturally aligned to "
1515+ f"0x{ size :x} ." )
1516+
14941517 self .gdb .p ("$mseccfg=0x4" ) # RLB
14951518 self .gdb .p ("$pmpcfg0=0x98" ) # L, NAPOT, !R, !W, !X
14961519 self .gdb .p ("$pmpaddr0="
0 commit comments