source: rtems/cpukit/score/cpu/sparc/cpu.c

Last change on this file was bcef89f2, checked in by Sebastian Huber <sebastian.huber@…>, on 05/19/23 at 06:18:25

Update company name

The embedded brains GmbH & Co. KG is the legal successor of embedded
brains GmbH.

  • Property mode set to 100644
File size: 9.9 KB
RevLine 
[e111974]1/* SPDX-License-Identifier: BSD-2-Clause */
2
[e0f91da]3/**
[955c045b]4 * @file
[c62d36f]5 *
[955c045b]6 * @ingroup RTEMSScoreCPUSPARC
7 *
8 * @brief This source file contains static assertions to ensure the consistency
9 *   of interfaces used in C and assembler and it contains the SPARC-specific
10 *   implementation of _CPU_Initialize(), _CPU_ISR_Get_level(), and
11 *   _CPU_Context_Initialize().
[e0f91da]12 */
13
14/*
[48816d7]15 *  COPYRIGHT (c) 1989-2007.
[c4808ca]16 *  On-Line Applications Research Corporation (OAR).
17 *
[bcef89f2]18 *  Copyright (c) 2017 embedded brains GmbH & Co. KG
[146adb1]19 *
[e111974]20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 *    notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 *    notice, this list of conditions and the following disclaimer in the
27 *    documentation and/or other materials provided with the distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
[c62d36f]40 */
41
[febaa8a]42#ifdef HAVE_CONFIG_H
43#include "config.h"
44#endif
45
[f8ad6c6f]46#include <rtems/score/percpu.h>
[022851a]47#include <rtems/score/tls.h>
[146adb1]48#include <rtems/score/thread.h>
[c62d36f]49
[2764bd43]50#if SPARC_HAS_FPU == 1
51  RTEMS_STATIC_ASSERT(
52    offsetof( Per_CPU_Control, cpu_per_cpu.fsr)
53      == SPARC_PER_CPU_FSR_OFFSET,
54    SPARC_PER_CPU_FSR_OFFSET
55  );
[146adb1]56
57  #if defined(SPARC_USE_LAZY_FP_SWITCH)
58    RTEMS_STATIC_ASSERT(
59      offsetof( Per_CPU_Control, cpu_per_cpu.fp_owner)
60        == SPARC_PER_CPU_FP_OWNER_OFFSET,
61      SPARC_PER_CPU_FP_OWNER_OFFSET
62    );
63  #endif
[2764bd43]64#endif
65
[97cf623d]66#define SPARC_ASSERT_OFFSET(field, off) \
67  RTEMS_STATIC_ASSERT( \
68    offsetof(Context_Control, field) == off ## _OFFSET, \
69    Context_Control_offset_ ## field \
70  )
71
72SPARC_ASSERT_OFFSET(g5, G5);
73SPARC_ASSERT_OFFSET(g7, G7);
[b2ec2d15]74
75RTEMS_STATIC_ASSERT(
76  offsetof(Context_Control, l0_and_l1) == L0_OFFSET,
77  Context_Control_offset_L0
78);
79
80RTEMS_STATIC_ASSERT(
81  offsetof(Context_Control, l0_and_l1) + 4 == L1_OFFSET,
82  Context_Control_offset_L1
83);
84
[97cf623d]85SPARC_ASSERT_OFFSET(l2, L2);
86SPARC_ASSERT_OFFSET(l3, L3);
87SPARC_ASSERT_OFFSET(l4, L4);
88SPARC_ASSERT_OFFSET(l5, L5);
89SPARC_ASSERT_OFFSET(l6, L6);
90SPARC_ASSERT_OFFSET(l7, L7);
91SPARC_ASSERT_OFFSET(i0, I0);
92SPARC_ASSERT_OFFSET(i1, I1);
93SPARC_ASSERT_OFFSET(i2, I2);
94SPARC_ASSERT_OFFSET(i3, I3);
95SPARC_ASSERT_OFFSET(i4, I4);
96SPARC_ASSERT_OFFSET(i5, I5);
97SPARC_ASSERT_OFFSET(i6_fp, I6_FP);
98SPARC_ASSERT_OFFSET(i7, I7);
99SPARC_ASSERT_OFFSET(o6_sp, O6_SP);
100SPARC_ASSERT_OFFSET(o7, O7);
101SPARC_ASSERT_OFFSET(psr, PSR);
102SPARC_ASSERT_OFFSET(isr_dispatch_disable, ISR_DISPATCH_DISABLE_STACK);
103
[38b59a6]104#if defined(RTEMS_SMP)
105SPARC_ASSERT_OFFSET(is_executing, SPARC_CONTEXT_CONTROL_IS_EXECUTING);
106#endif
107
[fedc6828]108#define SPARC_ASSERT_ISF_OFFSET(field, off) \
109  RTEMS_STATIC_ASSERT( \
110    offsetof(CPU_Interrupt_frame, field) == ISF_ ## off ## _OFFSET, \
111    CPU_Interrupt_frame_offset_ ## field \
112  )
113
114SPARC_ASSERT_ISF_OFFSET(psr, PSR);
115SPARC_ASSERT_ISF_OFFSET(pc, PC);
116SPARC_ASSERT_ISF_OFFSET(npc, NPC);
117SPARC_ASSERT_ISF_OFFSET(g1, G1);
118SPARC_ASSERT_ISF_OFFSET(g2, G2);
119SPARC_ASSERT_ISF_OFFSET(g3, G3);
120SPARC_ASSERT_ISF_OFFSET(g4, G4);
121SPARC_ASSERT_ISF_OFFSET(g5, G5);
122SPARC_ASSERT_ISF_OFFSET(g7, G7);
123SPARC_ASSERT_ISF_OFFSET(i0, I0);
124SPARC_ASSERT_ISF_OFFSET(i1, I1);
125SPARC_ASSERT_ISF_OFFSET(i2, I2);
126SPARC_ASSERT_ISF_OFFSET(i3, I3);
127SPARC_ASSERT_ISF_OFFSET(i4, I4);
128SPARC_ASSERT_ISF_OFFSET(i5, I5);
129SPARC_ASSERT_ISF_OFFSET(i6_fp, I6_FP);
130SPARC_ASSERT_ISF_OFFSET(i7, I7);
131SPARC_ASSERT_ISF_OFFSET(y, Y);
132SPARC_ASSERT_ISF_OFFSET(tpc, TPC);
133
[146adb1]134#define SPARC_ASSERT_FP_OFFSET(field, off) \
135  RTEMS_STATIC_ASSERT( \
136    offsetof(Context_Control_fp, field) == SPARC_FP_CONTEXT_OFFSET_ ## off, \
137    Context_Control_fp_offset_ ## field \
138  )
139
140SPARC_ASSERT_FP_OFFSET(f0_f1, F0_F1);
141SPARC_ASSERT_FP_OFFSET(f2_f3, F2_F3);
142SPARC_ASSERT_FP_OFFSET(f4_f5, F4_F5);
143SPARC_ASSERT_FP_OFFSET(f6_f7, F6_F7);
144SPARC_ASSERT_FP_OFFSET(f8_f9, F8_F9);
145SPARC_ASSERT_FP_OFFSET(f10_f11, F10_F11);
146SPARC_ASSERT_FP_OFFSET(f12_f13, F12_F13);
147SPARC_ASSERT_FP_OFFSET(f14_f15, F14_F15);
148SPARC_ASSERT_FP_OFFSET(f16_f17, F16_F17);
149SPARC_ASSERT_FP_OFFSET(f18_f19, F18_F19);
150SPARC_ASSERT_FP_OFFSET(f20_f21, F20_F21);
151SPARC_ASSERT_FP_OFFSET(f22_f23, F22_F23);
152SPARC_ASSERT_FP_OFFSET(f24_f25, F24_F25);
153SPARC_ASSERT_FP_OFFSET(f26_f27, F26_F27);
154SPARC_ASSERT_FP_OFFSET(f28_f29, F28_F29);
155SPARC_ASSERT_FP_OFFSET(f30_f31, F30_F31);
156SPARC_ASSERT_FP_OFFSET(fsr, FSR);
157
[76030c7]158RTEMS_STATIC_ASSERT(
[c539a865]159  sizeof(SPARC_Minimum_stack_frame) == SPARC_MINIMUM_STACK_FRAME_SIZE,
160  SPARC_MINIMUM_STACK_FRAME_SIZE
161);
162
[fedc6828]163/* https://devel.rtems.org/ticket/2352 */
164RTEMS_STATIC_ASSERT(
165  sizeof(CPU_Interrupt_frame) % CPU_ALIGNMENT == 0,
166  CPU_Interrupt_frame_alignment
167);
168
[d73e657e]169#define SPARC_ASSERT_REGISTER_WINDOW_OFFSET( member, off ) \
170  RTEMS_STATIC_ASSERT( \
171    offsetof( SPARC_Register_window, member ) == \
172      RTEMS_XCONCAT( SPARC_REGISTER_WINDOW_OFFSET_, off ), \
173    SPARC_Register_window ## member \
174  )
175
176SPARC_ASSERT_REGISTER_WINDOW_OFFSET( local[ 0 ], LOCAL( 0 ) );
177SPARC_ASSERT_REGISTER_WINDOW_OFFSET( local[ 1 ], LOCAL( 1 ) );
178SPARC_ASSERT_REGISTER_WINDOW_OFFSET( input[ 0 ], INPUT( 0 ) );
179SPARC_ASSERT_REGISTER_WINDOW_OFFSET( input[ 1 ], INPUT( 1 ) );
180
181RTEMS_STATIC_ASSERT(
182  sizeof( SPARC_Register_window ) == SPARC_REGISTER_WINDOW_SIZE,
183  SPARC_REGISTER_WINDOW_SIZE
184);
185
186#define SPARC_ASSERT_EXCEPTION_OFFSET( member, off ) \
187  RTEMS_STATIC_ASSERT( \
188    offsetof( CPU_Exception_frame, member ) == \
189      RTEMS_XCONCAT( SPARC_EXCEPTION_OFFSET_, off ), \
190    CPU_Exception_frame_offset_ ## member \
191  )
192
193SPARC_ASSERT_EXCEPTION_OFFSET( psr, PSR );
194SPARC_ASSERT_EXCEPTION_OFFSET( pc, PC );
195SPARC_ASSERT_EXCEPTION_OFFSET( npc, NPC );
196SPARC_ASSERT_EXCEPTION_OFFSET( trap, TRAP );
197SPARC_ASSERT_EXCEPTION_OFFSET( wim, WIM );
198SPARC_ASSERT_EXCEPTION_OFFSET( y, Y );
199SPARC_ASSERT_EXCEPTION_OFFSET( global[ 0 ], GLOBAL( 0 ) );
200SPARC_ASSERT_EXCEPTION_OFFSET( global[ 1 ], GLOBAL( 1 ) );
201SPARC_ASSERT_EXCEPTION_OFFSET( output[ 0 ], OUTPUT( 0 ) );
202SPARC_ASSERT_EXCEPTION_OFFSET( output[ 1 ], OUTPUT( 1 ) );
203
204#if SPARC_HAS_FPU == 1
205SPARC_ASSERT_EXCEPTION_OFFSET( fsr, FSR );
206SPARC_ASSERT_EXCEPTION_OFFSET( fp[ 0 ], FP( 0 ) );
207SPARC_ASSERT_EXCEPTION_OFFSET( fp[ 1 ], FP( 1 ) );
208#endif
209
210RTEMS_STATIC_ASSERT(
211  sizeof( CPU_Exception_frame ) == SPARC_EXCEPTION_FRAME_SIZE,
212  SPARC_EXCEPTION_FRAME_SIZE
213);
214
215RTEMS_STATIC_ASSERT(
216  sizeof( CPU_Exception_frame ) % CPU_ALIGNMENT == 0,
217  CPU_Exception_frame_alignment
218);
219
[7c2f2448]220/*
[9700578]221 *  _CPU_Initialize
[c62d36f]222 *
223 *  This routine performs processor dependent initialization.
224 *
[c03e2bc]225 *  INPUT PARAMETERS: NONE
[9700578]226 *
227 *  Output Parameters: NONE
[80f7732]228 *
[9700578]229 *  NOTE: There is no need to save the pointer to the thread dispatch routine.
230 *        The SPARC's assembly code can reference it directly with no problems.
[c62d36f]231 */
232
[c03e2bc]233void _CPU_Initialize(void)
[c62d36f]234{
[146adb1]235#if defined(SPARC_USE_LAZY_FP_SWITCH)
236  __asm__ volatile (
237    ".global SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET\n"
238    ".set SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET, %0\n"
239    ".global SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET\n"
240    ".set SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET, %1\n"
241    :
242    : "i" (offsetof(Thread_Control, Registers.fp_context)),
243      "i" (offsetof(Thread_Control, fp_context))
244  );
[477e2d19]245#endif
[c62d36f]246}
247
[2a0a6851]248uint32_t   _CPU_ISR_Get_level( void )
[c62d36f]249{
[2a0a6851]250  uint32_t   level;
[80f7732]251
[c62d36f]252  sparc_get_interrupt_level( level );
[80f7732]253
[c62d36f]254  return level;
255}
256
257void _CPU_Context_Initialize(
[9700578]258  Context_Control  *the_context,
[2a0a6851]259  uint32_t         *stack_base,
260  uint32_t          size,
261  uint32_t          new_level,
[9700578]262  void             *entry_point,
[022851a]263  bool              is_fp,
264  void             *tls_area
[c62d36f]265)
266{
[2a0a6851]267    uint32_t     stack_high;  /* highest "stack aligned" address */
268    uint32_t     tmp_psr;
[80f7732]269
[c62d36f]270    /*
271     *  On CPUs with stacks which grow down (i.e. SPARC), we build the stack
[80f7732]272     *  based on the stack_high address.
[c62d36f]273     */
[80f7732]274
[df4fcaa]275    stack_high = ((uint32_t)(stack_base) + size);
[9700578]276    stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
[80f7732]277
[c62d36f]278    /*
[9700578]279     *  See the README in this directory for a diagram of the stack.
[c62d36f]280     */
[80f7732]281
[df4fcaa]282    the_context->o7    = ((uint32_t) entry_point) - 8;
[427dcee]283    the_context->o6_sp = stack_high - SPARC_MINIMUM_STACK_FRAME_SIZE;
[48816d7]284    the_context->i6_fp = 0;
[c62d36f]285
[9700578]286    /*
287     *  Build the PSR for the task.  Most everything can be 0 and the
288     *  CWP is corrected during the context switch.
289     *
290     *  The EF bit determines if the floating point unit is available.
291     *  The FPU is ONLY enabled if the context is associated with an FP task
292     *  and this SPARC model has an FPU.
293     */
[c62d36f]294
295    sparc_get_psr( tmp_psr );
[9700578]296    tmp_psr &= ~SPARC_PSR_PIL_MASK;
297    tmp_psr |= (new_level << 8) & SPARC_PSR_PIL_MASK;
298    tmp_psr &= ~SPARC_PSR_EF_MASK;      /* disabled by default */
[80f7732]299
[78cac9b]300    /* _CPU_Context_restore_heir() relies on this */
301    _Assert( ( tmp_psr & SPARC_PSR_ET_MASK ) != 0 );
302
[9700578]303#if (SPARC_HAS_FPU == 1)
304    /*
305     *  If this bit is not set, then a task gets a fault when it accesses
306     *  a floating point register.  This is a nice way to detect floating
307     *  point tasks which are not currently declared as such.
308     */
309
310    if ( is_fp )
311      tmp_psr |= SPARC_PSR_EF_MASK;
312#endif
313    the_context->psr = tmp_psr;
[a32835a3]314
315  /*
316   *  Since THIS thread is being created, there is no way that THIS
[4fea054c]317   *  thread can have an interrupt stack frame on its stack.
[a32835a3]318   */
[4fea054c]319  the_context->isr_dispatch_disable = 0;
[022851a]320
321  if ( tls_area != NULL ) {
[4c89fbcd]322    void *tcb = _TLS_Initialize_area( tls_area );
[022851a]323
324    the_context->g7 = (uintptr_t) tcb;
325  }
[c62d36f]326}
Note: See TracBrowser for help on using the repository browser.