RTEMS  5.0.0
cpuimpl.h
Go to the documentation of this file.
1 
7 /*
8  * Copyright (c) 2013, 2018 embedded brains GmbH
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #ifndef _RTEMS_SCORE_CPUIMPL_H
33 #define _RTEMS_SCORE_CPUIMPL_H
34 
35 #include <rtems/score/cpu.h>
36 
47 #if defined(__riscv_atomic) && __riscv_xlen == 64
48 #define CPU_PER_CPU_CONTROL_SIZE 48
49 #elif defined(__riscv_atomic) && __riscv_xlen == 32
50 #define CPU_PER_CPU_CONTROL_SIZE 32
51 #elif __riscv_xlen == 64
52 #define CPU_PER_CPU_CONTROL_SIZE 32
53 #elif __riscv_xlen == 32
54 #define CPU_PER_CPU_CONTROL_SIZE 16
55 #endif
56 
57 #ifdef RTEMS_SMP
58 #define RISCV_CONTEXT_IS_EXECUTING 0
59 #endif
60 
61 #define RISCV_CONTEXT_ISR_DISPATCH_DISABLE 4
62 
63 #if __riscv_xlen == 32
64 
65 #define RISCV_CONTEXT_RA 8
66 #define RISCV_CONTEXT_SP 12
67 #define RISCV_CONTEXT_TP 16
68 #define RISCV_CONTEXT_S0 20
69 #define RISCV_CONTEXT_S1 24
70 #define RISCV_CONTEXT_S2 28
71 #define RISCV_CONTEXT_S3 32
72 #define RISCV_CONTEXT_S4 36
73 #define RISCV_CONTEXT_S5 40
74 #define RISCV_CONTEXT_S6 44
75 #define RISCV_CONTEXT_S7 48
76 #define RISCV_CONTEXT_S8 52
77 #define RISCV_CONTEXT_S9 56
78 #define RISCV_CONTEXT_S10 60
79 #define RISCV_CONTEXT_S11 64
80 
81 #define RISCV_INTERRUPT_FRAME_MSTATUS 0
82 #define RISCV_INTERRUPT_FRAME_MEPC 4
83 #define RISCV_INTERRUPT_FRAME_A2 8
84 #define RISCV_INTERRUPT_FRAME_S0 12
85 #define RISCV_INTERRUPT_FRAME_S1 16
86 #define RISCV_INTERRUPT_FRAME_RA 20
87 #define RISCV_INTERRUPT_FRAME_A3 24
88 #define RISCV_INTERRUPT_FRAME_A4 28
89 #define RISCV_INTERRUPT_FRAME_A5 32
90 #define RISCV_INTERRUPT_FRAME_A6 36
91 #define RISCV_INTERRUPT_FRAME_A7 40
92 #define RISCV_INTERRUPT_FRAME_T0 44
93 #define RISCV_INTERRUPT_FRAME_T1 48
94 #define RISCV_INTERRUPT_FRAME_T2 52
95 #define RISCV_INTERRUPT_FRAME_T3 56
96 #define RISCV_INTERRUPT_FRAME_T4 60
97 #define RISCV_INTERRUPT_FRAME_T5 64
98 #define RISCV_INTERRUPT_FRAME_T6 68
99 
100 #if __riscv_flen == 0
101 
102 #define RISCV_INTERRUPT_FRAME_A0 72
103 #define RISCV_INTERRUPT_FRAME_A1 76
104 
105 #define CPU_INTERRUPT_FRAME_SIZE 80
106 
107 #elif __riscv_flen == 32
108 
109 #define RISCV_CONTEXT_FCSR 68
110 
111 #define RISCV_CONTEXT_F( x ) ( 72 + 4 * x )
112 
113 #define RISCV_INTERRUPT_FRAME_FCSR 72
114 
115 #define RISCV_INTERRUPT_FRAME_F( x ) ( 76 + 4 * x )
116 
117 #define RISCV_INTERRUPT_FRAME_A0 156
118 #define RISCV_INTERRUPT_FRAME_A1 160
119 
120 #define CPU_INTERRUPT_FRAME_SIZE 176
121 
122 #elif __riscv_flen == 64
123 
124 #define RISCV_CONTEXT_FCSR 68
125 
126 #define RISCV_CONTEXT_F( x ) ( 72 + 8 * x )
127 
128 #define RISCV_INTERRUPT_FRAME_FCSR 72
129 
130 #define RISCV_INTERRUPT_FRAME_F( x ) ( 80 + 8 * x )
131 
132 #define RISCV_INTERRUPT_FRAME_A0 240
133 #define RISCV_INTERRUPT_FRAME_A1 244
134 
135 #define CPU_INTERRUPT_FRAME_SIZE 256
136 
137 #endif /* __riscv_flen */
138 
139 #define RISCV_EXCEPTION_FRAME_X( x ) ( CPU_INTERRUPT_FRAME_SIZE + 4 * x )
140 
141 #elif __riscv_xlen == 64
142 
143 #define RISCV_CONTEXT_RA 8
144 #define RISCV_CONTEXT_SP 16
145 #define RISCV_CONTEXT_TP 24
146 #define RISCV_CONTEXT_S0 32
147 #define RISCV_CONTEXT_S1 40
148 #define RISCV_CONTEXT_S2 48
149 #define RISCV_CONTEXT_S3 56
150 #define RISCV_CONTEXT_S4 64
151 #define RISCV_CONTEXT_S5 72
152 #define RISCV_CONTEXT_S6 80
153 #define RISCV_CONTEXT_S7 88
154 #define RISCV_CONTEXT_S8 96
155 #define RISCV_CONTEXT_S9 104
156 #define RISCV_CONTEXT_S10 112
157 #define RISCV_CONTEXT_S11 120
158 
159 #define RISCV_INTERRUPT_FRAME_MSTATUS 0
160 #define RISCV_INTERRUPT_FRAME_MEPC 8
161 #define RISCV_INTERRUPT_FRAME_A2 16
162 #define RISCV_INTERRUPT_FRAME_S0 24
163 #define RISCV_INTERRUPT_FRAME_S1 32
164 #define RISCV_INTERRUPT_FRAME_RA 40
165 #define RISCV_INTERRUPT_FRAME_A3 48
166 #define RISCV_INTERRUPT_FRAME_A4 56
167 #define RISCV_INTERRUPT_FRAME_A5 64
168 #define RISCV_INTERRUPT_FRAME_A6 72
169 #define RISCV_INTERRUPT_FRAME_A7 80
170 #define RISCV_INTERRUPT_FRAME_T0 88
171 #define RISCV_INTERRUPT_FRAME_T1 96
172 #define RISCV_INTERRUPT_FRAME_T2 104
173 #define RISCV_INTERRUPT_FRAME_T3 112
174 #define RISCV_INTERRUPT_FRAME_T4 120
175 #define RISCV_INTERRUPT_FRAME_T5 128
176 #define RISCV_INTERRUPT_FRAME_T6 136
177 
178 #if __riscv_flen == 0
179 
180 #define RISCV_INTERRUPT_FRAME_A0 144
181 #define RISCV_INTERRUPT_FRAME_A1 152
182 
183 #define CPU_INTERRUPT_FRAME_SIZE 160
184 
185 #elif __riscv_flen == 32
186 
187 #define RISCV_CONTEXT_FCSR 128
188 
189 #define RISCV_CONTEXT_F( x ) ( 132 + 4 * x )
190 
191 #define RISCV_INTERRUPT_FRAME_FCSR 144
192 
193 #define RISCV_INTERRUPT_FRAME_F( x ) ( 148 + 4 * x )
194 
195 #define RISCV_INTERRUPT_FRAME_A0 232
196 #define RISCV_INTERRUPT_FRAME_A1 240
197 
198 #define CPU_INTERRUPT_FRAME_SIZE 256
199 
200 #elif __riscv_flen == 64
201 
202 #define RISCV_CONTEXT_FCSR 128
203 
204 #define RISCV_CONTEXT_F( x ) ( 136 + 8 * x )
205 
206 #define RISCV_INTERRUPT_FRAME_FCSR 144
207 
208 #define RISCV_INTERRUPT_FRAME_F( x ) ( 152 + 8 * x )
209 
210 #define RISCV_INTERRUPT_FRAME_A0 312
211 #define RISCV_INTERRUPT_FRAME_A1 320
212 
213 #define CPU_INTERRUPT_FRAME_SIZE 336
214 
215 #endif /* __riscv_flen */
216 
217 #define RISCV_EXCEPTION_FRAME_X( x ) ( CPU_INTERRUPT_FRAME_SIZE + 8 * x )
218 
219 #endif /* __riscv_xlen */
220 
221 #define RISCV_EXCEPTION_FRAME_MCAUSE RISCV_EXCEPTION_FRAME_X( 0 )
222 #define RISCV_EXCEPTION_FRAME_SP RISCV_EXCEPTION_FRAME_X( 1 )
223 #define RISCV_EXCEPTION_FRAME_GP RISCV_EXCEPTION_FRAME_X( 2 )
224 #define RISCV_EXCEPTION_FRAME_TP RISCV_EXCEPTION_FRAME_X( 3 )
225 #define RISCV_EXCEPTION_FRAME_S2 RISCV_EXCEPTION_FRAME_X( 4 )
226 #define RISCV_EXCEPTION_FRAME_S3 RISCV_EXCEPTION_FRAME_X( 5 )
227 #define RISCV_EXCEPTION_FRAME_S4 RISCV_EXCEPTION_FRAME_X( 6 )
228 #define RISCV_EXCEPTION_FRAME_S5 RISCV_EXCEPTION_FRAME_X( 7 )
229 #define RISCV_EXCEPTION_FRAME_S6 RISCV_EXCEPTION_FRAME_X( 8 )
230 #define RISCV_EXCEPTION_FRAME_S7 RISCV_EXCEPTION_FRAME_X( 9 )
231 #define RISCV_EXCEPTION_FRAME_S8 RISCV_EXCEPTION_FRAME_X( 10 )
232 #define RISCV_EXCEPTION_FRAME_S9 RISCV_EXCEPTION_FRAME_X( 11 )
233 #define RISCV_EXCEPTION_FRAME_S10 RISCV_EXCEPTION_FRAME_X( 12 )
234 #define RISCV_EXCEPTION_FRAME_S11 RISCV_EXCEPTION_FRAME_X( 13 )
235 
236 #if __riscv_flen > 0
237 
238 #define RISCV_CONTEXT_FS0 RISCV_CONTEXT_F( 0 )
239 #define RISCV_CONTEXT_FS1 RISCV_CONTEXT_F( 1 )
240 #define RISCV_CONTEXT_FS2 RISCV_CONTEXT_F( 2 )
241 #define RISCV_CONTEXT_FS3 RISCV_CONTEXT_F( 3 )
242 #define RISCV_CONTEXT_FS4 RISCV_CONTEXT_F( 4 )
243 #define RISCV_CONTEXT_FS5 RISCV_CONTEXT_F( 5 )
244 #define RISCV_CONTEXT_FS6 RISCV_CONTEXT_F( 6 )
245 #define RISCV_CONTEXT_FS7 RISCV_CONTEXT_F( 7 )
246 #define RISCV_CONTEXT_FS8 RISCV_CONTEXT_F( 8 )
247 #define RISCV_CONTEXT_FS9 RISCV_CONTEXT_F( 9 )
248 #define RISCV_CONTEXT_FS10 RISCV_CONTEXT_F( 10 )
249 #define RISCV_CONTEXT_FS11 RISCV_CONTEXT_F( 11 )
250 
251 #define RISCV_INTERRUPT_FRAME_FT0 RISCV_INTERRUPT_FRAME_F( 0 )
252 #define RISCV_INTERRUPT_FRAME_FT1 RISCV_INTERRUPT_FRAME_F( 1 )
253 #define RISCV_INTERRUPT_FRAME_FT2 RISCV_INTERRUPT_FRAME_F( 2 )
254 #define RISCV_INTERRUPT_FRAME_FT3 RISCV_INTERRUPT_FRAME_F( 3 )
255 #define RISCV_INTERRUPT_FRAME_FT4 RISCV_INTERRUPT_FRAME_F( 4 )
256 #define RISCV_INTERRUPT_FRAME_FT5 RISCV_INTERRUPT_FRAME_F( 5 )
257 #define RISCV_INTERRUPT_FRAME_FT6 RISCV_INTERRUPT_FRAME_F( 6 )
258 #define RISCV_INTERRUPT_FRAME_FT7 RISCV_INTERRUPT_FRAME_F( 7 )
259 #define RISCV_INTERRUPT_FRAME_FT8 RISCV_INTERRUPT_FRAME_F( 8 )
260 #define RISCV_INTERRUPT_FRAME_FT9 RISCV_INTERRUPT_FRAME_F( 9 )
261 #define RISCV_INTERRUPT_FRAME_FT10 RISCV_INTERRUPT_FRAME_F( 10 )
262 #define RISCV_INTERRUPT_FRAME_FT11 RISCV_INTERRUPT_FRAME_F( 11 )
263 #define RISCV_INTERRUPT_FRAME_FA0 RISCV_INTERRUPT_FRAME_F( 12 )
264 #define RISCV_INTERRUPT_FRAME_FA1 RISCV_INTERRUPT_FRAME_F( 13 )
265 #define RISCV_INTERRUPT_FRAME_FA2 RISCV_INTERRUPT_FRAME_F( 14 )
266 #define RISCV_INTERRUPT_FRAME_FA3 RISCV_INTERRUPT_FRAME_F( 15 )
267 #define RISCV_INTERRUPT_FRAME_FA4 RISCV_INTERRUPT_FRAME_F( 16 )
268 #define RISCV_INTERRUPT_FRAME_FA5 RISCV_INTERRUPT_FRAME_F( 17 )
269 #define RISCV_INTERRUPT_FRAME_FA6 RISCV_INTERRUPT_FRAME_F( 18 )
270 #define RISCV_INTERRUPT_FRAME_FA7 RISCV_INTERRUPT_FRAME_F( 19 )
271 
272 #if __riscv_flen == 32
273 #define RISCV_EXCEPTION_FRAME_F( x ) ( RISCV_EXCEPTION_FRAME_X( 14 ) + 4 * x )
274 #elif __riscv_flen == 64
275 #define RISCV_EXCEPTION_FRAME_F( x ) ( RISCV_EXCEPTION_FRAME_X( 14 ) + 8 * x )
276 #endif
277 
278 #define RISCV_EXCEPTION_FRAME_FS0 RISCV_EXCEPTION_FRAME_F( 0 )
279 #define RISCV_EXCEPTION_FRAME_FS1 RISCV_EXCEPTION_FRAME_F( 1 )
280 #define RISCV_EXCEPTION_FRAME_FS2 RISCV_EXCEPTION_FRAME_F( 2 )
281 #define RISCV_EXCEPTION_FRAME_FS3 RISCV_EXCEPTION_FRAME_F( 3 )
282 #define RISCV_EXCEPTION_FRAME_FS4 RISCV_EXCEPTION_FRAME_F( 4 )
283 #define RISCV_EXCEPTION_FRAME_FS5 RISCV_EXCEPTION_FRAME_F( 5 )
284 #define RISCV_EXCEPTION_FRAME_FS6 RISCV_EXCEPTION_FRAME_F( 6 )
285 #define RISCV_EXCEPTION_FRAME_FS7 RISCV_EXCEPTION_FRAME_F( 7 )
286 #define RISCV_EXCEPTION_FRAME_FS8 RISCV_EXCEPTION_FRAME_F( 8 )
287 #define RISCV_EXCEPTION_FRAME_FS9 RISCV_EXCEPTION_FRAME_F( 9 )
288 #define RISCV_EXCEPTION_FRAME_FS10 RISCV_EXCEPTION_FRAME_F( 10 )
289 #define RISCV_EXCEPTION_FRAME_FS11 RISCV_EXCEPTION_FRAME_F( 11 )
290 
291 #endif /* __riscv_flen */
292 
293 #ifndef ASM
294 
295 #ifdef __cplusplus
296 extern "C" {
297 #endif
298 
299 /* Core Local Interruptor (CLINT) */
300 
301 typedef union {
302  uint64_t val_64;
303  uint32_t val_32[2];
305 
306 typedef struct {
307  uint32_t msip[4096];
308  RISCV_CLINT_timer_reg mtimecmp[2048];
309  uint32_t reserved_8000[4094];
310  RISCV_CLINT_timer_reg mtime;
311  uint32_t reserved_c000[4096];
313 
314 /* Platform-Level Interrupt Controller (PLIC) */
315 
316 #define RISCV_PLIC_MAX_INTERRUPTS 1024
317 
318 typedef struct {
319  uint32_t priority_threshold;
320  uint32_t claim_complete;
321  uint32_t reserved_8[1022];
323 
324 typedef struct {
325  uint32_t priority[RISCV_PLIC_MAX_INTERRUPTS];
326  uint32_t pending[1024];
327  uint32_t enable[16320][32];
330 
331 typedef struct {
332 #ifdef __riscv_atomic
333  uint64_t clear_reservations;
334  uint32_t reserved_for_alignment_of_interrupt_frame[ 2 ];
335 #endif
336  volatile RISCV_PLIC_hart_regs *plic_hart_regs;
337  volatile uint32_t *plic_m_ie;
338  volatile RISCV_CLINT_timer_reg *clint_mtimecmp;
339  volatile uint32_t *clint_msip;
341 
342 struct Per_CPU_Control;
343 
344 void _RISCV_Interrupt_dispatch(
345  uintptr_t mcause,
346  struct Per_CPU_Control *cpu_self
347 );
348 
349 static inline uint32_t _RISCV_Read_FCSR( void )
350 {
351  uint32_t fcsr;
352 
353  __asm__ volatile ( "frcsr %0" : "=&r" ( fcsr ) );
354 
355  return fcsr;
356 }
357 
358 /*
359  * The RISC-V ISA provides a rdtime instruction, however, it is implemented in
360  * most chips via a trap-and-emulate. Using this in machine mode makes no
361  * sense. Use the memory-mapped mtime register directly instead. The address
362  * of this register is platform-specific and provided via the device tree.
363  *
364  * To allow better code generation provide a const (_RISCV_Counter) and a
365  * mutable (_RISCV_Counter_mutable) declaration for this pointer variable
366  * (defined in assembler code).
367  *
368  * See code generated for this test case:
369  *
370  * extern volatile int * const c;
371  *
372  * extern volatile int *v;
373  *
374  * int fc(void)
375  * {
376  * int a = *c;
377  * __asm__ volatile("" ::: "memory");
378  * return *c - a;
379  * }
380  *
381  * int fv(void)
382  * {
383  * int a = *v;
384  * __asm__ volatile("" ::: "memory");
385  * return *v - a;
386  * }
387  */
388 extern volatile uint32_t *_RISCV_Counter_mutable;
389 
390 /*
391  * Initial value of _RISCV_Counter and _RISCV_Counter_mutable. Must be
392  * provided by the BSP.
393  */
394 extern volatile uint32_t _RISCV_Counter_register;
395 
396 #ifdef RTEMS_SMP
397 
398 static inline struct Per_CPU_Control *_RISCV_Get_current_per_CPU_control( void )
399 {
400  struct Per_CPU_Control *cpu_self;
401 
402  __asm__ volatile ( "csrr %0, mscratch" : "=r" ( cpu_self ) );
403 
404  return cpu_self;
405 }
406 
407 #define _CPU_Get_current_per_CPU_control() _RISCV_Get_current_per_CPU_control()
408 
409 #endif /* RTEMS_SMP */
410 
411 void _CPU_Context_volatile_clobber( uintptr_t pattern );
412 
413 void _CPU_Context_validate( uintptr_t pattern );
414 
416 {
417  __asm__ volatile ( "unimp" );
418 }
419 
421 {
422  __asm__ volatile ( "nop" );
423 }
424 
425 #ifdef __cplusplus
426 }
427 #endif
428 
429 #endif /* ASM */
430 
433 #endif /* _RTEMS_SCORE_CPUIMPL_H */
Definition: cpuimpl.h:306
#define CPU_MAXIMUM_PROCESSORS
Maximum number of processors of all systems supported by this CPU port.
Definition: cpu.h:250
Definition: cpuimpl.h:324
#define RTEMS_INLINE_ROUTINE
Definition: basedefs.h:65
The CPU specific per-CPU control.
Definition: cpuimpl.h:54
Per CPU Core Structure.
Definition: percpu.h:290
Definition: cpuimpl.h:301
RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation(void)
Emits a no operation instruction (nop).
Definition: cpuimpl.h:132
register struct Per_CPU_Control *_SPARC_Per_CPU_current __asm__("g6")
The pointer to the current per-CPU control is available via register g6.
Definition: cpuimpl.h:318
RTEMS_INLINE_ROUTINE void _CPU_Instruction_illegal(void)
Emits an illegal instruction.
Definition: cpuimpl.h:122