Skip to content

Fault the PMP hardware

The previous tutorial skipped the PMP configuration from the instruction bus. Here, LiteInjector targets the PMP hardware itself: a signal inside the CPU that raises the access fault when the software touches a protected area. Resetting this signal at the right time lets the access through without any exception.

This shows how LiteInjector can fault signals of a Verilog IP: the VexRiscv Verilog is instrumented to bring the PMP signal out of the CPU, where the emulator can reach it.

The SoC used in this tutorial: LiteInjector on the PMP signal of the instrumented VexRiscv Secure CPU.

You need: a Digilent Basys3 board, a USB-UART adapter for the UART bridge, and the installation done. The files are in examples/poc_basys3_pmp_hardware.

The example provides a VexRiscv Secure variant that exports the PMP signal, and a LiteX CPU wrapper that declares it. Copy them into your LiteX installation (paths relative to the example folder, for a LiteX installed next to LiteInjector):

Terminal window
$ cd liteinjector/examples/poc_basys3_pmp_hardware
$ cp hardware/VexRiscv_Secure_PoC.v ../../../pythondata-cpu-vexriscv/pythondata_cpu_vexriscv/verilog/
$ cp hardware/core.py ../../../litex/litex/soc/cores/cpu/vexriscv/core.py
Terminal window
$ ./digilent_basys3.py --cpu-variant=secure+poc --csr-csv=csr.csv --integrated-main-ram-size=0x2000 --build --load
$ cd software
$ make Vex
$ litex_term /dev/ttyUSB0 --kernel=PMPTestWrite_VexRiscv.bin

Then use the serialboot command of the BIOS, or reset the board, to boot the program.

The campaign is simple: when the PMP signal is raised, reset it on the same cycle.

  1. Start litex_server on the UART bridge, in its own terminal.

    Terminal window
    $ litex_server --uart --uart-port /dev/ttyUSB1
  2. Arm the emulator, then boot the program.

    Terminal window
    $ liteinjector_cli run --when pmp_output=0x1 --fault bit-reset:pmp_output

The CPU is not interrupted and the program writes to the protected area.