108 lines
2.5 KiB
ArmAsm
108 lines
2.5 KiB
ArmAsm
/*
|
|
* Copyright (c) 2022 BayLibre, SAS
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/toolchain.h>
|
|
#include <zephyr/linker/sections.h>
|
|
#include <zephyr/arch/cpu.h>
|
|
#include "asm_macros.inc"
|
|
|
|
#define CSR_PMPCFG_BASE 0x3a0
|
|
#define CSR_PMPADDR_BASE 0x3b0
|
|
|
|
/*
|
|
* Prototype:
|
|
*
|
|
* void z_riscv_write_pmp_entries(unsigned int start, // a0
|
|
* unsigned int end, // a1
|
|
* bool clear_trailing_entries, // a2
|
|
* unsigned long *pmp_addr, // a3
|
|
* unsigned long *pmp_cfg) // a4
|
|
*
|
|
* Called from pmp.c to write a range of PMP entries.
|
|
*
|
|
* PMP registers are accessed with the csr instruction which only takes an
|
|
* immediate value as the actual register. In order to avoid traversing
|
|
* the whole register list, we use the start index to jump directly to the
|
|
* location corresponding to the start of the wanted range. For this to work
|
|
* we disallow compressed instructions so the update block sizes are easily
|
|
* known (luckily they're all power-of-2's simplifying the code further).
|
|
*
|
|
* start < end && end <= CONFIG_PMP_SLOTS must be true.
|
|
*/
|
|
|
|
GTEXT(z_riscv_write_pmp_entries)
|
|
SECTION_FUNC(TEXT, z_riscv_write_pmp_entries)
|
|
|
|
la t0, pmpaddr_store
|
|
slli t1, a0, 4 /* 16-byte instruction blocks */
|
|
add t0, t0, t1
|
|
jr t0
|
|
|
|
pmpaddr_store:
|
|
|
|
.option push
|
|
.option norvc
|
|
.set _index, 0
|
|
.rept CONFIG_PMP_SLOTS
|
|
lr t0, (RV_REGSIZE * _index)(a3)
|
|
li t1, _index + 1
|
|
csrw (CSR_PMPADDR_BASE + _index), t0
|
|
beq t1, a1, pmpaddr_done
|
|
.set _index, _index + 1
|
|
.endr
|
|
.option pop
|
|
|
|
pmpaddr_done:
|
|
|
|
/*
|
|
* Move to the pmpcfg space:
|
|
* a0 = a0 / RV_REGSIZE
|
|
* a1 = (a1 + RV_REGSIZE - 1) / RV_REGSIZE
|
|
*/
|
|
la t0, pmpcfg_store
|
|
srli a0, a0, RV_REGSHIFT
|
|
slli t1, a0, 4 /* 16-byte instruction blocks */
|
|
add t0, t0, t1
|
|
addi a1, a1, RV_REGSIZE - 1
|
|
srli a1, a1, RV_REGSHIFT
|
|
jr t0
|
|
|
|
pmpcfg_store:
|
|
|
|
.option push
|
|
.option norvc
|
|
.set _index, 0
|
|
.rept (CONFIG_PMP_SLOTS / RV_REGSIZE)
|
|
lr t0, (RV_REGSIZE * _index)(a4)
|
|
addi a0, a0, 1
|
|
csrw (CSR_PMPCFG_BASE + RV_REGSIZE/4 * _index), t0
|
|
beq a0, a1, pmpcfg_done
|
|
.set _index, _index + 1
|
|
.endr
|
|
.option pop
|
|
|
|
pmpcfg_done:
|
|
|
|
beqz a2, done
|
|
|
|
la t0, pmpcfg_zerotail
|
|
slli a0, a0, 2 /* 4-byte instruction blocks */
|
|
add t0, t0, a0
|
|
jr t0
|
|
|
|
pmpcfg_zerotail:
|
|
|
|
.option push
|
|
.option norvc
|
|
.set _index, 0
|
|
.rept (CONFIG_PMP_SLOTS / RV_REGSIZE)
|
|
csrw (CSR_PMPCFG_BASE + RV_REGSIZE/4 * _index), zero
|
|
.set _index, _index + 1
|
|
.endr
|
|
.option pop
|
|
|
|
done: ret
|