From 536142c556ff18ccb55bd560ef2d3dadfa4949da Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Fri, 13 Dec 2024 13:51:30 +0000 Subject: [PATCH] [rtl,pmp] Allow all accesses to Debug Module in debug mode The RISC-V Debug Specification (current release 1.0.0-rc4) in Section A.2 states that the PMP must not disallow accesses to addresses of the Debug Module when the hart is in debug mode, regardless of how the PMP is configured. This commit changes the PMP accordingly. Signed-off-by: Andreas Kurth --- .../rtl/ibex_riscv_compliance.sv | 2 ++ dv/uvm/core_ibex/tb/core_ibex_tb_top.sv | 2 ++ .../simple_system/rtl/ibex_simple_system.sv | 2 ++ rtl/ibex_core.sv | 5 +++++ rtl/ibex_pmp.sv | 17 ++++++++++++++++- rtl/ibex_top.sv | 8 ++++++++ rtl/ibex_top_tracing.sv | 4 ++++ 7 files changed, 39 insertions(+), 1 deletion(-) diff --git a/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv b/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv index 8d3669ef33..10d0bb053d 100644 --- a/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv +++ b/dv/riscv_compliance/rtl/ibex_riscv_compliance.sv @@ -155,6 +155,8 @@ module ibex_riscv_compliance ( .DbgTriggerEn (DbgTriggerEn ), .SecureIbex (SecureIbex ), .ICacheScramble (ICacheScramble ), + .DmBaseAddr (32'h00000000 ), + .DmAddrMask (32'h00000003 ), .DmHaltAddr (32'h00000000 ), .DmExceptionAddr (32'h00000000 ) ) u_top ( diff --git a/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv b/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv index 601509975d..5ca14c0664 100644 --- a/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv +++ b/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv @@ -84,6 +84,8 @@ module core_ibex_tb_top; assign {scramble_key, scramble_nonce} = scrambling_key_if.d_data; ibex_top_tracing #( + .DmBaseAddr (32'h`BOOT_ADDR ), + .DmAddrMask (32'h0000_0007 ), .DmHaltAddr (32'h`BOOT_ADDR + 'h0 ), .DmExceptionAddr (32'h`BOOT_ADDR + 'h4 ), .PMPEnable (PMPEnable ), diff --git a/examples/simple_system/rtl/ibex_simple_system.sv b/examples/simple_system/rtl/ibex_simple_system.sv index ac74691d68..e466ac286d 100644 --- a/examples/simple_system/rtl/ibex_simple_system.sv +++ b/examples/simple_system/rtl/ibex_simple_system.sv @@ -204,6 +204,8 @@ module ibex_simple_system ( .WritebackStage ( WritebackStage ), .BranchPredictor ( BranchPredictor ), .DbgTriggerEn ( DbgTriggerEn ), + .DmBaseAddr ( 32'h00100000 ), + .DmAddrMask ( 32'h00000003 ), .DmHaltAddr ( 32'h00100000 ), .DmExceptionAddr ( 32'h00100000 ) ) u_top ( diff --git a/rtl/ibex_core.sv b/rtl/ibex_core.sv index 807e315133..67ab922466 100644 --- a/rtl/ibex_core.sv +++ b/rtl/ibex_core.sv @@ -44,6 +44,8 @@ module ibex_core import ibex_pkg::*; #( parameter int unsigned RegFileDataWidth = 32, parameter bit MemECC = 1'b0, parameter int unsigned MemDataWidth = MemECC ? 32 + 7 : 32, + parameter int unsigned DmBaseAddr = 32'h1A110000, + parameter int unsigned DmAddrMask = 32'h00000FFF, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808 ) ( @@ -1177,6 +1179,8 @@ module ibex_core import ibex_pkg::*; #( assign pmp_priv_lvl[PMP_D] = priv_mode_lsu; ibex_pmp #( + .DmBaseAddr (DmBaseAddr), + .DmAddrMask (DmAddrMask), .PMPGranularity(PMPGranularity), .PMPNumChan (PMPNumChan), .PMPNumRegions (PMPNumRegions) @@ -1185,6 +1189,7 @@ module ibex_core import ibex_pkg::*; #( .csr_pmp_cfg_i (csr_pmp_cfg), .csr_pmp_addr_i (csr_pmp_addr), .csr_pmp_mseccfg_i(csr_pmp_mseccfg), + .debug_mode_i (debug_mode), .priv_mode_i (pmp_priv_lvl), // Access checking channels .pmp_req_addr_i (pmp_req_addr), diff --git a/rtl/ibex_pmp.sv b/rtl/ibex_pmp.sv index 48c3a7ed67..93b9d889da 100644 --- a/rtl/ibex_pmp.sv +++ b/rtl/ibex_pmp.sv @@ -5,6 +5,8 @@ `include "dv_fcov_macros.svh" module ibex_pmp #( + parameter int unsigned DmBaseAddr = 32'h1A110000, + parameter int unsigned DmAddrMask = 32'h00000FFF, // Granularity of NAPOT access, // 0 = No restriction, 1 = 8 byte, 2 = 16 byte, 3 = 32 byte, etc. parameter int unsigned PMPGranularity = 0, @@ -18,6 +20,8 @@ module ibex_pmp #( input logic [33:0] csr_pmp_addr_i [PMPNumRegions], input ibex_pkg::pmp_mseccfg_t csr_pmp_mseccfg_i, + input logic debug_mode_i, + input ibex_pkg::priv_lvl_e priv_mode_i [PMPNumChan], // Access checking channels input logic [33:0] pmp_req_addr_i [PMPNumChan], @@ -37,6 +41,7 @@ module ibex_pmp #( logic [PMPNumChan-1:0][PMPNumRegions-1:0] region_match_all; logic [PMPNumChan-1:0][PMPNumRegions-1:0] region_basic_perm_check; logic [PMPNumChan-1:0][PMPNumRegions-1:0] region_perm_check; + logic [PMPNumChan-1:0] debug_mode_allowed_access; /////////////////////// // Functions for PMP // @@ -48,6 +53,7 @@ module ibex_pmp #( // | // region_match_all --------------------------------> access_fault_check <---------- // | + // !debug_mode_allowed_access ------------------------------> & // \--> pmp_req_err_o // Compute permissions checks that apply when MSECCFG.MML is set. Added for Smepmp support. @@ -226,6 +232,13 @@ module ibex_pmp #( pmp_req_addr_i[c][PMPGranularity+2-1:0]}; end + // Determine whether the core is in debug mode and the access is to an address in the range of + // the Debug Module. According to Section A.2 of the RISC-V Debug Specification, the PMP must + // not disallow fetches, loads, or stores in the address range associated with the Debug Module + // when the hart is in debug mode. + assign debug_mode_allowed_access[c] = debug_mode_i & + ((pmp_req_addr_i[c] & ~DmAddrMask) == DmBaseAddr); + // Once the permission checks of the regions are done, decide if the access is // denied by figuring out the matching region and its permission check. assign pmp_req_err_o[c] = access_fault_check(csr_pmp_mseccfg_i.mmwp, @@ -233,7 +246,9 @@ module ibex_pmp #( pmp_req_type_i[c], region_match_all[c], priv_mode_i[c], - region_perm_check[c]); + region_perm_check[c]) & + // No error if the access is allowed as Debug Module access. + ~debug_mode_allowed_access[c]; // Access fails check against one region but access allowed due to another higher-priority // region. diff --git a/rtl/ibex_top.sv b/rtl/ibex_top.sv index 8991c17251..06023c4b55 100644 --- a/rtl/ibex_top.sv +++ b/rtl/ibex_top.sv @@ -37,6 +37,8 @@ module ibex_top import ibex_pkg::*; #( parameter int unsigned ICacheScrNumPrinceRoundsHalf = 2, parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, + parameter int unsigned DmBaseAddr = 32'h1A110000, + parameter int unsigned DmAddrMask = 32'h00000FFF, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808, // Default seed and nonce for scrambling @@ -313,6 +315,8 @@ module ibex_top import ibex_pkg::*; #( .RegFileDataWidth (RegFileDataWidth), .MemECC (MemECC), .MemDataWidth (MemDataWidth), + .DmBaseAddr (DmBaseAddr), + .DmAddrMask (DmAddrMask), .DmHaltAddr (DmHaltAddr), .DmExceptionAddr (DmExceptionAddr) ) u_ibex_core ( @@ -1120,6 +1124,10 @@ module ibex_top import ibex_pkg::*; #( assign alert_major_bus_o = core_alert_major_bus | lockstep_alert_major_bus; assign alert_minor_o = core_alert_minor | lockstep_alert_minor; + // Parameter assertions + `ASSERT_INIT(DmHaltAddrInRange_A, (DmHaltAddr & ~DmAddrMask) == DmBaseAddr) + `ASSERT_INIT(DmExceptionAddrInRange_A, (DmExceptionAddr & ~DmAddrMask) == DmBaseAddr) + // X checks for top-level outputs `ASSERT_KNOWN(IbexInstrReqX, instr_req_o) `ASSERT_KNOWN_IF(IbexInstrReqPayloadX, instr_addr_o, instr_req_o) diff --git a/rtl/ibex_top_tracing.sv b/rtl/ibex_top_tracing.sv index 14fcfb2994..b9f8045c06 100644 --- a/rtl/ibex_top_tracing.sv +++ b/rtl/ibex_top_tracing.sv @@ -27,6 +27,8 @@ module ibex_top_tracing import ibex_pkg::*; #( parameter bit ICacheScramble = 1'b0, parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, + parameter int unsigned DmBaseAddr = 32'h1A110000, + parameter int unsigned DmAddrMask = 32'h00000FFF, parameter int unsigned DmHaltAddr = 32'h1A110800, parameter int unsigned DmExceptionAddr = 32'h1A110808 ) ( @@ -184,6 +186,8 @@ module ibex_top_tracing import ibex_pkg::*; #( .ICacheScramble ( ICacheScramble ), .RndCnstLfsrSeed ( RndCnstLfsrSeed ), .RndCnstLfsrPerm ( RndCnstLfsrPerm ), + .DmBaseAddr ( DmBaseAddr ), + .DmAddrMask ( DmAddrMask ), .DmHaltAddr ( DmHaltAddr ), .DmExceptionAddr ( DmExceptionAddr ) ) u_ibex_top (