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

Last change on this file since 03e4d1e9 was 03e4d1e9, checked in by Sebastian Huber <sebastian.huber@…>, on 06/29/22 at 12:37:47

score: Add _CPU_Use_thread_local_storage()

At some point during system initialization, the idle threads are created.
Afterwards, the boot processor basically executes within the context of an idle
thread with thread dispatching disabled. On some architectures, the
thread-local storage area of the associated thread must be set in dedicated
processor registers. Add the new CPU port function to do this:

void _CPU_Use_thread_local_storage( const Context_Control *context )

Close #4672.

  • Property mode set to 100644
File size: 13.0 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/**
38 * @defgroup RTEMSScoreCPURISCV RISC-V
39 *
40 * @ingroup RTEMSScoreCPU
41 *
42 * @brief RISCV Architecture Support
43 *
44 * @{
45 */
46
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
296extern "C" {
297#endif
298
299/* Core Local Interruptor (CLINT) */
300
301typedef union {
302  uint64_t val_64;
303  uint32_t val_32[2];
304} RISCV_CLINT_timer_reg;
305
306typedef 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];
312} RISCV_CLINT_regs;
313
314/* Platform-Level Interrupt Controller (PLIC) */
315
316#define RISCV_PLIC_MAX_INTERRUPTS 1024
317
318typedef struct {
319  uint32_t priority_threshold;
320  uint32_t claim_complete;
321  uint32_t reserved_8[1022];
322} RISCV_PLIC_hart_regs;
323
324typedef struct {
325  uint32_t priority[RISCV_PLIC_MAX_INTERRUPTS];
326  uint32_t pending[1024];
327  uint32_t enable[16320][32];
328  RISCV_PLIC_hart_regs harts[CPU_MAXIMUM_PROCESSORS];
329} RISCV_PLIC_regs;
330
331typedef 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;
340} CPU_Per_CPU_control;
341
342struct Per_CPU_Control;
343
344void _RISCV_Interrupt_dispatch(
345  uintptr_t               mcause,
346  struct Per_CPU_Control *cpu_self
347);
348
349static 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 */
388extern 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 */
394extern volatile uint32_t _RISCV_Counter_register;
395
396#ifdef RTEMS_SMP
397
398static inline struct Per_CPU_Control *_RISCV_Get_current_per_CPU_control( void )
399{
400  struct Per_CPU_Control *cpu_self;
401
402  __asm__ volatile (
403    ".option push\n"
404    ".option arch, +zicsr\n"
405    "csrr %0, mscratch\n"
406    ".option pop" :
407    "=r" ( cpu_self )
408  );
409
410  return cpu_self;
411}
412
413#define _CPU_Get_current_per_CPU_control() _RISCV_Get_current_per_CPU_control()
414
415#endif /* RTEMS_SMP */
416
417RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error );
418
419void _CPU_Context_volatile_clobber( uintptr_t pattern );
420
421void _CPU_Context_validate( uintptr_t pattern );
422
423RTEMS_INLINE_ROUTINE void _CPU_Instruction_illegal( void )
424{
425  __asm__ volatile ( "unimp" );
426}
427
428RTEMS_INLINE_ROUTINE void _CPU_Instruction_no_operation( void )
429{
430  __asm__ volatile ( "nop" );
431}
432
433RTEMS_INLINE_ROUTINE void _CPU_Use_thread_local_storage(
434  const Context_Control *context
435)
436{
437   register uintptr_t tp __asm__( "tp" );
438
439   tp = context->tp;
440
441   /* Make sure that the register assignment is not optimized away */
442   __asm__ volatile ( "" : : "r" ( tp ) );
443}
444
445#ifdef __cplusplus
446}
447#endif
448
449#endif /* ASM */
450
451/** @} */
452
453#endif /* _RTEMS_SCORE_CPUIMPL_H */
Note: See TracBrowser for help on using the repository browser.