Skip to content

OpenC910: PMP-denied addressed cache operations complete while ordinary loads fault #59

Description

@KnightGOKU

Summary

OpenC910 custom addressed cache operations complete successfully on an address protected by PMP. Under the same PMP configuration, an ordinary load from the same address raises an access fault.

The minimal software-visible POC is a locked M-mode cache operation:

  • PMP0 = locked 4KB NAPOT deny on the target page
  • ordinary lw from the target traps
  • dcache.cva on the same target returns successfully

Expected result:

  • the addressed cache operation should not silently complete on a PMP-denied block

Actual result on OpenC910:

  • the cache operation retires successfully

Test Case

The testcase configures pmpaddr0 = 0x181ff and pmpcfg0 = 0x98, which makes the page containing 0x60080 a locked NAPOT no-access region. It then runs either the ordinary load control or the addressed cache operation on the same target address:

.include "openc910_min_common.inc"

.equ TARGET_ADDR,              0x60080
.equ TARGET_PAGE_NAPOT,        0x181ff
.equ PMP_DENY_LOCKED_NAPOT,    0x98

.text
.align 6
.global main
main:
  la    t0, trap_handler
  csrw  mtvec, t0

  li    t0, TARGET_ADDR
  li    t1, 0x1122334455667788
  sd    t1, 0(t0)
  fence

  li    t0, TARGET_PAGE_NAPOT
  csrw  pmpaddr0, t0
  li    t0, PMP_DENY_LOCKED_NAPOT
  csrw  pmpcfg0, t0
  fence

  li    t0, TARGET_ADDR

#if ACCESS_KIND == 5
  lw    t1, 0(t0)          # ordinary load control
#else
  .word 0x0252800b         # dcache.cva t0
#endif

  la    a0, fail_msg
  jal   ra, oracle_puts
1:
  j     1b

trap_handler:
  csrr  t0, mcause
  li    t1, 5
  beq   t0, t1, expected_trap
  li    t1, 7
  beq   t0, t1, expected_trap

  la    a0, unexpected_trap_msg
  jal   ra, oracle_puts
2:
  j     2b

expected_trap:
  la    a0, pass_msg
  jal   ra, oracle_puts
3:
  j     3b

.section .rodata
pass_msg:
  .asciz "PASS\n"
fail_msg:
  .asciz "FAIL\n"
unexpected_trap_msg:
  .asciz "UNEXPECTED_TRAP\n"

On OpenC910, ordinary lw prints PASS, while dcache.cva prints FAIL.

How to reproduce

Build OpenC910's native Verilator simulator

cd openc910/smart_run
make compile SIM=verilator THREADS=8
make buildVerilator

Compile and run the failing testcase

/opt/riscv/bin/riscv64-unknown-elf-gcc -c -march=rv64gc_zicsr_zifencei -mabi=lp64d -O2 openc910_min_crt0.S -o openc910_min_crt0.o
/opt/riscv/bin/riscv64-unknown-elf-gcc -c -march=rv64gc_zicsr_zifencei -mabi=lp64d -O2 -DACCESS_KIND=1 -DDELAY_NOPS=1 openc910_pmp_locked_dcache_op_param.S -o openc910_pmp_locked_dcache_op_param.o
/opt/riscv/bin/riscv64-unknown-elf-gcc -nostdlib -nostartfiles -march=rv64gc_zicsr_zifencei -mabi=lp64d -T openc910_min_linker.ld openc910_min_crt0.o openc910_pmp_locked_dcache_op_param.o -o openc910_pmp_locked_dcache_op_param.elf
/opt/riscv/bin/riscv64-unknown-elf-objcopy -O srec openc910_pmp_locked_dcache_op_param.elf openc910_pmp_locked_dcache_op_param_inst.hex -j .text* -j .rodata* -j .eh_frame*
/opt/riscv/bin/riscv64-unknown-elf-objcopy -O srec openc910_pmp_locked_dcache_op_param.elf openc910_pmp_locked_dcache_op_param_data.hex -j .data* -j .bss -j .sbss -j .COMMON
../tests/bin/Srec2vmem openc910_pmp_locked_dcache_op_param_inst.hex inst.pat
../tests/bin/Srec2vmem openc910_pmp_locked_dcache_op_param_data.hex data.pat
./obj_dir/Vtop

Observed output:

  • FAIL

Meaning:

  • PASS = the PMP-denied operation raised an access-fault trap
  • FAIL = the PMP-denied cache operation returned successfully
  • ILLEGAL, SETUP_FAIL, UNEXPECTED_TRAP = diagnostic failures

Test Case: test.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions