diff --git a/pipelined/testbench/tests.vh b/pipelined/testbench/tests.vh index 218a2602..1b5bb573 100644 --- a/pipelined/testbench/tests.vh +++ b/pipelined/testbench/tests.vh @@ -1548,9 +1548,9 @@ string wally32i[] = '{ string wally32priv[] = '{ `WALLYTEST, - "rv32i_m/privilege/WALLY-MMU-SV32", "3080", - "rv32i_m/privilege/WALLY-PMP", "3080", - "rv32i_m/privilege/WALLY-PMA", "3080" + "rv32i_m/privilege/WALLY-MMU-SV32", "4080", + "rv32i_m/privilege/WALLY-PMP", "4080", + "rv32i_m/privilege/WALLY-PMA", "4080" }; string wally32periph[] = '{ diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-MMU-SV32.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-MMU-SV32.S index 91681f81..69ba260b 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-MMU-SV32.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-MMU-SV32.S @@ -22,9 +22,18 @@ /////////////////////////////////////////// #include "WALLY-TEST-LIB-32.h" -// Test library includes and handler for each type of test, a trap handler, imperas compliance instructions -// Ideally this should mean that a test can be written by simply adding .8byte statements as below. +INIT_TESTS + +s_file_begin: +j test_loop_setup // begin test loop/table tests instead of executing inline code. + +INIT_TEST_TABLE + +TEST_STACK_AND_DATA + +.align 2 +test_cases: # --------------------------------------------------------------------------------------------- # Test Contents # diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-PMA.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-PMA.S index 80d6d504..475a6dd8 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-PMA.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-PMA.S @@ -35,9 +35,18 @@ #define PLIC_RANGE 0x03FFFFFF #include "WALLY-TEST-LIB-32.h" -// Test library includes and handler for each type of test, a trap handler, imperas compliance instructions -// Ideally this should mean that a test can be written by simply adding .4byte statements as below. +INIT_TESTS + +s_file_begin: +j test_loop_setup // begin test loop/table tests instead of executing inline code. + +INIT_TEST_TABLE + +TEST_STACK_AND_DATA + +.align 2 +test_cases: # --------------------------------------------------------------------------------------------- # Test Contents # diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-PMP.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-PMP.S index 887bfd97..d1d02cf2 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-PMP.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-PMP.S @@ -22,9 +22,18 @@ /////////////////////////////////////////// #include "WALLY-TEST-LIB-32.h" -// Test library includes and handler for each type of test, a trap handler, imperas compliance instructions -// Ideally this should mean that a test can be written by simply adding .4byte statements as below. +INIT_TESTS + +s_file_begin: +j test_loop_setup // begin test loop/table tests instead of executing inline code. + +INIT_TEST_TABLE + +TEST_STACK_AND_DATA + +.align 2 +test_cases: # --------------------------------------------------------------------------------------------- # Test Contents # @@ -45,22 +54,22 @@ # Test 12.3.2.2.1 Config: Write known values and set PMP config according to table 12.4 in the *** riscv book, copied below # write pmpaddr regs - # | Reg | pmpaddr | pmpcfg | L | A | X | W | R | Comments | -.4byte 0x0, 0x0FFFFFFF, write_pmpaddr_0 # | 0 | 0x0FFFFFFF | 1F | 0 | NAPOT | 0 | 1 | 1 | I/O 00000000-7FFFFFFF RW | -.4byte 0x1, 0x20040000, write_pmpaddr_0 # | 1 | 0x20040000 | 00 | 0 | OFF | 0 | 0 | 0 | | -.4byte 0x2, 0x2004003F, write_pmpaddr_0 # | 2 | 0x2004003F | 09 | 0 | TOR | 0 | 0 | 1 | 80100000-801000FF R | -.4byte 0x3, 0x20040080, write_pmpaddr_0 # | 3 | 0x20040080 | 00 | 0 | OFF | 0 | 0 | 0 | | -.4byte 0x4, 0x20040084, write_pmpaddr_0 # | 4 | 0x20040084 | 0C | 0 | TOR | 1 | 0 | 0 | 80100200-80100210 X | -.4byte 0x5, 0x200400C0, write_pmpaddr_0 # | 5 | 0x200400C0 | 90 | 1 | NA4 | 0 | 0 | 0 | 80100300-80100303 locked out | -.4byte 0x6, 0x2004013F, write_pmpaddr_0 # | 6 | 0x2004013F | 18 | 0 | NAPOT | 0 | 0 | 0 | 80100400-801004FF no access | + # | Reg | pmpaddr | pmpcfg | L | A | X | W | R | Comments | +.4byte 0x0, 0x0FFFFFFF, write_pmpaddr_0 # | 0 | 0x0FFFFFFF | 1F | 0 | NAPOT | 0 | 1 | 1 | I/O 00000000-7FFFFFFF RW | +.4byte 0x1, 0x20040000, write_pmpaddr_1 # | 1 | 0x20040000 | 00 | 0 | OFF | 0 | 0 | 0 | | +.4byte 0x2, 0x2004003F, write_pmpaddr_2 # | 2 | 0x2004003F | 09 | 0 | TOR | 0 | 0 | 1 | 80100000-801000FF R | +.4byte 0x3, 0x20040080, write_pmpaddr_3 # | 3 | 0x20040080 | 00 | 0 | OFF | 0 | 0 | 0 | | +.4byte 0x4, 0x20040084, write_pmpaddr_4 # | 4 | 0x20040084 | 0C | 0 | TOR | 1 | 0 | 0 | 80100200-80100210 X | +.4byte 0x5, 0x200400C0, write_pmpaddr_5 # | 5 | 0x200400C0 | 90 | 1 | NA4 | 0 | 0 | 0 | 80100300-80100303 locked out | +.4byte 0x6, 0x2004013F, write_pmpaddr_6 # | 6 | 0x2004013F | 18 | 0 | NAPOT | 0 | 0 | 0 | 80100400-801004FF no access | # Pmpaddr 7-14 are all zeroed out in this test, so they don't need writes. -.4byte 0xF, 0x2FFFFFFF, write_pmpaddr_0 # | 15 | 0x2FFFFFFF | 1F | 0 | NAPOT | 1 | 1 | 1 | Main mem 80000000-FFFFFFFF RWX| +.4byte 0xF, 0x2FFFFFFF, write_pmpaddr_15 # | 15 | 0x2FFFFFFF | 1F | 0 | NAPOT | 1 | 1 | 1 | Main mem 80000000-FFFFFFFF RWX| # write pmpcfg regs with the information in the table above. this should also write the value of these registers to the output. .4byte 0x0, 0x0009001F, write_pmpcfg_0 # write pmpcfg0, output 0x0009001F -.4byte 0x1, 0x0018900C, write_pmpcfg_0 # write pmpcfg1, output 0x0018900C +.4byte 0x1, 0x0018900C, write_pmpcfg_1 # write pmpcfg1, output 0x0018900C # pmpcfg2 is zeroed out, so it doesn't need a write -.4byte 0x3, 0x1F000000, write_pmpcfg_0 # write pmpcfg3, output 0x1F000000 +.4byte 0x3, 0x1F000000, write_pmpcfg_3 # write pmpcfg3, output 0x1F000000 # write known values to memory where W=0. This should be possible since we're in machine mode. .4byte 0x80100010, 0x600DAA, write32_test # write to pmpaddr 1-2 range @@ -74,9 +83,9 @@ # attempt to write to pmpaddr5 and pmp5cfg after lockout -.4byte 0x1, 0x0018FF0C, write_pmpcfg_0 # attempt to edit only pmp5cfg (pmpcfg1[8:15]) after lockout. +.4byte 0x1, 0x0018FF0C, write_pmpcfg_1 # attempt to edit only pmp5cfg (pmpcfg1[8:15]) after lockout. # instruction ignored, output is 0x0018900C, NOT 0x0018FF0C -.4byte 0x5, 0xFFFFFFFF, write_pmpaddr_0 # attempt to edit pmpaddr5 after lockout. +.4byte 0x5, 0xFFFFFFFF, write_pmpaddr_5 # attempt to edit pmpaddr5 after lockout. # instruction ignored, output is 0x200400C0, NOT 0xFFFFFFFF # Test 12.3.2.2.2 Machine mode access diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-TEST-LIB-32.h b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-TEST-LIB-32.h index 31bd1194..b96ee15a 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-TEST-LIB-32.h +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-TEST-LIB-32.h @@ -4,7 +4,7 @@ // // Author: Kip Macsai-Goren // -// Created 2021-07-20 +// Created 2021-07-19 // // Copyright (C) 2021 Harvey Mudd College & Oklahoma State University // @@ -23,6 +23,9 @@ #include "model_test.h" #include "arch_test.h" + +.macro INIT_TESTS + RVTEST_ISA("RV32I") .section .text.init @@ -31,7 +34,7 @@ rvtest_entry_point: RVMODEL_BOOT RVTEST_CODE_BEGIN - // --------------------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------------- // Initialization Overview: // // Initialize x6 as a virtual pointer to the test results @@ -56,9 +59,9 @@ RVTEST_CODE_BEGIN li a1, 0 li a2, 0 // reset trap handler inputs to zero - // go to first test! - j test_setup - + // go to beginning of S file where we can decide between using the test data loop + // or using the macro inline code insertion + j s_file_begin // --------------------------------------------------------------------------------------------- // General traps Handler @@ -225,12 +228,16 @@ ecallhandler_changetousermode: j trapreturn instrfault: - lw x1, -4(sp) // load return address int x1 (the address after the jal into faulting page) + lw x1, -4(sp) // load return address int x1 (the address AFTER the jal into faulting page) j trapreturn_finished // puts x1 into mepc, restores stack and returns to program (outside of faulting page) +illegalinstr: + j trapreturn // return to the code after recording the mcause + accessfault: // *** What do I have to do here? j trapreturn + // Table of trap behavior // lists what to do on each exception (not interrupts) // unexpected exceptions should cause segfaults for easy detection @@ -239,13 +246,13 @@ accessfault: .align 2 // aligns this data table to an 4 byte boundary trap_handler_vector_table: .4byte segfault // 0: instruction address misaligned - .4byte instrfault // 1: instruction access fault - .4byte segfault // 2: illegal instruction + .4byte instrfault // 1: instruction access fault + .4byte illegalinstr // 2: illegal instruction .4byte segfault // 3: breakpoint .4byte segfault // 4: load address misaligned - .4byte accessfault // 5: load access fault + .4byte accessfault // 5: load access fault .4byte segfault // 6: store address misaligned - .4byte accessfault // 7: store access fault + .4byte accessfault // 7: store access fault .4byte ecallhandler // 8: ecall from U-mode .4byte ecallhandler // 9: ecall from S-mode .4byte segfault // 10: reserved @@ -260,6 +267,220 @@ trap_return_pagetype_table: .4byte 0xC // 0: kilopage has 12 offset bits .4byte 0x16 // 1: megapage has 22 offset bits +.endm + +// Test Summary table! + +// Test Name : Description : Fault output value : Normal output values +// ---------------------:-------------------------------------------:-------------------------------------------:------------------------------------------------------ +// write64_test : Write 64 bits to address : 0x6, 0x7, or 0xf : None +// write32_test : Write 32 bits to address : 0x6, 0x7, or 0xf : None +// write16_test : Write 16 bits to address : 0x6, 0x7, or 0xf : None +// write08_test : Write 8 bits to address : 0x6, 0x7, or 0xf : None +// read64_test : Read 64 bits from address : 0x4, 0x5, or 0xd, then 0xbad : readvalue in hex +// read32_test : Read 32 bitsfrom address : 0x4, 0x5, or 0xd, then 0xbad : readvalue in hex +// read16_test : Read 16 bitsfrom address : 0x4, 0x5, or 0xd, then 0xbad : readvalue in hex +// read08_test : Read 8 bitsfrom address : 0x4, 0x5, or 0xd, then 0xbad : readvalue in hex +// executable_test : test executable on virtual page : 0x0, 0x1, or 0xc, then 0xbad : value of x7 modified by exectuion code (usually 0x111) +// terminate_test : terminate tests : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 +// goto_baremetal : satp.MODE = bare metal : None : None +// goto_sv32 : satp.MODE = sv32 : None : None +// goto_m_mode : go to mahcine mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 +// goto_s_mode : go to supervisor mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 +// goto_u_mode : go to user mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 +// write_read_csr : write to specified CSR : old CSR value, 0x2, depending on perms : value written to CSR +// csr_r_access : test read-only permissions on CSR : 0xbad : 0x2, then 0x11 + +// *** TESTS TO ADD: execute inline, read unknown value out, read CSR unknown value, just read CSR value + +.macro WRITE32 ADDR VAL + // attempt to write VAL to ADDR + // Success outputs: + // None + // Fault outputs: + // 0x6: misaligned address + // 0x7: access fault + // 0xf: page fault + li x29, \VAL + li x30, \ADDR + sw x29, 0(x30) +.endm + +.macro WRITE16 ADDR VAL + // all write tests have the same description/outputs as write64 + li x29, \VAL + li x30, \ADDR + sh x29, 0(x30) +.endm + +.macro WRITE08 ADDR VAL + // all write tests have the same description/outputs as write64 + li x29, \VAL + li x30, \ADDR + sb x29, 0(x30) +.endm + +.macro READ32 ADDR + // Attempt read at ADDR. Write the value read out to the output *** Consider adding specific test for reading a non known value + // Success outputs: + // value read out from ADDR + // Fault outputs: + // One of the following followed by 0xBAD + // 0x4: misaligned address + // 0x5: access fault + // 0xD: page fault + li x7, 0xBAD // bad value that will be overwritten on good reads. + li x29, \ADDR + lw x7, 0(x29) + sw x7, 0(x6) + addi x6, x6, 4 + addi x16, x16, 4 +.endm + +.macro READ16 ADDR + // All reads have the same description/outputs as read32. + // They will store the sign extended value of what was read out at ADDR + li x7, 0xBAD // bad value that will be overwritten on good reads. + li x29, \ADDR + lh x7, 0(x29) + sw x7, 0(x6) + addi x6, x6, 4 + addi x16, x16, 4 +.endm + +.macro READ08 ADDR + // All reads have the same description/outputs as read64. + // They will store the sign extended value of what was read out at ADDR + li x7, 0xBAD // bad value that will be overwritten on good reads. + li x29, \ADDR + lb x7, 0(x29) + sw x7, 0(x6) + addi x6, x6, 4 + addi x16, x16, 4 +.endm + +// These goto_x_mode tests all involve invoking the trap handler, +// So their outputs are inevitably: +// 0x8: test called from U mode +// 0x9: test called from S mode +// 0xB: test called from M mode +// they generally do not fault or cause issues as long as these modes are enabled +// *** add functionality to check if modes are enabled before jumping? maybe cause a fault if not? + +.macro GOTO_M_MODE RETURN_VPN RETURN_PAGETYPE + li a0, 2 // determine trap handler behavior (go to machine mode) + li a1, \RETURN_VPN // return VPN + li a2, \RETURN_PAGETYPE // return page types + ecall // writes mcause to the output. + // now in S mode +.endm + +.macro GOTO_S_MODE RETURN_VPN RETURN_PAGETYPE + li a0, 3 // determine trap handler behavior (go to supervisor mode) + li a1, \RETURN_VPN // return VPN + li a2, \RETURN_PAGETYPE // return page types + ecall // writes mcause to the output. + // now in S mode +.endm + +.macro GOTO_U_MODE RETURN_VPN RETURN_PAGETYPE + li a0, 4 // determine trap handler behavior (go to user mode) + li a1, \RETURN_VPN // return VPN + li a2, \RETURN_PAGETYPE // return page types + ecall // writes mcause to the output. + // now in S mode +.endm + +// These tests change virtual memory settings, turning it on/off and changing between types. +// They don't have outputs as any error with turning on virtual memory should reveal itself in the tests *** Consider changing this policy? + +.macro GOTO_BAREMETAL + // Turn translation off + li x7, 0 // satp.MODE value for bare metal (0) + slli x7, x7, 31 + li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field. *** add option for different pagetable location + add x7, x7, x28 + csrw satp, x7 + sfence.vma x0, x0 // *** flushes global pte's as well +.endm + +.macro GOTO_SV32 + // Turn on sv39 virtual memory + li x7, 1 // satp.MODE value for Sv32 (1) + slli x7, x7, 31 + li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field. *** add option for different pagetable location + add x7, x7, x28 + csrw satp, x7 + sfence.vma x0, x0 // *** flushes global pte's as well +.endm + +.macro WRITE_READ_CSR CSR VAL + // attempt to write CSR with VAL. Note: this also tests read access to CSR + // Success outputs: + // value read back out from CSR after writing + // Fault outputs: + // The previous CSR value before write attempt + // *** Most likely 0x2, the mcause for illegal instruction if we don't have write or read access + li x30, 0xbad // load bad value to be overwritten by csrr + li x29, \VAL + csrw \CSR\(), x29 + csrr x30, \CSR + sw x30, 0(x6) + addi x6, x6, 4 + addi x16, x16, 4 +.endm + +.macro CSR_R_ACCESS CSR + // verify that a csr is accessible to read but not to write + // Success outputs: + // 0x2, then + // 0x11 *** consider changing to something more meaningful + // Fault outputs: + // 0xBAD *** consider changing this one as well. in general, do we need the branching if it hould cause an illegal instruction fault? + csrr x29, \CSR + csrwi \CSR\(), 0xA // Attempt to write a 'random' value to the CSR + csrr x30, \CSR + bne x30, x29, 1f // 1f represents write_access + li x30, 0x11 // Write failed, confirming read only permissions. + j 2f // j r_access_end +1: // w_access (write succeeded, violating read-only) + li x30, 0xBAD +2: // r_access end + sw x30, 0(x6) + addi x6, x6, 4 + addi x16, x16, 4 +.endm + +.macro EXECUTE_AT_ADDRESS ADDR + // Execute the code already written to ADDR, returning the value in x7. + // *** Note: this test itself doesn't write the code to ADDR because it might be callled at a point where we dont have write access to ADDR + // Assumes the code modifies x7, usually to become 0x111. + // Sample code: 0x11100393 (li x7, 0x111), 0x00008067 (ret) + // Success outputs: + // modified value of x7. (0x111 if you use the sample code) + // Fault outputs: + // One of the following followed by 0xBAD + // 0x0: misaligned address + // 0x1: access fault + // 0xC: page fault + fence.i // forces caches and main memory to sync so execution code written to ADDR can run. + li x7, 0xBAD + li x28, \ADDR + jalr x28 // jump to executable test code + sw x7, 0(x6) + addi x6, x6, 4 + addi x16, x16, 4 +.endm + +.macro END_TESTS + // invokes one final ecall to return to machine mode then terminates this program, so the output is + // 0x8: termination called from U mode + // 0x9: termination called from S mode + // 0xB: termination called from M mode + j terminate_test + +.endm + // --------------------------------------------------------------------------------------------- // Test Handler // @@ -269,17 +490,18 @@ trap_return_pagetype_table: // Input parameters: // // x28: - // Address input for the test taking place (think address to read/write, new address to return to, etc...) + // Address input for the test taking place (think: address to read/write, new address to return to, etc...) // // x29: - // Value input for the test taking place (think value to write, any other extra info needed) + // Value input for the test taking place (think: value to write, any other extra info needed) // // x30: - // Test type input that determines which kind of test will take place. Encoding for this input is in the table/case statements below - // + // Label for the location of the test that's about to take place // ------------------------------------------------------------------------------------------------------------------------------------ -test_setup: +.macro INIT_TEST_TABLE // *** Consider renaming this test. to what??? + +test_loop_setup: la x5, test_cases test_loop: @@ -298,25 +520,25 @@ test_loop: jr x30 -// Test Name : Description : Fault output value : Normal output values -// ----------------------:---------------------------------------:------------------------:------------------------------------------------------ -// write32_test : Write 32 bits to address : 0xf : None -// write16_test : Write 16 bits to address : 0xf : None -// write08_test : Write 8 bits to address : 0xf : None -// read32_test : Read 32 bits from address : 0xd, 0xbad : readvalue in hex -// read16_test : Read 16 bits from address : 0xd, 0xbad : readvalue in hex -// read08_test : Read 8 bits from address : 0xd, 0xbad : readvalue in hex -// executable_test : test executable at address : 0xc, 0xbad : leading 12 bits of the li instr written to address. In general this is 0x111. (be sure to also write a return instruction) -// terminate_test : terminate tests : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 -// goto_baremetal : satp.MODE = bare metal : None : None -// goto_sv32 : satp.MODE = sv32 : None : None -// write_mxr_sum : write sstatus.[19:18] = MXR, SUM bits : None : None -// goto_m_mode : go to mahcine mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 -// goto_s_mode : go to supervisor mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 -// goto_u_mode : go to user mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 -// write_pmpcfg_x : Write one of the pmpcfg csr's : mstatuses?, 0xD : readback of pmpcfg value -// write_pmpaddr_x : Write one of the pmpaddr csr's : None : readback of pmpaddr value - +// Test Name : Description : Fault output value : Normal output values +// ----------------------:-------------------------------------------:------------------------:------------------------------------------------------ +// write32_test : Write 32 bits to address : 0xf : None +// write16_test : Write 16 bits to address : 0xf : None +// write08_test : Write 8 bits to address : 0xf : None +// read32_test : Read 32 bits from address : 0xd, 0xbad : readvalue in hex +// read16_test : Read 16 bits from address : 0xd, 0xbad : readvalue in hex +// read08_test : Read 8 bits from address : 0xd, 0xbad : readvalue in hex +// executable_test : test executable on virtual page : 0xc, 0xbad : value of x7 modified by exectuion code (usually 0x111) +// terminate_test : terminate tests : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 +// goto_baremetal : satp.MODE = bare metal : None : None +// goto_sv39 : satp.MODE = sv39 : None : None +// goto_sv48 : satp.MODE = sv48 : None : None +// write_mxr_sum : write sstatus.[19:18] = MXR, SUM bits : None : None +// goto_m_mode : go to mahcine mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 +// goto_s_mode : go to supervisor mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 +// goto_u_mode : go to user mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8 +// write_pmpcfg_x : Write one of the pmpcfg csr's : mstatuses?, 0xD : readback of pmpcfg value +// write_pmpaddr_x : Write one of the pmpaddr csr's : None : readback of pmpaddr value write32_test: // address to write in x28, word value in x29 @@ -360,9 +582,9 @@ read08_test: addi x16, x16, 4 j test_loop // go to next test case - goto_s_mode: - li a0, 3 // Trap handler behavior (go to machine mode) + // return to address in x28, + li a0, 3 // Trap handler behavior (go to supervisor mode) mv a1, x28 // return VPN mv a2, x29 // return page types ecall // writes mcause to the output. @@ -385,21 +607,11 @@ goto_u_mode: goto_baremetal: // Turn translation off - li x7, 0 // satp.MODE value for bare metal (0) - slli x7, x7, 31 - li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field. - add x7, x7, x28 - csrw satp, x7 - sfence.vma x0, x0 // *** flushes global pte's as well. Be careful + GOTO_BAREMETAL j test_loop // go to next test case goto_sv32: - li x7, 1 // satp.MODE value for Sv39 (1) - slli x7, x7, 31 - li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field. - add x7, x7, x28 - csrw satp, x7 - sfence.vma x0, x0 // *** flushes global pte's as well. Be careful + GOTO_SV32 j test_loop // go to next test case write_mxr_sum: @@ -415,25 +627,26 @@ write_mxr_sum: write_pmpcfg_0: // writes the value in x29 to the pmpcfg register specified in x28. - li x7, 0x0 - bne x7, x28, write_pmpcfg_1 + // then writes the final value of pmpcfgX to the output. csrw pmpcfg0, x29 csrr x30, pmpcfg0 + j write_pmpcfg_end + write_pmpcfg_1: - li x7, 0x1 - bne x7, x28, write_pmpcfg_2 csrw pmpcfg1, x29 - csrr x30, pmpcfg1 + csrr x30, pmpcfg1 + j write_pmpcfg_end + write_pmpcfg_2: - li x7, 0x2 - bne x7, x28, write_pmpcfg_3 csrw pmpcfg2, x29 csrr x30, pmpcfg2 + j write_pmpcfg_end + write_pmpcfg_3: - li x7, 0x3 - bne x7, x28, write_pmpcfg_end csrw pmpcfg3, x29 csrr x30, pmpcfg3 + j write_pmpcfg_end + write_pmpcfg_end: sw x30, 0(x6) addi x6, x6, 4 @@ -441,103 +654,88 @@ write_pmpcfg_end: j test_loop write_pmpaddr_0: + // write_read_csr pmpaddr0, x29 // writes the value in x29 to the pmpaddr register specified in x28. // then writes the final value of pmpaddrX to the output. - li x7, 0x0 - bne x7, x28, write_pmpaddr_1 csrw pmpaddr0, x29 csrr x30, pmpaddr0 j write_pmpaddr_end + write_pmpaddr_1: - li x7, 0x1 - bne x7, x28, write_pmpaddr_2 csrw pmpaddr1, x29 csrr x30, pmpaddr1 j write_pmpaddr_end + write_pmpaddr_2: - li x7, 0x2 - bne x7, x28, write_pmpaddr_3 csrw pmpaddr2, x29 csrr x30, pmpaddr2 j write_pmpaddr_end + write_pmpaddr_3: - li x7, 0x3 - bne x7, x28, write_pmpaddr_4 csrw pmpaddr3, x29 csrr x30, pmpaddr3 j write_pmpaddr_end + write_pmpaddr_4: - li x7, 0x4 - bne x7, x28, write_pmpaddr_5 csrw pmpaddr4, x29 csrr x30, pmpaddr4 j write_pmpaddr_end + write_pmpaddr_5: - li x7, 0x5 - bne x7, x28, write_pmpaddr_6 csrw pmpaddr5, x29 csrr x30, pmpaddr5 j write_pmpaddr_end + write_pmpaddr_6: - li x7, 0x6 - bne x7, x28, write_pmpaddr_7 csrw pmpaddr6, x29 csrr x30, pmpaddr6 j write_pmpaddr_end + write_pmpaddr_7: - li x7, 0x7 - bne x7, x28, write_pmpaddr_8 csrw pmpaddr7, x29 csrr x30, pmpaddr7 j write_pmpaddr_end + write_pmpaddr_8: - li x7, 0x8 - bne x7, x28, write_pmpaddr_9 csrw pmpaddr8, x29 csrr x30, pmpaddr8 j write_pmpaddr_end + write_pmpaddr_9: - li x7, 0x9 - bne x7, x28, write_pmpaddr_10 csrw pmpaddr9, x29 csrr x30, pmpaddr9 j write_pmpaddr_end + write_pmpaddr_10: - li x7, 0xA - bne x7, x28, write_pmpaddr_11 csrw pmpaddr10, x29 csrr x30, pmpaddr10 j write_pmpaddr_end + write_pmpaddr_11: - li x7, 0xB - bne x7, x28, write_pmpaddr_12 csrw pmpaddr11, x29 csrr x30, pmpaddr11 j write_pmpaddr_end + write_pmpaddr_12: - li x7, 0xC - bne x7, x28, write_pmpaddr_13 csrw pmpaddr12, x29 csrr x30, pmpaddr12 j write_pmpaddr_end + write_pmpaddr_13: - li x7, 0xD - bne x7, x28, write_pmpaddr_14 csrw pmpaddr13, x29 csrr x30, pmpaddr13 j write_pmpaddr_end + write_pmpaddr_14: - li x7, 0xE - bne x7, x28, write_pmpaddr_15 csrw pmpaddr14, x29 csrr x30, pmpaddr14 j write_pmpaddr_end + write_pmpaddr_15: - li x7, 0xF - bne x7, x28, write_pmpaddr_end csrw pmpaddr15, x29 csrr x30, pmpaddr15 j write_pmpaddr_end + write_pmpaddr_end: sw x30, 0(x6) addi x6, x6, 4 @@ -555,18 +753,21 @@ executable_test: addi x16, x16, 4 j test_loop +.endm - +// notably, terminate_test is not a part of the test table macro because it needs to be defined +// in any type of test, macro or test table, for the trap handler to work terminate_test: li a0, 2 // Trap handler behavior (go to machine mode) ecall // writes mcause to the output. csrw mtvec, x4 // restore original trap handler to halt program - RVTEST_CODE_END RVMODEL_HALT +.macro TEST_STACK_AND_DATA + RVTEST_DATA_BEGIN .align 4 rvtest_data: @@ -575,14 +776,12 @@ RVTEST_DATA_END .align 2 // align stack to 4 byte boundary bottom_of_stack: - .fill 1024, 4, 0xdeadbeef + .fill 1024, 4, 0xdeadbeef top_of_stack: - RVMODEL_DATA_BEGIN -// next lines through test cases copied over from old framework test_1_res: .fill 1024, 4, 0xdeadbeef @@ -602,6 +801,4 @@ gpr_save: #endif -.align 2 -test_cases: - +.endm