Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:25

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2015, 2017 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include <rtems/asm.h>
0033 #include <rtems/score/cpuimpl.h>
0034 #include <rtems/score/percpu.h>
0035 
0036 #define FRAME_OFFSET_BUFFER_0 (SPARC_MINIMUM_STACK_FRAME_SIZE)
0037 #define FRAME_OFFSET_BUFFER_1 (FRAME_OFFSET_BUFFER_0 + 0x04)
0038 #define FRAME_OFFSET_BUFFER_2 (FRAME_OFFSET_BUFFER_1 + 0x04)
0039 #define FRAME_OFFSET_L0 (FRAME_OFFSET_BUFFER_2 + 0x04)
0040 #define FRAME_OFFSET_L1 (FRAME_OFFSET_L0 + 0x04)
0041 #define FRAME_OFFSET_L2 (FRAME_OFFSET_L1 + 0x04)
0042 #define FRAME_OFFSET_L3 (FRAME_OFFSET_L2 + 0x04)
0043 #define FRAME_OFFSET_L4 (FRAME_OFFSET_L3 + 0x04)
0044 #define FRAME_OFFSET_L5 (FRAME_OFFSET_L4 + 0x04)
0045 #define FRAME_OFFSET_L6 (FRAME_OFFSET_L5 + 0x04)
0046 #define FRAME_OFFSET_L7 (FRAME_OFFSET_L6 + 0x04)
0047 #define FRAME_OFFSET_I0 (FRAME_OFFSET_L7 + 0x04)
0048 #define FRAME_OFFSET_I1 (FRAME_OFFSET_I0 + 0x04)
0049 #define FRAME_OFFSET_I2 (FRAME_OFFSET_I1 + 0x04)
0050 #define FRAME_OFFSET_I3 (FRAME_OFFSET_I2 + 0x04)
0051 #define FRAME_OFFSET_I4 (FRAME_OFFSET_I3 + 0x04)
0052 #define FRAME_OFFSET_I5 (FRAME_OFFSET_I4 + 0x04)
0053 #define FRAME_OFFSET_I6 (FRAME_OFFSET_I5 + 0x04)
0054 #define FRAME_OFFSET_I7 (FRAME_OFFSET_I6 + 0x04)
0055 #define FRAME_END (FRAME_OFFSET_I7 + 0x04)
0056 #define FRAME_SIZE \
0057   ((FRAME_END + CPU_STACK_ALIGNMENT - 1) & ~(CPU_STACK_ALIGNMENT - 1))
0058 
0059 /*
0060  * The FSR pattern is masked with undefined fields, reserved fields, ftt
0061  * (cleared by fmovs), cexc (cleared by fmovs), and system-specific values
0062  * (e.g. FPU architecture version, FP queue).
0063  */
0064 #define FSR_PATTERN_MASK 0xcf800fe0
0065 
0066 .macro check_register reg
0067     sub %g1, 1, %g1
0068     cmp %g1, \reg
0069     bne restore_registers
0070      nop
0071 .endm
0072 
0073 .macro check_float_register reg
0074     sub %g1, 1, %g1
0075     st  \reg, [%sp + FRAME_OFFSET_BUFFER_0]
0076     cmp %g0, %sp
0077     fmovs   \reg, \reg
0078     be  restore_registers
0079      nop
0080     cmp %g0, %g0
0081     fmovs   \reg, \reg
0082     bne restore_registers
0083      nop
0084     ld  [%sp + FRAME_OFFSET_BUFFER_0], %o1
0085     cmp %g1, %o1
0086     bne restore_registers
0087      nop
0088 .endm
0089 
0090 .macro write_register reg
0091     add %g1, 1, %g1
0092     mov %g1, \reg
0093 .endm
0094 
0095 .macro write_float_register reg
0096     add %g1, 1, %g1
0097     st  %g1, [%sp + FRAME_OFFSET_BUFFER_0]
0098     ld  [%sp + FRAME_OFFSET_BUFFER_0], \reg
0099 .endm
0100 
0101         .align 4
0102         PUBLIC(_CPU_Context_validate)
0103 SYM(_CPU_Context_validate):
0104 
0105     /* g2 indicates if the FPU should be checked */
0106 #if defined(SPARC_USE_LAZY_FP_SWITCH)
0107     ld  [%g6 + PER_CPU_OFFSET_EXECUTING], %g2
0108     ld  [%g2 + %lo(SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET)], %g2
0109 #else
0110     mov %psr, %g2
0111     sethi   %hi(SPARC_PSR_EF_MASK), %g3
0112     and %g2, %g3, %g2
0113 #endif
0114 
0115     /* g1 is used to save the original pattern */
0116     mov %o0, %g1
0117 
0118     /* g4 establishes window counter */
0119     clr %g4
0120 
0121     add %sp, -FRAME_SIZE, %sp
0122 
0123     st  %l0, [%sp + FRAME_OFFSET_L0]
0124     st  %l1, [%sp + FRAME_OFFSET_L1]
0125     st  %l2, [%sp + FRAME_OFFSET_L2]
0126     st  %l3, [%sp + FRAME_OFFSET_L3]
0127     st  %l4, [%sp + FRAME_OFFSET_L4]
0128     st  %l5, [%sp + FRAME_OFFSET_L5]
0129     st  %l6, [%sp + FRAME_OFFSET_L6]
0130     st  %l7, [%sp + FRAME_OFFSET_L7]
0131     st  %i0, [%sp + FRAME_OFFSET_I0]
0132     st  %i1, [%sp + FRAME_OFFSET_I1]
0133     st  %i2, [%sp + FRAME_OFFSET_I2]
0134     st  %i3, [%sp + FRAME_OFFSET_I3]
0135     st  %i4, [%sp + FRAME_OFFSET_I4]
0136     st  %i5, [%sp + FRAME_OFFSET_I5]
0137     st  %i6, [%sp + FRAME_OFFSET_I6]
0138     st  %i7, [%sp + FRAME_OFFSET_I7]
0139 
0140     cmp %g4, 0
0141     bne write_locals_and_outputs
0142      nop
0143     be  check_for_fp
0144      nop
0145 
0146 new_check_cycle:
0147     clr %g4
0148     add %g4, 1, %g4
0149     ld  [%sp + FRAME_OFFSET_BUFFER_1], %g1
0150     b   switch_to_next_window
0151      nop
0152     /* Write pattern values into registers */
0153 
0154 check_for_fp:
0155     cmp %g2, 0
0156     be  write_y
0157      nop
0158 
0159     /* Write masked pattern to FSR */
0160     st  %fsr, [%sp + FRAME_OFFSET_BUFFER_0]
0161     ld  [%sp + FRAME_OFFSET_BUFFER_0], %o1
0162     add %g1, 1, %g1
0163     sethi   %hi(FSR_PATTERN_MASK), %g3
0164     or  %g3, %lo(FSR_PATTERN_MASK), %g3
0165     and %g1, %g3, %g3
0166     or  %o1, %g3, %g3
0167     st  %g3, [%sp + FRAME_OFFSET_BUFFER_0]
0168     ld  [%sp + FRAME_OFFSET_BUFFER_0], %fsr
0169 
0170     write_float_register    %f0
0171     write_float_register    %f1
0172     write_float_register    %f2
0173     write_float_register    %f3
0174     write_float_register    %f4
0175     write_float_register    %f5
0176     write_float_register    %f6
0177     write_float_register    %f7
0178     write_float_register    %f8
0179     write_float_register    %f9
0180     write_float_register    %f10
0181     write_float_register    %f11
0182     write_float_register    %f12
0183     write_float_register    %f13
0184     write_float_register    %f14
0185     write_float_register    %f15
0186     write_float_register    %f16
0187     write_float_register    %f17
0188     write_float_register    %f18
0189     write_float_register    %f19
0190     write_float_register    %f20
0191     write_float_register    %f21
0192     write_float_register    %f22
0193     write_float_register    %f23
0194     write_float_register    %f24
0195     write_float_register    %f25
0196     write_float_register    %f26
0197     write_float_register    %f27
0198     write_float_register    %f28
0199     write_float_register    %f29
0200     write_float_register    %f30
0201     write_float_register    %f31
0202 
0203 write_y:
0204     write_register  %y
0205 
0206     write_register  %i0
0207     write_register  %i1
0208     write_register  %i2
0209     write_register  %i3
0210     write_register  %i4
0211     write_register  %i5
0212     /* Don't write register $i6 => frame pointer */
0213     /* Don't write register $i7 => return address */
0214     b   write_locals_and_outputs
0215      nop
0216 
0217 switch_to_next_window:
0218     save    %sp, -FRAME_SIZE, %sp
0219 
0220 write_locals_and_outputs:
0221     /* l0 is used as a scratch register */
0222     write_register  %l1
0223     write_register  %l2
0224     write_register  %l3
0225     write_register  %l4
0226     write_register  %l5
0227     write_register  %l6
0228     write_register  %l7
0229     write_register  %o1
0230     write_register  %o2
0231     write_register  %o3
0232     write_register  %o4
0233     write_register  %o5
0234     /* Don't write register $o6 => stack pointer */
0235     /* Don't write register $o7 => return address */
0236 
0237     add %g4, 1, %g4
0238     cmp %g4, 1
0239     bne no_store
0240      nop
0241     st  %g1, [%sp + FRAME_OFFSET_BUFFER_1]
0242 
0243 no_store:
0244     cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
0245     bne switch_to_next_window
0246      nop
0247 
0248     /* Dummy increment to set up reverse mechanism for checking process */
0249     add %g1, 1, %g1
0250     clr %g4
0251 
0252     /* Checking begins here */
0253 window_checking:
0254     cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
0255     be  y_checking
0256      nop
0257 
0258 further_checking:
0259     cmp %g4, 0
0260     bne goto_local_registers
0261      nop
0262 
0263     /* Check normal registers */
0264     check_register  %o5
0265     check_register  %o4
0266     check_register  %o3
0267     check_register  %o2
0268     check_register  %o1
0269 
0270 goto_local_registers:
0271     check_register  %l7
0272     check_register  %l6
0273     check_register  %l5
0274     check_register  %l4
0275     check_register  %l3
0276     check_register  %l2
0277     check_register  %l1
0278 
0279     check_register  %i5
0280     check_register  %i4
0281     check_register  %i3
0282     check_register  %i2
0283     check_register  %i1
0284     /*
0285     For the last window i0 also needs to be checked as this variable
0286     is not overwritten by the outputs of another window.
0287     */
0288     add %g4, 1, %g4
0289     cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
0290     bne dont_check_i0
0291      nop
0292     check_register  %i0
0293     b   y_checking
0294      nop
0295 
0296 dont_check_i0:
0297     restore
0298 
0299     ba  window_checking
0300      nop
0301 
0302     /* Check Y register */
0303 y_checking:
0304     st  %o1, [%sp + FRAME_OFFSET_BUFFER_2]
0305     mov %y, %o1
0306     check_register  %o1
0307     ld  [%sp + FRAME_OFFSET_BUFFER_2], %o1
0308     cmp %g2, 0
0309     be  new_check_cycle
0310      nop
0311 
0312     st  %o1, [%sp + FRAME_OFFSET_BUFFER_2]
0313     SPARC_LEON3FT_B2BST_NOP
0314     /* Check floating point registers */
0315     check_float_register    %f31
0316     check_float_register    %f30
0317     check_float_register    %f29
0318     check_float_register    %f28
0319     check_float_register    %f27
0320     check_float_register    %f26
0321     check_float_register    %f25
0322     check_float_register    %f24
0323     check_float_register    %f23
0324     check_float_register    %f22
0325     check_float_register    %f21
0326     check_float_register    %f20
0327     check_float_register    %f19
0328     check_float_register    %f18
0329     check_float_register    %f17
0330     check_float_register    %f16
0331     check_float_register    %f15
0332     check_float_register    %f14
0333     check_float_register    %f13
0334     check_float_register    %f12
0335     check_float_register    %f11
0336     check_float_register    %f10
0337     check_float_register    %f9
0338     check_float_register    %f8
0339     check_float_register    %f7
0340     check_float_register    %f6
0341     check_float_register    %f5
0342     check_float_register    %f4
0343     check_float_register    %f3
0344     check_float_register    %f2
0345     check_float_register    %f1
0346     check_float_register    %f0
0347 
0348     st  %fsr, [%sp + FRAME_OFFSET_BUFFER_0]
0349     ld  [%sp + FRAME_OFFSET_BUFFER_0], %o1
0350     sub %g1, 1, %g1
0351     clr %g3
0352     sethi   %hi(FSR_PATTERN_MASK), %g3
0353     or  %g3, %lo(FSR_PATTERN_MASK), %g3
0354     and %g1, %g3, %g3
0355     and %o1, %g3, %o1
0356     cmp %o1, %g3
0357     bne restore_registers
0358      ld [%sp + FRAME_OFFSET_BUFFER_2], %o1
0359 
0360     b   new_check_cycle
0361      nop
0362 
0363     /****** RESTORE STARTS HERE *******/
0364 
0365     /* Restore non-volatile registers */
0366 
0367 restore_registers:
0368     and %g4, (SPARC_NUMBER_OF_REGISTER_WINDOWS - 1), %g4
0369     cmp %g4, 0
0370     be  real_restore
0371      nop
0372     restore
0373     sub %g4, 1, %g4
0374     bne restore_registers
0375      nop
0376 
0377 real_restore:
0378     ld  [%sp + FRAME_OFFSET_L0], %l0
0379     ld  [%sp + FRAME_OFFSET_L1], %l1
0380     ld  [%sp + FRAME_OFFSET_L2], %l2
0381     ld  [%sp + FRAME_OFFSET_L3], %l3
0382     ld  [%sp + FRAME_OFFSET_L4], %l4
0383     ld  [%sp + FRAME_OFFSET_L5], %l5
0384     ld  [%sp + FRAME_OFFSET_L6], %l6
0385     ld  [%sp + FRAME_OFFSET_L7], %l7
0386     ld  [%sp + FRAME_OFFSET_I0], %i0
0387     ld  [%sp + FRAME_OFFSET_I1], %i1
0388     ld  [%sp + FRAME_OFFSET_I2], %i2
0389     ld  [%sp + FRAME_OFFSET_I3], %i3
0390     ld  [%sp + FRAME_OFFSET_I4], %i4
0391     ld  [%sp + FRAME_OFFSET_I5], %i5
0392     ld  [%sp + FRAME_OFFSET_I6], %i6
0393     ld  [%sp + FRAME_OFFSET_I7], %i7
0394 
0395     sub %sp, -FRAME_SIZE, %sp
0396 
0397 return_value:
0398     /* Load callback address and jump back */
0399     jmp %o7 + 8
0400      add    %sp, FRAME_SIZE, %sp