]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/sun4v/sun4v/swtch.S
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / sun4v / sun4v / swtch.S
1 /*-
2  * Copyright (c) 2001 Jake Burkholder.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <machine/asm.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <machine/asi.h>
31 #include <machine/asmacros.h>
32 #include <machine/fsr.h>
33 #include <machine/hypervisorvar.h>
34 #include <machine/ktr.h>
35 #include <machine/pcb.h>
36 #include <machine/tstate.h>
37
38 #include "assym.s"
39
40         .register       %g2, #ignore
41         .register       %g3, #ignore
42
43 #define PCB_REG %g6
44
45 #define MEMBAR_PRE      membar  #LoadStore|#StoreStore
46 #define MEMBAR_POST     membar  #LoadLoad
47
48 #define ATOMIC_CLEAR_INT_BIT(addr, old, bit, new, label) \
49         MEMBAR_PRE              ; \
50         ld      [addr], old     ; \
51 label:  andn    old, bit, new   ; \
52         cas     [addr], old, new ; \
53         cmp     old, new        ; \
54         bne,a,pn        %icc, label ## b ; \
55           ld    [addr], old     ; \
56         MEMBAR_POST
57         
58 #define ATOMIC_SET_INT_BIT(addr, old, bit, new, label) \
59         MEMBAR_PRE              ; \
60         ld      [addr], old     ; \
61 label:  or      old, bit, new   ; \
62         cas     [addr], old, new ; \
63         cmp     old, new        ; \
64         bne,a,pn        %icc, label ## b ; \
65           ld    [addr], old     ; \
66         MEMBAR_POST     
67 /*
68  * void cpu_throw(struct thread *old, struct thread *new)
69  */
70 ENTRY(cpu_throw)
71         save    %sp, -CCFSZ, %sp
72         flushw
73         ba      %xcc, .Lsw1
74          mov    %i1, %i0
75 END(cpu_throw)
76         
77 /*
78  * void cpu_switch(struct thread *old, struct thread *new)
79  */
80 ENTRY(cpu_switch)
81         save    %sp, -CCFSZ, %sp
82         ldx     [PCPU(CURPCB)], PCB_REG
83         mov     %i1, %i0
84
85         /*
86          * If the current thread was using floating point in the kernel, save
87          * its context.  The userland floating point context has already been
88          * saved in that case.
89          */
90         rd      %fprs, %l2
91         andcc   %l2, FPRS_FEF, %g0
92         bz,a,pt %xcc, 1f
93          nop
94         call    savefpctx
95          add    PCB_REG, PCB_KFP, %o0
96         ba,a    %xcc, 2f
97          nop
98
99         /*
100          * If the current thread was using floating point in userland, save
101          * its context.
102          */
103 1:      sub     PCB_REG, TF_SIZEOF, %l2
104         ldx     [%l2 + TF_FPRS], %l3
105         andcc   %l3, FPRS_FEF, %g0
106         bz,a,pt %xcc, 2f
107          nop
108         call    savefpctx
109          add    PCB_REG, PCB_UFP, %o0
110         andn    %l3, FPRS_FEF, %l3
111         stx     %l3, [%l2 + TF_FPRS]
112
113         ldx     [PCB_REG + PCB_FLAGS], %l3
114         or      %l3, PCB_FEF, %l3
115         stx     %l3, [PCB_REG + PCB_FLAGS]
116
117         /*
118          * Flush the windows out to the stack and save the current frame
119          * pointer and program counter.
120          */
121 2:      flushw
122         stx     %fp, [PCB_REG + PCB_SP]
123         stx     %i7, [PCB_REG + PCB_PC]
124
125
126         /*
127          * Load the new thread's frame pointer and program counter, and set
128          * the current thread and pcb.
129          */
130 .Lsw1:
131 #if KTR_COMPILE & KTR_PROC & 0
132         CATR(KTR_PROC, "cpu_switch: new td=%p pc=%#lx fp=%#lx"
133             , %g1, %g2, %g3, 7, 8, 9)
134         stx     %i0, [%g1 + KTR_PARM1]
135         ldx     [%i0 + TD_PCB], %g2
136         ldx     [%g2 + PCB_PC], %g3
137         stx     %g3, [%g1 + KTR_PARM2]
138         ldx     [%g2 + PCB_SP], %g3
139         stx     %g3, [%g1 + KTR_PARM3]
140 9:
141 #endif
142         
143         ldx     [%i0 + TD_PCB], %i1
144
145         stx     %i0, [PCPU(CURTHREAD)]
146         stx     %i1, [PCPU(CURPCB)]
147
148         mov     %i1, PCB_REG                            ! load in new PCB
149
150         ldx     [PCB_REG + PCB_SP], %fp
151         ldx     [PCB_REG + PCB_PC], %i7
152         sub     %fp, CCFSZ, %sp
153
154         /*
155          * Point to the pmaps of the new process, and of the last non-kernel
156          * process to run.
157          */
158         ldx     [%i0 + TD_PROC], %i2
159         ldx     [PCPU(PMAP)], %l2
160         ldx     [%i2 + P_VMSPACE], %i5
161         add     %i5, VM_PMAP, %i2
162
163 #if KTR_COMPILE & KTR_PROC & 0
164         CATR(KTR_PROC, "cpu_switch: new pmap=%p old pmap=%p"
165             , %g1, %g2, %g3, 7, 8, 9)
166         stx     %i2, [%g1 + KTR_PARM1]
167         stx     %l2, [%g1 + KTR_PARM2]
168 9:
169 #endif
170         /*
171          * If they are the same we are done.
172          */
173         cmp     %l2, %i2                        ! current pmap == new pmap?
174         be,a,pn %xcc, 5f
175           nop
176         ldx     [%i2 + PM_CONTEXT], %l5         ! new context
177         ldx     [%l2 + PM_CONTEXT], %l3         ! old context
178         cmp     %g0, %l5
179         be,pn   %xcc, 5f                        ! new context == kernel?
180           ld    [PCPU(CPUMASK)], %l4
181
182         brz     %l3, 10f                        ! old context == kernel?
183           nop
184         
185         /*
186          * Mark the old pmap as no longer active on this CPU
187          */
188         add     %l2, PM_ACTIVE, %l2
189         ATOMIC_CLEAR_INT_BIT(%l2, %l3, %l4, %l6, 8)     
190         
191 10:
192         add     %i2,  PM_ACTIVE, %i3
193         ATOMIC_SET_INT_BIT(%i3, %l3, %l4, %l6, 11)
194
195         add     %i2, PM_TLBACTIVE, %i3
196         ATOMIC_SET_INT_BIT(%i3, %l3, %l4, %l6, 12)
197         
198         mov     SCRATCH_REG_HASH_USER, %l6
199         mov     SCRATCH_REG_TSB_USER, %l7
200         ldx     [%i2 + PM_HASHSCRATCH], %l3     
201         ldx     [%i2 + PM_TSBSCRATCH], %l4
202         stx     %i2, [PCPU(PMAP)]
203
204         SET_SCRATCH(%l6,%l3)                    ! XXX we're assuming the 
205         SET_SCRATCH(%l7,%l4)                    ! scratch values <= 32 bits
206
207
208         ldx     [%i2 + PM_TSB_RA], %l3
209
210         mov     MMU_CID_S, %l6
211
212         mov     1, %o0
213         mov     %l3, %o1
214         mov     MMU_TSB_CTXNON0, %o5
215         ta      FAST_TRAP
216         cmp     %g0, %o0
217         be      %xcc, 4f
218           nop
219         MAGIC_TRAP_ON
220         MAGIC_EXIT
221         
222 4:      /*
223          * install the new secondary context number in the cpu.
224          */
225         
226         SET_MMU_CONTEXT(%l6, %l5)
227         membar #Sync
228         /*
229          * Done.  Return and load the new process's window from the stack.
230          */
231 5:      ret
232          restore
233 END(cpu_switch)
234
235 ENTRY(savectx)
236         save    %sp, -CCFSZ, %sp
237         flushw
238         call    savefpctx
239          add    %i0, PCB_UFP, %o0
240         stx     %fp, [%i0 + PCB_SP]
241         stx     %i7, [%i0 + PCB_PC]
242         ret
243          restore %g0, 0, %o0
244 END(savectx)
245
246 /*
247  * void savefpctx(uint32_t *);
248  */
249 ENTRY(savefpctx)
250         wr      %g0, FPRS_FEF, %fprs
251         std     %f0, [%o0 + (0 * 64)] 
252         std     %f16, [%o0 + (1 * 64)] 
253         std     %f32, [%o0 + (2 * 64)] 
254         std     %f48, [%o0 + (3 * 64)] 
255         retl
256          wr     %g0, 0, %fprs
257 END(savefpctx)