1 /*
2  * Copyright (c) 2020 BayLibre, SAS
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef CORE_PMP_H_
8 #define CORE_PMP_H_
9 
10 /* Configuration register flags (cfg_val)*/
11 #define PMP_R		0x01	/* Allow read */
12 #define PMP_W		0x02	/* Allow write */
13 #define PMP_X		0x04	/* Allow execute */
14 #define PMP_A		0x18	/* Address-matching mode field */
15 #define PMP_L		0x80	/* PMP entry is locked */
16 #define PMP_OFF		0x00	/* Null region */
17 #define PMP_TOR		0x08	/* Top of range */
18 #define PMP_NA4		0x10	/* Naturally aligned four-byte region */
19 #define PMP_NAPOT	0x18	/* Naturally aligned power-of-two region */
20 
21 #define PMP_SHIFT_ADDR	2
22 #define PMP_TYPE_MASK		0x18
23 #define TO_PMP_ADDR(addr)	((addr) >> PMP_SHIFT_ADDR)
24 #define FROM_PMP_ADDR(addr)	((addr) << PMP_SHIFT_ADDR)
25 #define TO_NAPOT_RANGE(size)	(((size) - 1) >> 1)
26 #define TO_PMP_NAPOT(addr, size)	TO_PMP_ADDR(addr | \
27 					TO_NAPOT_RANGE(size))
28 
29 #ifdef CONFIG_PMP_STACK_GUARD
30 
31 #define PMP_GUARD_ALIGN_AND_SIZE CONFIG_PMP_STACK_GUARD_MIN_SIZE
32 
33 #else
34 
35 #define PMP_GUARD_ALIGN_AND_SIZE 0
36 
37 #endif /* CONFIG_PMP_STACK_GUARD */
38 
39 #ifdef CONFIG_RISCV_PMP
40 
41 /*
42  * @brief Set a Physical Memory Protection slot
43  *
44  * Configure a memory region to be secured by one of the 16 PMP entries.
45  *
46  * @param index		Number of the targeted PMP entrie (0 to 15 only).
47  * @param cfg_val	Configuration value (cf datasheet or defined flags)
48  * @param addr_val	Address register value
49  *
50  * This function shall only be called from Secure state.
51  *
52  * @return -1 if bad argument, 0 otherwise.
53  */
54 int z_riscv_pmp_set(unsigned int index, ulong_t cfg_val, ulong_t addr_val);
55 
56 /*
57  * @brief Reset to 0 all PMP setup registers
58  */
59 void z_riscv_pmp_clear_config(void);
60 
61 /*
62  * @brief Print PMP setup register for info/debug
63  */
64 void z_riscv_pmp_print(unsigned int index);
65 #endif /* CONFIG_RISCV_PMP */
66 
67 #if defined(CONFIG_USERSPACE)
68 
69 /*
70  * @brief Configure RISCV user thread access to the stack
71  *
72  * Determine and save allow access setup in thread structure.
73  *
74  * @param thread Thread info data pointer.
75  */
76 void z_riscv_init_user_accesses(struct k_thread *thread);
77 
78 /*
79  * @brief Apply RISCV user thread access to the stack
80  *
81  * Write user access setup saved in this thread structure.
82  *
83  * @param thread Thread info data pointer.
84  */
85 void z_riscv_configure_user_allowed_stack(struct k_thread *thread);
86 
87 /*
88  * @brief Add a new RISCV stack access
89  *
90  * Add a new memory permission area in the existing
91  * pmp setup of the thread.
92  *
93  * @param thread Thread info data pointer.
94  * @param addr   Start address of the memory area.
95  * @param size   Size of the memory area.
96  * @param flags  Pemissions: PMP_R, PMP_W, PMP_X, PMP_L
97  */
98 void z_riscv_pmp_add_dynamic(struct k_thread *thread,
99 			ulong_t addr,
100 			ulong_t size,
101 			unsigned char flags);
102 #endif /* CONFIG_USERSPACE */
103 
104 #ifdef CONFIG_PMP_STACK_GUARD
105 
106 /*
107  * @brief Configure RISCV stack guard for interrupt stack
108  *
109  * Write PMP registers to prevent RWX access from all privilege mode.
110  */
111 void z_riscv_configure_interrupt_stack_guard(void);
112 
113 /*
114  * @brief Configure RISCV stack guard
115  *
116  * Determine and save stack guard setup in thread structure.
117  *
118  * @param thread Thread info data pointer.
119  */
120 void z_riscv_init_stack_guard(struct k_thread *thread);
121 
122 /*
123  * @brief Apply RISCV stack guard
124  *
125  * Write stack guard setup saved in this thread structure.
126  *
127  * @param thread Thread info data pointer.
128  */
129 void z_riscv_configure_stack_guard(struct k_thread *thread);
130 #endif /* CONFIG_PMP_STACK_GUARD */
131 
132 #if defined(CONFIG_PMP_STACK_GUARD) || defined(CONFIG_USERSPACE)
133 
134 /*
135  * @brief Initialize thread PMP setup value to 0
136  *
137  * @param thread Thread info data pointer.
138  */
139 void z_riscv_pmp_init_thread(struct k_thread *thread);
140 #endif /* CONFIG_PMP_STACK_GUARD || CONFIG_USERSPACE */
141 
142 #endif /* CORE_PMP_H_ */
143