1 /*
2  * Copyright (c) 2015 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #pragma once
9 
10 #include <lk/compiler.h>
11 #include <arch/defines.h>
12 #include <arch/riscv/asm.h>
13 
14 #define RISCV_USER_OFFSET   (0u)
15 #define RISCV_SUPER_OFFSET  (1u)
16 #define RISCV_HYPER_OFFSET  (2u)
17 #define RISCV_MACH_OFFSET   (3u)
18 
19 #if RISCV_M_MODE
20 # define RISCV_XMODE_OFFSET     (RISCV_MACH_OFFSET)
21 # define RISCV_XRET             mret
22 #elif RISCV_S_MODE
23 # define RISCV_XMODE_OFFSET     (RISCV_SUPER_OFFSET)
24 # define RISCV_XRET             sret
25 #else
26 # error Unrecognized RISC-V privilege level selected
27 #endif
28 
29 #define RISCV_CSR_XMODE_BITS     (RISCV_XMODE_OFFSET << 8)
30 
31 // These CSRs are only in user CSR space (still readable by all modes though)
32 #define RISCV_CSR_CYCLE     (0xc00)
33 #define RISCV_CSR_TIME      (0xc01)
34 #define RISCV_CSR_INSRET    (0xc02)
35 #define RISCV_CSR_CYCLEH    (0xc80)
36 #define RISCV_CSR_TIMEH     (0xc81)
37 #define RISCV_CSR_INSRETH   (0xc82)
38 
39 #define RISCV_CSR_XSTATUS   (0x000 | RISCV_CSR_XMODE_BITS)
40 #define RISCV_CSR_XIE       (0x004 | RISCV_CSR_XMODE_BITS)
41 #define RISCV_CSR_XTVEC     (0x005 | RISCV_CSR_XMODE_BITS)
42 #define RISCV_CSR_XSCRATCH  (0x040 | RISCV_CSR_XMODE_BITS)
43 #define RISCV_CSR_XEPC      (0x041 | RISCV_CSR_XMODE_BITS)
44 #define RISCV_CSR_XCAUSE    (0x042 | RISCV_CSR_XMODE_BITS)
45 #define RISCV_CSR_XTVAL     (0x043 | RISCV_CSR_XMODE_BITS)
46 #define RISCV_CSR_XIP       (0x044 | RISCV_CSR_XMODE_BITS)
47 
48 #if RISCV_M_MODE // Machine-mode only CSRs
49 #define RISCV_CSR_MCYCLE    (0xb00)
50 #define RISCV_CSR_MVENDORID (0xf11)
51 #define RISCV_CSR_MARCHID   (0xf12)
52 #define RISCV_CSR_MIMPID    (0xf13)
53 #define RISCV_CSR_MHARTID   (0xf14)
54 #define RISCV_CSR_MISA      (0x301)
55 #endif // RISCV_M_MODE
56 
57 #if RISCV_S_MODE // Supervisor-mode only CSRs
58 #define RISCV_CSR_SATP      (0x180)
59 #endif
60 
61 #define RISCV_CSR_XSTATUS_IE    (1ul << (RISCV_XMODE_OFFSET + 0))
62 #define RISCV_CSR_XSTATUS_PIE   (1ul << (RISCV_XMODE_OFFSET + 4))
63 #define RISCV_CSR_XSTATUS_SPP   (1ul << 8)
64 #define RISCV_CSR_XSTATUS_SUM   (1ul << 18)
65 #define RISCV_CSR_XSTATUS_MXR   (1ul << 19)
66 #define RISCV_CSR_XSTATUS_FS_SHIFT (13)
67 #define RISCV_CSR_XSTATUS_FS_MASK (3ul << RISCV_CSR_XSTATUS_FS_SHIFT)
68 
69 #define RISCV_CSR_XIE_SIE       (1ul << (RISCV_XMODE_OFFSET + 0))
70 #define RISCV_CSR_XIE_TIE       (1ul << (RISCV_XMODE_OFFSET + 4))
71 #define RISCV_CSR_XIE_EIE       (1ul << (RISCV_XMODE_OFFSET + 8))
72 
73 #define RISCV_CSR_XIP_SIP       (1ul << (RISCV_XMODE_OFFSET + 0))
74 #define RISCV_CSR_XIP_TIP       (1ul << (RISCV_XMODE_OFFSET + 4))
75 #define RISCV_CSR_XIP_EIP       (1ul << (RISCV_XMODE_OFFSET + 8))
76 
77 // Interrupts, top bit set in cause register
78 #define RISCV_INTERRUPT_USWI        0       // software interrupt
79 #define RISCV_INTERRUPT_SSWI        1
80 #define RISCV_INTERRUPT_MSWI        3
81 #define RISCV_INTERRUPT_UTIM        4       // timer interrupt
82 #define RISCV_INTERRUPT_STIM        5
83 #define RISCV_INTERRUPT_MTIM        7
84 #define RISCV_INTERRUPT_UEXT        8       // external interrupt
85 #define RISCV_INTERRUPT_SEXT        9
86 #define RISCV_INTERRUPT_MEXT        11
87 
88 // The 3 interupts above, for the current mode
89 #define RISCV_INTERRUPT_XSWI        (RISCV_XMODE_OFFSET)
90 #define RISCV_INTERRUPT_XTIM        (4 + RISCV_XMODE_OFFSET)
91 #define RISCV_INTERRUPT_XEXT        (8 + RISCV_XMODE_OFFSET)
92 
93 // Exceptions
94 #define RISCV_EXCEPTION_IADDR_MISALIGN      0
95 #define RISCV_EXCEPTION_IACCESS_FAULT       1
96 #define RISCV_EXCEPTION_ILLEGAL_INS         2
97 #define RISCV_EXCEPTION_BREAKPOINT          3
98 #define RISCV_EXCEPTION_LOAD_ADDR_MISALIGN  4
99 #define RISCV_EXCEPTION_LOAD_ACCESS_FAULT   5
100 #define RISCV_EXCEPTION_STORE_ADDR_MISALIGN 6
101 #define RISCV_EXCEPTION_STORE_ACCESS_FAULT  7
102 #define RISCV_EXCEPTION_ENV_CALL_U_MODE     8
103 #define RISCV_EXCEPTION_ENV_CALL_S_MODE     9
104 #define RISCV_EXCEPTION_ENV_CALL_M_MODE     11
105 #define RISCV_EXCEPTION_INS_PAGE_FAULT      12
106 #define RISCV_EXCEPTION_LOAD_PAGE_FAULT     13
107 #define RISCV_EXCEPTION_STORE_PAGE_FAULT    15
108 
109 #ifndef ASSEMBLY
110 #define __ASM_STR(x)    #x
111 
112 #define riscv_csr_clear(csr, bits) \
113 ({ \
114     ulong __val = bits; \
115     __asm__ volatile( \
116         "csrc   " __ASM_STR(csr) ", %0" \
117         :: "rK" (__val) \
118         : "memory"); \
119 })
120 
121 #define riscv_csr_read_clear(csr, bits) \
122 ({ \
123     ulong __val = bits; \
124     ulong __val_out; \
125     __asm__ volatile( \
126         "csrrc   %0, " __ASM_STR(csr) ", %1" \
127         : "=r"(__val_out) \
128         : "rK" (__val) \
129         : "memory"); \
130     __val_out; \
131 })
132 
133 #define riscv_csr_set(csr, bits) \
134 ({ \
135     ulong __val = bits; \
136     __asm__ volatile( \
137         "csrs   " __ASM_STR(csr) ", %0" \
138         :: "rK" (__val) \
139         : "memory"); \
140 })
141 
142 #define riscv_csr_read(csr) \
143 ({ \
144     ulong __val; \
145     __asm__ volatile( \
146         "csrr   %0, " __ASM_STR(csr) \
147         : "=r" (__val) \
148         :: "memory"); \
149     __val; \
150 })
151 
152 #define riscv_csr_write(csr, val) \
153 ({ \
154     ulong __val = (ulong)val; \
155     __asm__ volatile( \
156         "csrw   " __ASM_STR(csr) ", %0" \
157         :: "rK" (__val) \
158         : "memory"); \
159     __val; \
160 })
161 
162 #include <arch/riscv/iframe.h>
163 
164 struct riscv_percpu {
165     // must be first field in the struct
166     struct thread *curr_thread;
167     unsigned int cpu_num;
168     unsigned int hart_id;
169 } __ALIGNED(CACHE_LINE);
170 
171 // percpu pointer is held in the tp register while in the kernel
riscv_get_percpu(void)172 static inline struct riscv_percpu *riscv_get_percpu(void) {
173     struct riscv_percpu *cpu;
174     __asm__ volatile("mv %0, tp" : "=&r"(cpu));
175     return cpu;
176 }
177 
riscv_set_percpu(struct riscv_percpu * cpu)178 static inline void riscv_set_percpu(struct riscv_percpu *cpu) {
179     __asm__ volatile("mv tp, %0" :: "r"(cpu));
180 }
181 
182 // current thread is always at the start of the percpu struct
riscv_get_current_thread(void)183 static inline struct thread *riscv_get_current_thread(void) {
184     struct thread *t;
185 #if __riscv_xlen == 32
186     __asm__ volatile("lw %0, 0(tp)" : "=&r"(t));
187 #else
188     __asm__ volatile("ld %0, 0(tp)" : "=&r"(t));
189 #endif
190     return t;
191 }
192 
riscv_set_current_thread(struct thread * t)193 static inline void riscv_set_current_thread(struct thread *t) {
194 #if __riscv_xlen == 32
195     __asm__ volatile("sw %0, 0(tp)" :: "r"(t));
196 #else
197     __asm__ volatile("sd %0, 0(tp)" :: "r"(t));
198 #endif
199 }
200 
riscv_current_hart(void)201 static inline uint riscv_current_hart(void) {
202 #if RISCV_M_MODE
203     return riscv_csr_read(RISCV_CSR_MHARTID);
204 #else
205     return riscv_get_percpu()->hart_id;
206 #endif
207 }
208 
209 void riscv_set_secondary_count(int count);
210 
211 void riscv_exception_entry(void);
212 enum handler_return riscv_timer_exception(void);
213 enum handler_return riscv_software_exception(void);
214 enum handler_return riscv_platform_irq(void);
215 void riscv_syscall_handler(struct riscv_short_iframe *frame);
216 
217 // If using S mode, time seems to be implemented in clint.h
218 // TODO: clean up by moving into its own header
219 #if RISCV_S_MODE
220 # if __riscv_xlen == 32
riscv_get_time(void)221 static inline uint64_t riscv_get_time(void) {
222     uint32_t hi, lo;
223 
224     do {
225         hi = riscv_csr_read(RISCV_CSR_TIMEH);
226         lo = riscv_csr_read(RISCV_CSR_TIME);
227     } while (hi != riscv_csr_read(RISCV_CSR_TIMEH));
228 
229     return (((uint64_t)hi << 32) | lo);
230 }
231 # else
riscv_get_time(void)232 static inline uint64_t riscv_get_time(void) {
233     return riscv_csr_read(RISCV_CSR_TIME);
234 }
235 # endif
236 #endif
237 
238 #endif /* ASSEMBLY */
239