forked from Github_Repos/cvw
merged test macros in with 32 bit tests
This commit is contained in:
parent
72e83db9fe
commit
943c4d9d7c
@ -1548,9 +1548,9 @@ string wally32i[] = '{
|
|||||||
|
|
||||||
string wally32priv[] = '{
|
string wally32priv[] = '{
|
||||||
`WALLYTEST,
|
`WALLYTEST,
|
||||||
"rv32i_m/privilege/WALLY-MMU-SV32", "3080",
|
"rv32i_m/privilege/WALLY-MMU-SV32", "4080",
|
||||||
"rv32i_m/privilege/WALLY-PMP", "3080",
|
"rv32i_m/privilege/WALLY-PMP", "4080",
|
||||||
"rv32i_m/privilege/WALLY-PMA", "3080"
|
"rv32i_m/privilege/WALLY-PMA", "4080"
|
||||||
};
|
};
|
||||||
|
|
||||||
string wally32periph[] = '{
|
string wally32periph[] = '{
|
||||||
|
@ -22,9 +22,18 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
#include "WALLY-TEST-LIB-32.h"
|
#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
|
# Test Contents
|
||||||
#
|
#
|
||||||
|
@ -35,9 +35,18 @@
|
|||||||
#define PLIC_RANGE 0x03FFFFFF
|
#define PLIC_RANGE 0x03FFFFFF
|
||||||
|
|
||||||
#include "WALLY-TEST-LIB-32.h"
|
#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
|
# Test Contents
|
||||||
#
|
#
|
||||||
|
@ -22,9 +22,18 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
#include "WALLY-TEST-LIB-32.h"
|
#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
|
# 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
|
# 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
|
# write pmpaddr regs
|
||||||
# | Reg | pmpaddr | pmpcfg | L | A | X | W | R | Comments |
|
# | 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 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 0x1, 0x20040000, write_pmpaddr_1 # | 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 0x2, 0x2004003F, write_pmpaddr_2 # | 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 0x3, 0x20040080, write_pmpaddr_3 # | 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 0x4, 0x20040084, write_pmpaddr_4 # | 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 0x5, 0x200400C0, write_pmpaddr_5 # | 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 |
|
.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.
|
# 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.
|
# 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 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
|
# 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.
|
# 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
|
.4byte 0x80100010, 0x600DAA, write32_test # write to pmpaddr 1-2 range
|
||||||
@ -74,9 +83,9 @@
|
|||||||
|
|
||||||
|
|
||||||
# attempt to write to pmpaddr5 and pmp5cfg after lockout
|
# 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
|
# 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
|
# instruction ignored, output is 0x200400C0, NOT 0xFFFFFFFF
|
||||||
|
|
||||||
# Test 12.3.2.2.2 Machine mode access
|
# Test 12.3.2.2.2 Machine mode access
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
//
|
//
|
||||||
// Author: Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
// Author: Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||||
//
|
//
|
||||||
// Created 2021-07-20
|
// Created 2021-07-19
|
||||||
//
|
//
|
||||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||||
//
|
//
|
||||||
@ -23,6 +23,9 @@
|
|||||||
|
|
||||||
#include "model_test.h"
|
#include "model_test.h"
|
||||||
#include "arch_test.h"
|
#include "arch_test.h"
|
||||||
|
|
||||||
|
.macro INIT_TESTS
|
||||||
|
|
||||||
RVTEST_ISA("RV32I")
|
RVTEST_ISA("RV32I")
|
||||||
|
|
||||||
.section .text.init
|
.section .text.init
|
||||||
@ -31,7 +34,7 @@ rvtest_entry_point:
|
|||||||
RVMODEL_BOOT
|
RVMODEL_BOOT
|
||||||
RVTEST_CODE_BEGIN
|
RVTEST_CODE_BEGIN
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------
|
||||||
// Initialization Overview:
|
// Initialization Overview:
|
||||||
//
|
//
|
||||||
// Initialize x6 as a virtual pointer to the test results
|
// Initialize x6 as a virtual pointer to the test results
|
||||||
@ -56,9 +59,9 @@ RVTEST_CODE_BEGIN
|
|||||||
li a1, 0
|
li a1, 0
|
||||||
li a2, 0 // reset trap handler inputs to zero
|
li a2, 0 // reset trap handler inputs to zero
|
||||||
|
|
||||||
// go to first test!
|
// go to beginning of S file where we can decide between using the test data loop
|
||||||
j test_setup
|
// or using the macro inline code insertion
|
||||||
|
j s_file_begin
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------
|
||||||
// General traps Handler
|
// General traps Handler
|
||||||
@ -225,12 +228,16 @@ ecallhandler_changetousermode:
|
|||||||
j trapreturn
|
j trapreturn
|
||||||
|
|
||||||
instrfault:
|
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)
|
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:
|
accessfault:
|
||||||
// *** What do I have to do here?
|
// *** What do I have to do here?
|
||||||
j trapreturn
|
j trapreturn
|
||||||
|
|
||||||
// Table of trap behavior
|
// Table of trap behavior
|
||||||
// lists what to do on each exception (not interrupts)
|
// lists what to do on each exception (not interrupts)
|
||||||
// unexpected exceptions should cause segfaults for easy detection
|
// unexpected exceptions should cause segfaults for easy detection
|
||||||
@ -239,13 +246,13 @@ accessfault:
|
|||||||
.align 2 // aligns this data table to an 4 byte boundary
|
.align 2 // aligns this data table to an 4 byte boundary
|
||||||
trap_handler_vector_table:
|
trap_handler_vector_table:
|
||||||
.4byte segfault // 0: instruction address misaligned
|
.4byte segfault // 0: instruction address misaligned
|
||||||
.4byte instrfault // 1: instruction access fault
|
.4byte instrfault // 1: instruction access fault
|
||||||
.4byte segfault // 2: illegal instruction
|
.4byte illegalinstr // 2: illegal instruction
|
||||||
.4byte segfault // 3: breakpoint
|
.4byte segfault // 3: breakpoint
|
||||||
.4byte segfault // 4: load address misaligned
|
.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 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 // 8: ecall from U-mode
|
||||||
.4byte ecallhandler // 9: ecall from S-mode
|
.4byte ecallhandler // 9: ecall from S-mode
|
||||||
.4byte segfault // 10: reserved
|
.4byte segfault // 10: reserved
|
||||||
@ -260,6 +267,220 @@ trap_return_pagetype_table:
|
|||||||
.4byte 0xC // 0: kilopage has 12 offset bits
|
.4byte 0xC // 0: kilopage has 12 offset bits
|
||||||
.4byte 0x16 // 1: megapage has 22 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
|
// Test Handler
|
||||||
//
|
//
|
||||||
@ -269,17 +490,18 @@ trap_return_pagetype_table:
|
|||||||
// Input parameters:
|
// Input parameters:
|
||||||
//
|
//
|
||||||
// x28:
|
// 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:
|
// 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:
|
// 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
|
la x5, test_cases
|
||||||
|
|
||||||
test_loop:
|
test_loop:
|
||||||
@ -298,25 +520,25 @@ test_loop:
|
|||||||
|
|
||||||
jr x30
|
jr x30
|
||||||
|
|
||||||
// Test Name : Description : Fault output value : Normal output values
|
// Test Name : Description : Fault output value : Normal output values
|
||||||
// ----------------------:---------------------------------------:------------------------:------------------------------------------------------
|
// ----------------------:-------------------------------------------:------------------------:------------------------------------------------------
|
||||||
// write32_test : Write 32 bits to address : 0xf : None
|
// write32_test : Write 32 bits to address : 0xf : None
|
||||||
// write16_test : Write 16 bits to address : 0xf : None
|
// write16_test : Write 16 bits to address : 0xf : None
|
||||||
// write08_test : Write 8 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
|
// read32_test : Read 32 bits from address : 0xd, 0xbad : readvalue in hex
|
||||||
// read16_test : Read 16 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
|
// 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)
|
// 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
|
// 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_baremetal : satp.MODE = bare metal : None : None
|
||||||
// goto_sv32 : satp.MODE = sv32 : None : None
|
// goto_sv39 : satp.MODE = sv39 : None : None
|
||||||
// write_mxr_sum : write sstatus.[19:18] = MXR, SUM bits : None : None
|
// goto_sv48 : satp.MODE = sv48 : None : None
|
||||||
// goto_m_mode : go to mahcine mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
// write_mxr_sum : write sstatus.[19:18] = MXR, SUM bits : None : None
|
||||||
// goto_s_mode : go to supervisor mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
// goto_m_mode : go to mahcine 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
|
// goto_s_mode : go to supervisor 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
|
// goto_u_mode : go to user mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||||
// write_pmpaddr_x : Write one of the pmpaddr csr's : None : readback of pmpaddr value
|
// 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:
|
write32_test:
|
||||||
// address to write in x28, word value in x29
|
// address to write in x28, word value in x29
|
||||||
@ -360,9 +582,9 @@ read08_test:
|
|||||||
addi x16, x16, 4
|
addi x16, x16, 4
|
||||||
j test_loop // go to next test case
|
j test_loop // go to next test case
|
||||||
|
|
||||||
|
|
||||||
goto_s_mode:
|
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 a1, x28 // return VPN
|
||||||
mv a2, x29 // return page types
|
mv a2, x29 // return page types
|
||||||
ecall // writes mcause to the output.
|
ecall // writes mcause to the output.
|
||||||
@ -385,21 +607,11 @@ goto_u_mode:
|
|||||||
|
|
||||||
goto_baremetal:
|
goto_baremetal:
|
||||||
// Turn translation off
|
// Turn translation off
|
||||||
li x7, 0 // satp.MODE value for bare metal (0)
|
GOTO_BAREMETAL
|
||||||
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
|
|
||||||
j test_loop // go to next test case
|
j test_loop // go to next test case
|
||||||
|
|
||||||
goto_sv32:
|
goto_sv32:
|
||||||
li x7, 1 // satp.MODE value for Sv39 (1)
|
GOTO_SV32
|
||||||
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
|
|
||||||
j test_loop // go to next test case
|
j test_loop // go to next test case
|
||||||
|
|
||||||
write_mxr_sum:
|
write_mxr_sum:
|
||||||
@ -415,25 +627,26 @@ write_mxr_sum:
|
|||||||
|
|
||||||
write_pmpcfg_0:
|
write_pmpcfg_0:
|
||||||
// writes the value in x29 to the pmpcfg register specified in x28.
|
// writes the value in x29 to the pmpcfg register specified in x28.
|
||||||
li x7, 0x0
|
// then writes the final value of pmpcfgX to the output.
|
||||||
bne x7, x28, write_pmpcfg_1
|
|
||||||
csrw pmpcfg0, x29
|
csrw pmpcfg0, x29
|
||||||
csrr x30, pmpcfg0
|
csrr x30, pmpcfg0
|
||||||
|
j write_pmpcfg_end
|
||||||
|
|
||||||
write_pmpcfg_1:
|
write_pmpcfg_1:
|
||||||
li x7, 0x1
|
|
||||||
bne x7, x28, write_pmpcfg_2
|
|
||||||
csrw pmpcfg1, x29
|
csrw pmpcfg1, x29
|
||||||
csrr x30, pmpcfg1
|
csrr x30, pmpcfg1
|
||||||
|
j write_pmpcfg_end
|
||||||
|
|
||||||
write_pmpcfg_2:
|
write_pmpcfg_2:
|
||||||
li x7, 0x2
|
|
||||||
bne x7, x28, write_pmpcfg_3
|
|
||||||
csrw pmpcfg2, x29
|
csrw pmpcfg2, x29
|
||||||
csrr x30, pmpcfg2
|
csrr x30, pmpcfg2
|
||||||
|
j write_pmpcfg_end
|
||||||
|
|
||||||
write_pmpcfg_3:
|
write_pmpcfg_3:
|
||||||
li x7, 0x3
|
|
||||||
bne x7, x28, write_pmpcfg_end
|
|
||||||
csrw pmpcfg3, x29
|
csrw pmpcfg3, x29
|
||||||
csrr x30, pmpcfg3
|
csrr x30, pmpcfg3
|
||||||
|
j write_pmpcfg_end
|
||||||
|
|
||||||
write_pmpcfg_end:
|
write_pmpcfg_end:
|
||||||
sw x30, 0(x6)
|
sw x30, 0(x6)
|
||||||
addi x6, x6, 4
|
addi x6, x6, 4
|
||||||
@ -441,103 +654,88 @@ write_pmpcfg_end:
|
|||||||
j test_loop
|
j test_loop
|
||||||
|
|
||||||
write_pmpaddr_0:
|
write_pmpaddr_0:
|
||||||
|
// write_read_csr pmpaddr0, x29
|
||||||
// writes the value in x29 to the pmpaddr register specified in x28.
|
// writes the value in x29 to the pmpaddr register specified in x28.
|
||||||
// then writes the final value of pmpaddrX to the output.
|
// then writes the final value of pmpaddrX to the output.
|
||||||
li x7, 0x0
|
|
||||||
bne x7, x28, write_pmpaddr_1
|
|
||||||
csrw pmpaddr0, x29
|
csrw pmpaddr0, x29
|
||||||
csrr x30, pmpaddr0
|
csrr x30, pmpaddr0
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_1:
|
write_pmpaddr_1:
|
||||||
li x7, 0x1
|
|
||||||
bne x7, x28, write_pmpaddr_2
|
|
||||||
csrw pmpaddr1, x29
|
csrw pmpaddr1, x29
|
||||||
csrr x30, pmpaddr1
|
csrr x30, pmpaddr1
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_2:
|
write_pmpaddr_2:
|
||||||
li x7, 0x2
|
|
||||||
bne x7, x28, write_pmpaddr_3
|
|
||||||
csrw pmpaddr2, x29
|
csrw pmpaddr2, x29
|
||||||
csrr x30, pmpaddr2
|
csrr x30, pmpaddr2
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_3:
|
write_pmpaddr_3:
|
||||||
li x7, 0x3
|
|
||||||
bne x7, x28, write_pmpaddr_4
|
|
||||||
csrw pmpaddr3, x29
|
csrw pmpaddr3, x29
|
||||||
csrr x30, pmpaddr3
|
csrr x30, pmpaddr3
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_4:
|
write_pmpaddr_4:
|
||||||
li x7, 0x4
|
|
||||||
bne x7, x28, write_pmpaddr_5
|
|
||||||
csrw pmpaddr4, x29
|
csrw pmpaddr4, x29
|
||||||
csrr x30, pmpaddr4
|
csrr x30, pmpaddr4
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_5:
|
write_pmpaddr_5:
|
||||||
li x7, 0x5
|
|
||||||
bne x7, x28, write_pmpaddr_6
|
|
||||||
csrw pmpaddr5, x29
|
csrw pmpaddr5, x29
|
||||||
csrr x30, pmpaddr5
|
csrr x30, pmpaddr5
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_6:
|
write_pmpaddr_6:
|
||||||
li x7, 0x6
|
|
||||||
bne x7, x28, write_pmpaddr_7
|
|
||||||
csrw pmpaddr6, x29
|
csrw pmpaddr6, x29
|
||||||
csrr x30, pmpaddr6
|
csrr x30, pmpaddr6
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_7:
|
write_pmpaddr_7:
|
||||||
li x7, 0x7
|
|
||||||
bne x7, x28, write_pmpaddr_8
|
|
||||||
csrw pmpaddr7, x29
|
csrw pmpaddr7, x29
|
||||||
csrr x30, pmpaddr7
|
csrr x30, pmpaddr7
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_8:
|
write_pmpaddr_8:
|
||||||
li x7, 0x8
|
|
||||||
bne x7, x28, write_pmpaddr_9
|
|
||||||
csrw pmpaddr8, x29
|
csrw pmpaddr8, x29
|
||||||
csrr x30, pmpaddr8
|
csrr x30, pmpaddr8
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_9:
|
write_pmpaddr_9:
|
||||||
li x7, 0x9
|
|
||||||
bne x7, x28, write_pmpaddr_10
|
|
||||||
csrw pmpaddr9, x29
|
csrw pmpaddr9, x29
|
||||||
csrr x30, pmpaddr9
|
csrr x30, pmpaddr9
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_10:
|
write_pmpaddr_10:
|
||||||
li x7, 0xA
|
|
||||||
bne x7, x28, write_pmpaddr_11
|
|
||||||
csrw pmpaddr10, x29
|
csrw pmpaddr10, x29
|
||||||
csrr x30, pmpaddr10
|
csrr x30, pmpaddr10
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_11:
|
write_pmpaddr_11:
|
||||||
li x7, 0xB
|
|
||||||
bne x7, x28, write_pmpaddr_12
|
|
||||||
csrw pmpaddr11, x29
|
csrw pmpaddr11, x29
|
||||||
csrr x30, pmpaddr11
|
csrr x30, pmpaddr11
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_12:
|
write_pmpaddr_12:
|
||||||
li x7, 0xC
|
|
||||||
bne x7, x28, write_pmpaddr_13
|
|
||||||
csrw pmpaddr12, x29
|
csrw pmpaddr12, x29
|
||||||
csrr x30, pmpaddr12
|
csrr x30, pmpaddr12
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_13:
|
write_pmpaddr_13:
|
||||||
li x7, 0xD
|
|
||||||
bne x7, x28, write_pmpaddr_14
|
|
||||||
csrw pmpaddr13, x29
|
csrw pmpaddr13, x29
|
||||||
csrr x30, pmpaddr13
|
csrr x30, pmpaddr13
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_14:
|
write_pmpaddr_14:
|
||||||
li x7, 0xE
|
|
||||||
bne x7, x28, write_pmpaddr_15
|
|
||||||
csrw pmpaddr14, x29
|
csrw pmpaddr14, x29
|
||||||
csrr x30, pmpaddr14
|
csrr x30, pmpaddr14
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_15:
|
write_pmpaddr_15:
|
||||||
li x7, 0xF
|
|
||||||
bne x7, x28, write_pmpaddr_end
|
|
||||||
csrw pmpaddr15, x29
|
csrw pmpaddr15, x29
|
||||||
csrr x30, pmpaddr15
|
csrr x30, pmpaddr15
|
||||||
j write_pmpaddr_end
|
j write_pmpaddr_end
|
||||||
|
|
||||||
write_pmpaddr_end:
|
write_pmpaddr_end:
|
||||||
sw x30, 0(x6)
|
sw x30, 0(x6)
|
||||||
addi x6, x6, 4
|
addi x6, x6, 4
|
||||||
@ -555,18 +753,21 @@ executable_test:
|
|||||||
addi x16, x16, 4
|
addi x16, x16, 4
|
||||||
j test_loop
|
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:
|
terminate_test:
|
||||||
|
|
||||||
li a0, 2 // Trap handler behavior (go to machine mode)
|
li a0, 2 // Trap handler behavior (go to machine mode)
|
||||||
ecall // writes mcause to the output.
|
ecall // writes mcause to the output.
|
||||||
csrw mtvec, x4 // restore original trap handler to halt program
|
csrw mtvec, x4 // restore original trap handler to halt program
|
||||||
|
|
||||||
|
|
||||||
RVTEST_CODE_END
|
RVTEST_CODE_END
|
||||||
RVMODEL_HALT
|
RVMODEL_HALT
|
||||||
|
|
||||||
|
.macro TEST_STACK_AND_DATA
|
||||||
|
|
||||||
RVTEST_DATA_BEGIN
|
RVTEST_DATA_BEGIN
|
||||||
.align 4
|
.align 4
|
||||||
rvtest_data:
|
rvtest_data:
|
||||||
@ -575,14 +776,12 @@ RVTEST_DATA_END
|
|||||||
|
|
||||||
.align 2 // align stack to 4 byte boundary
|
.align 2 // align stack to 4 byte boundary
|
||||||
bottom_of_stack:
|
bottom_of_stack:
|
||||||
.fill 1024, 4, 0xdeadbeef
|
.fill 1024, 4, 0xdeadbeef
|
||||||
top_of_stack:
|
top_of_stack:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RVMODEL_DATA_BEGIN
|
RVMODEL_DATA_BEGIN
|
||||||
|
|
||||||
// next lines through test cases copied over from old framework
|
|
||||||
test_1_res:
|
test_1_res:
|
||||||
.fill 1024, 4, 0xdeadbeef
|
.fill 1024, 4, 0xdeadbeef
|
||||||
|
|
||||||
@ -602,6 +801,4 @@ gpr_save:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.align 2
|
.endm
|
||||||
test_cases:
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user