3
3
* "LICENSE" for information on usage and redistribution of this file.
4
4
*/
5
5
6
- #if !RV32_HAS (SYSTEM )
7
- #error "Do not manage to build this file unless you enable system support."
8
- #endif
9
-
10
6
#include <assert.h>
11
7
12
8
#include "devices/plic.h"
13
9
#include "devices/uart.h"
14
10
#include "riscv_private.h"
11
+ #include "system.h"
15
12
16
- #if RV32_HAS ( SYSTEM ) && !RV32_HAS (ELF_LOADER )
13
+ #if !RV32_HAS (ELF_LOADER )
17
14
void emu_update_uart_interrupts (riscv_t * rv )
18
15
{
19
16
vm_attr_t * attr = PRIV (rv );
@@ -24,84 +21,6 @@ void emu_update_uart_interrupts(riscv_t *rv)
24
21
attr -> plic -> active &= ~IRQ_UART_BIT ;
25
22
plic_update_interrupts (attr -> plic );
26
23
}
27
-
28
- #define MMIO_R 1
29
- #define MMIO_W 0
30
-
31
- enum SUPPORTED_MMIO {
32
- MMIO_PLIC ,
33
- MMIO_UART ,
34
- };
35
-
36
- /* clang-format off */
37
- #define MMIO_OP (io , rw ) \
38
- switch(io){ \
39
- case MMIO_PLIC: \
40
- IIF(rw)( /* read */ \
41
- mmio_read_val = plic_read (PRIV (rv )-> plic , addr & 0x3FFFFFF ); \
42
- plic_update_interrupts (PRIV (rv )-> plic ); \
43
- return mmio_read_val ; \
44
- , /* write */ \
45
- plic_write (PRIV (rv )-> plic , addr & 0x3FFFFFF , val ); \
46
- plic_update_interrupts (PRIV (rv )-> plic ); \
47
- return ; \
48
- ) \
49
- break ; \
50
- case MMIO_UART : \
51
- IIF (rw )( /* read */ \
52
- mmio_read_val = u8250_read (PRIV (rv )-> uart , addr & 0xFFFFF ); \
53
- emu_update_uart_interrupts (rv ); \
54
- return mmio_read_val ; \
55
- , /* write */ \
56
- u8250_write (PRIV (rv )-> uart , addr & 0xFFFFF , val ); \
57
- emu_update_uart_interrupts (rv ); \
58
- return ; \
59
- ) \
60
- break ; \
61
- default : \
62
- fprintf (stderr , "unknown MMIO type %d\n" , io ); \
63
- break ; \
64
- }
65
- /* clang-format on */
66
-
67
- #define MMIO_READ () \
68
- do { \
69
- uint32_t mmio_read_val; \
70
- if ((addr >> 28) == 0xF) { /* MMIO at 0xF_______ */ \
71
- /* 256 regions of 1MiB */ \
72
- switch ((addr >> 20 ) & MASK (8 )) { \
73
- case 0x0 : \
74
- case 0x2 : /* PLIC (0 - 0x3F) */ \
75
- MMIO_OP (MMIO_PLIC , MMIO_R ); \
76
- break ; \
77
- case 0x40 : /* UART */ \
78
- MMIO_OP (MMIO_UART , MMIO_R ); \
79
- break ; \
80
- default : \
81
- __UNREACHABLE ; \
82
- break ; \
83
- } \
84
- } \
85
- } while (0 )
86
-
87
- #define MMIO_WRITE () \
88
- do { \
89
- if ((addr >> 28) == 0xF) { /* MMIO at 0xF_______ */ \
90
- /* 256 regions of 1MiB */ \
91
- switch ((addr >> 20 ) & MASK (8 )) { \
92
- case 0x0 : \
93
- case 0x2 : /* PLIC (0 - 0x3F) */ \
94
- MMIO_OP (MMIO_PLIC , MMIO_W ); \
95
- break ; \
96
- case 0x40 : /* UART */ \
97
- MMIO_OP (MMIO_UART , MMIO_W ); \
98
- break ; \
99
- default : \
100
- __UNREACHABLE ; \
101
- break ; \
102
- } \
103
- } \
104
- } while (0 )
105
24
#endif
106
25
107
26
static bool ppn_is_valid (riscv_t * rv , uint32_t ppn )
@@ -116,14 +35,7 @@ static bool ppn_is_valid(riscv_t *rv, uint32_t ppn)
116
35
? (uint32_t *) (attr->mem->mem_base + (ppn << (RV_PG_SHIFT))) \
117
36
: NULL
118
37
119
- /* Walk through page tables and get the corresponding PTE by virtual address if
120
- * exists
121
- * @rv: RISC-V emulator
122
- * @addr: virtual address
123
- * @level: the level of which the PTE is located
124
- * @return: NULL if a not found or fault else the corresponding PTE
125
- */
126
- static uint32_t * mmu_walk (riscv_t * rv , const uint32_t addr , uint32_t * level )
38
+ uint32_t * mmu_walk (riscv_t * rv , const uint32_t addr , uint32_t * level )
127
39
{
128
40
vm_attr_t * attr = PRIV (rv );
129
41
uint32_t ppn = rv -> csr_satp & MASK (22 );
@@ -178,81 +90,71 @@ static uint32_t *mmu_walk(riscv_t *rv, const uint32_t addr, uint32_t *level)
178
90
/* FIXME: handle access fault, addr out of range check */
179
91
#define MMU_FAULT_CHECK (op , rv , pte , addr , access_bits ) \
180
92
mmu_##op##_fault_check(rv, pte, addr, access_bits)
181
- #define MMU_FAULT_CHECK_IMPL (op , pgfault ) \
182
- static bool mmu_##op##_fault_check(riscv_t *rv, pte_t *pte, uint32_t addr, \
183
- uint32_t access_bits) \
184
- { \
185
- uint32_t scause; \
186
- uint32_t stval = addr; \
187
- switch (access_bits) { \
188
- case PTE_R: \
189
- scause = PAGEFAULT_LOAD; \
190
- break; \
191
- case PTE_W: \
192
- scause = PAGEFAULT_STORE; \
193
- break; \
194
- case PTE_X: \
195
- scause = PAGEFAULT_INSN; \
196
- break; \
197
- default: \
198
- __UNREACHABLE; \
199
- break; \
200
- } \
201
- if (pte && (!(*pte & PTE_V))) { \
202
- SET_CAUSE_AND_TVAL_THEN_TRAP(rv, scause, stval); \
203
- return false; \
204
- } \
205
- if (!(pte && (*pte & access_bits))) { \
206
- SET_CAUSE_AND_TVAL_THEN_TRAP(rv, scause, stval); \
207
- return false; \
208
- } \
209
- /* \
210
- * (1) When MXR=0, only loads from pages marked readable (R=1) will \
211
- * succeed. \
212
- * \
213
- * (2) When MXR=1, loads from pages marked either readable or \
214
- * executable (R=1 or X=1) will succeed. \
215
- */ \
216
- if (pte && ((!(SSTATUS_MXR & rv -> csr_sstatus ) && !(* pte & PTE_R ) && \
217
- (access_bits == PTE_R )) || \
218
- ((SSTATUS_MXR & rv -> csr_sstatus ) && \
219
- !((* pte & PTE_R ) | (* pte & PTE_X )) && \
220
- (access_bits == PTE_R )))) { \
221
- SET_CAUSE_AND_TVAL_THEN_TRAP (rv , scause , stval ); \
222
- return false; \
223
- } \
224
- /* \
225
- * When SUM=0, S-mode memory accesses to pages that are accessible by \
226
- * U-mode will fault. \
227
- */ \
228
- if (pte && rv -> priv_mode == RV_PRIV_S_MODE && \
229
- !(SSTATUS_SUM & rv -> csr_sstatus ) && (* pte & PTE_U )) { \
230
- SET_CAUSE_AND_TVAL_THEN_TRAP (rv , scause , stval ); \
231
- return false; \
232
- } \
233
- /* PTE not found, map it in handler */ \
234
- if (!pte ) { \
235
- SET_CAUSE_AND_TVAL_THEN_TRAP (rv , scause , stval ); \
236
- return false; \
237
- } \
238
- /* valid PTE */ \
239
- return true; \
93
+ #define MMU_FAULT_CHECK_IMPL (op , pgfault ) \
94
+ bool mmu_##op##_fault_check(riscv_t *rv, pte_t *pte, uint32_t addr, \
95
+ uint32_t access_bits) \
96
+ { \
97
+ uint32_t scause; \
98
+ uint32_t stval = addr; \
99
+ switch (access_bits) { \
100
+ case PTE_R: \
101
+ scause = PAGEFAULT_LOAD; \
102
+ break; \
103
+ case PTE_W: \
104
+ scause = PAGEFAULT_STORE; \
105
+ break; \
106
+ case PTE_X: \
107
+ scause = PAGEFAULT_INSN; \
108
+ break; \
109
+ default: \
110
+ __UNREACHABLE; \
111
+ break; \
112
+ } \
113
+ if (pte && (!(*pte & PTE_V))) { \
114
+ SET_CAUSE_AND_TVAL_THEN_TRAP(rv, scause, stval); \
115
+ return false; \
116
+ } \
117
+ if (!(pte && (*pte & access_bits))) { \
118
+ SET_CAUSE_AND_TVAL_THEN_TRAP(rv, scause, stval); \
119
+ return false; \
120
+ } \
121
+ /* \
122
+ * (1) When MXR=0, only loads from pages marked readable (R=1) will \
123
+ * succeed. \
124
+ * \
125
+ * (2) When MXR=1, loads from pages marked either readable or \
126
+ * executable (R=1 or X=1) will succeed. \
127
+ */ \
128
+ if (pte && ((!(SSTATUS_MXR & rv -> csr_sstatus ) && !(* pte & PTE_R ) && \
129
+ (access_bits == PTE_R )) || \
130
+ ((SSTATUS_MXR & rv -> csr_sstatus ) && \
131
+ !((* pte & PTE_R ) | (* pte & PTE_X )) && \
132
+ (access_bits == PTE_R )))) { \
133
+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , scause , stval ); \
134
+ return false; \
135
+ } \
136
+ /* \
137
+ * When SUM=0, S-mode memory accesses to pages that are accessible by \
138
+ * U-mode will fault. \
139
+ */ \
140
+ if (pte && rv -> priv_mode == RV_PRIV_S_MODE && \
141
+ !(SSTATUS_SUM & rv -> csr_sstatus ) && (* pte & PTE_U )) { \
142
+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , scause , stval ); \
143
+ return false; \
144
+ } \
145
+ /* PTE not found, map it in handler */ \
146
+ if (!pte ) { \
147
+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , scause , stval ); \
148
+ return false; \
149
+ } \
150
+ /* valid PTE */ \
151
+ return true; \
240
152
}
241
153
242
154
MMU_FAULT_CHECK_IMPL (ifetch , pagefault_insn )
243
155
MMU_FAULT_CHECK_IMPL (read , pagefault_load )
244
156
MMU_FAULT_CHECK_IMPL (write , pagefault_store )
245
157
246
- #define get_ppn_and_offset () \
247
- uint32_t ppn; \
248
- uint32_t offset; \
249
- do { \
250
- assert(pte); \
251
- ppn = *pte >> (RV_PG_SHIFT - 2) << RV_PG_SHIFT; \
252
- offset = level == 1 ? addr & MASK((RV_PG_SHIFT + 10)) \
253
- : addr & MASK(RV_PG_SHIFT); \
254
- } while (0)
255
-
256
158
/* The IO handler that operates when the Memory Management Unit (MMU)
257
159
* is enabled during system emulation is responsible for managing
258
160
* input/output operations. These callbacks are designed to implement
0 commit comments