Skip to content

Commit 0e83965

Browse files
committed
cpu/riscv: Add PMP driver
1 parent 561e193 commit 0e83965

File tree

17 files changed

+561
-1
lines changed

17 files changed

+561
-1
lines changed

Makefile.dep

+4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ ifneq (,$(filter mpu_noexec_ram,$(USEMODULE)))
3333
FEATURES_REQUIRED += cortexm_mpu
3434
endif
3535

36+
ifneq (,$(filter pmp_noexec_ram,$(USEMODULE)))
37+
FEATURES_REQUIRED += periph_pmp
38+
endif
39+
3640
ifneq (,$(filter lwip_%,$(USEMODULE)))
3741
USEPKG += lwip
3842
endif

core/lib/include/panic.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ typedef enum {
3737
PANIC_HARD_REBOOT,
3838
PANIC_ASSERT_FAIL,
3939
PANIC_EXPECT_FAIL,
40+
PANIC_MEM_MANAGE, /**< memory management fault */
4041
#ifdef MODULE_CORTEXM_COMMON
4142
PANIC_NMI_HANDLER, /**< non maskable interrupt */
4243
PANIC_HARD_FAULT, /**< hard fault */
4344
#if defined(CPU_CORE_CORTEX_M3) || defined(CPU_CORE_CORTEX_M33) || \
4445
defined(CPU_CORE_CORTEX_M4) || defined(CPU_CORE_CORTEX_M4F) || \
4546
defined(CPU_CORE_CORTEX_M7)
46-
PANIC_MEM_MANAGE, /**< memory controller interrupt */
4747
PANIC_BUS_FAULT, /**< bus fault */
4848
PANIC_USAGE_FAULT, /**< undefined instruction or unaligned access */
4949
PANIC_DEBUG_MON, /**< debug interrupt */

cpu/fe310/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ config CPU_FAM_FE310
1313
select HAS_PERIPH_GPIO
1414
select HAS_PERIPH_GPIO_IRQ
1515
select HAS_PERIPH_PM
16+
select HAS_PERIPH_PMP
1617
select HAS_PERIPH_PLIC
1718
select HAS_PERIPH_RTT_OVERFLOW
1819
select HAS_PERIPH_RTT_SET_COUNTER

cpu/fe310/Makefile.features

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ CPU_CORE := rv32imac
33
FEATURES_PROVIDED += periph_cpuid
44
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
55
FEATURES_PROVIDED += periph_pm
6+
FEATURES_PROVIDED += periph_pmp
67
FEATURES_PROVIDED += periph_plic
78
FEATURES_PROVIDED += periph_rtt_overflow
89
FEATURES_PROVIDED += periph_rtt_set_counter

cpu/fe310/include/cpu_conf.h

+6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ extern "C" {
3636
*/
3737
#define PLIC_BASE_ADDR (PLIC_CTRL_ADDR)
3838

39+
/**
40+
* @brief Number of available PMP regions
41+
* Note, the upper 8 regions are hardwired to zero!
42+
*/
43+
#define NUM_PMP_ENTRIES 16
44+
3945
#ifdef __cplusplus
4046
}
4147
#endif

cpu/riscv_common/include/pmp.h

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright (C) 2023 Bennet Blischke <[email protected]>
3+
*
4+
* This file is subject to the terms and conditions of the GNU Lesser General
5+
* Public License v2.1. See the file LICENSE in the top level directory for more
6+
* details.
7+
*/
8+
9+
/**
10+
* @ingroup cpu_riscv_common
11+
* @{
12+
*
13+
* @file
14+
* @brief RISC-V PMP configuration options
15+
*
16+
* RISCV implementations using this peripheral must define the `NUM_PMP_ENTRIES`
17+
* `NUM_PMP_ENTRIES` must be 16 or 64.
18+
*
19+
* @author Bennet Blischke
20+
*/
21+
22+
#ifndef PMP_H
23+
#define PMP_H
24+
25+
#include <assert.h>
26+
#include <stdint.h>
27+
28+
#ifdef __cplusplus
29+
extern "C" {
30+
#endif
31+
32+
/**
33+
* @name Bit masks for the PMP configuration register
34+
* @{
35+
*/
36+
#define PMP_NONE 0x00 /**< No access allowed at all */
37+
#define PMP_R 0x01 /**< Allow read access */
38+
#define PMP_W 0x02 /**< Allow write access */
39+
#define PMP_X 0x04 /**< Allow execution */
40+
41+
#define PMP_A 0x18 /**< Addressing mode mask */
42+
#define PMP_OFF 0x00 /**< Disable this pmp entry */
43+
#define PMP_TOR 0x08 /**< Top-of-range addressing mode */
44+
#define PMP_NA4 0x10 /**< Naturally aligned four-byte region */
45+
#define PMP_NAPOT 0x18 /**< Naturally aligned power-of-two region, ≥8 bytes */
46+
47+
#define PMP_L 0x80 /**< Lock; read-only config & applies to machine-mode */
48+
/** @} */
49+
50+
/**
51+
* @brief Create a NAPOT formatted address
52+
*
53+
* @param addr Base address, must be aligned to the size of the region
54+
* @param size Size of the region in bytes
55+
*/
56+
static inline uint32_t make_napot(uint32_t addr, uint32_t size)
57+
{
58+
assert(addr % size == 0);
59+
return addr | ((size - 1) >> 1);
60+
}
61+
62+
/**
63+
* @brief Writes a complete pmpcfg register
64+
*
65+
* @param reg_num Register number
66+
* @param value Value to write
67+
*/
68+
void write_pmpcfg(uint8_t reg_num, uint32_t value);
69+
70+
/**
71+
* @brief Read a complete pmpcfg register
72+
*
73+
* @param[in] reg_num Register number
74+
*
75+
* @return Contents of the specified register
76+
*/
77+
uint32_t read_pmpcfg(uint8_t reg_num);
78+
79+
/**
80+
* @brief Writes a complete pmpaddr register
81+
*
82+
* @param reg_num Register number
83+
* @param value Value to write
84+
*/
85+
void write_pmpaddr(uint8_t reg_num, uint32_t value);
86+
87+
/**
88+
* @brief Read a complete pmpaddr register
89+
*
90+
* @param[in] reg_num Register number
91+
*
92+
* @return Contents of the specified register
93+
*/
94+
uint32_t read_pmpaddr(uint8_t reg_num);
95+
96+
/**
97+
* @brief Read a single pmpcfg sub-register
98+
*
99+
* @param[in] entry Sub-register number
100+
*
101+
* @return Contents of the specified sub-register
102+
*/
103+
uint8_t get_pmpcfg(uint8_t entry);
104+
105+
/**
106+
* @brief Set's a single pmpcfg sub-register
107+
*
108+
* @param entry Sub-register number
109+
* @param value Value to write
110+
*/
111+
void set_pmpcfg(uint8_t entry, uint8_t value);
112+
113+
/**
114+
* @brief Prints a single pmpcfg sub-register human readable
115+
*
116+
* @param entry Register number to print
117+
*/
118+
void print_pmpcfg(uint8_t entry);
119+
120+
#ifdef __cplusplus
121+
}
122+
#endif
123+
124+
#endif /* PMP_H */
125+
/** @} */

cpu/riscv_common/include/vendor/riscv_csr.h

+3
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@
171171

172172
#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
173173

174+
#define CSR_PMPCFG0 0x3a0 // PMP configuration base register
175+
#define CSR_PMPADDR0 0x3b0 // PMP address base register
176+
174177
#ifdef __riscv
175178

176179
#ifdef __riscv64

cpu/riscv_common/irq_arch.c

+8
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ static void handle_trap(uword_t mcause)
134134
write_csr(mepc, return_pc + 4);
135135
break;
136136
}
137+
#ifdef MODULE_PERIPH_PMP
138+
case CAUSE_FAULT_FETCH:
139+
core_panic(PANIC_MEM_MANAGE, "MEM MANAGE HANDLER (fetch)");
140+
case CAUSE_FAULT_LOAD:
141+
core_panic(PANIC_MEM_MANAGE, "MEM MANAGE HANDLER (load)");
142+
case CAUSE_FAULT_STORE:
143+
core_panic(PANIC_MEM_MANAGE, "MEM MANAGE HANDLER (store)");
144+
#endif
137145
default:
138146
#ifdef DEVELHELP
139147
printf("Unhandled trap:\n");

cpu/riscv_common/periph/Kconfig

+6
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,10 @@ config MODULE_PERIPH_PLIC
3232
help
3333
Platform-Level interrupt controller driver.
3434

35+
config MODULE_PERIPH_PMP
36+
bool
37+
depends on HAS_PERIPH_PMP
38+
help
39+
Physical memory protection driver.
40+
3541
endif # MODULE_RISCV_COMMON_PERIPH

0 commit comments

Comments
 (0)