diff --git a/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.csv b/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.csv index aa233dbbfb..5c9e6559a6 100644 --- a/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.csv +++ b/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.csv @@ -58,7 +58,7 @@ CLIC 8675ec,Interrupt CSR,mtvt,"Function ptr reads treated as instruction fetch, Note, instruction fetch is treated as an implicit read, thus do not require PMP read permissions, but execute permission is required. -Both the pointer fetch and the fetch of the actual instruction located at the pointer address should be covered by the above restrictions. ",Assertion Check,"ENV capability, not specific test",Functional Coverage,clic::invalid_mtvt_ptr_exec_mret +Both the pointer fetch and the fetch of the actual instruction located at the pointer address should be covered by the above restrictions. ",Assertion Check,"ENV capability, not specific test",Functional Coverage,"clic::invalid_mtvt_ptr_exec_mret, minhv_pma_block.c" UM v0.3.0 Common,Interrupt CSR,mtvt,"Always aligned to 2^(max(6, 2+SMCLIC_ID_WIDTH)","Assert that mtvt [max(6, 2+SMCLIC_ID_WIDTH)-1:0] = 0",Assertion Check,"ENV capability, not specific test",Functional Coverage,a_mtvt_alignment_correct CLIC 8675ec,Interrupt CSR,mtvt,"Determine alignment by software access, Write ones to lower order bits and read back",Test that correct alignment can be inferred by writing to these fields and read back.,Self Checking Test,Directed Self-Checking,Testcase,clic :: w_mtvt_rd_alignment diff --git a/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.json b/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.json index 3f639822ff..ed0491458a 100644 --- a/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.json +++ b/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.json @@ -338,7 +338,7 @@ "Pass/Fail Criteria": "Assertion Check", "Test Type": "ENV capability, not specific test", "Coverage Method": "Functional Coverage", - "Link to Coverage": "clic::invalid_mtvt_ptr_exec_mret" + "Link to Coverage": "clic::invalid_mtvt_ptr_exec_mret, minhv_pma_block.c" }, { "Requirement Location": "UM v0.3.0 Common", diff --git a/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.xlsx b/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.xlsx index fed058066c..9af84b6604 100644 Binary files a/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.xlsx and b/cv32e40s/docs/VerifPlans/Simulation/interrupts/CV32E40SX_CLIC.xlsx differ diff --git a/cv32e40s/regress/cv32e40s_full.yaml b/cv32e40s/regress/cv32e40s_full.yaml index 4ce0a40bd0..97184ca53b 100644 --- a/cv32e40s/regress/cv32e40s_full.yaml +++ b/cv32e40s/regress/cv32e40s_full.yaml @@ -583,3 +583,9 @@ tests: dir: cv32e40s/sim/uvmt cmd: make test TEST=mhpmcounter_write_test + minhv_pma_block: + description: test minhv=1 and pma block of mepc address + builds: [ uvmt_cv32e40s_pma_2 ] + dir: cv32e40s/sim/uvmt + cmd: make test TEST=minhv_pma_block + diff --git a/cv32e40s/tests/cfg/pma_test_cfg_2.yaml b/cv32e40s/tests/cfg/pma_test_cfg_2.yaml index 0edf69a0db..185269bf16 100644 --- a/cv32e40s/tests/cfg/pma_test_cfg_2.yaml +++ b/cv32e40s/tests/cfg/pma_test_cfg_2.yaml @@ -2,6 +2,7 @@ name: pma_test_cfg_2 description: PMA configuration for the PMA_TEST_CFG_2 test case compile_flags: > +define+PMA_TEST_CFG_2 + +define+CLIC_EN +define+ZBA_ZBB_ZBC_ZBS plusargs: > +enable_pma=1 diff --git a/cv32e40s/tests/programs/custom/minhv_pma_block/minhv_pma_block.c b/cv32e40s/tests/programs/custom/minhv_pma_block/minhv_pma_block.c new file mode 100644 index 0000000000..cafc28a3ff --- /dev/null +++ b/cv32e40s/tests/programs/custom/minhv_pma_block/minhv_pma_block.c @@ -0,0 +1,172 @@ +// +// Copyright 2023 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// Author: Kristine Døsvik +// +// Test minhv=1 and pma block of mepc address. +// +///////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "bsp.h" + +#define RND_ADDRS_IN_PMA_CFG_2_IO_REGION 0xE0100010 + +extern volatile uint32_t recovery_pt_mret; +volatile uint32_t g_entered_trap_handler; +volatile uint32_t g_trapped_mcause; + +int execute_from_io_region(); +__attribute__((interrupt ("machine"))) void u_sw_irq_handler(void); +void trap_handler(void); + + +int main(int argc, char **argv){ + + int is_failure = 0; + + is_failure += execute_from_io_region(); + + if(is_failure){ + return EXIT_FAILURE; + } else { + return EXIT_SUCCESS; + } +} + + +int execute_from_io_region() { + + volatile uint32_t io_addr = RND_ADDRS_IN_PMA_CFG_2_IO_REGION; + volatile uint32_t mcause_excode = 0x0; + volatile uint32_t mcause_excode_expected = EXC_CAUSE_INSTR_ACC_FAULT; //Execution attempt from I/O region. + volatile uint32_t mret_dont_trap = 0; + volatile uint32_t test_fail = 0; + g_entered_trap_handler = 0; + + // Load an IO memory address into mepc + __asm__ volatile ( R"( + csrrw zero, mepc, %[io_addr] + )" :: [io_addr] "r"(io_addr)); + + // Set minhv and mpp = M + __asm__ volatile ( R"( + lui t0, 0x70000 + csrrs zero, mcause, t0 + )"::: "t0"); + + __asm__ volatile ( R"( + mret + )":::); + + // Mret traps. + + // This should never execute (deliberate dead code), as the mret make the pc take a jump + mret_dont_trap += 1; + + // Execution should continue here + __asm__ volatile ( R"( + .global recovery_pt_mret + recovery_pt_mret: add x0, x0, x0 + )":::); + + + mcause_excode = g_trapped_mcause & 0x7ff; + + printf("Mret traps: %08lx, expected: 1\n", g_entered_trap_handler); + printf("Mret dont trap: %08lx, expected: 0\n", mret_dont_trap); + printf("mcause excode: %08lx, expected: %08lx (execution attempt from I/O region).\n", mcause_excode, mcause_excode_expected); + test_fail += (g_entered_trap_handler != 1) || mret_dont_trap || (mcause_excode != mcause_excode_expected); + + printf("g_trapped_mcause: %08lx", g_trapped_mcause); + + return test_fail; +} + + +__attribute__((interrupt ("machine"))) +void u_sw_irq_handler(void) { + __asm__ volatile (R"( + # Backup all GPRs + sw a0, -4(sp) + sw a1, -8(sp) + sw a2, -12(sp) + sw a3, -16(sp) + sw a4, -20(sp) + sw a5, -24(sp) + sw a6, -28(sp) + sw a7, -32(sp) + sw t0, -36(sp) + sw t1, -40(sp) + sw t2, -44(sp) + sw t3, -48(sp) + sw t4, -52(sp) + sw t5, -56(sp) + sw t6, -60(sp) + addi sp, sp, -64 + cm.push {ra, s0-s11}, -64 + + # Call the handler actual + call ra, trap_handler + + # Restore all GPRs + cm.pop {ra, s0-s11}, 64 + addi sp, sp, 64 + lw a0, -4(sp) + lw a1, -8(sp) + lw a2, -12(sp) + lw a3, -16(sp) + lw a4, -20(sp) + lw a5, -24(sp) + lw a6, -28(sp) + lw a7, -32(sp) + lw t0, -36(sp) + lw t1, -40(sp) + lw t2, -44(sp) + lw t3, -48(sp) + lw t4, -52(sp) + lw t5, -56(sp) + lw t6, -60(sp) + + # Restore "sp" + # csrr sp, dscratch0 + + # Done + mret + )"); +} + +void trap_handler(void) { + + g_entered_trap_handler += 1; + + __asm__ volatile ( R"( + # Get recovery mepc and replace mepc + la t0, recovery_pt_mret + csrrw zero, mepc, t0 + + # read and clear mcause except mpp, which is set + 4: lui t0, 0x30000 + csrrw %[g_trapped_mcause], mcause, t0 + + )" : [g_trapped_mcause]"=r"(g_trapped_mcause) :: "t0"); + + return; +} + diff --git a/cv32e40s/tests/programs/custom/minhv_pma_block/test.yaml b/cv32e40s/tests/programs/custom/minhv_pma_block/test.yaml new file mode 100644 index 0000000000..4f43e93d63 --- /dev/null +++ b/cv32e40s/tests/programs/custom/minhv_pma_block/test.yaml @@ -0,0 +1,8 @@ +name: minhv_pma_block +uvm_test: uvmt_$(CV_CORE_LC)_firmware_test_c +description: > + Use CFG=p,a_test_cfg_2. Test minhv=1 and pma block of mepc address +plusargs: > + +clic_irq_clear_on_ack=0 +cflags: > + -mno-relax