~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/sparc/kernel/rtrap_64.S

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * rtrap.S: Preparing for return from trap on Sparc V9.
 
3
 *
 
4
 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
 
5
 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
 
6
 */
 
7
 
 
8
 
 
9
#include <asm/asi.h>
 
10
#include <asm/pstate.h>
 
11
#include <asm/ptrace.h>
 
12
#include <asm/spitfire.h>
 
13
#include <asm/head.h>
 
14
#include <asm/visasm.h>
 
15
#include <asm/processor.h>
 
16
 
 
17
#define         RTRAP_PSTATE            (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
 
18
#define         RTRAP_PSTATE_IRQOFF     (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
 
19
#define         RTRAP_PSTATE_AG_IRQOFF  (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
 
20
 
 
21
                .text
 
22
                .align                  32
 
23
__handle_softirq:
 
24
                call                    do_softirq
 
25
                 nop
 
26
                ba,a,pt                 %xcc, __handle_softirq_continue
 
27
                 nop
 
28
__handle_preemption:
 
29
                call                    schedule
 
30
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
 
31
                ba,pt                   %xcc, __handle_preemption_continue
 
32
                 wrpr                   %g0, RTRAP_PSTATE_IRQOFF, %pstate
 
33
 
 
34
__handle_user_windows:
 
35
                call                    fault_in_user_windows
 
36
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
 
37
                ba,pt                   %xcc, __handle_preemption_continue
 
38
                 wrpr                   %g0, RTRAP_PSTATE_IRQOFF, %pstate
 
39
 
 
40
__handle_userfpu:
 
41
                rd                      %fprs, %l5
 
42
                andcc                   %l5, FPRS_FEF, %g0
 
43
                sethi                   %hi(TSTATE_PEF), %o0
 
44
                be,a,pn                 %icc, __handle_userfpu_continue
 
45
                 andn                   %l1, %o0, %l1
 
46
                ba,a,pt                 %xcc, __handle_userfpu_continue
 
47
 
 
48
__handle_signal:
 
49
                mov                     %l5, %o1
 
50
                add                     %sp, PTREGS_OFF, %o0
 
51
                mov                     %l0, %o2
 
52
                call                    do_notify_resume
 
53
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
 
54
                wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
 
55
 
 
56
                /* Signal delivery can modify pt_regs tstate, so we must
 
57
                 * reload it.
 
58
                 */
 
