Back to home page

LXR

 
 

    


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

0001 /*
0002  *  systrap.S
0003  *
0004  *  This file contains emulated system calls using software trap 0.
0005  *  The following calls are supported:
0006  *
0007  *    + SYS_exit    (halt)
0008  *    + SYS_irqdis  (disable interrupts)
0009  *    + SYS_irqset  (set interrupt level)
0010  *
0011  *  COPYRIGHT:
0012  *
0013  *  COPYRIGHT (c) 1995. European Space Agency.
0014  *  Copyright (C) 2016, 2017 embedded brains GmbH & Co. KG
0015  *
0016  *  This terms of the RTEMS license apply to this file.
0017  *
0018  */
0019 
0020 #include <rtems/asm.h>
0021 #include <rtems/score/cpuimpl.h>
0022 #include <rtems/score/percpu.h>
0023 #include "syscall.h"
0024 
0025     .section    ".text"
0026     /*
0027      *  system call - halt
0028      *
0029      *  On entry:
0030      *
0031      *    l0 = psr (from trap table)
0032      *    l1 = pc
0033      *    l2 = npc
0034      *    g1 = system call id (1)
0035      *
0036      *  System Call 1 (exit):
0037      *    g2 = additional exit code 1
0038      *    g3 = additional exit code 2
0039      */
0040 
0041     PUBLIC(syscall)
0042 
0043 SYM(syscall):
0044     ta  0           ! syscall 1, halt with %g1,%g2,%g3 info
0045 
0046     PUBLIC(bsp_reset)
0047     PUBLIC(sparc_syscall_exit)
0048 
0049 SYM(bsp_reset):
0050 SYM(sparc_syscall_exit):
0051 
0052     mov SYS_exit, %g1
0053     mov %o0, %g2    ! Additional exit code 1
0054     mov %o1, %g3    ! Additional exit code 2
0055     ta  SPARC_SWTRAP_SYSCALL
0056 
0057     /*
0058      *  system call - Interrupt Disable
0059      *
0060      *  On entry:
0061      *
0062      *    l0 = psr (from trap table)
0063      *    l1 = pc
0064      *    l2 = npc
0065      *    l3 = psr | SPARC_PSR_PIL_MASK
0066      *
0067      *  On exit:
0068      *    g1 = old psr (to user)
0069      */
0070 
0071 .align 32               ! Align to 32-byte cache-line
0072     PUBLIC(syscall_irqdis)
0073 
0074 SYM(syscall_irqdis):
0075     mov %l3, %psr           ! Set PSR. Write delay 3 instr
0076     or  %l0, SPARC_PSR_ET_MASK, %g1 ! return old PSR with ET=1
0077     nop                 ! PSR write delay
0078     jmp %l2             ! Return to after TA 9.
0079      rett   %l2 + 4
0080 
0081     /*
0082      *  system call - Interrupt Enable
0083      *
0084      *  On entry:
0085      *
0086      *    l0 = psr (from trap table)
0087      *    l1 = pc
0088      *    l2 = npc
0089      *    l3 = psr & ~0x0f00
0090      *    g1 = new PIL to write (from user)
0091      */
0092 
0093 .align 32               ! Align to 32-byte cache-line
0094     PUBLIC(syscall_irqen)
0095 
0096 SYM(syscall_irqen):
0097     and %g1, SPARC_PSR_PIL_MASK, %l4    ! %l4 = (%g1 & 0xf00)
0098     wr  %l3, %l4, %psr          ! PSR = (PSR & ~0xf00) ^ %l4
0099     nop; nop                ! PSR write delay;
0100     jmp %l2             ! Return to after TA 10.
0101      rett   %l2 + 4
0102 
0103 #if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
0104     /*
0105      *  system call - Interrupt disable and set PSR[EF] according to caller
0106      *                specified %g1
0107      *
0108      *  On entry:
0109      *
0110      *    g1 = the desired PSR[EF] value (from caller)
0111      *    l0 = psr (from trap table)
0112      *    l1 = pc
0113      *    l2 = npc
0114      *    l3 = psr | SPARC_PSR_PIL_MASK
0115      *
0116      *  On exit:
0117      *    g1 = old psr (to user)
0118      */
0119 
0120 .align 32               ! Align to 32-byte cache-line
0121     PUBLIC(syscall_irqdis_fp)
0122 
0123 SYM(syscall_irqdis_fp):
0124     /*
0125      * We cannot use an intermediate value for operations with the PSR[EF]
0126      * bit since they use a 13-bit sign extension and PSR[EF] is bit 12.
0127      */
0128     sethi   %hi(SPARC_PSR_EF_MASK), %l4
0129 
0130     andn    %l3, %l4, %l3           ! Clear PSR[EF]
0131     and %g1, %l4, %g1           ! Select PSR[EF] only from %g1
0132     or  %l3, %g1, %l3           ! Set PSR[EF] according to %g1
0133     mov %l3, %psr           ! Set PSR. Write delay 3 instr
0134     or  %l0, SPARC_PSR_ET_MASK, %g1 ! return old PSR with ET=1
0135     nop                 ! PSR write delay
0136     jmp %l2             ! Return to after TA 9.
0137      rett   %l2 + 4
0138 #endif
0139 
0140 #if defined(SPARC_USE_LAZY_FP_SWITCH)
0141 
0142     /*
0143      *  system call - Perform a lazy floating point switch
0144      *
0145      *  On entry:
0146      *
0147      *    l0 = psr (from trap table)
0148      *    l1 = pc
0149      *    l2 = npc
0150      *    l3 = SPARC_PSR_EF_MASK
0151      */
0152 
0153 .align 32               ! Align to 32-byte cache-line
0154     PUBLIC(syscall_lazy_fp_switch)
0155 
0156 SYM(syscall_lazy_fp_switch):
0157     ld  [%g6 + PER_CPU_OFFSET_EXECUTING], %l4
0158     ld  [%g6 + PER_CPU_ISR_NEST_LEVEL], %l5
0159     ld  [%l4 + %lo(SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET)], %l6
0160     ld  [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET], %l7
0161 
0162     /* Ensure that we are not in interrupt context */
0163     cmp %l5, 0
0164     bne .Lillegal_use_of_floating_point_unit
0165      or %l0, %l3, %l0
0166 
0167     /* Ensure that we are a proper floating point thread */
0168     cmp %l6, 0
0169     be  .Lillegal_use_of_floating_point_unit
0170      ld [%l4 + %lo(SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET)], %l6
0171 
0172     /* Set PSR[EF] to 1, PSR write delay 3 instructions! */
0173     mov %l0, %psr
0174 
0175     /*
0176      * Check if there is a floating point owner.  We have to check this
0177      * here, since the floating point owner may have been deleted in the
0178      * meantime.  Save the floating point context if necessary.
0179      */
0180     cmp %l7, 0
0181     be  .Lfp_save_done
0182      nop
0183     ld  [%l7 + %lo(SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET)], %l5
0184     std %f0, [%l5 + SPARC_FP_CONTEXT_OFFSET_F0_F1]
0185     SPARC_LEON3FT_B2BST_NOP
0186     std %f2, [%l5 + SPARC_FP_CONTEXT_OFFSET_F2_F3]
0187     SPARC_LEON3FT_B2BST_NOP
0188     std %f4, [%l5 + SPARC_FP_CONTEXT_OFFSET_F4_F5]
0189     SPARC_LEON3FT_B2BST_NOP
0190     std %f6, [%l5 + SPARC_FP_CONTEXT_OFFSET_F6_F7]
0191     SPARC_LEON3FT_B2BST_NOP
0192     std %f8, [%l5 + SPARC_FP_CONTEXT_OFFSET_F8_F9]
0193     SPARC_LEON3FT_B2BST_NOP
0194     std %f10, [%l5 + SPARC_FP_CONTEXT_OFFSET_F10_F11]
0195     SPARC_LEON3FT_B2BST_NOP
0196     std %f12, [%l5 + SPARC_FP_CONTEXT_OFFSET_F12_F13]
0197     SPARC_LEON3FT_B2BST_NOP
0198     std %f14, [%l5 + SPARC_FP_CONTEXT_OFFSET_F14_F15]
0199     SPARC_LEON3FT_B2BST_NOP
0200     std %f16, [%l5 + SPARC_FP_CONTEXT_OFFSET_F16_F17]
0201     SPARC_LEON3FT_B2BST_NOP
0202     std %f18, [%l5 + SPARC_FP_CONTEXT_OFFSET_F18_F19]
0203     SPARC_LEON3FT_B2BST_NOP
0204     std %f20, [%l5 + SPARC_FP_CONTEXT_OFFSET_F20_F21]
0205     SPARC_LEON3FT_B2BST_NOP
0206     std %f22, [%l5 + SPARC_FP_CONTEXT_OFFSET_F22_F23]
0207     SPARC_LEON3FT_B2BST_NOP
0208     std %f24, [%l5 + SPARC_FP_CONTEXT_OFFSET_F24_F25]
0209     SPARC_LEON3FT_B2BST_NOP
0210     std %f26, [%l5 + SPARC_FP_CONTEXT_OFFSET_F26_F27]
0211     SPARC_LEON3FT_B2BST_NOP
0212     std %f28, [%l5 + SPARC_FP_CONTEXT_OFFSET_F28_F29]
0213     SPARC_LEON3FT_B2BST_NOP
0214     std %f30, [%l5 + SPARC_FP_CONTEXT_OFFSET_F30_F31]
0215     SPARC_LEON3FT_B2BST_NOP
0216     st  %fsr, [%l5 + SPARC_FP_CONTEXT_OFFSET_FSR]
0217     st  %g0, [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET]
0218     st  %l5, [%l7 + %lo(SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET)]
0219 
0220 .Lfp_save_done:
0221 
0222     /* Restore the floating point context if necessary */
0223     st  %g0, [%l4 + %lo(SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET)]
0224     cmp %l6, 0
0225     be  .Lfp_restore_done
0226      nop
0227     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F0_F1], %f0
0228     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F2_F3], %f2
0229     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F4_F5], %f4
0230     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F6_F7], %f6
0231     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F8_F9], %f8
0232     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F10_F11], %f10
0233     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F12_F13], %f12
0234     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F14_F15], %f14
0235     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F16_F17], %f16
0236     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F18_F19], %f18
0237     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F20_F21], %f20
0238     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F22_F23], %f22
0239     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F24_F25], %f24
0240     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F26_F27], %f26
0241     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F28_F29], %f28
0242     ldd [%l6 + SPARC_FP_CONTEXT_OFFSET_F30_F31], %f30
0243     ld  [%l6 + SPARC_FP_CONTEXT_OFFSET_FSR], %fsr
0244 
0245 .Lfp_restore_done:
0246 
0247     /*
0248      * Restore condition codes.  PSR[EF] is 1 here.  Take PSR write delay
0249      * into account (maximum is three instructions).
0250      */
0251     mov %l0, %psr
0252     nop
0253 
0254     /* Now, retry the floating point instruction with PSR[EF] == 1 */
0255     jmp %l1
0256      rett   %l2
0257 
0258 .Lillegal_use_of_floating_point_unit:
0259 
0260     /*
0261      * There is no need to restore the condition codes here, since
0262      * _Internal_error() does not return.
0263      */
0264     sethi   %hi(_Internal_error), %l1
0265     or  %l1, %lo(_Internal_error), %l1
0266     mov 38, %i0
0267     jmp %l1
0268      rett   %l1 + 4
0269 #endif
0270 
0271 #if defined(RTEMS_PARAVIRT)
0272 
0273         PUBLIC(_SPARC_Get_PSR)
0274 
0275 SYM(_SPARC_Get_PSR):
0276 
0277     retl
0278      rd     %psr, %o0
0279 
0280         PUBLIC(_SPARC_Set_PSR)
0281 
0282 SYM(_SPARC_Set_PSR):
0283 
0284     mov     %o0, %psr
0285     nop
0286     nop
0287     nop
0288     retl
0289      nop
0290 
0291         PUBLIC(_SPARC_Get_TBR)
0292 
0293 SYM(_SPARC_Get_TBR):
0294 
0295     retl
0296      rd    %tbr, %o0
0297 
0298         PUBLIC(_SPARC_Set_TBR)
0299 
0300 SYM(_SPARC_Set_TBR):
0301 
0302     retl
0303      wr    %o0, 0, %tbr
0304 
0305 #endif /* defined(RTEMS_PARAVIRT) */
0306 
0307 /* end of file */