Skip to content

Commit 1860766

Browse files
committed
debug: enhance set_pmp_deny to support alignment checks
- set size considering the minimum PMP granularity supported by the hart. Signed-off-by: Hiroo HAYASHI <[email protected]>
1 parent 7af6beb commit 1860766

File tree

3 files changed

+49
-17
lines changed

3 files changed

+49
-17
lines changed

debug/gdbserver.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -276,11 +276,13 @@ def test(self):
276276
self.access_test(8, 'long long')
277277

278278
class MemTestReadInvalid(SimpleMemoryTest):
279+
def early_applicable(self):
280+
return self.target.support_set_pmp_deny
281+
279282
def test(self):
280283
bad_address = self.hart.bad_address
281-
if self.target.support_set_pmp_deny:
282-
self.set_pmp_deny(bad_address)
283-
self.gdb.command("monitor riscv set_mem_access progbuf abstract")
284+
self.set_pmp_deny(bad_address, 4)
285+
self.gdb.command("monitor riscv set_mem_access progbuf abstract")
284286
good_address = self.hart.ram + 0x80
285287

286288
self.write_nop_program(2)
@@ -296,10 +298,9 @@ def test(self):
296298
self.gdb.stepi() # Don't let gdb cache register read
297299
assertEqual(self.gdb.p(f"*((int*)0x{good_address:x})"), 0xabcdef)
298300
assertEqual(self.gdb.p("$s0"), 0x12345678)
299-
if self.target.support_set_pmp_deny:
300-
self.reset_pmp_deny()
301-
self.gdb.command("monitor riscv set_mem_access progbuf sysbus "
302-
"abstract")
301+
self.reset_pmp_deny()
302+
self.gdb.command("monitor riscv set_mem_access progbuf sysbus "
303+
"abstract")
303304

304305
#class MemTestWriteInvalid(SimpleMemoryTest):
305306
# def test(self):
@@ -2200,7 +2201,7 @@ class EtriggerTest(DebugTest):
22002201
# TODO: There should be a check that a exception trigger is really not
22012202
# supported if it is marked as unsupported.
22022203
def early_applicable(self):
2203-
return self.target.support_etrigger
2204+
return self.target.support_etrigger and self.target.support_set_pmp_deny
22042205

22052206
def setup(self):
22062207
DebugTest.setup(self)
@@ -2214,9 +2215,8 @@ def test(self):
22142215
# Set fox to a bad pointer so we'll get a load access exception later.
22152216
# Use NULL if a known-bad address is not provided.
22162217
bad_address = self.hart.bad_address or 0
2217-
if self.target.support_set_pmp_deny:
2218-
self.set_pmp_deny(bad_address)
2219-
self.gdb.command("monitor riscv set_mem_access progbuf abstract")
2218+
self.set_pmp_deny(bad_address, 1)
2219+
self.gdb.command("monitor riscv set_mem_access progbuf abstract")
22202220
self.gdb.p(f"fox=(char*)0x{bad_address:08x}")
22212221
output = self.gdb.c()
22222222
# We should not be at handle_trap
@@ -2225,10 +2225,9 @@ def test(self):
22252225
# actual exception handler.
22262226
assertIn("breakpoint", output)
22272227
assertIn("trap_entry", self.gdb.where())
2228-
if self.target.support_set_pmp_deny:
2229-
self.reset_pmp_deny()
2230-
self.gdb.command("monitor riscv set_mem_access progbuf sysbus "
2231-
"abstract")
2228+
self.reset_pmp_deny()
2229+
self.gdb.command("monitor riscv set_mem_access progbuf sysbus "
2230+
"abstract")
22322231

22332232
class IcountTest(DebugTest):
22342233
compile_args = ("programs/infinite_loop.S", )

debug/targets.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ class Target:
148148
# Support set_pmp_deny to create invalid addresses.
149149
support_set_pmp_deny = False
150150

151+
# Minimum PMP granularity supported by the target, in bytes.
152+
minimum_pmp_granularity = 4
153+
151154
# Supports an address/data match trigger of type 2
152155
support_mcontrol = True
153156

debug/testlib.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,13 @@ def classSetup(self):
14531453
# FIXME: OpenOCD doesn't handle PRIV now
14541454
#self.gdb.p("$priv=3")
14551455

1456+
def setup(self):
1457+
BaseTest.setup(self)
1458+
if self.target.support_set_pmp_deny:
1459+
assertEqual(self.target.minimum_pmp_granularity,
1460+
self.get_minimum_pmp_granularity(),
1461+
"minimum_pmp_granularity does not match target's.")
1462+
14561463
def postMortem(self):
14571464
if not self.gdb:
14581465
return
@@ -1489,9 +1496,32 @@ def exec_sfence_vma(self):
14891496
# PMP changes require an sfence.vma, 0x12000073 is sfence.vma
14901497
self.gdb.command("monitor riscv exec_progbuf 0x12000073")
14911498

1492-
def set_pmp_deny(self, address, size=4 * 1024):
1499+
def ctz(self, i):
1500+
# count trailing zeros
1501+
return (i & -i).bit_length() - 1
1502+
1503+
def get_minimum_pmp_granularity(self):
1504+
# Determine the minimum PMP granularity supported by this hart.
1505+
# cf. RISC-V Privileged Architecture, 3.7.1.1. Address Matching
1506+
self.gdb.p("$pmpcfg0=0") # Null region
1507+
self.gdb.p("$pmpaddr0=-1") # All ones
1508+
readback = self.gdb.p("$pmpaddr0")
1509+
return 2**(self.ctz(readback) + 2)
1510+
1511+
def set_pmp_deny(self, address, size):
14931512
# Enable physical memory protection, no permission to access specific
1494-
# address range (default 4KB).
1513+
# address range. The size must be a power of two and the address must be
1514+
# naturally aligned to the size.
1515+
1516+
# PMP requires size to be at least the minimum granularity.
1517+
# The minimum granularity for NAPOT mode is 8 bytes.
1518+
size = max(size, self.target.minimum_pmp_granularity, 8)
1519+
1520+
if 2**self.ctz(address) < size:
1521+
raise TestNotApplicable(
1522+
f"address 0x{address:x} should be naturally aligned to "
1523+
f"0x{size:x}.")
1524+
14951525
self.gdb.p("$mseccfg=0x4") # RLB
14961526
self.gdb.p("$pmpcfg0=0x98") # L, NAPOT, !R, !W, !X
14971527
self.gdb.p("$pmpaddr0="

0 commit comments

Comments
 (0)