source: rtems/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h @ cfc9573

Last change on this file since cfc9573 was cfc9573, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 27, 2018 at 12:47:17 PM

riscv: Rework CPU counter support

Update #3433.

  • Property mode set to 100644
File size: 12.4 KB
Line 
1/**
2 * @file
3 *
4 * @brief CPU Port Implementation API
5 */
6
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
37#if defined(__riscv_atomic) && __riscv_xlen == 64
38#define CPU_PER_CPU_CONTROL_SIZE 48
39#elif defined(__riscv_atomic) && __riscv_xlen == 32
40#define CPU_PER_CPU_CONTROL_SIZE 32
41#elif __riscv_xlen == 64
42#define CPU_PER_CPU_CONTROL_SIZE 32
43#elif __riscv_xlen == 32
44#define CPU_PER_CPU_CONTROL_SIZE 16
45#endif
46
47#ifdef RTEMS_SMP
48#define RISCV_CONTEXT_IS_EXECUTING 0
49#endif
50
51#define RISCV_CONTEXT_ISR_DISPATCH_DISABLE 4
52
53#if __riscv_xlen == 32
54
55#define RISCV_CONTEXT_RA 8
56#define RISCV_CONTEXT_SP 12
57#define RISCV_CONTEXT_TP 16
58#define RISCV_CONTEXT_S0 20
59#define RISCV_CONTEXT_S1 24
60#define RISCV_CONTEXT_S2 28
61#define RISCV_CONTEXT_S3 32
62#define RISCV_CONTEXT_S4 36
63#define RISCV_CONTEXT_S5 40
64#define RISCV_CONTEXT_S6 44
65#define RISCV_CONTEXT_S7 48
66#define RISCV_CONTEXT_S8 52
67#define RISCV_CONTEXT_S9 56
68#define RISCV_CONTEXT_S10 60
69#define RISCV_CONTEXT_S11 64
70
71#define RISCV_INTERRUPT_FRAME_MSTATUS 0
72#define RISCV_INTERRUPT_FRAME_MEPC 4
73#define RISCV_INTERRUPT_FRAME_A2 8
74#define RISCV_INTERRUPT_FRAME_S0 12
75#define RISCV_INTERRUPT_FRAME_S1 16
76#define RISCV_INTERRUPT_FRAME_RA 20
77#define RISCV_INTERRUPT_FRAME_A3 24
78#define RISCV_INTERRUPT_FRAME_A4 28
79#define RISCV_INTERRUPT_FRAME_A5 32
80#define RISCV_INTERRUPT_FRAME_A6 36
81#define RISCV_INTERRUPT_FRAME_A7 40
82#define RISCV_INTERRUPT_FRAME_T0 44
83#define RISCV_INTERRUPT_FRAME_T1 48
84#define RISCV_INTERRUPT_FRAME_T2 52
85#define RISCV_INTERRUPT_FRAME_T3 56
86#define RISCV_INTERRUPT_FRAME_T4 60
87#define RISCV_INTERRUPT_FRAME_T5 64
88#define RISCV_INTERRUPT_FRAME_T6 68
89
90#if __riscv_flen == 0
91
92#define RISCV_INTERRUPT_FRAME_A0 72
93#define RISCV_INTERRUPT_FRAME_A1 76
94
95#define CPU_INTERRUPT_FRAME_SIZE 80
96
97#elif __riscv_flen == 32
98
99#define RISCV_CONTEXT_FCSR 68
100
101#define RISCV_CONTEXT_F( x ) ( 72 + 4 * x )
102
103#define RISCV_INTERRUPT_FRAME_FCSR 72
104
105#define RISCV_INTERRUPT_FRAME_F( x ) ( 76 + 4 * x )
106
107#define RISCV_INTERRUPT_FRAME_A0 156
108#define RISCV_INTERRUPT_FRAME_A1 160
109
110#define CPU_INTERRUPT_FRAME_SIZE 176
111
112#elif __riscv_flen == 64
113
114#define RISCV_CONTEXT_FCSR 68
115
116#define RISCV_CONTEXT_F( x ) ( 72 + 8 * x )
117
118#define RISCV_INTERRUPT_FRAME_FCSR 72
119
120#define RISCV_INTERRUPT_FRAME_F( x ) ( 80 + 8 * x )
121
122#define RISCV_INTERRUPT_FRAME_A0 240
123#define RISCV_INTERRUPT_FRAME_A1 244
124
125#define CPU_INTERRUPT_FRAME_SIZE 256
126
127#endif /* __riscv_flen */
128
129#define RISCV_EXCEPTION_FRAME_X( x ) ( CPU_INTERRUPT_FRAME_SIZE + 4 * x )
130
131#elif __riscv_xlen == 64
132
133#define RISCV_CONTEXT_RA 8
134#define RISCV_CONTEXT_SP 16
135#define RISCV_CONTEXT_TP 24
136#define RISCV_CONTEXT_S0 32
137#define RISCV_CONTEXT_S1 40
138#define RISCV_CONTEXT_S2 48
139#define RISCV_CONTEXT_S3 56
140#define RISCV_CONTEXT_S4 64
141#define RISCV_CONTEXT_S5 72
142#define RISCV_CONTEXT_S6 80
143#define RISCV_CONTEXT_S7 88
144#define RISCV_CONTEXT_S8 96
145#define RISCV_CONTEXT_S9 104
146#define RISCV_CONTEXT_S10 112
147#define RISCV_CONTEXT_S11 120
148
149#define RISCV_INTERRUPT_FRAME_MSTATUS 0
150#define RISCV_INTERRUPT_FRAME_MEPC 8
151#define RISCV_INTERRUPT_FRAME_A2 16
152#define RISCV_INTERRUPT_FRAME_S0 24
153#define RISCV_INTERRUPT_FRAME_S1 32
154#define RISCV_INTERRUPT_FRAME_RA 40
155#define RISCV_INTERRUPT_FRAME_A3 48
156#define RISCV_INTERRUPT_FRAME_A4 56
157#define RISCV_INTERRUPT_FRAME_A5 64
158#define RISCV_INTERRUPT_FRAME_A6 72
159#define RISCV_INTERRUPT_FRAME_A7 80
160#define RISCV_INTERRUPT_FRAME_T0 88
161#define RISCV_INTERRUPT_FRAME_T1 96
162#define RISCV_INTERRUPT_FRAME_T2 104
163#define RISCV_INTERRUPT_FRAME_T3 112
164#define RISCV_INTERRUPT_FRAME_T4 120
165#define RISCV_INTERRUPT_FRAME_T5 128
166#define RISCV_INTERRUPT_FRAME_T6 136
167
168#if __riscv_flen == 0
169
170#define RISCV_INTERRUPT_FRAME_A0 144
171#define RISCV_INTERRUPT_FRAME_A1 152
172
173#define CPU_INTERRUPT_FRAME_SIZE 160
174
175#elif __riscv_flen == 32
176
177#define RISCV_CONTEXT_FCSR 128
178
179#define RISCV_CONTEXT_F( x ) ( 132 + 4 * x )
180
181#define RISCV_INTERRUPT_FRAME_FCSR 144
182
183#define RISCV_INTERRUPT_FRAME_F( x ) ( 148 + 4 * x )
184
185#define RISCV_INTERRUPT_FRAME_A0 232
186#define RISCV_INTERRUPT_FRAME_A1 240
187
188#define CPU_INTERRUPT_FRAME_SIZE 256
189
190#elif __riscv_flen == 64
191
192#define RISCV_CONTEXT_FCSR 128
193
194#define RISCV_CONTEXT_F( x ) ( 136 + 8 * x )
195
196#define RISCV_INTERRUPT_FRAME_FCSR 144
197
198#define RISCV_INTERRUPT_FRAME_F( x ) ( 152 + 8 * x )
199
200#define RISCV_INTERRUPT_FRAME_A0 312
201#define RISCV_INTERRUPT_FRAME_A1 320
202
203#define CPU_INTERRUPT_FRAME_SIZE 336
204
205#endif /* __riscv_flen */
206
207#define RISCV_EXCEPTION_FRAME_X( x ) ( CPU_INTERRUPT_FRAME_SIZE + 8 * x )
208
209#endif /* __riscv_xlen */
210
211#define RISCV_EXCEPTION_FRAME_MCAUSE RISCV_EXCEPTION_FRAME_X( 0 )
212#define RISCV_EXCEPTION_FRAME_SP RISCV_EXCEPTION_FRAME_X( 1 )
213#define RISCV_EXCEPTION_FRAME_GP RISCV_EXCEPTION_FRAME_X( 2 )
214#define RISCV_EXCEPTION_FRAME_TP RISCV_EXCEPTION_FRAME_X( 3 )
215#define RISCV_EXCEPTION_FRAME_S2 RISCV_EXCEPTION_FRAME_X( 4 )
216#define RISCV_EXCEPTION_FRAME_S3 RISCV_EXCEPTION_FRAME_X( 5 )
217#define RISCV_EXCEPTION_FRAME_S4 RISCV_EXCEPTION_FRAME_X( 6 )
218#define RISCV_EXCEPTION_FRAME_S5 RISCV_EXCEPTION_FRAME_X( 7 )
219#define RISCV_EXCEPTION_FRAME_S6 RISCV_EXCEPTION_FRAME_X( 8 )
220#define RISCV_EXCEPTION_FRAME_S7 RISCV_EXCEPTION_FRAME_X( 9 )
221#define RISCV_EXCEPTION_FRAME_S8 RISCV_EXCEPTION_FRAME_X( 10 )
222#define RISCV_EXCEPTION_FRAME_S9 RISCV_EXCEPTION_FRAME_X( 11 )
223#define RISCV_EXCEPTION_FRAME_S10 RISCV_EXCEPTION_FRAME_X( 12 )
224#define RISCV_EXCEPTION_FRAME_S11 RISCV_EXCEPTION_FRAME_X( 13 )
225
226#if __riscv_flen > 0
227
228#define RISCV_CONTEXT_FS0 RISCV_CONTEXT_F( 0 )
229#define RISCV_CONTEXT_FS1 RISCV_CONTEXT_F( 1 )
230#define RISCV_CONTEXT_FS2 RISCV_CONTEXT_F( 2 )
231#define RISCV_CONTEXT_FS3 RISCV_CONTEXT_F( 3 )
232#define RISCV_CONTEXT_FS4 RISCV_CONTEXT_F( 4 )
233#define RISCV_CONTEXT_FS5 RISCV_CONTEXT_F( 5 )
234#define RISCV_CONTEXT_FS6 RISCV_CONTEXT_F( 6 )
235#define RISCV_CONTEXT_FS7 RISCV_CONTEXT_F( 7 )
236#define RISCV_CONTEXT_FS8 RISCV_CONTEXT_F( 8 )
237#define RISCV_CONTEXT_FS9 RISCV_CONTEXT_F( 9 )
238#define RISCV_CONTEXT_FS10 RISCV_CONTEXT_F( 10 )
239#define RISCV_CONTEXT_FS11 RISCV_CONTEXT_F( 11 )
240
241#define RISCV_INTERRUPT_FRAME_FT0 RISCV_INTERRUPT_FRAME_F( 0 )
242#define RISCV_INTERRUPT_FRAME_FT1 RISCV_INTERRUPT_FRAME_F( 1 )
243#define RISCV_INTERRUPT_FRAME_FT2 RISCV_INTERRUPT_FRAME_F( 2 )
244#define RISCV_INTERRUPT_FRAME_FT3 RISCV_INTERRUPT_FRAME_F( 3 )
245#define RISCV_INTERRUPT_FRAME_FT4 RISCV_INTERRUPT_FRAME_F( 4 )
246#define RISCV_INTERRUPT_FRAME_FT5 RISCV_INTERRUPT_FRAME_F( 5 )
247#define RISCV_INTERRUPT_FRAME_FT6 RISCV_INTERRUPT_FRAME_F( 6 )
248#define RISCV_INTERRUPT_FRAME_FT7 RISCV_INTERRUPT_FRAME_F( 7 )
249#define RISCV_INTERRUPT_FRAME_FT8 RISCV_INTERRUPT_FRAME_F( 8 )
250#define RISCV_INTERRUPT_FRAME_FT9 RISCV_INTERRUPT_FRAME_F( 9 )
251#define RISCV_INTERRUPT_FRAME_FT10 RISCV_INTERRUPT_FRAME_F( 10 )
252#define RISCV_INTERRUPT_FRAME_FT11 RISCV_INTERRUPT_FRAME_F( 11 )
253#define RISCV_INTERRUPT_FRAME_FA0 RISCV_INTERRUPT_FRAME_F( 12 )
254#define RISCV_INTERRUPT_FRAME_FA1 RISCV_INTERRUPT_FRAME_F( 13 )
255#define RISCV_INTERRUPT_FRAME_FA2 RISCV_INTERRUPT_FRAME_F( 14 )
256#define RISCV_INTERRUPT_FRAME_FA3 RISCV_INTERRUPT_FRAME_F( 15 )
257#define RISCV_INTERRUPT_FRAME_FA4 RISCV_INTERRUPT_FRAME_F( 16 )
258#define RISCV_INTERRUPT_FRAME_FA5 RISCV_INTERRUPT_FRAME_F( 17 )
259#define RISCV_INTERRUPT_FRAME_FA6 RISCV_INTERRUPT_FRAME_F( 18 )
260#define RISCV_INTERRUPT_FRAME_FA7 RISCV_INTERRUPT_FRAME_F( 19 )
261
262#if __riscv_flen == 32
263#define RISCV_EXCEPTION_FRAME_F( x ) ( RISCV_EXCEPTION_FRAME_X( 14 ) + 4 * x )
264#elif __riscv_flen == 64
265#define RISCV_EXCEPTION_FRAME_F( x ) ( RISCV_EXCEPTION_FRAME_X( 14 ) + 8 * x )
266#endif
267
268#define RISCV_EXCEPTION_FRAME_FS0 RISCV_EXCEPTION_FRAME_F( 0 )
269#define RISCV_EXCEPTION_FRAME_FS1 RISCV_EXCEPTION_FRAME_F( 1 )
270#define RISCV_EXCEPTION_FRAME_FS2 RISCV_EXCEPTION_FRAME_F( 2 )
271#define RISCV_EXCEPTION_FRAME_FS3 RISCV_EXCEPTION_FRAME_F( 3 )
272#define RISCV_EXCEPTION_FRAME_FS4 RISCV_EXCEPTION_FRAME_F( 4 )
273#define RISCV_EXCEPTION_FRAME_FS5 RISCV_EXCEPTION_FRAME_F( 5 )
274#define RISCV_EXCEPTION_FRAME_FS6 RISCV_EXCEPTION_FRAME_F( 6 )
275#define RISCV_EXCEPTION_FRAME_FS7 RISCV_EXCEPTION_FRAME_F( 7 )
276#define RISCV_EXCEPTION_FRAME_FS8 RISCV_EXCEPTION_FRAME_F( 8 )
277#define RISCV_EXCEPTION_FRAME_FS9 RISCV_EXCEPTION_FRAME_F( 9 )
278#define RISCV_EXCEPTION_FRAME_FS10 RISCV_EXCEPTION_FRAME_F( 10 )
279#define RISCV_EXCEPTION_FRAME_FS11 RISCV_EXCEPTION_FRAME_F( 11 )
280
281#endif /* __riscv_flen */
282
283#ifndef ASM
284
285#ifdef __cplusplus
286extern "C" {
287#endif
288
289/* Core Local Interruptor (CLINT) */
290
291typedef union {
292  uint64_t val_64;
293  uint32_t val_32[2];
294} RISCV_CLINT_timer_reg;
295
296typedef struct {
297  uint32_t msip[4096];
298  RISCV_CLINT_timer_reg mtimecmp[2048];
299  uint32_t reserved_8000[4094];
300  RISCV_CLINT_timer_reg mtime;
301  uint32_t reserved_c000[4096];
302} RISCV_CLINT_regs;
303
304/* Platform-Level Interrupt Controller (PLIC) */
305
306#define RISCV_PLIC_MAX_INTERRUPTS 1024
307
308typedef struct {
309  uint32_t priority_threshold;
310  uint32_t claim_complete;
311  uint32_t reserved_8[1022];
312} RISCV_PLIC_hart_regs;
313
314typedef struct {
315  uint32_t priority[RISCV_PLIC_MAX_INTERRUPTS];
316  uint32_t pending[1024];
317  uint32_t enable[16320][32];
318  RISCV_PLIC_hart_regs harts[CPU_MAXIMUM_PROCESSORS];
319} RISCV_PLIC_regs;
320
321typedef struct {
322#ifdef __riscv_atomic
323  uint64_t clear_reservations;
324  uint32_t reserved_for_alignment_of_interrupt_frame[ 2 ];
325#endif
326  volatile RISCV_PLIC_hart_regs *plic_hart_regs;
327  volatile uint32_t *plic_m_ie;
328  volatile RISCV_CLINT_timer_reg *clint_mtimecmp;
329  volatile uint32_t *clint_msip;
330} CPU_Per_CPU_control;
331
332struct Per_CPU_Control;
333
334void _RISCV_Interrupt_dispatch(
335  uintptr_t               mcause,
336  struct Per_CPU_Control *cpu_self
337);
338
339static inline uint32_t _RISCV_Read_FCSR( void )
340{
341  uint32_t fcsr;
342
343  __asm__ volatile ( "frcsr %0" : "=&r" ( fcsr ) );
344
345  return fcsr;
346}
347
348/*
349 * The RISC-V ISA provides a rdtime instruction, however, it is implemented in
350 * most chips via a trap-and-emulate.  Using this in machine mode makes no
351 * sense.  Use the memory-mapped mtime register directly instead.  The address
352 * of this register is platform-specific and provided via the device tree.
353 *
354 * To allow better code generation provide a const (_RISCV_Counter) and a
355 * mutable (_RISCV_Counter_mutable) declaration for this pointer variable
356 * (defined in assembler code).
357 *
358 * See code generated for this test case:
359 *
360 * extern volatile int * const c;
361 *
362 * extern volatile int *v;
363 *
364 * int fc(void)
365 * {
366 *   int a = *c;
367 *   __asm__ volatile("" ::: "memory");
368 *   return *c - a;
369 * }
370 *
371 * int fv(void)
372 * {
373 *   int a = *v;
374 *   __asm__ volatile("" ::: "memory");
375 *   return *v - a;
376 * }
377 */
378extern volatile uint32_t *_RISCV_Counter_mutable;
379
380/*
381 * Initial value of _RISCV_Counter and _RISCV_Counter_mutable.  Must be
382 * provided by the BSP.
383 */
384extern volatile uint32_t _RISCV_Counter_register;
385
386#ifdef RTEMS_SMP
387
388static inline struct Per_CPU_Control *_RISCV_Get_current_per_CPU_control( void )
389{
390  struct Per_CPU_Control *cpu_self;
391
392  __asm__ volatile ( "csrr %0, mscratch" : "=r" ( cpu_self ) );
393
394  return cpu_self;
395}
396
397#define _CPU_Get_current_per_CPU_control() _RISCV_Get_current_per_CPU_control()
398
399#endif /* RTEMS_SMP */
400
401void _CPU_Context_volatile_clobber( uintptr_t pattern );
402
403void _CPU_Context_validate( uintptr_t pattern );
404
405RTEMS_INLINE_ROUTINE void _CPU_Instruction_illegal( void )
406{
407  __asm__ volatile ( "unimp" );
408}
409
410RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
411{
412  __asm__ volatile ( "nop" );
413}
414
415#ifdef __cplusplus
416}
417#endif
418
419#endif /* ASM */
420
421#endif /* _RTEMS_SCORE_CPUIMPL_H */
Note: See TracBrowser for help on using the repository browser.