#include "tb_cxxrtl_io.h" #include "hazard3_irq.h" #include // Test intent: check that IRQs interrupting PC-setting phase of cm.popret does // not cause stack corruption. (This is not covered by zmp_irq_kill) uint32_t __attribute__((naked)) foreground_task(uint32_t iters) { asm volatile ( // Save sp and ra "addi sp, sp, -16\n" "sw s0, 0(sp)\n" "sw ra, 4(sp)\n" "mv s0, sp\n" "li a1, 0xf00b0000\n" // Short push + popret sequence "1:\n" "la ra, 2f\n" ".hword 0xb852\n" // cm.push {ra,s0},-16 ".hword 0xbe52\n" // cm.popret {ra,s0}, 16 "2:\n" // Check we haven't moved the stack pointer or lost our s0 contents "bne s0, sp, 3f\n" "addi a0, a0, -1\n" "addi a1, a1, 1\n" "bgtz a0, 1b\n" // Normal return -- we've been counting up in a1 as we count down in // a0, so return a1 to confirm we iterated the expected number of times "mv a0, a1\n" "lw s0, 0(sp)\n" "lw ra, 4(sp)\n" "addi sp, sp, 16\n" "ret\n" "3:\n" // Uh oh, either sp or s0 changed. Panic! "mv sp, s0\n" "j panic_sp_changed\n" ); } void __attribute__((noreturn)) panic_sp_changed(void) { tb_puts("Stack pointer changed, that wasn't supposed to happen!\n"); tb_exit(-1); __builtin_unreachable(); } void __attribute__((interrupt)) isr_machine_timer(void) { unsigned int dwell = rand() % 301; mm_timer->mtimecmp = mm_timer->mtime + dwell; } int main() { tb_puts("Starting\n"); timer_irq_enable(true); global_irq_enable(true); const uint32_t expected_iterations = 1000; tb_printf("Running %u iterations\n", expected_iterations); uint32_t result = foreground_task(expected_iterations); tb_printf("Result: %08x\n", result); tb_assert(result == 0xf00b0000u + expected_iterations, "Wrong number of iterations"); return 0; } /*EXPECTED-OUTPUT*************************************************************** Starting Running 1000 iterations Result: f00b03e8 *******************************************************************************/