[RTL PMP] Fix address matching bugs

- Partial matching not relevant for 32bit only accesses
- Apply region size masking correctly
This commit is contained in:
Tom Roberts 2019-10-02 13:03:07 +01:00 committed by Tom Roberts
parent 2aacd2b98b
commit f35db04b7c

View file

@ -27,7 +27,7 @@ module ibex_pmp #(
);
import ibex_pkg::*;
import ibex_pkg::*;
// Access Checking Signals
logic [33:0] region_start_addr [PMPNumRegions];
@ -35,7 +35,6 @@ module ibex_pmp #(
logic [PMPNumChan-1:0][PMPNumRegions-1:0] region_match_high;
logic [PMPNumChan-1:0][PMPNumRegions-1:0] region_match_low;
logic [PMPNumChan-1:0][PMPNumRegions-1:0] region_match_both;
logic [PMPNumChan-1:0][PMPNumRegions-1:0] region_match_partial;
logic [PMPNumChan-1:0][PMPNumRegions-1:0] region_perm_check;
logic [PMPNumChan-1:0][PMPNumRegions-1:0] machine_access_fault;
logic [PMPNumChan-1:0][PMPNumRegions-1:0] user_access_allowed;
@ -80,12 +79,9 @@ module ibex_pmp #(
(region_start_addr[r][33:PMPGranularity+2] &
region_addr_mask[r]));
assign region_match_high[c][r] = (pmp_req_addr_i[c][33:PMPGranularity+2] <=
(csr_pmp_addr_i[r][33:PMPGranularity+2] &
region_addr_mask[r]));
csr_pmp_addr_i[r][33:PMPGranularity+2]);
assign region_match_both[c][r] = region_match_low[c][r] & region_match_high[c][r] &
(csr_pmp_cfg_i[r].mode != PMP_MODE_OFF);
assign region_match_partial[c][r] = (region_match_low[c][r] ^ region_match_high[c][r]) &
(csr_pmp_cfg_i[r].mode != PMP_MODE_OFF);
// Check specific required permissions
assign region_perm_check[c][r] =
((pmp_req_type_i[c] == PMP_ACC_EXEC) & csr_pmp_cfg_i[r].exec) |
@ -94,14 +90,8 @@ module ibex_pmp #(
// In machine mode, any match to a locked region without sufficient permissions is a fault
assign machine_access_fault[c][r] = region_match_both[c][r] & csr_pmp_cfg_i[r].lock &
~region_perm_check[c][r];
if (r == 0) begin : g_region0
// In any other mode, any access should fault unless is matches a region
assign user_access_allowed[c][r] = region_match_both[c][r] & region_perm_check[c][r];
end else begin : g_oth_regions
assign user_access_allowed[c][r] = region_match_both[c][r] & region_perm_check[c][r] &
// any higher priority (lower region number) partial match should also cause a fault
~|region_match_partial[c][r-1:0];
end
// In any other mode, any access should fault unless is matches a region
assign user_access_allowed[c][r] = region_match_both[c][r] & region_perm_check[c][r];
end
assign access_fault[c] = (priv_mode_i[c] == PRIV_LVL_M) ? |machine_access_fault[c] :
~|user_access_allowed[c];