diff options
-rw-r--r-- | bbl/bbl.c | 47 |
1 files changed, 47 insertions, 0 deletions
@@ -40,6 +40,52 @@ static void filter_dtb(uintptr_t source) filter_compat(dest, "riscv,debug-013"); } +static void protect_memory(void) +{ + // Check to see if up to four PMP registers are implemented. + // Ignore the illegal-instruction trap if PMPs aren't supported. + uintptr_t a0 = 0, a1 = 0, a2 = 0, a3 = 0, tmp, cfg; + asm volatile ("la %[tmp], 1f\n\t" + "csrrw %[tmp], mtvec, %[tmp]\n\t" + "csrw pmpaddr0, %[m1]\n\t" + "csrr %[a0], pmpaddr0\n\t" + "csrw pmpaddr1, %[m1]\n\t" + "csrr %[a1], pmpaddr1\n\t" + "csrw pmpaddr2, %[m1]\n\t" + "csrr %[a2], pmpaddr2\n\t" + "csrw pmpaddr3, %[m1]\n\t" + "csrr %[a3], pmpaddr3\n\t" + ".align 2\n\t" + "1: csrw mtvec, %[tmp]" + : [tmp] "=&r" (tmp), + [a0] "+r" (a0), [a1] "+r" (a1), [a2] "+r" (a2), [a3] "+r" (a3) + : [m1] "r" (-1UL)); + + // We need at least four PMP registers to protect M-mode from S-mode. + if (!(a0 & a1 & a2 & a3)) + return setup_pmp(); + + // Prevent S-mode access to our part of memory. + extern char _ftext, _etext, _end; + a0 = (uintptr_t)&_ftext >> PMP_SHIFT; + a1 = (uintptr_t)&_etext >> PMP_SHIFT; + cfg = PMP_TOR << 8; + // Give S-mode free rein of everything else. + a2 = -1; + cfg |= (PMP_NAPOT | PMP_R | PMP_W | PMP_X) << 16; + // No use for PMP 3 just yet. + a3 = 0; + + // Plug it all in. + asm volatile ("csrw pmpaddr0, %[a0]\n\t" + "csrw pmpaddr1, %[a1]\n\t" + "csrw pmpaddr2, %[a2]\n\t" + "csrw pmpaddr3, %[a3]\n\t" + "csrw pmpcfg0, %[cfg]" + :: [a0] "r" (a0), [a1] "r" (a1), [a2] "r" (a2), [a3] "r" (a3), + [cfg] "r" (cfg)); +} + void boot_other_hart(uintptr_t unused __attribute__((unused))) { const void* entry; @@ -61,6 +107,7 @@ void boot_other_hart(uintptr_t unused __attribute__((unused))) #ifdef BBL_BOOT_MACHINE enter_machine_mode(entry, hartid, dtb_output()); #else /* Run bbl in supervisor mode */ + protect_memory(); enter_supervisor_mode(entry, hartid, dtb_output()); #endif } |