1 /*
2  * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3  * Copyright 2015, 2016 Hesham Almatary <heshamelmatary@gmail.com>
4  *
5  * SPDX-License-Identifier: GPL-2.0-only
6  */
7 
8 #pragma once
9 
10 #include <util.h>
11 
12 #include <mode/hardware.h>
13 
14 /* Privileged CSR definitions */
15 #define SSTATUS_SPIE  0x00000020
16 #define SSTATUS_SPP   0x00000100
17 #define SSTATUS_FS    0x00006000
18 
19 #define SSTATUS_FS_CLEAN    0x00004000
20 #define SSTATUS_FS_INITIAL  0x00002000
21 #define SSTATUS_FS_DIRTY    0x00006000
22 
23 #define SATP_MODE_OFF  0
24 #define SATP_MODE_SV32 1
25 #define SATP_MODE_SV39 8
26 #define SATP_MODE_SV48 9
27 
28 #ifndef __ASSEMBLER__
29 
30 #include <config.h>
31 #include <linker.h>
32 
33 #include <arch/types.h>
34 #include <sel4/sel4_arch/constants.h>
35 
36 /* The size is for HiFive Unleashed */
37 #define L1_CACHE_LINE_SIZE_BITS     6
38 #define L1_CACHE_LINE_SIZE          BIT(L1_CACHE_LINE_SIZE_BITS)
39 
40 #define PAGE_BITS seL4_PageBits
41 
42 /* MMU RISC-V related definitions. See RISC-V manual priv-1.10 */
43 
44 /* Extract the n-level PT index from a virtual address. This works for any
45  * configured RISC-V system with CONFIG_PT_LEVEL (which can be 2 on Sv32,
46  * 3 on Sv39, or 4 on Sv48)
47  */
48 #define RISCV_GET_PT_INDEX(addr, n)  (((addr) >> (((PT_INDEX_BITS) * (((CONFIG_PT_LEVELS) - 1) - (n))) + seL4_PageBits)) & MASK(PT_INDEX_BITS))
49 #define RISCV_GET_LVL_PGSIZE_BITS(n) (((PT_INDEX_BITS) * (((CONFIG_PT_LEVELS) - 1) - (n))) + seL4_PageBits)
50 #define RISCV_GET_LVL_PGSIZE(n)      BIT(RISCV_GET_LVL_PGSIZE_BITS((n)))
51 /*
52  * These values are defined in RISC-V priv-1.10 manual, they represent the
53  * exception codes saved in scause register (by the hardware) on traps.
54  */
55 enum vm_fault_type {
56     RISCVInstructionMisaligned = 0,
57     RISCVInstructionAccessFault = 1,
58     RISCVInstructionIllegal = 2,
59     RISCVBreakpoint = 3,
60     /* reserved */
61     RISCVLoadAccessFault = 5,
62     RISCVAddressMisaligned = 6,
63     RISCVStoreAccessFault = 7,
64     RISCVEnvCall = 8,
65     /* 9-11 reserved */
66     RISCVInstructionPageFault = 12,
67     RISCVLoadPageFault = 13,
68     /* 14 - reserved */
69     RISCVStorePageFault = 15
70                           /* >= 16 reserved */
71 };
72 typedef word_t vm_fault_type_t;
73 
74 enum frameSizeConstants {
75     RISCVPageBits        = seL4_PageBits,
76     RISCVMegaPageBits    = seL4_LargePageBits,
77 #if CONFIG_PT_LEVELS > 2
78     RISCVGigaPageBits    = seL4_HugePageBits,
79 #endif
80 #if CONFIG_PT_LEVELS > 3
81     RISCVTeraPageBits    = seL4_TeraPageBits
82 #endif
83 };
84 
85 enum vm_page_size {
86     RISCV_4K_Page,
87     RISCV_Mega_Page,
88     RISCV_Giga_Page,
89     RISCV_Tera_Page
90 };
91 typedef word_t vm_page_size_t;
92 
pageBitsForSize(vm_page_size_t pagesize)93 static inline word_t CONST pageBitsForSize(vm_page_size_t pagesize)
94 {
95     switch (pagesize) {
96     case RISCV_4K_Page:
97         return RISCVPageBits;
98 
99     case RISCV_Mega_Page:
100         return RISCVMegaPageBits;
101 
102 #if CONFIG_PT_LEVELS > 2
103     case RISCV_Giga_Page:
104         return RISCVGigaPageBits;
105 #endif
106 
107 #if CONFIG_PT_LEVELS > 3
108     case RISCV_Tera_Page:
109         return RISCVTeraPageBits;
110 #endif
111 
112     default:
113         fail("Invalid page size");
114     }
115 }
116 
arch_clean_invalidate_caches(void)117 static inline void arch_clean_invalidate_caches(void)
118 {
119     /* RISC-V doesn't have an architecture defined way of flushing caches */
120 }
121 #endif /* __ASSEMBLER__ */
122 
123 #define LOAD_S STRINGIFY(LOAD)
124 #define STORE_S STRINGIFY(STORE)
125 
126 #define IPI_MEM_BARRIER \
127     do { \
128         asm volatile("fence rw,rw" ::: "memory"); \
129     } while (0)
130 
131