aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2020-03-26 09:09:34 -0700
committerGitHub <noreply@github.com>2020-03-26 09:09:34 -0700
commit7351b31ffa1c72e16d2d8da3021c9ff5edbbf821 (patch)
treead7c9434c22126edadc727449b1cf9d3e6ebb5f0
parent094985d1cfafe00548751285271bf8aab40f8d6d (diff)
downloadriscv-tests-7351b31ffa1c72e16d2d8da3021c9ff5edbbf821.zip
riscv-tests-7351b31ffa1c72e16d2d8da3021c9ff5edbbf821.tar.gz
riscv-tests-7351b31ffa1c72e16d2d8da3021c9ff5edbbf821.tar.bz2
Improve address translation tests (#261)
* Improve address translation tests. Check that the mode we're testing is supported by hardware before running the test. Test with high address bits set, which catches a bug in OpenOCD. * Turn off PMP for address translation test. Otherwise it doesn't pass on HiFive Unleashed. * Run TranslateTest on random hart. Once https://github.com/riscv/riscv-openocd/pull/459 merges that will work.
-rwxr-xr-xdebug/gdbserver.py41
-rw-r--r--debug/programs/translate.c20
-rw-r--r--debug/testlib.py11
m---------env22
4 files changed, 59 insertions, 35 deletions
diff --git a/debug/gdbserver.py b/debug/gdbserver.py
index 8800137..da671d3 100755
--- a/debug/gdbserver.py
+++ b/debug/gdbserver.py
@@ -1229,15 +1229,7 @@ class PrivTest(GdbSingleHartTest):
self.supported.add(2)
self.supported.add(3)
- # Disable physical memory protection by allowing U mode access to all
- # memory.
- try:
- self.gdb.p("$pmpcfg0=0xf") # TOR, R, W, X
- self.gdb.p("$pmpaddr0=0x%x" %
- ((self.hart.ram + self.hart.ram_size) >> 2))
- except testlib.CouldNotFetch:
- # PMP registers are optional
- pass
+ self.disable_pmp()
# Ensure Virtual Memory is disabled if applicable (SATP register is not
# reset)
@@ -1294,16 +1286,27 @@ class TranslateTest(GdbTest):
compile_args = ("programs/translate.c", )
def setup(self):
- # TODO: If we use a random hart, then we get into trouble because
- # gdb_read_memory_packet() ignores which hart is currently selected, so
- # we end up reading satp from hart 0 when the address translation might
- # be set up on hart 1 only.
- self.gdb.select_hart(self.target.harts[0])
+ self.disable_pmp()
+
self.gdb.load()
self.gdb.b("main")
output = self.gdb.c()
assertRegex(output, r"\bmain\b")
+ def check_satp(self, mode):
+ if self.hart.xlen == 32:
+ satp = mode << 31
+ else:
+ satp = mode << 60
+ try:
+ self.gdb.p("$satp=0x%x" % satp)
+ except testlib.CouldNotFetch:
+ raise TestNotApplicable
+ readback = self.gdb.p("$satp")
+ self.gdb.p("$satp=0")
+ if readback != satp:
+ raise TestNotApplicable
+
def test_translation(self):
self.gdb.b("error")
self.gdb.b("handle_trap")
@@ -1315,11 +1318,19 @@ class TranslateTest(GdbTest):
assertEqual(0xdeadbeef, self.gdb.p("virtual[0]"))
assertEqual(0x55667788, self.gdb.p("virtual[1]"))
+SATP_MODE_OFF = 0
+SATP_MODE_SV32 = 1
+SATP_MODE_SV39 = 8
+SATP_MODE_SV48 = 9
+SATP_MODE_SV57 = 10
+SATP_MODE_SV64 = 11
+
class Sv32Test(TranslateTest):
def early_applicable(self):
return self.hart.xlen == 32
def test(self):
+ self.check_satp(SATP_MODE_SV32)
self.gdb.p("vms=&sv32")
self.test_translation()
@@ -1328,6 +1339,7 @@ class Sv39Test(TranslateTest):
return self.hart.xlen > 32
def test(self):
+ self.check_satp(SATP_MODE_SV39)
self.gdb.p("vms=&sv39")
self.test_translation()
@@ -1336,6 +1348,7 @@ class Sv48Test(TranslateTest):
return self.hart.xlen > 32
def test(self):
+ self.check_satp(SATP_MODE_SV48)
self.gdb.p("vms=&sv48")
self.test_translation()
diff --git a/debug/programs/translate.c b/debug/programs/translate.c
index ebeb92d..c0424bf 100644
--- a/debug/programs/translate.c
+++ b/debug/programs/translate.c
@@ -23,6 +23,7 @@ typedef struct {
unsigned ppn_offset_bits[5];
unsigned entry_width_bytes;
unsigned vpn_width_bits;
+ unsigned vaddr_bits;
} virtual_memory_system_t;
static virtual_memory_system_t sv32 = {
@@ -31,7 +32,8 @@ static virtual_memory_system_t sv32 = {
.ppn_width_bits = {12, 10, 10},
.ppn_offset_bits = {0, 12, 22},
.entry_width_bytes = 4,
- .vpn_width_bits = 10
+ .vpn_width_bits = 10,
+ .vaddr_bits = 32
};
static virtual_memory_system_t sv39 = {
@@ -40,7 +42,8 @@ static virtual_memory_system_t sv39 = {
.ppn_width_bits = {12, 9, 9, 26},
.ppn_offset_bits = {0, 12, 21, 30},
.entry_width_bytes = 8,
- .vpn_width_bits = 9
+ .vpn_width_bits = 9,
+ .vaddr_bits = 39
};
static virtual_memory_system_t sv48 = {
@@ -49,7 +52,8 @@ static virtual_memory_system_t sv48 = {
.ppn_width_bits = {12, 9, 9, 9, 26},
.ppn_offset_bits = {0, 12, 21, 30, 39},
.entry_width_bytes = 8,
- .vpn_width_bits = 9
+ .vpn_width_bits = 9,
+ .vaddr_bits = 48
};
static virtual_memory_system_t *vms;
@@ -152,12 +156,20 @@ int main()
void *master_table = get_page();
setup_page_table(master_table, vms->levels-1, 0);
uint32_t *physical = get_page();
- uint32_t *virtual = (uint32_t *) (((reg_t) physical) ^ ((reg_t) 0x40000000));
+ //uint32_t *virtual = (uint32_t *) (((reg_t) physical) ^ ((reg_t) 0x40000000));
+ uint32_t *virtual = (uint32_t *) (((reg_t) physical) ^ (((reg_t) 0xf) << (vms->vaddr_bits - 4)));
+ // Virtual addresses must be sign-extended.
+ if (vms->vaddr_bits < sizeof(virtual) * 8 && (reg_t) virtual & ((reg_t) 1<<(vms->vaddr_bits-1)))
+ virtual = (uint32_t *) (
+ (reg_t) virtual | ~(((reg_t) 1 << vms->vaddr_bits) - 1));
add_entry(master_table, 0, (reg_t) virtual, (reg_t) physical);
unsigned long satp = set_field(0, SATP_MODE, vms->mode);
satp = set_field(satp, SATP_PPN, ((unsigned long) master_table) >> 12);
write_csr(satp, satp);
+ satp = read_csr(satp);
+ if (get_field(satp, SATP_MODE) != vms->mode)
+ error();
reg_t mstatus = read_csr(mstatus);
mstatus |= MSTATUS_MPRV;
diff --git a/debug/testlib.py b/debug/testlib.py
index 3d714df..36f1f17 100644
--- a/debug/testlib.py
+++ b/debug/testlib.py
@@ -1076,6 +1076,17 @@ class GdbTest(BaseTest):
self.gdb.select_hart(self.hart)
+ def disable_pmp(self):
+ # Disable physical memory protection by allowing U mode access to all
+ # memory.
+ try:
+ self.gdb.p("$pmpcfg0=0xf") # TOR, R, W, X
+ self.gdb.p("$pmpaddr0=0x%x" %
+ ((self.hart.ram + self.hart.ram_size) >> 2))
+ except CouldNotFetch:
+ # PMP registers are optional
+ pass
+
class GdbSingleHartTest(GdbTest):
def classSetup(self):
GdbTest.classSetup(self)
diff --git a/env b/env
-Subproject 500b89fb41ae857f5a1a0d6df382812cfce0b82
+Subproject 68cad7baf3ed0a4553fffd14726d24519ee1296