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

5
Last change on this file since dd32e2b2 was dd32e2b2, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 6, 2018 at 6:12:40 AM

riscv: Implement CPU counter

Update #3433.

  • Property mode set to 100644
File size: 10.4 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_CACHE_LINE_BYTES 64
68
69#if __riscv_xlen == 32
70
71#define CPU_SIZEOF_POINTER 4
72
73#define CPU_STACK_MINIMUM_SIZE 4096
74
75#elif __riscv_xlen == 64
76
77#define CPU_SIZEOF_POINTER 8
78
79#define CPU_STACK_MINIMUM_SIZE 8192
80
81#endif /* __riscv_xlen */
82
83#define CPU_ALIGNMENT 8
84
85#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
86
87#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
88
89#define CPU_STACK_ALIGNMENT 16
90
91#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
92
93/*
94 *  Processor defined structures required for cpukit/score.
95 */
96
97#ifndef ASM
98
99#if __riscv_flen == 32
100typedef float RISCV_Float;
101#elif __riscv_flen == 64
102typedef double RISCV_Float;
103#endif
104
105typedef struct {
106#ifdef RTEMS_SMP
107  volatile uint32_t is_executing;
108#else
109  uint32_t reserved;
110#endif
111  uint32_t isr_dispatch_disable;
112  uintptr_t ra;
113  uintptr_t sp;
114  uintptr_t tp;
115  uintptr_t s0;
116  uintptr_t s1;
117  uintptr_t s2;
118  uintptr_t s3;
119  uintptr_t s4;
120  uintptr_t s5;
121  uintptr_t s6;
122  uintptr_t s7;
123  uintptr_t s8;
124  uintptr_t s9;
125  uintptr_t s10;
126  uintptr_t s11;
127#if __riscv_flen > 0
128  uint32_t fcsr;
129  RISCV_Float fs0;
130  RISCV_Float fs1;
131  RISCV_Float fs2;
132  RISCV_Float fs3;
133  RISCV_Float fs4;
134  RISCV_Float fs5;
135  RISCV_Float fs6;
136  RISCV_Float fs7;
137  RISCV_Float fs8;
138  RISCV_Float fs9;
139  RISCV_Float fs10;
140  RISCV_Float fs11;
141#endif
142} Context_Control;
143
144#define _CPU_Context_Get_SP( _context ) \
145  (_context)->sp
146
147#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
148
149#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
150
151#define _CPU_Initialize_vectors()
152
153static inline uint32_t riscv_interrupt_disable( void )
154{
155  unsigned long mstatus;
156
157  __asm__ volatile (
158    "csrrc %0, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE ) :
159      "=&r" ( mstatus )
160  );
161
162  return mstatus & RISCV_MSTATUS_MIE;
163}
164
165static inline void riscv_interrupt_enable( uint32_t level )
166{
167  __asm__ volatile ( "csrrs zero, mstatus, %0" : : "r" ( level ) );
168}
169
170#define _CPU_ISR_Disable( _level ) \
171    _level = riscv_interrupt_disable()
172
173#define _CPU_ISR_Enable( _level )  \
174  riscv_interrupt_enable( _level )
175
176#define _CPU_ISR_Flash( _level ) \
177  do{ \
178      _CPU_ISR_Enable( _level ); \
179      riscv_interrupt_disable(); \
180    } while(0)
181
182RTEMS_INLINE_ROUTINE bool _CPU_ISR_Is_enabled( unsigned long level )
183{
184  return ( level & RISCV_MSTATUS_MIE ) != 0;
185}
186
187RTEMS_INLINE_ROUTINE void _CPU_ISR_Set_level( uint32_t level )
188{
189  if ( ( level & CPU_MODES_INTERRUPT_MASK) == 0 ) {
190    __asm__ volatile (
191      "csrrs zero, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE )
192    );
193  } else {
194    __asm__ volatile (
195      "csrrc zero, mstatus, " RTEMS_XSTRING( RISCV_MSTATUS_MIE )
196    );
197  }
198}
199
200uint32_t _CPU_ISR_Get_level( void );
201
202/* end of ISR handler macros */
203
204void _CPU_Context_Initialize(
205  Context_Control *context,
206  void            *stack_area_begin,
207  size_t           stack_area_size,
208  uint32_t         new_level,
209  void          ( *entry_point )( void ),
210  bool             is_fp,
211  void            *tls_area
212);
213
214#define _CPU_Context_Restart_self( _the_context ) \
215   _CPU_Context_restore( (_the_context) )
216
217extern void _CPU_Fatal_halt(uint32_t source, uint32_t error) RTEMS_NO_RETURN;
218
219#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
220
221#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
222
223#define CPU_MAXIMUM_PROCESSORS 32
224
225typedef uint16_t Priority_bit_map_Word;
226
227typedef struct {
228  unsigned long x[32];;
229} CPU_Exception_frame;
230
231/**
232 * @brief Prints the exception frame via printk().
233 *
234 * @see rtems_fatal() and RTEMS_FATAL_SOURCE_EXCEPTION.
235 */
236void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
237
238
239/* end of Priority handler macros */
240
241/* functions */
242
243/*
244 *  _CPU_Initialize
245 *
246 *  This routine performs CPU dependent initialization.
247 *
248 */
249
250void _CPU_Initialize(
251  void
252);
253
254/*
255 *  _CPU_ISR_install_raw_handler
256 *
257 *  This routine installs a "raw" interrupt handler directly into the
258 *  processor's vector table.
259 *
260 */
261
262void _CPU_ISR_install_raw_handler(
263  uint32_t    vector,
264  proc_ptr    new_handler,
265  proc_ptr   *old_handler
266);
267
268/*
269 *  _CPU_ISR_install_vector
270 *
271 *  This routine installs an interrupt vector.
272 *
273 *  NO_CPU Specific Information:
274 *
275 *  XXX document implementation including references if appropriate
276 */
277
278void _CPU_ISR_install_vector(
279  unsigned long    vector,
280  proc_ptr   new_handler,
281  proc_ptr   *old_handler
282);
283
284/*
285 *  _CPU_Thread_Idle_body
286 *
287 *  This routine is the CPU dependent IDLE thread body.
288 *
289 *  NOTE:  It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
290 *         is TRUE.
291 *
292 */
293
294void *_CPU_Thread_Idle_body( uintptr_t ignored );
295
296/*
297 *  _CPU_Context_switch
298 *
299 *  This routine switches from the run context to the heir context.
300 *
301 *  RISCV Specific Information:
302 *
303 *  Please see the comments in the .c file for a description of how
304 *  this function works. There are several things to be aware of.
305 */
306
307void _CPU_Context_switch(
308  Context_Control  *run,
309  Context_Control  *heir
310);
311
312/*
313 *  _CPU_Context_restore
314 *
315 *  This routine is generally used only to restart self in an
316 *  efficient manner.  It may simply be a label in _CPU_Context_switch.
317 *
318 *  NOTE: May be unnecessary to reload some registers.
319 *
320 */
321
322void _CPU_Context_restore(
323  Context_Control *new_context
324) RTEMS_NO_RETURN;
325
326/*  The following routine swaps the endian format of an unsigned int.
327 *  It must be static because it is referenced indirectly.
328 *
329 *  This version will work on any processor, but if there is a better
330 *  way for your CPU PLEASE use it.  The most common way to do this is to:
331 *
332 *     swap least significant two bytes with 16-bit rotate
333 *     swap upper and lower 16-bits
334 *     swap most significant two bytes with 16-bit rotate
335 *
336 *  Some CPUs have special instructions which swap a 32-bit quantity in
337 *  a single instruction (e.g. i486).  It is probably best to avoid
338 *  an "endian swapping control bit" in the CPU.  One good reason is
339 *  that interrupts would probably have to be disabled to insure that
340 *  an interrupt does not try to access the same "chunk" with the wrong
341 *  endian.  Another good reason is that on some CPUs, the endian bit
342 *  endianness for ALL fetches -- both code and data -- so the code
343 *  will be fetched incorrectly.
344 *
345 */
346
347static inline uint32_t CPU_swap_u32(
348  uint32_t value
349)
350{
351  uint32_t   byte1, byte2, byte3, byte4, swapped;
352
353  byte4 = (value >> 24) & 0xff;
354  byte3 = (value >> 16) & 0xff;
355  byte2 = (value >> 8)  & 0xff;
356  byte1 =  value        & 0xff;
357
358  swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
359  return ( swapped );
360}
361
362#define CPU_swap_u16( value ) \
363  (((value&0xff) << 8) | ((value >> 8)&0xff))
364
365void _CPU_Context_volatile_clobber( uintptr_t pattern );
366
367void _CPU_Context_validate( uintptr_t pattern );
368
369typedef uint32_t CPU_Counter_ticks;
370
371uint32_t _CPU_Counter_frequency( void );
372
373static inline CPU_Counter_ticks _CPU_Counter_read( void )
374{
375  unsigned long ticks;
376
377  __asm__ volatile ( "rdtime %0" : "=&r" ( ticks ) );
378
379  return (uint32_t) ticks;
380}
381
382static inline CPU_Counter_ticks _CPU_Counter_difference(
383  CPU_Counter_ticks second,
384  CPU_Counter_ticks first
385)
386{
387  return second - first;
388}
389
390#ifdef RTEMS_SMP
391
392uint32_t _CPU_SMP_Initialize( void );
393
394bool _CPU_SMP_Start_processor( uint32_t cpu_index );
395
396void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
397
398void _CPU_SMP_Prepare_start_multitasking( void );
399
400static inline uint32_t _CPU_SMP_Get_current_processor( void )
401{
402  unsigned long mhartid;
403
404  __asm__ volatile ( "csrr %0, mhartid" : "=&r" ( mhartid ) );
405
406  return (uint32_t) mhartid;
407}
408
409void _CPU_SMP_Send_interrupt( uint32_t target_processor_index );
410
411static inline void _CPU_SMP_Processor_event_broadcast( void )
412{
413  __asm__ volatile ( "" : : : "memory" );
414}
415
416static inline void _CPU_SMP_Processor_event_receive( void )
417{
418  __asm__ volatile ( "" : : : "memory" );
419}
420
421static inline bool _CPU_Context_Get_is_executing(
422  const Context_Control *context
423)
424{
425  return context->is_executing;
426}
427
428static inline void _CPU_Context_Set_is_executing(
429  Context_Control *context,
430  bool is_executing
431)
432{
433  context->is_executing = is_executing;
434}
435
436#endif /* RTEMS_SMP */
437
438/** Type that can store a 32-bit integer or a pointer. */
439typedef uintptr_t CPU_Uint32ptr;
440
441#endif /* ASM */
442
443#ifdef __cplusplus
444}
445#endif
446
447#endif
Note: See TracBrowser for help on using the repository browser.