59
                ldx                     [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
 
60
                sethi                   %hi(0xf << 20), %l4
 
61
                and                     %l1, %l4, %l4
 
62
                ba,pt                   %xcc, __handle_preemption_continue
 
63
                 andn                   %l1, %l4, %l1
 
64
 
 
65
                /* When returning from a NMI (%pil==15) interrupt we want to
 
66
                 * avoid running softirqs, doing IRQ tracing, preempting, etc.
 
67
                 */
 
68
                .globl                  rtrap_nmi
 
69
rtrap_nmi:      ldx                     [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
 
70
                sethi                   %hi(0xf << 20), %l4
 
71
                and                     %l1, %l4, %l4
 
72
                andn                    %l1, %l4, %l1
 
73
                srl                     %l4, 20, %l4
 
74
                ba,pt                   %xcc, rtrap_no_irq_enable
 
75
                 wrpr                   %l4, %pil
 
76
 
 
77
                .align                  64
 
78
                .globl                  rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall
 
79
rtrap_irq:
 
80
rtrap:
 
81
#ifndef CONFIG_SMP
 
82
                sethi                   %hi(__cpu_data), %l0
 
83
                lduw                    [%l0 + %lo(__cpu_data)], %l1
 
84
#else
 
85
                sethi                   %hi(__cpu_data), %l0
 
86
                or                      %l0, %lo(__cpu_data), %l0
 
87
                lduw                    [%l0 + %g5], %l1
 
88
#endif
 
89
                cmp                     %l1, 0
 
90
 
 
91
                /* mm/ultra.S:xcall_report_regs KNOWS about this load. */
 
92
                bne,pn                  %icc, __handle_softirq
 
93
                 ldx                    [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
 
94
__handle_softirq_continue:
 
95
rtrap_xcall:
 
96
                sethi                   %hi(0xf << 20), %l4
 
97
                and                     %l1, %l4, %l4
 
98
                andn                    %l1, %l4, %l1
 
99
                srl                     %l4, 20, %l4
 
100
#ifdef CONFIG_TRACE_IRQFLAGS
 
101
                brnz,pn                 %l4, rtrap_no_irq_enable
 
102
                 nop
 
103
                call                    trace_hardirqs_on
 
104
                 nop
 
105
                /* Do not actually set the %pil here.  We will do that
 
106
                 * below after we clear PSTATE_IE in the %pstate register.
 
107
                 * If we re-enable interrupts here, we can recurse down
 
108
                 * the hardirq stack potentially endlessly, causing a
 
109
                 * stack overflow.
 
110
                 *
 
111
                 * It is tempting to put this test and trace_hardirqs_on
 
112
                 * call at the 'rt_continue' label, but that will not work
 
113
                 * as that path hits unconditionally and we do not want to
 
114
                 * execute this in NMI return paths, for example.
 
115
                 */
 
116
#endif
 
117
rtrap_no_irq_enable:
 
118
                andcc                   %l1, TSTATE_PRIV, %l3
 
119
                bne,pn                  %icc, to_kernel
 
120
                 nop
 
121
 
 
122
                /* We must hold IRQs off and atomically test schedule+signal
 
123
                 * state, then hold them off all the way back to userspace.
 
124
                 * If we are returning to kernel, none of this matters.  Note
 
125
                 * that we are disabling interrupts via PSTATE_IE, not using
 
126
                 * %pil.
 
127
                 *
 
128
                 * If we do not do this, there is a window where we would do
 
129
                 * the tests, later the signal/resched event arrives but we do
 
130
                 * not process it since we are still in kernel mode.  It would
 
131
                 * take until the next local IRQ before the signal/resched
 
132
                 * event would be handled.
 
133
                 *
 
134
                 * This also means that if we have to deal with user
 
135
                 * windows, we have to redo all of these sched+signal checks
 
136
                 * with IRQs disabled.
 
137
                 */
 
138
to_user:        wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
 
139
                wrpr                    0, %pil
 
140
__handle_preemption_continue:
 
141
                ldx                     [%g6 + TI_FLAGS], %l0
 
142
                sethi                   %hi(_TIF_USER_WORK_MASK), %o0
 
143
                or                      %o0, %lo(_TIF_USER_WORK_MASK), %o0
 
144
                andcc                   %l0, %o0, %g0
 
145
                sethi                   %hi(TSTATE_PEF), %o0
 
146
                be,pt                   %xcc, user_nowork
 
147
                 andcc                  %l1, %o0, %g0
 
148
                andcc                   %l0, _TIF_NEED_RESCHED, %g0
 
149
                bne,pn                  %xcc, __handle_preemption
 
150
                 andcc                  %l0, _TIF_DO_NOTIFY_RESUME_MASK, %g0
 
151
                bne,pn                  %xcc, __handle_signal
 
152
                 ldub                   [%g6 + TI_WSAVED], %o2
 
153
                brnz,pn                 %o2, __handle_user_windows
 
154
                 nop
 
155
                sethi                   %hi(TSTATE_PEF), %o0
 
156
                andcc                   %l1, %o0, %g0
 
157
 
 
158
                /* This fpdepth clear is necessary for non-syscall rtraps only */
 
159
user_nowork:
 
160
                bne,pn                  %xcc, __handle_userfpu
 
161
                 stb                    %g0, [%g6 + TI_FPDEPTH]
 
162
__handle_userfpu_continue:
 
163
 
 
164
rt_continue:    ldx                     [%sp + PTREGS_OFF + PT_V9_G1], %g1
 
165
                ldx                     [%sp + PTREGS_OFF + PT_V9_G2], %g2
 
166
 
 
167
                ldx                     [%sp + PTREGS_OFF + PT_V9_G3], %g3
 
168
                ldx                     [%sp + PTREGS_OFF + PT_V9_G4], %g4
 
169
                ldx                     [%sp + PTREGS_OFF + PT_V9_G5], %g5
 
170
                brz,pt                  %l3, 1f
 
171
                mov                     %g6, %l2
 
172
 
 
173
                /* Must do this before thread reg is clobbered below.  */
 
174
                LOAD_PER_CPU_BASE(%g5, %g6, %i0, %i1, %i2)
 
175
1:
 
176
                ldx                     [%sp + PTREGS_OFF + PT_V9_G6], %g6
 
177
                ldx                     [%sp + PTREGS_OFF + PT_V9_G7], %g7
 
178
 
 
179
                /* Normal globals are restored, go to trap globals.  */
 
180
661:            wrpr                    %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate
 
181
                nop
 
182
                .section                .sun4v_2insn_patch, "ax"
 
183
                .word                   661b
 
184
                wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
 
185
                SET_GL(1)
 
186
                .previous
 
187
 
 
188
                mov                     %l2, %g6
 
189
 
 
190
                ldx                     [%sp + PTREGS_OFF + PT_V9_I0], %i0
 
191
                ldx                     [%sp + PTREGS_OFF + PT_V9_I1], %i1
 
192
 
 
193
                ldx                     [%sp + PTREGS_OFF + PT_V9_I2], %i2
 
194
                ldx                     [%sp + PTREGS_OFF + PT_V9_I3], %i3
 
195
                ldx                     [%sp + PTREGS_OFF + PT_V9_I4], %i4
 
196
                ldx                     [%sp + PTREGS_OFF + PT_V9_I5], %i5
 
197
                ldx                     [%sp + PTREGS_OFF + PT_V9_I6], %i6
 
198
                ldx                     [%sp + PTREGS_OFF + PT_V9_I7], %i7
 
199
                ldx                     [%sp + PTREGS_OFF + PT_V9_TPC], %l2
 
200
                ldx                     [%sp + PTREGS_OFF + PT_V9_TNPC], %o2
 
201
 
 
202
                ld                      [%sp + PTREGS_OFF + PT_V9_Y], %o3
 
203
                wr                      %o3, %g0, %y
 
204
                wrpr                    %l4, 0x0, %pil
 
205
                wrpr                    %g0, 0x1, %tl
 
206
                andn                    %l1, TSTATE_SYSCALL, %l1
 
207
                wrpr                    %l1, %g0, %tstate
 
208
                wrpr                    %l2, %g0, %tpc
 
209
                wrpr                    %o2, %g0, %tnpc
 
210
 
 
211
                brnz,pn                 %l3, kern_rtt
 
212
                 mov                    PRIMARY_CONTEXT, %l7
 
213
 
 
214
661:            ldxa                    [%l7 + %l7] ASI_DMMU, %l0
 
215
                .section                .sun4v_1insn_patch, "ax"
 
216
                .word                   661b
 
217
                ldxa                    [%l7 + %l7] ASI_MMU, %l0
 
218
                .previous
 
219
 
 
220
                sethi                   %hi(sparc64_kern_pri_nuc_bits), %l1
 
221
                ldx                     [%l1 + %lo(sparc64_kern_pri_nuc_bits)], %l1
 
222
                or                      %l0, %l1, %l0
 
223
 
 
224
661:            stxa                    %l0, [%l7] ASI_DMMU
 
225
                .section                .sun4v_1insn_patch, "ax"
 
226
                .word                   661b
 
227
                stxa                    %l0, [%l7] ASI_MMU
 
228
                .previous
 
229
 
 
230
                sethi                   %hi(KERNBASE), %l7
 
231
                flush                   %l7
 
232
                rdpr                    %wstate, %l1
 
233
                rdpr                    %otherwin, %l2
 
234
                srl                     %l1, 3, %l1
 
235
 
 
236
                wrpr                    %l2, %g0, %canrestore
 
237
                wrpr                    %l1, %g0, %wstate
 
238
                brnz,pt                 %l2, user_rtt_restore
 
239
                 wrpr                   %g0, %g0, %otherwin
 
240
 
 
241
                ldx                     [%g6 + TI_FLAGS], %g3
 
242
                wr                      %g0, ASI_AIUP, %asi
 
243
                rdpr                    %cwp, %g1
 
244
                andcc                   %g3, _TIF_32BIT, %g0
 
245
                sub                     %g1, 1, %g1
 
246
                bne,pt                  %xcc, user_rtt_fill_32bit
 
247
                 wrpr                   %g1, %cwp
 
248
                ba,a,pt                 %xcc, user_rtt_fill_64bit
 
249
 
 
250
user_rtt_fill_fixup:
 
251
                rdpr    %cwp, %g1
 
252
                add     %g1, 1, %g1
 
253
                wrpr    %g1, 0x0, %cwp
 
254
 
 
255
                rdpr    %wstate, %g2
 
256
                sll     %g2, 3, %g2
 
257
                wrpr    %g2, 0x0, %wstate
 
258
 
 
259
                /* We know %canrestore and %otherwin are both zero.  */
 
260
 
 
261
                sethi   %hi(sparc64_kern_pri_context), %g2
 
262
                ldx     [%g2 + %lo(sparc64_kern_pri_context)], %g2
 
263
                mov     PRIMARY_CONTEXT, %g1
 
264
 
 
265
661:            stxa    %g2, [%g1] ASI_DMMU
 
266
                .section .sun4v_1insn_patch, "ax"
 
267
                .word   661b
 
268
                stxa    %g2, [%g1] ASI_MMU
 
269
                .previous
 
270
 
 
271
                sethi   %hi(KERNBASE), %g1
 
272
                flush   %g1
 
273
 
 
274
                or      %g4, FAULT_CODE_WINFIXUP, %g4
 
275
                stb     %g4, [%g6 + TI_FAULT_CODE]
 
276
                stx     %g5, [%g6 + TI_FAULT_ADDR]
 
277
 
 
278
                mov     %g6, %l1
 
279
                wrpr    %g0, 0x0, %tl
 
280
 
 
281
661:            nop
 
282
                .section                .sun4v_1insn_patch, "ax"
 
283
                .word                   661b
 
284
                SET_GL(0)
 
285
                .previous
 
286
 
 
287
                wrpr    %g0, RTRAP_PSTATE, %pstate
 
288
 
 
289
                mov     %l1, %g6
 
290
                ldx     [%g6 + TI_TASK], %g4
 
291
                LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
 
292
                call    do_sparc64_fault
 
293
                 add    %sp, PTREGS_OFF, %o0
 
294
                ba,pt   %xcc, rtrap
 
295
                 nop
 
296
 
 
297
user_rtt_pre_restore:
 
298
                add                     %g1, 1, %g1
 
299
                wrpr                    %g1, 0x0, %cwp
 
300
 
 
301
user_rtt_restore:
 
302
                restore
 
303
                rdpr                    %canrestore, %g1
 
304
                wrpr                    %g1, 0x0, %cleanwin
 
305
                retry
 
306
                nop
 
307
 
 
308
kern_rtt:       rdpr                    %canrestore, %g1
 
309
                brz,pn                  %g1, kern_rtt_fill
 
310
                 nop
 
311
kern_rtt_restore:
 
312
                stw                     %g0, [%sp + PTREGS_OFF + PT_V9_MAGIC]
 
313
                restore
 
314
                retry
 
315
 
 
316
to_kernel:
 
317
#ifdef CONFIG_PREEMPT
 
318
                ldsw                    [%g6 + TI_PRE_COUNT], %l5
 
319
                brnz                    %l5, kern_fpucheck
 
320
                 ldx                    [%g6 + TI_FLAGS], %l5
 
321
                andcc                   %l5, _TIF_NEED_RESCHED, %g0
 
322
                be,pt                   %xcc, kern_fpucheck
 
323
                 nop
 
324
                cmp                     %l4, 0
 
325
                bne,pn                  %xcc, kern_fpucheck
 
326
                 sethi                  %hi(PREEMPT_ACTIVE), %l6
 
327
                stw                     %l6, [%g6 + TI_PRE_COUNT]
 
328
                call                    schedule
 
329
                 nop
 
330
                ba,pt                   %xcc, rtrap
 
331
                 stw                    %g0, [%g6 + TI_PRE_COUNT]
 
332
#endif
 
333
kern_fpucheck:  ldub                    [%g6 + TI_FPDEPTH], %l5
 
334
                brz,pt                  %l5, rt_continue
 
335
                 srl                    %l5, 1, %o0
 
336
                add                     %g6, TI_FPSAVED, %l6
 
337
                ldub                    [%l6 + %o0], %l2
 
338
                sub                     %l5, 2, %l5
 
339
 
 
340
                add                     %g6, TI_GSR, %o1
 
341
                andcc                   %l2, (FPRS_FEF|FPRS_DU), %g0
 
342
                be,pt                   %icc, 2f
 
343
                 and                    %l2, FPRS_DL, %l6
 
344
                andcc                   %l2, FPRS_FEF, %g0
 
345
                be,pn                   %icc, 5f
 
346
                 sll                    %o0, 3, %o5
 
347
                rd                      %fprs, %g1
 
348
 
 
349
                wr                      %g1, FPRS_FEF, %fprs
 
350
                ldx                     [%o1 + %o5], %g1
 
351
                add                     %g6, TI_XFSR, %o1
 
352
                sll                     %o0, 8, %o2
 
353
                add                     %g6, TI_FPREGS, %o3
 
354
                brz,pn                  %l6, 1f
 
355
                 add                    %g6, TI_FPREGS+0x40, %o4
 
356
 
 
357
                membar                  #Sync
 
358
                ldda                    [%o3 + %o2] ASI_BLK_P, %f0
 
359
                ldda                    [%o4 + %o2] ASI_BLK_P, %f16
 
360
                membar                  #Sync
 
361
1:              andcc                   %l2, FPRS_DU, %g0
 
362
                be,pn                   %icc, 1f
 
363
                 wr                     %g1, 0, %gsr
 
364
                add                     %o2, 0x80, %o2
 
365
                membar                  #Sync
 
366
                ldda                    [%o3 + %o2] ASI_BLK_P, %f32
 
367
                ldda                    [%o4 + %o2] ASI_BLK_P, %f48
 
368
1:              membar                  #Sync
 
369
                ldx                     [%o1 + %o5], %fsr
 
370
2:              stb                     %l5, [%g6 + TI_FPDEPTH]
 
371
                ba,pt                   %xcc, rt_continue
 
372
                 nop
 
373
5:              wr                      %g0, FPRS_FEF, %fprs
 
374
                sll                     %o0, 8, %o2
 
375
 
 
376
                add                     %g6, TI_FPREGS+0x80, %o3
 
377
                add                     %g6, TI_FPREGS+0xc0, %o4
 
378
                membar                  #Sync
 
379
                ldda                    [%o3 + %o2] ASI_BLK_P, %f32
 
380
                ldda                    [%o4 + %o2] ASI_BLK_P, %f48
 
381
                membar                  #Sync
 
382
                wr                      %g0, FPRS_DU, %fprs
 
383
                ba,pt                   %xcc, rt_continue
 
384
                 stb                    %l5, [%g6 + TI_FPDEPTH]