aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-12-16 13:52:28 +0000
committerPeter Maydell <peter.maydell@linaro.org>2022-12-16 13:56:30 +0000
commita0cd0b1d0bc78b8ffe3292fbb4f14e4a15e16b7b (patch)
tree47e3a16cea58dd39a0d535bc15664ec07bfa2853
parent5b6fc3606b96f858479c2d7ac1b1fd296b762f12 (diff)
test15: Add execution tests from small MPU regions
Add some tests of execution from small MPU regions. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--test15.c90
1 files changed, 84 insertions, 6 deletions
diff --git a/test15.c b/test15.c
index 7f3b37e..7ecc846 100644
--- a/test15.c
+++ b/test15.c
@@ -69,6 +69,38 @@ void checkfault(unsigned v)
}
}
+typedef int testfn(int);
+
+static int tryexec(volatile char *p)
+{
+ uint32_t tval = 0;
+ testfn *f = (testfn *)((uintptr_t)p | 1);
+ testDiag("Tryexec %" PRIx32, (uint32_t)p);
+ /* The assumption is that the code at the dest address is
+ * adds r0, #1; bx lr
+ * so we can call it, and it will increment our value for us.
+ * For non-executable code the exception handler will
+ * by-hand do the function return back to lr.
+ */
+ tval = f(tval);
+ testDiag("Returned with %" PRIx32, tval);
+ if (expect_fault == EXPECT_NO_FAULT && tval != 1) {
+ testFail("expected code to return 1 but got %" PRId32 "\n", tval);
+ return 0;
+ }
+ return 1;
+}
+
+static void write_exec_test_insns(volatile char *p)
+{
+ /* Write the "adds r0, #1; bx lr" sequence we'll use
+ * in tryexec().
+ */
+ volatile uint16_t *px = (uint16_t*)p;
+ px[0] = 0x3001; /* adds r0, 1 */
+ px[1] = 0x4770; /* bx lr */
+}
+
void hard(uint32_t *sp)
{
testDiag("In HardFault handler");
@@ -91,12 +123,28 @@ void hard_entry(void)
void mem(uint32_t *sp)
{
- uint32_t addr;
+ uint32_t cfsr = in32(SCB(0xd28));
+ uint32_t addr = in32(SCB(0xd34));
+
+ out32(SCB(0xd28), 0xff); /* W1C the MMFSR bits */
sp = get_src_stack(sp);
- inst_skip(sp);
- addr = in32((void*)0xe000ed34);
- testDiag("In MemFault, Addr 0x%" PRIx32 ", from 0x%" PRIx32, addr, sp[6]);
+
+ testDiag("In MemFault, CFSR 0x%" PRIx32 ", from 0x%" PRIX32, cfsr, sp[6]);
+ if (cfsr & 0x80) {
+ testDiag("...MMARVALID set, MMFAR is 0x%" PRIx32, addr);
+ }
+
+ if (cfsr & 0x1) {
+ /* IACCVIOL -- set PC to LR. Note that the LR will have the
+ * bit-0-means-Thumb convention but an exception frame PC slot
+ * has the "raw" PC.
+ */
+ sp[6] = sp[5] & ~1;
+ } else {
+ /* DACCVIOL -- just skip offending insn */
+ inst_skip(sp);
+ }
switch(expect_fault) {
case EXPECT_MEMFAULT:
@@ -174,7 +222,7 @@ void main(void)
mpu_type = in32(SCB(0xD90));
has_mpu = ((mpu_type >> 8) & 0xff) != 0;
- testInit(4);
+ testInit(8);
if (!has_mpu) {
testDiag("No MPU present: nothing to test here");
@@ -201,10 +249,14 @@ void main(void)
set_mpu(4, (uint32_t)testpage, 512,
MPU_XN|MPU_NORMAL|MPU_NANA);
set_mpu(5, (uint32_t)testpage + 512, 256,
- MPU_XN|MPU_NORMAL|MPU_RWRW);
+ MPU_NORMAL|MPU_RWRW);
set_mpu(6, (uint32_t)testpage + 768, 256,
MPU_XN|MPU_NORMAL|MPU_NANA);
+ write_exec_test_insns(testpage + 256);
+ write_exec_test_insns(testpage + 600);
+ write_exec_test_insns(testpage + 768);
+
testDiag("Enable MPU");
enable_mpu(1,1,0);
@@ -228,5 +280,31 @@ void main(void)
try(testpage + 600);
checkfault(EXPECT_NO_FAULT);
+ /* Try to execute from various parts of the small page */
+ expect_fault = EXPECT_NO_FAULT;
+ testDiag("Execute from the accessible small page (should not fault)");
+ // TODO we get a HardFault here...
+ if (tryexec(testpage + 600)) {
+ checkfault(EXPECT_NO_FAULT);
+ }
+
+ expect_fault = EXPECT_MEMFAULT;
+ testDiag("Execute from the preceding small page (should fault)");
+ if (tryexec(testpage + 256)) {
+ checkfault(EXPECT_TAKEN_MEMFAULT);
+ }
+
+ expect_fault = EXPECT_MEMFAULT;
+ testDiag("Execute from the following small page (should fault)");
+ if (tryexec(testpage + 768)) {
+ checkfault(EXPECT_TAKEN_MEMFAULT);
+ }
+
+ expect_fault = EXPECT_NO_FAULT;
+ testDiag("Execute from the accessible small page again (should not fault)");
+ if (tryexec(testpage + 600)) {
+ checkfault(EXPECT_NO_FAULT);
+ }
+
testDiag("Done.");
}