1/* 2 * Copyright (c) 2022 BayLibre, SAS 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7#include <zephyr/toolchain.h> 8#include <zephyr/linker/sections.h> 9#include <zephyr/arch/cpu.h> 10#include "asm_macros.inc" 11 12#define CSR_PMPCFG_BASE 0x3a0 13#define CSR_PMPADDR_BASE 0x3b0 14 15/* 16 * Prototype: 17 * 18 * void z_riscv_write_pmp_entries(unsigned int start, // a0 19 * unsigned int end, // a1 20 * bool clear_trailing_entries, // a2 21 * unsigned long *pmp_addr, // a3 22 * unsigned long *pmp_cfg) // a4 23 * 24 * Called from pmp.c to write a range of PMP entries. 25 * 26 * PMP registers are accessed with the csr instruction which only takes an 27 * immediate value as the actual register. In order to avoid traversing 28 * the whole register list, we use the start index to jump directly to the 29 * location corresponding to the start of the wanted range. For this to work 30 * we disallow compressed instructions so the update block sizes are easily 31 * known (luckily they're all power-of-2's simplifying the code further). 32 * 33 * start < end && end <= CONFIG_PMP_SLOTS must be true. 34 */ 35 36GTEXT(z_riscv_write_pmp_entries) 37SECTION_FUNC(TEXT, z_riscv_write_pmp_entries) 38 39 la t0, pmpaddr_store 40 slli t1, a0, 4 /* 16-byte instruction blocks */ 41 add t0, t0, t1 42 jr t0 43 44pmpaddr_store: 45 46 .option push 47 .option norvc 48 .set _index, 0 49 .rept CONFIG_PMP_SLOTS 50 lr t0, (RV_REGSIZE * _index)(a3) 51 li t1, _index + 1 52 csrw (CSR_PMPADDR_BASE + _index), t0 53 beq t1, a1, pmpaddr_done 54 .set _index, _index + 1 55 .endr 56 .option pop 57 58pmpaddr_done: 59 60 /* 61 * Move to the pmpcfg space: 62 * a0 = a0 / RV_REGSIZE 63 * a1 = (a1 + RV_REGSIZE - 1) / RV_REGSIZE 64 */ 65 la t0, pmpcfg_store 66 srli a0, a0, RV_REGSHIFT 67 slli t1, a0, 4 /* 16-byte instruction blocks */ 68 add t0, t0, t1 69 addi a1, a1, RV_REGSIZE - 1 70 srli a1, a1, RV_REGSHIFT 71 jr t0 72 73pmpcfg_store: 74 75 .option push 76 .option norvc 77 .set _index, 0 78 .rept (CONFIG_PMP_SLOTS / RV_REGSIZE) 79 lr t0, (RV_REGSIZE * _index)(a4) 80 addi a0, a0, 1 81 csrw (CSR_PMPCFG_BASE + RV_REGSIZE/4 * _index), t0 82 beq a0, a1, pmpcfg_done 83 .set _index, _index + 1 84 .endr 85 .option pop 86 87pmpcfg_done: 88 89 beqz a2, done 90 91 la t0, pmpcfg_zerotail 92 slli a0, a0, 2 /* 4-byte instruction blocks */ 93 add t0, t0, a0 94 jr t0 95 96pmpcfg_zerotail: 97 98 .option push 99 .option norvc 100 .set _index, 0 101 .rept (CONFIG_PMP_SLOTS / RV_REGSIZE) 102 csrw (CSR_PMPCFG_BASE + RV_REGSIZE/4 * _index), zero 103 .set _index, _index + 1 104 .endr 105 .option pop 106 107done: ret 108