33 * "LICENSE" for information on usage and redistribution of this file.
44 */
55
6- #if !RV32_HAS (SYSTEM )
7- #error "Do not manage to build this file unless you enable system support."
8- #endif
9-
106#include <assert.h>
117
12- #include "devices/plic.h"
13- #include "devices/uart.h"
14- #include "devices/virtio.h"
15- #include "riscv_private.h"
16-
17- #define R 1
18- #define W 0
8+ #include "system.h"
199
20- #if RV32_HAS ( SYSTEM ) && !RV32_HAS (ELF_LOADER )
10+ #if !RV32_HAS (ELF_LOADER )
2111void emu_update_uart_interrupts (riscv_t * rv )
2212{
2313 vm_attr_t * attr = PRIV (rv );
@@ -29,7 +19,7 @@ void emu_update_uart_interrupts(riscv_t *rv)
2919 plic_update_interrupts (attr -> plic );
3020}
3121
32- static void emu_update_vblk_interrupts (riscv_t * rv )
22+ void emu_update_vblk_interrupts (riscv_t * rv )
3323{
3424 vm_attr_t * attr = PRIV (rv );
3525 if (attr -> vblk -> interrupt_status )
@@ -38,112 +28,6 @@ static void emu_update_vblk_interrupts(riscv_t *rv)
3828 attr -> plic -> active &= ~IRQ_VBLK_BIT ;
3929 plic_update_interrupts (attr -> plic );
4030}
41- /*
42- * Linux kernel might create signal frame when returning from trap
43- * handling, which modifies the SEPC CSR. Thus, the fault instruction
44- * cannot always redo. For example, invalid memory access causes SIGSEGV.
45- */
46- extern bool need_handle_signal ;
47- #define CHECK_PENDING_SIGNAL (rv , signal_flag ) \
48- do { \
49- signal_flag = (rv->csr_sepc != rv->last_csr_sepc); \
50- } while (0)
51-
52- #define MMIO_R 1
53- #define MMIO_W 0
54-
55- enum SUPPORTED_MMIO {
56- MMIO_PLIC ,
57- MMIO_UART ,
58- MMIO_VIRTIOBLK ,
59- };
60-
61- /* clang-format off */
62- #define MMIO_OP (io , rw ) \
63- switch(io){ \
64- case MMIO_PLIC: \
65- IIF(rw)( /* read */ \
66- mmio_read_val = plic_read (PRIV (rv )-> plic , addr & 0x3FFFFFF ); \
67- plic_update_interrupts (PRIV (rv )-> plic ); \
68- return mmio_read_val ; \
69- , /* write */ \
70- plic_write (PRIV (rv )-> plic , addr & 0x3FFFFFF , val ); \
71- plic_update_interrupts (PRIV (rv )-> plic ); \
72- return ; \
73- ) \
74- break ; \
75- case MMIO_UART : \
76- IIF (rw )( /* read */ \
77- mmio_read_val = u8250_read (PRIV (rv )-> uart , addr & 0xFFFFF ); \
78- emu_update_uart_interrupts (rv ); \
79- return mmio_read_val ; \
80- , /* write */ \
81- u8250_write (PRIV (rv )-> uart , addr & 0xFFFFF , val ); \
82- emu_update_uart_interrupts (rv ); \
83- return ; \
84- ) \
85- break ; \
86- case MMIO_VIRTIOBLK : \
87- IIF (rw )( /* read */ \
88- mmio_read_val = virtio_blk_read (PRIV (rv )-> vblk , addr & 0xFFFFF ); \
89- emu_update_vblk_interrupts (rv ); \
90- return mmio_read_val ; \
91- , /* write */ \
92- virtio_blk_write (PRIV (rv )-> vblk , addr & 0xFFFFF , val ); \
93- emu_update_vblk_interrupts (rv ); \
94- return ; \
95- ) \
96- break ; \
97- default : \
98- rv_log_error ("Unknown MMIO type %d" , io ); \
99- break ; \
100- }
101- /* clang-format on */
102-
103- #define MMIO_READ () \
104- do { \
105- uint32_t mmio_read_val; \
106- if ((addr >> 28) == 0xF) { /* MMIO at 0xF_______ */ \
107- /* 256 regions of 1MiB */ \
108- switch ((addr >> 20 ) & MASK (8 )) { \
109- case 0x0 : \
110- case 0x2 : /* PLIC (0 - 0x3F) */ \
111- MMIO_OP (MMIO_PLIC , MMIO_R ); \
112- break ; \
113- case 0x40 : /* UART */ \
114- MMIO_OP (MMIO_UART , MMIO_R ); \
115- break ; \
116- case 0x42 : /* Virtio-blk */ \
117- MMIO_OP (MMIO_VIRTIOBLK , MMIO_R ); \
118- break ; \
119- default : \
120- __UNREACHABLE ; \
121- break ; \
122- } \
123- } \
124- } while (0 )
125-
126- #define MMIO_WRITE () \
127- do { \
128- if ((addr >> 28) == 0xF) { /* MMIO at 0xF_______ */ \
129- /* 256 regions of 1MiB */ \
130- switch ((addr >> 20 ) & MASK (8 )) { \
131- case 0x0 : \
132- case 0x2 : /* PLIC (0 - 0x3F) */ \
133- MMIO_OP (MMIO_PLIC , MMIO_W ); \
134- break ; \
135- case 0x40 : /* UART */ \
136- MMIO_OP (MMIO_UART , MMIO_W ); \
137- break ; \
138- case 0x42 : /* Virtio-blk */ \
139- MMIO_OP (MMIO_VIRTIOBLK , MMIO_W ); \
140- break ; \
141- default : \
142- __UNREACHABLE ; \
143- break ; \
144- } \
145- } \
146- } while (0 )
14731#endif
14832
14933static bool ppn_is_valid (riscv_t * rv , uint32_t ppn )
@@ -221,8 +105,8 @@ pte_t *mmu_walk(riscv_t *rv, const uint32_t vaddr, uint32_t *level)
221105#define MMU_FAULT_CHECK (op , rv , pte , vaddr , access_bits ) \
222106 mmu_##op##_fault_check(rv, pte, vaddr, access_bits)
223107#define MMU_FAULT_CHECK_IMPL (op , pgfault ) \
224- static bool mmu_##op##_fault_check(riscv_t *rv, pte_t *pte, \
225- uint32_t vaddr, uint32_t access_bits) \
108+ bool mmu_##op##_fault_check(riscv_t *rv, pte_t *pte, uint32_t vaddr, \
109+ uint32_t access_bits) \
226110 { \
227111 uint32_t scause; \
228112 uint32_t stval = vaddr; \
@@ -285,16 +169,6 @@ MMU_FAULT_CHECK_IMPL(ifetch, pagefault_insn)
285169MMU_FAULT_CHECK_IMPL (read , pagefault_load )
286170MMU_FAULT_CHECK_IMPL (write , pagefault_store )
287171
288- uint32_t ppn ;
289- uint32_t offset ;
290- #define get_ppn_and_offset () \
291- do { \
292- assert(pte); \
293- ppn = *pte >> (RV_PG_SHIFT - 2) << RV_PG_SHIFT; \
294- offset = level == 1 ? vaddr & MASK((RV_PG_SHIFT + 10)) \
295- : vaddr & MASK(RV_PG_SHIFT); \
296- } while (0)
297-
298172/* The IO handler that operates when the Memory Management Unit (MMU)
299173 * is enabled during system emulation is responsible for managing
300174 * input/output operations. These callbacks are designed to implement
@@ -449,7 +323,7 @@ static void mmu_write_b(riscv_t *rv, const uint32_t vaddr, const uint8_t val)
449323 * TODO: dTLB can be introduced here to
450324 * cache the gVA to gPA tranlation.
451325 */
452- static uint32_t mmu_translate (riscv_t * rv , uint32_t vaddr , bool rw )
326+ uint32_t mmu_translate (riscv_t * rv , uint32_t vaddr , bool rw )
453327{
454328 if (!rv -> csr_satp )
455329 return vaddr ;
0 commit comments