diff --git a/debug/gdbserver.py b/debug/gdbserver.py index 1a74a950e..e7dcd4258 100755 --- a/debug/gdbserver.py +++ b/debug/gdbserver.py @@ -278,6 +278,9 @@ def test(self): class MemTestReadInvalid(SimpleMemoryTest): def test(self): bad_address = self.hart.bad_address + if self.target.support_set_pmp_deny: + self.set_pmp_deny(bad_address) + self.gdb.command("monitor riscv set_mem_access progbuf abstract") good_address = self.hart.ram + 0x80 self.write_nop_program(2) @@ -293,6 +296,10 @@ def test(self): self.gdb.stepi() # Don't let gdb cache register read assertEqual(self.gdb.p(f"*((int*)0x{good_address:x})"), 0xabcdef) assertEqual(self.gdb.p("$s0"), 0x12345678) + if self.target.support_set_pmp_deny: + self.reset_pmp_deny() + self.gdb.command("monitor riscv set_mem_access progbuf sysbus" + "abstract") #class MemTestWriteInvalid(SimpleMemoryTest): # def test(self): @@ -2182,6 +2189,9 @@ def test(self): # Set fox to a bad pointer so we'll get a load access exception later. # Use NULL if a known-bad address is not provided. bad_address = self.hart.bad_address or 0 + if self.target.support_set_pmp_deny: + self.set_pmp_deny(bad_address) + self.gdb.command("monitor riscv set_mem_access progbuf abstract") self.gdb.p(f"fox=(char*)0x{bad_address:08x}") output = self.gdb.c() # We should not be at handle_trap @@ -2190,6 +2200,10 @@ def test(self): # actual exception handler. assertIn("breakpoint", output) assertIn("trap_entry", self.gdb.where()) + if self.target.support_set_pmp_deny: + self.reset_pmp_deny() + self.gdb.command("monitor riscv set_mem_access progbuf sysbus" + "abstract") class IcountTest(DebugTest): compile_args = ("programs/infinite_loop.S", ) diff --git a/debug/targets.py b/debug/targets.py index bb7a5cf15..c2d43a39b 100644 --- a/debug/targets.py +++ b/debug/targets.py @@ -141,6 +141,9 @@ class Target: # Instruction count limit icount_limit = 4 + # Support set_pmp_deny to create invalid addresses. + support_set_pmp_deny = False + # Internal variables: directory = None temporary_files = [] diff --git a/debug/testlib.py b/debug/testlib.py index cf62863cf..a52683613 100644 --- a/debug/testlib.py +++ b/debug/testlib.py @@ -1485,6 +1485,22 @@ def parkOtherHarts(self, symbol=None): self.gdb.select_hart(self.hart) self.gdb.command(f"monitor targets {self.hart.id}") + def set_pmp_deny(self, address, size=4 * 1024): + # Enable physical memory protection, no permission to access specific + # address range (default 4KB). + self.gdb.p("$mseccfg=0x4") # RLB + self.gdb.p("$pmpcfg0=0x98") # L, NAPOT, !R, !W, !X + self.gdb.p("$pmpaddr0=" + f"0x{((address >> 2) | ((size - 1) >> 3)):x}") + # PMP changes require an sfence.vma, 0x12000073 is sfence.vma + self.gdb.command("monitor riscv exec_progbuf 0x12000073") + + def reset_pmp_deny(self): + self.gdb.p("$pmpcfg0=0") + self.gdb.p("$pmpaddr0=0") + # PMP changes require an sfence.vma, 0x12000073 is sfence.vma + self.gdb.command("monitor riscv exec_progbuf 0x12000073") + def disable_pmp(self): # Disable physical memory protection by allowing U mode access to all # memory.