Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 49 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ jobs:

- name: Build PMP CSR test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 \
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_csr_test \
contrib/fw/pmp-csr-test/pmp_csr_test.S
Expand All @@ -102,7 +102,7 @@ jobs:

- name: Build PMP enforcement test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 \
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_enforce_test \
contrib/fw/pmp-enforce-test/pmp_enforce_test.S
Expand All @@ -112,7 +112,7 @@ jobs:

- name: Build PMP shift test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 \
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_shift_test \
contrib/fw/pmp-shift-test/pmp_shift_test.S
Expand All @@ -122,7 +122,7 @@ jobs:

- name: Build PMP upper-cfg test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 \
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_upper_cfg_test \
contrib/fw/pmp-upper-cfg-test/pmp_upper_cfg_test.S
Expand All @@ -132,7 +132,7 @@ jobs:

- name: Build PMP cfg2 test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 \
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_cfg2_test \
contrib/fw/pmp-cfg2-test/pmp_cfg2_test.S
Expand All @@ -142,7 +142,7 @@ jobs:

- name: Build PMP TOR test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 \
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_tor_test \
contrib/fw/pmp-tor-test/pmp_tor_test.S
Expand All @@ -152,7 +152,7 @@ jobs:

- name: Build PMP 64-entry pmpaddr test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 \
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_64entry_addr_test \
contrib/fw/pmp-64entry-addr-test/pmp_64entry_addr_test.S
Expand All @@ -162,7 +162,7 @@ jobs:

- name: Build PMP 64-entry pmpcfg test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 \
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_64entry_cfg_test \
contrib/fw/pmp-64entry-cfg-test/pmp_64entry_cfg_test.S
Expand All @@ -172,10 +172,50 @@ jobs:

- name: Build PMP 8-entry guard test firmware (VP/S5 model)
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 \
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_8entry_guard_test \
contrib/fw/pmp-8entry-guard-test/pmp_8entry_guard_test.S

- name: rv64gc_mp_8 8-entry enforcement test - interp (VP/S5 model)
run: LD_LIBRARY_PATH=. ./riscv-sim -f pmp_8entry_guard_test --isa rv64gc_mp_8 --backend interp

- name: Build PMP fetch deny test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_fetch_deny_test \
contrib/fw/pmp-fetch-deny-test/pmp_fetch_deny_test.S

- name: rv64gc_mp_64 fetch execute-permission test - interp
run: LD_LIBRARY_PATH=. ./riscv-sim -f pmp_fetch_deny_test --isa rv64gc_mp_64 --backend interp

- name: Build PMP fetch straddle test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_fetch_straddle_test \
contrib/fw/pmp-fetch-straddle-test/pmp_fetch_straddle_test.S

- name: rv64gc_mp_64 straddling-fetch sector test - interp
run: LD_LIBRARY_PATH=. ./riscv-sim -f pmp_fetch_straddle_test --isa rv64gc_mp_64 --backend interp

- name: Build PMP lock test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_lock_test \
contrib/fw/pmp-lock-test/pmp_lock_test.S

- name: rv64gc_mp_64 lock-bit test - interp
run: LD_LIBRARY_PATH=. ./riscv-sim -f pmp_lock_test --isa rv64gc_mp_64 --backend interp

- name: Build PMP no-entry U-mode test firmware
run: |
riscv64-unknown-elf-gcc -nostdlib -march=rv64gc -mabi=lp64 -I contrib/fw \
-Wl,-Ttext=0x10000,--no-dynamic-linker \
-o pmp_noentry_umode_test \
contrib/fw/pmp-noentry-umode-test/pmp_noentry_umode_test.S

- name: rv64gc_mup no-entry U-mode denial test - interp
run: LD_LIBRARY_PATH=. ./riscv-sim -f pmp_noentry_umode_test --isa rv64gc_mup --backend interp
13 changes: 4 additions & 9 deletions contrib/fw/pmp-64entry-addr-test/pmp_64entry_addr_test.S
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Pass: readback matches written sentinel -> j . (exit 0)
// Fail: any trap (unregistered CSR) or readback mismatch -> semihosting SYS_EXIT (exit 2)

#include "pmp_test_common.h"

.section .text
.globl _start
_start:
Expand All @@ -15,12 +17,5 @@ _start:

j . // pass

fail:
li a0, 0x18
.option push
.option norvc
slli zero, zero, 0x1f
ebreak
srai zero, zero, 7
.option pop
j .
trap_entry fail
semihosting_fail
19 changes: 8 additions & 11 deletions contrib/fw/pmp-64entry-cfg-test/pmp_64entry_cfg_test.S
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
// Verify pmpcfg4 (CSR 0x3A4, holds entries 32-39 on RV64) is accessible and persistent.
// Tests 64-entry pmpcfg registration.
// Pass: write 0x9F -> read back 0x9F -> write 0 -> read back 0 -> j . (exit 0)
// The probe value deliberately leaves L (0x80) clear: locking entry 32 would freeze its
// config byte, so the clear below could not be observed.
// Pass: write 0x1F -> read back 0x1F -> write 0 -> read back 0 -> j . (exit 0)
// Fail: any trap or readback mismatch -> semihosting SYS_EXIT (exit 2)

#include "pmp_test_common.h"

.section .text
.globl _start
_start:
la t0, fail
csrw mtvec, t0

// Write and verify a non-zero value
li t0, 0x9F
li t0, 0x1F
csrw 0x3A4, t0 // pmpcfg4 write
csrr t1, 0x3A4 // pmpcfg4 read
bne t0, t1, fail // must match
Expand All @@ -23,12 +27,5 @@ _start:

j . // pass

