Skip to content

Commit

Permalink
Merge pull request #363 from stnolting/pmp_locking
Browse files Browse the repository at this point in the history
Fix PMP locking
  • Loading branch information
stnolting authored Jul 11, 2022
2 parents 31af2f9 + 339fba0 commit 50f1cbc
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 35 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ mimpid = 0x01040312 => 01.04.03.12 => Version 01.04.03.12 => v1.4.3.12


| Date (*dd.mm.yyyy*) | Version | Comment |
|:----------:|:-------:|:--------|
|:-------------------:|:-------:|:--------|
| 11.07.2022 | 1.7.3.8 | **physical memory protection(PMP)**: locking entry `i` in TOR mode will now also prevent write access to `pmpaddr(i-1)` (RISC-V compatibility); [#363](https://github.com/stnolting/neorv32/pull/363) |
| 09.07.2022 | 1.7.3.7 | :bug: fixed **bootloader's** byte order when using the flash for application storage: :warning: was BIG-endian, is now also LITTLE-endian; [#362](https://github.com/stnolting/neorv32/pull/362) |
| 08.07.2022 | 1.7.3.6 | :test_tube: added burst mode option to **XIP module** to accelerate consecutive flash read accesses; :warning: fixed XIP endianness: was BIG-endian and is now LITTLE-endian; [#361](https://github.com/stnolting/neorv32/pull/361) |
| 08.07.2022 | 1.7.3.5 | Update "raw" executable generation options of makefile and image generator; [#360](https://github.com/stnolting/neorv32/pull/360) |
Expand Down
15 changes: 5 additions & 10 deletions docs/datasheet/cpu.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,18 @@ has been moved to a separate repository: https://github.com/stnolting/neorv32-ve
:sectnums:
==== RISC-V Incompatibility Issues and Limitations

This list shows the currently identified issues regarding full RISC-V-compatibility. Note that most
of the cases listed below are "special cases" that should not occur in "normal" programs. However,
some of these incompatibilities can be circumvented using software emulation (for example for
handling unaligned memory accesses).
This list shows the currently identified issues regarding full RISC-V-compatibility.

.Read-Only "Read-Write" CSRs
[IMPORTANT]
The NEORV32 <<_misa>> and <<_mtval>> CSRs are _read-only_ - the RISC-V specs. declare
these registers as _read/write_. Any machine-mode write access to them is ignored and will _not_
The NEORV32 <<_misa>> and <<_mtval>> CSRs are _read-only_ - the RISC-V specs. declares
these registers to be _read/write_. Any machine-mode write access to them is ignored and will _not_
cause any exceptions or side-effects to maintain RISC-V compatibility.

.Physical Memory Protection
.Physical Memory Protection (PMP)
[IMPORTANT]
The RISC-V-compatible NEORV32 <<_machine_physical_memory_protection_csrs>> only implements the **TOR**
(top of region) mode and only up to 16 PMP regions. Furthermore, the <<_pmpcfg>>'s _lock bits_ only lock
the according PMP entry and not the entries below. All region rules are checked in parallel **without**
prioritization so for identical memory regions the most restrictive PMP rule will be enforced.
(top of region) mode and only up to 16 PMP regions.

.No Hardware Support of Misaligned Memory Accesses
[WARNING]
Expand Down
3 changes: 2 additions & 1 deletion docs/datasheet/cpu_csr.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,8 @@ as the MSB is hardwired to zero
|=======================

[WARNING]
Setting the lock bit `L` **only locks the according PMP entry** and not the PMP entries below!
Setting the lock bit `L` and setting TOR mode in `pmpcfg(i)` will also lock write access to `pmpaddr(i-1)`.
See the RISC-V specs. for more information.


:sectnums!:
Expand Down
51 changes: 29 additions & 22 deletions rtl/core/neorv32_cpu_control.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -1872,30 +1872,37 @@ begin

-- physical memory protection --
-- --------------------------------------------------------------------
-- R/W: pmpcfg* - PMP configuration registers --
if (csr.addr(11 downto 2) = csr_class_pmpcfg_c) then -- pmp configuration CSR class
for i in 0 to PMP_NUM_REGIONS-1 loop
if (csr.addr(1 downto 0) = std_ulogic_vector(to_unsigned(i/4, 2))) then
if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg entry
csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R - read
csr.pmpcfg(i)(1) <= csr.wdata((i mod 4)*8+1); -- W - write
csr.pmpcfg(i)(2) <= csr.wdata((i mod 4)*8+2); -- X - execute
csr.pmpcfg(i)(3) <= csr.wdata((i mod 4)*8+3); -- A_L - mode low [TOR-mode only!]
csr.pmpcfg(i)(4) <= '0'; -- A_H - mode high [TOR-mode only!]
csr.pmpcfg(i)(5) <= '0'; -- reserved
csr.pmpcfg(i)(6) <= '0'; -- reserved
csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / also enforce in machine-mode)
if (PMP_NUM_REGIONS > 0) then
-- R/W: pmpcfg* - PMP configuration registers --
if (csr.addr(11 downto 2) = csr_class_pmpcfg_c) then -- pmp configuration CSR class
for i in 0 to PMP_NUM_REGIONS-1 loop
if (csr.addr(1 downto 0) = std_ulogic_vector(to_unsigned(i/4, 2))) then
if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg entry
csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R - read
csr.pmpcfg(i)(1) <= csr.wdata((i mod 4)*8+1); -- W - write
csr.pmpcfg(i)(2) <= csr.wdata((i mod 4)*8+2); -- X - execute
csr.pmpcfg(i)(3) <= csr.wdata((i mod 4)*8+3); -- A_L - mode low [TOR-mode only!]
csr.pmpcfg(i)(4) <= '0'; -- A_H - mode high [TOR-mode only!]
csr.pmpcfg(i)(5) <= '0'; -- reserved
csr.pmpcfg(i)(6) <= '0'; -- reserved
csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / also enforce in machine-mode)
end if;
end if;
end loop; -- i (pmpcfg entry)
end if;
-- R/W: pmpaddr* - PMP address registers --
if (csr.addr(11 downto 4) = csr_class_pmpaddr_c) then
for i in 0 to PMP_NUM_REGIONS-2 loop
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) and (csr.pmpcfg(i)(7) = '0') and -- unlocked access
((csr.pmpcfg(i+1)(7) = '0') or (csr.pmpcfg(i+1)(3) = '0')) then -- pmpcfg(i+1) not "LOCKED TOR" [TOR-mode only!]
csr.pmpaddr(i) <= csr.wdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2);
end if;
end loop; -- i (PMP regions)
-- very last entry --
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(PMP_NUM_REGIONS-1, 4))) and (csr.pmpcfg(PMP_NUM_REGIONS-1)(7) = '0') then -- unlocked access
csr.pmpaddr(PMP_NUM_REGIONS-1) <= csr.wdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2);
end if;
end loop; -- i (pmpcfg entry)
end if;
-- R/W: pmpaddr* - PMP address registers --
if (csr.addr(11 downto 4) = csr_class_pmpaddr_c) then
for i in 0 to PMP_NUM_REGIONS-1 loop
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
csr.pmpaddr(i) <= csr.wdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2);
end if;
end loop; -- i (PMP regions)
end if;
end if;

-- machine counter setup --
Expand Down
2 changes: 1 addition & 1 deletion rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ package neorv32_package is
-- Architecture Constants (do not modify!) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- native data path width - do not change!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01070307"; -- NEORV32 version - no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01070308"; -- NEORV32 version - no touchy!
constant archid_c : natural := 19; -- official RISC-V architecture ID - hands off!

-- Check if we're inside the Matrix -------------------------------------------------------
Expand Down

0 comments on commit 50f1cbc

Please sign in to comment.