The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/mips/swtch.S

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $        */
    2 /*-
    3  * Copyright (c) 1992, 1993
    4  *      The Regents of the University of California.  All rights reserved.
    5  *
    6  * This code is derived from software contributed to Berkeley by
    7  * Digital Equipment Corporation and Ralph Campbell.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  * Copyright (C) 1989 Digital Equipment Corporation.
   34  * Permission to use, copy, modify, and distribute this software and
   35  * its documentation for any purpose and without fee is hereby granted,
   36  * provided that the above copyright notice appears in all copies.
   37  * Digital Equipment Corporation makes no representations about the
   38  * suitability of this software for any purpose.  It is provided "as is"
   39  * without express or implied warranty.
   40  *
   41  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
   42  *      v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
   43  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
   44  *      v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
   45  * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
   46  *      v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
   47  *
   48  *      from: @(#)locore.s      8.5 (Berkeley) 1/4/94
   49  *      JNPR: swtch.S,v 1.6.2.1 2007/09/10 10:36:50 girish
   50  * $FreeBSD$
   51  */
   52 
   53 /*
   54  *      Contains code that is the first executed at boot time plus
   55  *      assembly language support routines.
   56  */
   57 
   58 #include <sys/syscall.h>
   59 #include <machine/asm.h>
   60 #include <machine/cpu.h>
   61 #include <machine/cpuregs.h>
   62 #include <machine/regnum.h>
   63 #include <machine/pte.h>
   64 #include <machine/pcb.h>
   65 
   66 #include "assym.inc"
   67 
   68         .set    noreorder                       # Noreorder is default style!
   69 
   70 /*
   71  * Setup for and return to user.
   72  */
   73 LEAF(fork_trampoline)
   74         move    a0,s0
   75         move    a1,s1
   76         jal     _C_LABEL(fork_exit)
   77         move    a2,s2                     #BDSlot
   78 
   79         DO_AST
   80 
   81         mfc0    v0, MIPS_COP_0_STATUS
   82         and     v0, ~(MIPS_SR_INT_IE)
   83         mtc0    v0, MIPS_COP_0_STATUS   # disable interrupts
   84         COP0_SYNC
   85 /*
   86  * The use of k1 for storing the PCB pointer must be done only
   87  * after interrupts are disabled.  Otherwise it will get overwritten
   88  * by the interrupt code.
   89  */
   90         .set    noat
   91         GET_CPU_PCPU(k1)
   92         PTR_L   k1, PC_CURPCB(k1)
   93 
   94         RESTORE_U_PCB_REG(t0, MULLO, k1)
   95         RESTORE_U_PCB_REG(t1, MULHI, k1)
   96         mtlo    t0
   97         mthi    t1
   98         RESTORE_U_PCB_REG(a0, PC, k1)
   99         RESTORE_U_PCB_REG(AT, AST, k1)
  100         RESTORE_U_PCB_REG(v0, V0, k1)
  101         MTC0    a0, MIPS_COP_0_EXC_PC   # set return address
  102 
  103         RESTORE_U_PCB_REG(v1, V1, k1)
  104         RESTORE_U_PCB_REG(a0, A0, k1)
  105         RESTORE_U_PCB_REG(a1, A1, k1)
  106         RESTORE_U_PCB_REG(a2, A2, k1)
  107         RESTORE_U_PCB_REG(a3, A3, k1)
  108         RESTORE_U_PCB_REG(t0, T0, k1)
  109         RESTORE_U_PCB_REG(t1, T1, k1)
  110         RESTORE_U_PCB_REG(t2, T2, k1)
  111         RESTORE_U_PCB_REG(t3, T3, k1)
  112         RESTORE_U_PCB_REG(ta0, TA0, k1)
  113         RESTORE_U_PCB_REG(ta1, TA1, k1)
  114         RESTORE_U_PCB_REG(ta2, TA2, k1)
  115         RESTORE_U_PCB_REG(ta3, TA3, k1)
  116         RESTORE_U_PCB_REG(s0, S0, k1)
  117         RESTORE_U_PCB_REG(s1, S1, k1)
  118         RESTORE_U_PCB_REG(s2, S2, k1)
  119         RESTORE_U_PCB_REG(s3, S3, k1)
  120         RESTORE_U_PCB_REG(s4, S4, k1)
  121         RESTORE_U_PCB_REG(s5, S5, k1)
  122         RESTORE_U_PCB_REG(s6, S6, k1)
  123         RESTORE_U_PCB_REG(s7, S7, k1)
  124         RESTORE_U_PCB_REG(t8, T8, k1)
  125         RESTORE_U_PCB_REG(t9, T9, k1)
  126         RESTORE_U_PCB_REG(k0, SR, k1)
  127         RESTORE_U_PCB_REG(gp, GP, k1)
  128         RESTORE_U_PCB_REG(s8, S8, k1)
  129         RESTORE_U_PCB_REG(ra, RA, k1)
  130         RESTORE_U_PCB_REG(sp, SP, k1)
  131         li      k1, ~MIPS_SR_INT_MASK
  132         and     k0, k0, k1
  133         mfc0    k1, MIPS_COP_0_STATUS
  134         and     k1, k1, MIPS_SR_INT_MASK
  135         or      k0, k0, k1
  136         mtc0    k0, MIPS_COP_0_STATUS   # switch to user mode (when eret...)
  137         HAZARD_DELAY
  138         sync
  139         eret
  140         .set    at
  141 END(fork_trampoline)
  142 
  143 /*
  144  * Update pcb, saving current processor state.
  145  * Note: this only works if pcbp != curproc's pcb since
  146  * cpu_switch() will copy over pcb_context.
  147  *
  148  *      savectx(struct pcb *pcbp);
  149  */
  150 LEAF(savectx)
  151         SAVE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0)
  152         SAVE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
  153         SAVE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
  154         SAVE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
  155         mfc0    v0, MIPS_COP_0_STATUS
  156         SAVE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
  157         SAVE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
  158         SAVE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
  159         SAVE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
  160         SAVE_U_PCB_CONTEXT(sp, PCB_REG_SP, a0)
  161         SAVE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
  162         SAVE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0)
  163         SAVE_U_PCB_CONTEXT(v0, PCB_REG_SR, a0)
  164         SAVE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
  165 
  166         move    v0, ra                  /* save 'ra' before we trash it */
  167         jal     1f
  168         nop
  169 1:
  170         SAVE_U_PCB_CONTEXT(ra, PCB_REG_PC, a0)
  171         move    ra, v0                  /* restore 'ra' before returning */
  172 
  173         j       ra
  174         move    v0, zero
  175 END(savectx)
  176 
  177 NESTED(cpu_throw, CALLFRAME_SIZ, ra)
  178         mfc0    t0, MIPS_COP_0_STATUS           # t0 = saved status register
  179         nop
  180         nop
  181         and     a3, t0, ~(MIPS_SR_INT_IE)
  182         mtc0    a3, MIPS_COP_0_STATUS           # Disable all interrupts
  183         ITLBNOPFIX
  184         j       mips_sw1                        # We're not interested in old 
  185                                                 # thread's context, so jump 
  186                                                 # right to action
  187         nop                                     # BDSLOT
  188 END(cpu_throw)
  189 
  190 /*
  191  * cpu_switch(struct thread *old, struct thread *new, struct mutex *mtx);
  192  *      a0 - old
  193  *      a1 - new
  194  *      a2 - mtx
  195  * Find the highest priority process and resume it.
  196  */
  197 NESTED(cpu_switch, CALLFRAME_SIZ, ra)
  198         mfc0    t0, MIPS_COP_0_STATUS           # t0 = saved status register
  199         nop
  200         nop
  201         and     a3, t0, ~(MIPS_SR_INT_IE)       
  202         mtc0    a3, MIPS_COP_0_STATUS           # Disable all interrupts
  203         ITLBNOPFIX
  204         beqz    a0, mips_sw1
  205         move    a3, a0
  206         PTR_L   a0, TD_PCB(a0)          # load PCB addr of curproc
  207         SAVE_U_PCB_CONTEXT(sp, PCB_REG_SP, a0)          # save old sp
  208         PTR_SUBU        sp, sp, CALLFRAME_SIZ
  209         REG_S   ra, CALLFRAME_RA(sp)
  210         .mask   0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
  211         SAVE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0)          # do a 'savectx()'
  212         SAVE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
  213         SAVE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
  214         SAVE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
  215         SAVE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
  216         SAVE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
  217         SAVE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
  218         SAVE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
  219         SAVE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
  220         SAVE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0)          # save return address
  221         SAVE_U_PCB_CONTEXT(t0, PCB_REG_SR, a0)          # save status register
  222         SAVE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
  223         jal     getpc
  224         nop
  225 getpc:
  226         SAVE_U_PCB_CONTEXT(ra, PCB_REG_PC, a0)          # save return address
  227 
  228 #ifdef CPU_CNMIPS
  229 
  230         lw      t2, TD_MDFLAGS(a3)              # get md_flags
  231         and     t1, t2, MDTD_COP2USED
  232         beqz    t1, cop2_untouched
  233         nop
  234 
  235         /* Clear cop2used flag */
  236         and     t2, t2, ~MDTD_COP2USED
  237         sw      t2, TD_MDFLAGS(a3)
  238 
  239         and     t2, t0, ~MIPS_SR_COP_2_BIT      # clear COP_2 enable bit
  240         SAVE_U_PCB_CONTEXT(t2, PCB_REG_SR, a0)  # save status register
  241 
  242         RESTORE_U_PCB_REG(t0, PS, a0)           # get CPU status register
  243         and     t2, t0, ~MIPS_SR_COP_2_BIT      # clear COP_2 enable bit
  244         SAVE_U_PCB_REG(t2, PS, a0)              # save stratus register
  245 
  246         /* preserve a0..a3 */
  247         move    s0, a0
  248         move    s1, a1
  249         move    s2, a2
  250         move    s3, a3
  251 
  252         /* does kernel own COP2 context? */
  253         lw      t1, TD_COP2OWNER(a3)            # get md_cop2owner
  254         beqz    t1, userland_cop2               # 0 - it's userland context
  255         nop
  256 
  257         PTR_L   a0, TD_COP2(a3)
  258         beqz    a0, no_cop2_context
  259         nop
  260 
  261         j       do_cop2_save
  262         nop
  263 
  264 userland_cop2:
  265 
  266         PTR_L   a0, TD_UCOP2(a3)
  267         beqz    a0, no_cop2_context
  268         nop
  269 
  270 do_cop2_save:
  271         jal     octeon_cop2_save
  272         nop
  273 
  274 no_cop2_context:
  275         move    a3, s3
  276         move    a2, s2
  277         move    a1, s1
  278         move    a0, s0
  279 
  280 cop2_untouched:
  281 #endif
  282 
  283         PTR_S   a2, TD_LOCK(a3)                 # Switchout td_lock 
  284 
  285 mips_sw1:
  286 #if defined(SMP) && defined(SCHED_ULE)
  287         PTR_LA  t0, _C_LABEL(blocked_lock)
  288 blocked_loop:
  289         PTR_L   t1, TD_LOCK(a1)
  290         beq     t0, t1, blocked_loop
  291         nop
  292 #endif
  293         move    s7, a1  # Store newthread
  294 /*
  295  * Switch to new context.
  296  */
  297         GET_CPU_PCPU(a3)
  298         PTR_S   a1, PC_CURTHREAD(a3)
  299         PTR_L   a2, TD_PCB(a1)
  300         PTR_S   a2, PC_CURPCB(a3)
  301         PTR_L   v0, TD_KSTACK(a1)
  302 #if defined(__mips_n64)
  303         PTR_LI  s0, MIPS_XKSEG_START
  304 #else
  305         PTR_LI  s0, MIPS_KSEG2_START            # If Uarea addr is below kseg2,
  306 #endif
  307         bltu    v0, s0, sw2                     # no need to insert in TLB.
  308         PTE_L   a1, TD_UPTE + 0(s7)             # a1 = u. pte #0
  309         PTE_L   a2, TD_UPTE + PTESIZE(s7)       # a2 = u. pte #1
  310 /*
  311  * Wiredown the USPACE of newproc in TLB entry#0.  Check whether target
  312  * USPACE is already in another place of TLB before that, and if so
  313  * invalidate that TLB entry.
  314  * NOTE: This is hard coded to UPAGES == 2.
  315  * Also, there should be no TLB faults at this point.
  316  */
  317         MTC0    v0, MIPS_COP_0_TLB_HI           # VPN = va
  318         HAZARD_DELAY
  319         tlbp                                    # probe VPN
  320         HAZARD_DELAY
  321         mfc0    s0, MIPS_COP_0_TLB_INDEX
  322         HAZARD_DELAY
  323 
  324         PTR_LI  t1, MIPS_KSEG0_START            # invalidate tlb entry
  325         bltz    s0, entry0set
  326         nop
  327         sll     s0, PAGE_SHIFT + 1
  328         addu    t1, s0
  329         MTC0    t1, MIPS_COP_0_TLB_HI
  330         PTE_MTC0        zero, MIPS_COP_0_TLB_LO0
  331         PTE_MTC0        zero, MIPS_COP_0_TLB_LO1
  332         HAZARD_DELAY
  333         tlbwi
  334         HAZARD_DELAY
  335         MTC0    v0, MIPS_COP_0_TLB_HI           # set VPN again
  336 
  337 entry0set:
  338 /* SMP!! - Works only for  unshared TLB case - i.e. no v-cpus */
  339         mtc0    zero, MIPS_COP_0_TLB_INDEX              # TLB entry #0
  340         HAZARD_DELAY
  341         PTE_MTC0        a1, MIPS_COP_0_TLB_LO0          # upte[0]
  342         HAZARD_DELAY
  343         PTE_MTC0        a2, MIPS_COP_0_TLB_LO1          # upte[1]
  344         HAZARD_DELAY
  345         tlbwi                                   # set TLB entry #0
  346         HAZARD_DELAY
  347 /*
  348  * Now running on new u struct.
  349  */
  350 sw2:
  351         PTR_L   s0, TD_PCB(s7)
  352         RESTORE_U_PCB_CONTEXT(sp, PCB_REG_SP, s0)
  353         PTR_LA  t1, _C_LABEL(pmap_activate)     # s7 = new proc pointer
  354         jalr    t1                              # s7 = new proc pointer
  355         move    a0, s7                          # BDSLOT
  356 /*
  357  * Restore registers and return.
  358  */
  359         move    a0, s0
  360         move    a1, s7
  361         RESTORE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
  362         RESTORE_U_PCB_CONTEXT(v0, PCB_REG_SR, a0)       # restore kernel context
  363         RESTORE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0)
  364         RESTORE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0)
  365         RESTORE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
  366         RESTORE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
  367         RESTORE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
  368         RESTORE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
  369         RESTORE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
  370         RESTORE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
  371         RESTORE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
  372         RESTORE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
  373 
  374         mfc0    t0, MIPS_COP_0_STATUS
  375         and     t0, t0, MIPS_SR_INT_MASK
  376         and     v0, v0, ~MIPS_SR_INT_MASK
  377         or      v0, v0, t0
  378         mtc0    v0, MIPS_COP_0_STATUS
  379         ITLBNOPFIX
  380 /*
  381  * Set the new thread's TLS pointer.
  382  *
  383  * Note that this code is removed if the CPU doesn't support ULRI by
  384  * remove_userlocal_code() in cpu.c.
  385  */
  386         .globl  cpu_switch_set_userlocal
  387 cpu_switch_set_userlocal:
  388         PTR_L   t0, TD_MDTLS(a1)                # Get TLS pointer
  389         PTR_L   t1, TD_PROC(a1)
  390         PTR_L   t1, P_MDTLS_TCB_OFFSET(t1)      # Get TLS/TCB offset
  391         PTR_ADDU v0, t0, t1
  392         MTC0    v0, MIPS_COP_0_USERLOCAL, 2     # write it to ULR for rdhwr
  393 
  394         j       ra
  395         nop
  396 END(cpu_switch)
  397 
  398 /*----------------------------------------------------------------------------
  399  *
  400  * MipsSwitchFPState --
  401  *
  402  *      Save the current state into 'from' and restore it from 'to'.
  403  *
  404  *      MipsSwitchFPState(from, to)
  405  *              struct thread *from;
  406  *              struct trapframe *to;
  407  *
  408  * Results:
  409  *      None.
  410  *
  411  * Side effects:
  412  *      None.
  413  *
  414  *----------------------------------------------------------------------------
  415  */
  416 LEAF(MipsSwitchFPState)
  417         .set push
  418         .set hardfloat
  419         mfc0    t1, MIPS_COP_0_STATUS   # Save old SR
  420         HAZARD_DELAY
  421 #if defined(__mips_n32) || defined(__mips_n64)
  422         or      t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR  # enable the coprocessor
  423 #else
  424         or      t0, t1, MIPS_SR_COP_1_BIT               # enable the coprocessor
  425 #endif
  426         mtc0    t0, MIPS_COP_0_STATUS
  427         HAZARD_DELAY
  428         ITLBNOPFIX
  429 
  430         beq     a0, zero, 1f            # skip save if NULL pointer
  431         nop
  432 /*
  433  * First read out the status register to make sure that all FP operations
  434  * have completed.
  435  */
  436         PTR_L   a0, TD_PCB(a0)                  # get pointer to pcb for proc
  437         cfc1    t0, MIPS_FPU_CSR                # stall til FP done
  438         cfc1    t0, MIPS_FPU_CSR                # now get status
  439         li      t3, ~MIPS_SR_COP_1_BIT
  440         RESTORE_U_PCB_REG(t2, PS, a0)           # get CPU status register
  441         SAVE_U_PCB_FPSR(t0, FSR_NUM, a0)        # save FP status
  442         and     t2, t2, t3                      # clear COP_1 enable bit
  443         SAVE_U_PCB_REG(t2, PS, a0)              # save new status register
  444 /*
  445  * Save the floating point registers.
  446  */
  447         SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
  448         SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
  449         SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
  450         SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
  451         SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
  452         SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
  453         SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
  454         SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
  455         SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
  456         SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
  457         SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
  458         SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
  459         SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
  460         SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
  461         SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
  462         SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
  463         SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
  464         SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
  465         SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
  466         SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
  467         SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
  468         SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
  469         SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
  470         SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
  471         SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
  472         SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
  473         SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
  474         SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
  475         SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
  476         SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
  477         SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
  478         SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
  479 
  480 1:
  481 /*
  482  *  Restore the floating point registers.
  483  */
  484         RESTORE_U_PCB_FPSR(t0, FSR_NUM, a1)     # get status register
  485         RESTORE_U_PCB_FPREG($f0, F0_NUM, a1)
  486         RESTORE_U_PCB_FPREG($f1, F1_NUM, a1)
  487         RESTORE_U_PCB_FPREG($f2, F2_NUM, a1)
  488         RESTORE_U_PCB_FPREG($f3, F3_NUM, a1)
  489         RESTORE_U_PCB_FPREG($f4, F4_NUM, a1)
  490         RESTORE_U_PCB_FPREG($f5, F5_NUM, a1)
  491         RESTORE_U_PCB_FPREG($f6, F6_NUM, a1)
  492         RESTORE_U_PCB_FPREG($f7, F7_NUM, a1)
  493         RESTORE_U_PCB_FPREG($f8, F8_NUM, a1)
  494         RESTORE_U_PCB_FPREG($f9, F9_NUM, a1)
  495         RESTORE_U_PCB_FPREG($f10, F10_NUM, a1)
  496         RESTORE_U_PCB_FPREG($f11, F11_NUM, a1)
  497         RESTORE_U_PCB_FPREG($f12, F12_NUM, a1)
  498         RESTORE_U_PCB_FPREG($f13, F13_NUM, a1)
  499         RESTORE_U_PCB_FPREG($f14, F14_NUM, a1)
  500         RESTORE_U_PCB_FPREG($f15, F15_NUM, a1)
  501         RESTORE_U_PCB_FPREG($f16, F16_NUM, a1)
  502         RESTORE_U_PCB_FPREG($f17, F17_NUM, a1)
  503         RESTORE_U_PCB_FPREG($f18, F18_NUM, a1)
  504         RESTORE_U_PCB_FPREG($f19, F19_NUM, a1)
  505         RESTORE_U_PCB_FPREG($f20, F20_NUM, a1)
  506         RESTORE_U_PCB_FPREG($f21, F21_NUM, a1)
  507         RESTORE_U_PCB_FPREG($f22, F22_NUM, a1)
  508         RESTORE_U_PCB_FPREG($f23, F23_NUM, a1)
  509         RESTORE_U_PCB_FPREG($f24, F24_NUM, a1)
  510         RESTORE_U_PCB_FPREG($f25, F25_NUM, a1)
  511         RESTORE_U_PCB_FPREG($f26, F26_NUM, a1)
  512         RESTORE_U_PCB_FPREG($f27, F27_NUM, a1)
  513         RESTORE_U_PCB_FPREG($f28, F28_NUM, a1)
  514         RESTORE_U_PCB_FPREG($f29, F29_NUM, a1)
  515         RESTORE_U_PCB_FPREG($f30, F30_NUM, a1)
  516         RESTORE_U_PCB_FPREG($f31, F31_NUM, a1)
  517 
  518         and     t0, t0, ~MIPS_FPU_EXCEPTION_BITS
  519         ctc1    t0, MIPS_FPU_CSR
  520         nop
  521 
  522         mtc0    t1, MIPS_COP_0_STATUS           # Restore the status register.
  523         ITLBNOPFIX
  524         j       ra
  525         nop
  526         .set pop
  527 END(MipsSwitchFPState)
  528 
  529 /*----------------------------------------------------------------------------
  530  *
  531  * MipsFPID --
  532  *
  533  *      Read and return the floating point implementation register.
  534  *
  535  *      uint32_t
  536  *      MipsFPID(void)
  537  *
  538  * Results:
  539  *      Floating point implementation register.
  540  *
  541  * Side effects:
  542  *      None.
  543  *
  544  *----------------------------------------------------------------------------
  545  */
  546 LEAF(MipsFPID)
  547         .set push
  548         .set hardfloat
  549         mfc0    t1, MIPS_COP_0_STATUS           # Save the status register.
  550         HAZARD_DELAY
  551 #if defined(__mips_n32) || defined(__mips_n64)
  552         or      t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR
  553 #else
  554         or      t0, t1, MIPS_SR_COP_1_BIT
  555 #endif
  556         mtc0    t0, MIPS_COP_0_STATUS           # Enable the coprocessor
  557         HAZARD_DELAY
  558         ITLBNOPFIX
  559         cfc1    v0, MIPS_FPU_ID
  560         mtc0    t1, MIPS_COP_0_STATUS           # Restore the status register.
  561         ITLBNOPFIX
  562         j       ra
  563         nop
  564         .set pop
  565 END(MipsFPID)
  566 
  567 /*----------------------------------------------------------------------------
  568  *
  569  * MipsSaveCurFPState --
  570  *
  571  *      Save the current floating point coprocessor state.
  572  *
  573  *      MipsSaveCurFPState(td)
  574  *              struct thread *td;
  575  *
  576  * Results:
  577  *      None.
  578  *
  579  * Side effects:
  580  *      machFPCurProcPtr is cleared.
  581  *
  582  *----------------------------------------------------------------------------
  583  */
  584 LEAF(MipsSaveCurFPState)
  585         .set push
  586         .set hardfloat
  587         PTR_L   a0, TD_PCB(a0)                  # get pointer to pcb for thread
  588         mfc0    t1, MIPS_COP_0_STATUS           # Disable interrupts and
  589         HAZARD_DELAY
  590 #if defined(__mips_n32) || defined(__mips_n64)
  591         or      t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR          #  enable the coprocessor
  592 #else
  593         or      t0, t1, MIPS_SR_COP_1_BIT                       #  enable the coprocessor
  594 #endif
  595         mtc0    t0, MIPS_COP_0_STATUS
  596         HAZARD_DELAY
  597         ITLBNOPFIX
  598         GET_CPU_PCPU(a1)
  599         PTR_S   zero, PC_FPCURTHREAD(a1)        # indicate state has been saved
  600 /*
  601  * First read out the status register to make sure that all FP operations
  602  * have completed.
  603  */
  604         RESTORE_U_PCB_REG(t2, PS, a0)           # get CPU status register
  605         li      t3, ~MIPS_SR_COP_1_BIT
  606         and     t2, t2, t3                      # clear COP_1 enable bit
  607         cfc1    t0, MIPS_FPU_CSR                # stall til FP done
  608         cfc1    t0, MIPS_FPU_CSR                # now get status
  609         SAVE_U_PCB_REG(t2, PS, a0)              # save new status register
  610         SAVE_U_PCB_FPSR(t0, FSR_NUM, a0)        # save FP status
  611 /*
  612  * Save the floating point registers.
  613  */
  614         SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
  615         SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
  616         SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
  617         SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
  618         SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
  619         SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
  620         SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
  621         SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
  622         SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
  623         SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
  624         SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
  625         SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
  626         SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
  627         SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
  628         SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
  629         SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
  630         SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
  631         SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
  632         SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
  633         SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
  634         SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
  635         SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
  636         SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
  637         SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
  638         SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
  639         SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
  640         SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
  641         SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
  642         SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
  643         SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
  644         SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
  645         SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
  646 
  647         mtc0    t1, MIPS_COP_0_STATUS           # Restore the status register.
  648         ITLBNOPFIX
  649         j       ra
  650         nop
  651         .set pop
  652 END(MipsSaveCurFPState)
  653 
  654 /*
  655  * This code is copied the user's stack for returning from signal handlers
  656  * (see sendsig() and sigreturn()). We have to compute the address
  657  * of the sigcontext struct for the sigreturn call.
  658  */
  659         .globl  _C_LABEL(sigcode)
  660 _C_LABEL(sigcode):
  661         PTR_ADDU        a0, sp, SIGF_UC         # address of ucontext
  662         li              v0, SYS_sigreturn
  663 # sigreturn (ucp)
  664         syscall
  665         break   0                               # just in case sigreturn fails
  666         .globl  _C_LABEL(esigcode)
  667 _C_LABEL(esigcode):
  668 
  669         .data
  670         .globl  szsigcode
  671 szsigcode:
  672         .long   esigcode-sigcode
  673         .text
  674 
  675 #if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
  676         .globl  _C_LABEL(sigcode32)
  677 _C_LABEL(sigcode32):
  678         addu            a0, sp, SIGF32_UC       # address of ucontext
  679         li              v0, SYS_sigreturn
  680 # sigreturn (ucp)
  681         syscall
  682         break   0                               # just in case sigreturn fails
  683         .globl  _C_LABEL(esigcode32)
  684 _C_LABEL(esigcode32):
  685 
  686         .data
  687         .globl  szsigcode32
  688 szsigcode32:
  689         .long   esigcode32-sigcode32
  690         .text
  691 #endif

Cache object: 6cb99bd3b45ee78e232bc3c8a0b0072b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.