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

5
Last change on this file since 52352387 was 52352387, checked in by Sebastian Huber <sebastian.huber@…>, on 06/28/18 at 07:32:26

riscv: Add floating-point support

Update #3433.

  • Property mode set to 100644
File size: 10.3 KB
Line 
1/**
2 * @file rtems/score/cpu.h
3 */
4
5/*
6 * Copyright (c) 2018 embedded brains GmbH
7 *
8 * Copyright (c) 2015 University of York.
9 * Hesham Almatary <hesham@alumni.york.ac.uk>
10 *
11 * COPYRIGHT (c) 1989-1999.
12 * On-Line Applications Research Corporation (OAR).
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 *    notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *    notice, this list of conditions and the following disclaimer in the
21 *    documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#ifndef _RISCV_CPU_H
37#define _RISCV_CPU_H
38
39#ifdef __cplusplus
40extern "C" {
41#endif
42
43#include <rtems/score/basedefs.h>
44#include <rtems/score/riscv.h>
45
46#define RISCV_MSTATUS_MIE 0x8
47
48#define CPU_INLINE_ENABLE_DISPATCH       FALSE
49#define CPU_UNROLL_ENQUEUE_PRIORITY      TRUE
50
51#define CPU_ISR_PASSES_FRAME_POINTER FALSE
52
53#define CPU_HARDWARE_FP                  FALSE
54#define CPU_SOFTWARE_FP                  FALSE
55#define CPU_ALL_TASKS_ARE_FP             FALSE
56#define CPU_IDLE_TASK_IS_FP              FALSE
57#define CPU_USE_DEFERRED_FP_SWITCH       FALSE
58#define CPU_PROVIDES_IDLE_THREAD_BODY    TRUE
59#define CPU_STACK_GROWS_UP               FALSE
60
61#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (64)))
62#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES     FALSE
63#define CPU_BIG_ENDIAN                           FALSE
64#define CPU_LITTLE_ENDIAN                        TRUE
65#define CPU_MODES_INTERRUPT_MASK   0x0000000000000001
66
67#define CPU_PER_CPU_CONTROL_SIZE 0
68
69#define CPU_CACHE_LINE_BYTES 64
70
71#if __riscv_xlen == 32
72
73#define CPU_SIZEOF_POINTER 4
74
75#define CPU_STACK_MINIMUM_SIZE 4096
76
77#elif __riscv_xlen == 64
78
79#define CPU_SIZEOF_POINTER 8
80
81#define CPU_STACK_MINIMUM_SIZE 8192
82
83#endif /* __riscv_xlen */
84
85#define CPU_ALIGNMENT 8
86
87#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
88
89#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
90
91#define CPU_STACK_ALIGNMENT 16
92
93#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
94
95/*
96 *  Processor defined structures required for cpukit/score.
97 */
98
99#ifndef ASM
100
101#if __riscv_flen == 32
102typedef float RISCV_Float;
103#elif __riscv_flen == 64
104typedef double RISCV_Float;
105#endif
106
107typedef struct {
108#ifdef RTEMS_SMP
109  volatile uint32_t is_executing;
110#else
111  uint32_t reserved;
112#endif
113  uint32_t isr_dispatch_disable;
114  uintptr_t ra;
115  uintptr_t sp;
116  uintptr_t tp;
117  uintptr_t s0;
118  uintptr_t s1;
119  uintptr_t s2;
120  uintptr_t s3;
121  uintptr_t s4;
122  uintptr_t s5;
123  uintptr_t s6;
124  uintptr_t s7;
125  uintptr_t s8;
126  uintptr_t s9;
127  uintptr_t s10;
128  uintptr_t s11;
129#if __riscv_flen > 0
130  uint32_t fcsr;
131  RISCV_Float fs0;
132  RISCV_Float fs1;
133  RISCV_Float fs2;
134  RISCV_Float fs3;
135  RISCV_Float fs4;
136  RISCV_Float fs5;
137  RISCV_Float fs6;
138  RISCV_Float fs7;
139  RISCV_Float fs8;
140  RISCV_Float fs9;
141  RISCV_Float fs10;
142  RISCV_Float fs11;
143#endif
144} Context_Control;
145
146#define _CPU_Context_Get_SP( _context ) \
147  (_context)->sp
148
149#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
150
151#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
152
153#define _CPU_Initialize_vectors()
154
155static inline uint32_t riscv_interrupt_disable( void )
156{
157  unsigned long mstatus;
158
159  __asm__ volatile (
160    "csrrc %0, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE ) :
161      "=&r" ( mstatus )
162  );
163
164  return mstatus & RISCV_MSTATUS_MIE;
165}
166
167static inline void riscv_interrupt_enable( uint32_t level )
168{
169  __asm__ volatile ( "csrrs zero, mstatus, %0" : : "r" ( level ) );
170}
171
172#define _CPU_ISR_Disable( _level ) \
173    _level = riscv_interrupt_disable()
174
175#define _CPU_ISR_Enable( _level )  \
176  riscv_interrupt_enable( _level )
177
178#define _CPU_ISR_Flash( _level ) \
179  do{ \
180      _CPU_ISR_Enable( _level ); \
181      riscv_interrupt_disable(); \
182    } while(0)
183
184RTEMS_INLINE_ROUTINE bool _CPU_ISR_Is_enabled( unsigned long level )
185{
186  return ( level & RISCV_MSTATUS_MIE ) != 0;
187}
188
189RTEMS_INLINE_ROUTINE void _CPU_ISR_Set_level( uint32_t level )
190{
191  if ( ( level & CPU_MODES_INTERRUPT_MASK) == 0 ) {
192    __asm__ volatile (
193      "csrrs zero, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE )
194    );
195  } else {
196    __asm__ volatile (
197      "csrrc zero, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE )
198    );
199  }
200}
201
202uint32_t _CPU_ISR_Get_level( void );
203
204/* end of ISR handler macros */
205
206void _CPU_Context_Initialize(
207  Context_Control *context,
208  void            *stack_area_begin,
209  size_t           stack_area_size,
210  uint32_t         new_level,
211  void          ( *entry_point )( void ),
212  bool             is_fp,
213  void            *tls_area
214);
215
216#define _CPU_Context_Restart_self( _the_context ) \
217   _CPU_Context_restore( (_the_context) )
218
219extern void _CPU_Fatal_halt(uint32_t source, uint32_t error) RTEMS_NO_RETURN;
220
221#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
222
223#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
224
225#define CPU_MAXIMUM_PROCESSORS 32
226
227typedef struct {
228  /* There is no CPU specific per-CPU state */
229} CPU_Per_CPU_control;
230
231typedef uint16_t Priority_bit_map_Word;
232
233typedef struct {
234  unsigned long x[32];;
235} CPU_Exception_frame;
236
237/**
238 * @brief Prints the exception frame via printk().
239 *
240 * @see rtems_fatal() and RTEMS_FATAL_SOURCE_EXCEPTION.
241 */
242void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
243
244
245/* end of Priority handler macros */
246
247/* functions */
248
249/*
250 *  _CPU_Initialize
251 *
252 *  This routine performs CPU dependent initialization.
253 *
254 */
255
256void _CPU_Initialize(
257  void
258);
259
260/*
261 *  _CPU_ISR_install_raw_handler
262 *
263 *  This routine installs a "raw" interrupt handler directly into the
264 *  processor's vector table.
265 *
266 */
267
268void _CPU_ISR_install_raw_handler(
269  uint32_t    vector,
270  proc_ptr    new_handler,
271  proc_ptr   *old_handler
272);
273
274/*
275 *  _CPU_ISR_install_vector
276 *
277 *  This routine installs an interrupt vector.
278 *
279 *  NO_CPU Specific Information:
280 *
281 *  XXX document implementation including references if appropriate
282 */
283
284void _CPU_ISR_install_vector(
285  unsigned long    vector,
286  proc_ptr   new_handler,
287  proc_ptr   *old_handler
288);
289
290/*
291 *  _CPU_Thread_Idle_body
292 *
293 *  This routine is the CPU dependent IDLE thread body.
294 *
295 *  NOTE:  It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
296 *         is TRUE.
297 *
298 */
299
300void *_CPU_Thread_Idle_body( uintptr_t ignored );
301
302/*
303 *  _CPU_Context_switch
304 *
305 *  This routine switches from the run context to the heir context.
306 *
307 *  RISCV Specific Information:
308 *
309 *  Please see the comments in the .c file for a description of how
310 *  this function works. There are several things to be aware of.
311 */
312
313void _CPU_Context_switch(
314  Context_Control  *run,
315  Context_Control  *heir
316);
317
318/*
319 *  _CPU_Context_restore
320 *
321 *  This routine is generally used only to restart self in an
322 *  efficient manner.  It may simply be a label in _CPU_Context_switch.
323 *
324 *  NOTE: May be unnecessary to reload some registers.
325 *
326 */
327
328void _CPU_Context_restore(
329  Context_Control *new_context
330) RTEMS_NO_RETURN;
331
332/*  The following routine swaps the endian format of an unsigned int.
333 *  It must be static because it is referenced indirectly.
334 *
335 *  This version will work on any processor, but if there is a better
336 *  way for your CPU PLEASE use it.  The most common way to do this is to:
337 *
338 *     swap least significant two bytes with 16-bit rotate
339 *     swap upper and lower 16-bits
340 *     swap most significant two bytes with 16-bit rotate
341 *
342 *  Some CPUs have special instructions which swap a 32-bit quantity in
343 *  a single instruction (e.g. i486).  It is probably best to avoid
344 *  an "endian swapping control bit" in the CPU.  One good reason is
345 *  that interrupts would probably have to be disabled to insure that
346 *  an interrupt does not try to access the same "chunk" with the wrong
347 *  endian.  Another good reason is that on some CPUs, the endian bit
348 *  endianness for ALL fetches -- both code and data -- so the code
349 *  will be fetched incorrectly.
350 *
351 */
352
353static inline uint32_t CPU_swap_u32(
354  uint32_t value
355)
356{
357  uint32_t   byte1, byte2, byte3, byte4, swapped;
358
359  byte4 = (value >> 24) & 0xff;
360  byte3 = (value >> 16) & 0xff;
361  byte2 = (value >> 8)  & 0xff;
362  byte1 =  value        & 0xff;
363
364  swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
365  return ( swapped );
366}
367
368#define CPU_swap_u16( value ) \
369  (((value&0xff) << 8) | ((value >> 8)&0xff))
370
371void _CPU_Context_volatile_clobber( uintptr_t pattern );
372
373void _CPU_Context_validate( uintptr_t pattern );
374
375typedef uint32_t CPU_Counter_ticks;
376
377uint32_t _CPU_Counter_frequency( void );
378
379CPU_Counter_ticks _CPU_Counter_read( void );
380
381#ifdef RTEMS_SMP
382
383uint32_t _CPU_SMP_Initialize( void );
384
385bool _CPU_SMP_Start_processor( uint32_t cpu_index );
386
387void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
388
389void _CPU_SMP_Prepare_start_multitasking( void );
390
391static inline uint32_t _CPU_SMP_Get_current_processor( void )
392{
393  unsigned long mhartid;
394
395  __asm__ volatile ( "csrr %0, mhartid" : "=&r" ( mhartid ) );
396
397  return (uint32_t) mhartid;
398}
399
400void _CPU_SMP_Send_interrupt( uint32_t target_processor_index );
401
402static inline void _CPU_SMP_Processor_event_broadcast( void )
403{
404  __asm__ volatile ( "" : : : "memory" );
405}
406
407static inline void _CPU_SMP_Processor_event_receive( void )
408{
409  __asm__ volatile ( "" : : : "memory" );
410}
411
412static inline bool _CPU_Context_Get_is_executing(
413  const Context_Control *context
414)
415{
416  return context->is_executing;
417}
418
419static inline void _CPU_Context_Set_is_executing(
420  Context_Control *context,
421  bool is_executing
422)
423{
424  context->is_executing = is_executing;
425}
426
427#endif /* RTEMS_SMP */
428
429/** Type that can store a 32-bit integer or a pointer. */
430typedef uintptr_t CPU_Uint32ptr;
431
432#endif /* ASM */
433
434#ifdef __cplusplus
435}
436#endif
437
438#endif
Note: See TracBrowser for help on using the repository browser.