Add tests for virtual priv register.
authorTim Newsome <tim@sifive.com>
Thu, 28 Jul 2016 21:47:12 +0000 (14:47 -0700)
committerTim Newsome <tim@sifive.com>
Thu, 28 Jul 2016 21:47:12 +0000 (14:47 -0700)
Users can use this register to inspect and change the privilege level of
the core. It doesn't make any assumptions about the actual underlying
debug mechanism (as opposed to having the user change DCSR directly,
which may not exist in all debug implementations).

debug/gdbserver.py
debug/programs/priv.S [new file with mode: 0644]

index 83e3c2f2d742ed3991c8008fb87ed1a806e7d99c..f20630e65e7d591e9dd6a9b4226825454224911f 100755 (executable)
@@ -466,6 +466,58 @@ class MprvTest(DeleteServer):
         output = self.gdb.command("p/x *(int*)(((char*)&data)-0x80000000)")
         self.assertIn("0xbead", output)
 
+class PrivTest(DeleteServer):
+    def setUp(self):
+        self.binary = target.compile("programs/priv.S")
+        self.server = target.server()
+        self.gdb = gdb()
+        self.gdb.command("file %s" % self.binary)
+        self.gdb.command("target extended-remote localhost:%d" % self.server.port)
+        self.gdb.load()
+
+        misa = self.gdb.p("$misa")
+        self.supported = set()
+        if misa & (1<<20):
+            self.supported.add(0)
+        if misa & (1<<18):
+            self.supported.add(1)
+        if misa & (1<<7):
+            self.supported.add(2)
+        self.supported.add(3)
+
+    def test_rw(self):
+        """Test reading/writing priv."""
+        for privilege in range(4):
+            self.gdb.p("$priv=%d" % privilege)
+            self.gdb.stepi()
+            actual = self.gdb.p("$priv")
+            self.assertIn(actual, self.supported)
+            if privilege in self.supported:
+                self.assertEqual(actual, privilege)
+
+    def test_change(self):
+        """Test that the core's privilege level actually changes."""
+
+        if 0 not in self.supported:
+            # TODO: return not applicable
+            return
+
+        self.gdb.b("main")
+        self.gdb.c()
+
+        # Machine mode
+        self.gdb.p("$priv=3")
+        main = self.gdb.p("$pc")
+        self.gdb.stepi()
+        self.assertEqual("%x" % self.gdb.p("$pc"), "%x" % (main+4))
+
+        # User mode
+        self.gdb.p("$priv=0")
+        self.gdb.stepi()
+        # Should have taken an exception, so be nowhere near main.
+        pc = self.gdb.p("$pc")
+        self.assertTrue(pc < main or pc > main + 0x100)
+
 class Target(object):
     directory = None
 
diff --git a/debug/programs/priv.S b/debug/programs/priv.S
new file mode 100644 (file)
index 0000000..2d20a65
--- /dev/null
@@ -0,0 +1,11 @@
+#include "../../env/encoding.h"
+
+        .global         main
+
+        .section        .text
+main:
+        # MISA is only readable from machine mode
+        csrr    t0, CSR_MISA
+        csrr    t0, CSR_MISA
+        csrr    t0, CSR_MISA
+        csrr    t0, CSR_MISA