fail:
li a0, 0x18
.option push
.option norvc
slli zero, zero, 0x1f
ebreak
srai zero, zero, 7
.option pop
j .
trap_entry fail
semihosting_fail
15 changes: 3 additions & 12 deletions contrib/fw/pmp-8entry-guard-test/pmp_8entry_guard_test.S
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,7 @@
// Pass: phase2_trap fires (load denied) -> j . (exit 0)
// Fail: CSR trap, load succeeds, or unexpected behavior -> semihosting SYS_EXIT (exit 2)

.macro semihosting_fail
li a0, 0x18
.option push
.option norvc
slli zero, zero, 0x1f
ebreak
srai zero, zero, 7
.option pop
j .
.endm
#include "pmp_test_common.h"

.section .text
.globl _start
Expand All @@ -39,10 +30,10 @@ _start:

semihosting_fail // no fault -> FAIL

phase1_trap:
trap_entry phase1_trap
semihosting_fail // CSR trap -> FAIL

phase2_trap:
trap_entry phase2_trap
j . // load denied as expected -> PASS

.align 2
Expand Down
13 changes: 4 additions & 9 deletions contrib/fw/pmp-cfg2-test/pmp_cfg2_test.S
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// Pass: pmpcfg2 readback == written value -> j . (exit 0)
// Fail: pmpcfg2 write traps OR readback wrong -> semihosting SYS_EXIT (exit 2)

#include "pmp_test_common.h"

.section .text
.globl _start
_start:
Expand All @@ -18,12 +20,5 @@ _start:

j . // pass: ISS detects j . and exits 0

fail:
li a0, 0x18
.option push
.option norvc
slli zero, zero, 0x1f
ebreak
srai zero, zero, 7
.option pop
j .
trap_entry fail
semihosting_fail
13 changes: 4 additions & 9 deletions contrib/fw/pmp-csr-test/pmp_csr_test.S
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Pass: j . detected as JUMP_TO_SELF by ISS, exits 0.
// Fail: semihosting SYS_EXIT sequence, ISS exits non-zero.

#include "pmp_test_common.h"

.section .text
.globl _start
_start:
Expand All @@ -18,15 +20,8 @@ _start:

j . // pass: ISS detects j . and exits 0

fail:
trap_entry fail
// Semihosting SYS_EXIT: the ISS checks for slli+ebreak+srai and intercepts
// before dispatching to mtvec. Must use 4-byte ebreak (not c.ebreak) so the
// check lands at the correct offsets (-4 and +4 from the ebreak address).
li a0, 0x18 // SYS_EXIT
.option push
.option norvc // force 4-byte ebreak (0x00100073), not 2-byte c.ebreak
slli zero, zero, 0x1f
ebreak
srai zero, zero, 7
.option pop
j . // fallback if semihosting is not configured
semihosting_fail
15 changes: 3 additions & 12 deletions contrib/fw/pmp-enforce-test/pmp_enforce_test.S
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,7 @@
// Pass: PMP denies load -> load fault fires -> j . (exit 0)
// Fail: any CSR trap, OR load succeeds without fault -> semihosting SYS_EXIT (exit 2)

.macro semihosting_fail
li a0, 0x18
.option push
.option norvc
slli zero, zero, 0x1f
ebreak
srai zero, zero, 7
.option pop
j .
.endm
#include "pmp_test_common.h"

.section .text
.globl _start
Expand All @@ -41,10 +32,10 @@ _start:

semihosting_fail // no fault: enforcement did not fire -> FAIL

phase1_trap:
trap_entry phase1_trap
semihosting_fail // CSR trapped: PMP unavailable -> FAIL

phase2_trap:
trap_entry phase2_trap
j . // load denied as expected -> PASS

.align 2
Expand Down
53 changes: 53 additions & 0 deletions contrib/fw/pmp-fetch-deny-test/pmp_fetch_deny_test.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// PMP execute-permission enforcement on instruction fetch.
//
// Instruction fetches use the IMEM address space rather than MEM, and no other
// PMP test exercises the fetch path or the X permission bit at all. This test
// pins that behaviour so the address-space guard in pmp.h read_mem cannot be
// narrowed to MEM alone without a test failing.
//
// Entry 0 is an NA4 region covering the 4 bytes at target, locked and with no
// X permission. L=1 is required because pmp_check grants M-mode unconditionally
// when L=0.
//
// Pass: fetch of target is denied and reports an instruction access fault -> j . (exit 0)
// Fail: any CSR trap, the fetch succeeds, or the cause is wrong -> semihosting SYS_EXIT (exit 2)

#include "pmp_test_common.h"

.section .text
.globl _start
_start:
// A CSR trap here means PMP is unavailable -> FAIL
la t0, csr_trap
csrw mtvec, t0

// pmpaddr0 = target >> 2 (NA4: covers exactly the 4 bytes at target)
la t5, target
srli t1, t5, 2
csrw pmpaddr0, t1

// pmpcfg0 byte 0 = 0x90 = NA4 (0x10) | L (0x80), no R/W/X
li t1, 0x90
csrw pmpcfg0, t1

la t0, pmp_fault
csrw mtvec, t0

jr t5 // fetch from target: PMP must deny (no X)

trap_entry csr_trap
semihosting_fail // CSR trapped: PMP unavailable -> FAIL

trap_entry pmp_fault
// A denied fetch is an instruction access fault, not a load access fault.
csrr t1, mcause
li t2, 1 // RV_CAUSE_FETCH_ACCESS
bne t1, t2, fail
j . // fetch denied with the correct cause -> PASS

fail:
semihosting_fail

.align 2 // 4-byte align so the NA4 region covers this exactly
target:
semihosting_fail // executed only if the fetch was allowed -> FAIL
Loading
Loading