Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sparc/kernel/entry.S
10817 views
1
/* arch/sparc/kernel/entry.S: Sparc trap low-level entry points.
2
*
3
* Copyright (C) 1995, 2007 David S. Miller ([email protected])
4
* Copyright (C) 1996 Eddie C. Dost ([email protected])
5
* Copyright (C) 1996 Miguel de Icaza ([email protected])
6
* Copyright (C) 1996-1999 Jakub Jelinek ([email protected])
7
* Copyright (C) 1997 Anton Blanchard ([email protected])
8
*/
9
10
#include <linux/errno.h>
11
12
#include <asm/head.h>
13
#include <asm/asi.h>
14
#include <asm/smp.h>
15
#include <asm/contregs.h>
16
#include <asm/ptrace.h>
17
#include <asm/asm-offsets.h>
18
#include <asm/psr.h>
19
#include <asm/vaddrs.h>
20
#include <asm/memreg.h>
21
#include <asm/page.h>
22
#include <asm/pgtable.h>
23
#include <asm/pgtsun4c.h>
24
#include <asm/winmacro.h>
25
#include <asm/signal.h>
26
#include <asm/obio.h>
27
#include <asm/mxcc.h>
28
#include <asm/thread_info.h>
29
#include <asm/param.h>
30
#include <asm/unistd.h>
31
32
#include <asm/asmmacro.h>
33
34
#define curptr g6
35
36
/* These are just handy. */
37
#define _SV save %sp, -STACKFRAME_SZ, %sp
38
#define _RS restore
39
40
#define FLUSH_ALL_KERNEL_WINDOWS \
41
_SV; _SV; _SV; _SV; _SV; _SV; _SV; \
42
_RS; _RS; _RS; _RS; _RS; _RS; _RS;
43
44
.text
45
46
#ifdef CONFIG_KGDB
47
.align 4
48
.globl arch_kgdb_breakpoint
49
.type arch_kgdb_breakpoint,#function
50
arch_kgdb_breakpoint:
51
ta 0x7d
52
retl
53
nop
54
.size arch_kgdb_breakpoint,.-arch_kgdb_breakpoint
55
#endif
56
57
#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
58
.align 4
59
.globl floppy_hardint
60
floppy_hardint:
61
/*
62
* This code cannot touch registers %l0 %l1 and %l2
63
* because SAVE_ALL depends on their values. It depends
64
* on %l3 also, but we regenerate it before a call.
65
* Other registers are:
66
* %l3 -- base address of fdc registers
67
* %l4 -- pdma_vaddr
68
* %l5 -- scratch for ld/st address
69
* %l6 -- pdma_size
70
* %l7 -- scratch [floppy byte, ld/st address, aux. data]
71
*/
72
73
/* Do we have work to do? */
74
sethi %hi(doing_pdma), %l7
75
ld [%l7 + %lo(doing_pdma)], %l7
76
cmp %l7, 0
77
be floppy_dosoftint
78
nop
79
80
/* Load fdc register base */
81
sethi %hi(fdc_status), %l3
82
ld [%l3 + %lo(fdc_status)], %l3
83
84
/* Setup register addresses */
85
sethi %hi(pdma_vaddr), %l5 ! transfer buffer
86
ld [%l5 + %lo(pdma_vaddr)], %l4
87
sethi %hi(pdma_size), %l5 ! bytes to go
88
ld [%l5 + %lo(pdma_size)], %l6
89
next_byte:
90
ldub [%l3], %l7
91
92
andcc %l7, 0x80, %g0 ! Does fifo still have data
93
bz floppy_fifo_emptied ! fifo has been emptied...
94
andcc %l7, 0x20, %g0 ! in non-dma mode still?
95
bz floppy_overrun ! nope, overrun
96
andcc %l7, 0x40, %g0 ! 0=write 1=read
97
bz floppy_write
98
sub %l6, 0x1, %l6
99
100
/* Ok, actually read this byte */
101
ldub [%l3 + 1], %l7
102
orcc %g0, %l6, %g0
103
stb %l7, [%l4]
104
bne next_byte
105
add %l4, 0x1, %l4
106
107
b floppy_tdone
108
nop
109
110
floppy_write:
111
/* Ok, actually write this byte */
112
ldub [%l4], %l7
113
orcc %g0, %l6, %g0
114
stb %l7, [%l3 + 1]
115
bne next_byte
116
add %l4, 0x1, %l4
117
118
/* fall through... */
119
floppy_tdone:
120
sethi %hi(pdma_vaddr), %l5
121
st %l4, [%l5 + %lo(pdma_vaddr)]
122
sethi %hi(pdma_size), %l5
123
st %l6, [%l5 + %lo(pdma_size)]
124
/* Flip terminal count pin */
125
set auxio_register, %l7
126
ld [%l7], %l7
127
128
set sparc_cpu_model, %l5
129
ld [%l5], %l5
130
subcc %l5, 1, %g0 /* enum { sun4c = 1 }; */
131
be 1f
132
ldub [%l7], %l5
133
134
or %l5, 0xc2, %l5
135
stb %l5, [%l7]
136
andn %l5, 0x02, %l5
137
b 2f
138
nop
139
140
1:
141
or %l5, 0xf4, %l5
142
stb %l5, [%l7]
143
andn %l5, 0x04, %l5
144
145
2:
146
/* Kill some time so the bits set */
147
WRITE_PAUSE
148
WRITE_PAUSE
149
150
stb %l5, [%l7]
151
152
/* Prevent recursion */
153
sethi %hi(doing_pdma), %l7
154
b floppy_dosoftint
155
st %g0, [%l7 + %lo(doing_pdma)]
156
157
/* We emptied the FIFO, but we haven't read everything
158
* as of yet. Store the current transfer address and
159
* bytes left to read so we can continue when the next
160
* fast IRQ comes in.
161
*/
162
floppy_fifo_emptied:
163
sethi %hi(pdma_vaddr), %l5
164
st %l4, [%l5 + %lo(pdma_vaddr)]
165
sethi %hi(pdma_size), %l7
166
st %l6, [%l7 + %lo(pdma_size)]
167
168
/* Restore condition codes */
169
wr %l0, 0x0, %psr
170
WRITE_PAUSE
171
172
jmp %l1
173
rett %l2
174
175
floppy_overrun:
176
sethi %hi(pdma_vaddr), %l5
177
st %l4, [%l5 + %lo(pdma_vaddr)]
178
sethi %hi(pdma_size), %l5
179
st %l6, [%l5 + %lo(pdma_size)]
180
/* Prevent recursion */
181
sethi %hi(doing_pdma), %l7
182
st %g0, [%l7 + %lo(doing_pdma)]
183
184
/* fall through... */
185
floppy_dosoftint:
186
rd %wim, %l3
187
SAVE_ALL
188
189
/* Set all IRQs off. */
190
or %l0, PSR_PIL, %l4
191
wr %l4, 0x0, %psr
192
WRITE_PAUSE
193
wr %l4, PSR_ET, %psr
194
WRITE_PAUSE
195
196
mov 11, %o0 ! floppy irq level (unused anyway)
197
mov %g0, %o1 ! devid is not used in fast interrupts
198
call sparc_floppy_irq
199
add %sp, STACKFRAME_SZ, %o2 ! struct pt_regs *regs
200
201
RESTORE_ALL
202
203
#endif /* (CONFIG_BLK_DEV_FD) */
204
205
/* Bad trap handler */
206
.globl bad_trap_handler
207
bad_trap_handler:
208
SAVE_ALL
209
210
wr %l0, PSR_ET, %psr
211
WRITE_PAUSE
212
213
add %sp, STACKFRAME_SZ, %o0 ! pt_regs
214
call do_hw_interrupt
215
mov %l7, %o1 ! trap number
216
217
RESTORE_ALL
218
219
/* For now all IRQ's not registered get sent here. handler_irq() will
220
* see if a routine is registered to handle this interrupt and if not
221
* it will say so on the console.
222
*/
223
224
.align 4
225
.globl real_irq_entry, patch_handler_irq
226
real_irq_entry:
227
SAVE_ALL
228
229
#ifdef CONFIG_SMP
230
.globl patchme_maybe_smp_msg
231
232
cmp %l7, 11
233
patchme_maybe_smp_msg:
234
bgu maybe_smp4m_msg
235
nop
236
#endif
237
238
real_irq_continue:
239
or %l0, PSR_PIL, %g2
240
wr %g2, 0x0, %psr
241
WRITE_PAUSE
242
wr %g2, PSR_ET, %psr
243
WRITE_PAUSE
244
mov %l7, %o0 ! irq level
245
patch_handler_irq:
246
call handler_irq
247
add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr
248
or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq
249
wr %g2, PSR_ET, %psr ! keep ET up
250
WRITE_PAUSE
251
252
RESTORE_ALL
253
254
#ifdef CONFIG_SMP
255
/* SMP per-cpu ticker interrupts are handled specially. */
256
smp4m_ticker:
257
bne real_irq_continue+4
258
or %l0, PSR_PIL, %g2
259
wr %g2, 0x0, %psr
260
WRITE_PAUSE
261
wr %g2, PSR_ET, %psr
262
WRITE_PAUSE
263
call smp4m_percpu_timer_interrupt
264
add %sp, STACKFRAME_SZ, %o0
265
wr %l0, PSR_ET, %psr
266
WRITE_PAUSE
267
RESTORE_ALL
268
269
/* Here is where we check for possible SMP IPI passed to us
270
* on some level other than 15 which is the NMI and only used
271
* for cross calls. That has a separate entry point below.
272
*
273
* IPIs are sent on Level 12, 13 and 14. See IRQ_IPI_*.
274
*/
275
maybe_smp4m_msg:
276
GET_PROCESSOR4M_ID(o3)
277
sethi %hi(sun4m_irq_percpu), %l5
278
sll %o3, 2, %o3
279
or %l5, %lo(sun4m_irq_percpu), %o5
280
sethi %hi(0x70000000), %o2 ! Check all soft-IRQs
281
ld [%o5 + %o3], %o1
282
ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending
283
andcc %o3, %o2, %g0
284
be,a smp4m_ticker
285
cmp %l7, 14
286
/* Soft-IRQ IPI */
287
st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x70000000
288
WRITE_PAUSE
289
ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending
290
WRITE_PAUSE
291
or %l0, PSR_PIL, %l4
292
wr %l4, 0x0, %psr
293
WRITE_PAUSE
294
wr %l4, PSR_ET, %psr
295
WRITE_PAUSE
296
srl %o3, 28, %o2 ! shift for simpler checks below
297
maybe_smp4m_msg_check_single:
298
andcc %o2, 0x1, %g0
299
beq,a maybe_smp4m_msg_check_mask
300
andcc %o2, 0x2, %g0
301
call smp_call_function_single_interrupt
302
nop
303
andcc %o2, 0x2, %g0
304
maybe_smp4m_msg_check_mask:
305
beq,a maybe_smp4m_msg_check_resched
306
andcc %o2, 0x4, %g0
307
call smp_call_function_interrupt
308
nop
309
andcc %o2, 0x4, %g0
310
maybe_smp4m_msg_check_resched:
311
/* rescheduling is done in RESTORE_ALL regardless, but incr stats */
312
beq,a maybe_smp4m_msg_out
313
nop
314
call smp_resched_interrupt
315
nop
316
maybe_smp4m_msg_out:
317
RESTORE_ALL
318
319
.align 4
320
.globl linux_trap_ipi15_sun4m
321
linux_trap_ipi15_sun4m:
322
SAVE_ALL
323
sethi %hi(0x80000000), %o2
324
GET_PROCESSOR4M_ID(o0)
325
sethi %hi(sun4m_irq_percpu), %l5
326
or %l5, %lo(sun4m_irq_percpu), %o5
327
sll %o0, 2, %o0
328
ld [%o5 + %o0], %o5
329
ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending
330
andcc %o3, %o2, %g0
331
be 1f ! Must be an NMI async memory error
332
st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000
333
WRITE_PAUSE
334
ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending
335
WRITE_PAUSE
336
or %l0, PSR_PIL, %l4
337
wr %l4, 0x0, %psr
338
WRITE_PAUSE
339
wr %l4, PSR_ET, %psr
340
WRITE_PAUSE
341
call smp4m_cross_call_irq
342
nop
343
b ret_trap_lockless_ipi
344
clr %l6
345
1:
346
/* NMI async memory error handling. */
347
sethi %hi(0x80000000), %l4
348
sethi %hi(sun4m_irq_global), %o5
349
ld [%o5 + %lo(sun4m_irq_global)], %l5
350
st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000
351
WRITE_PAUSE
352
ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
353
WRITE_PAUSE
354
or %l0, PSR_PIL, %l4
355
wr %l4, 0x0, %psr
356
WRITE_PAUSE
357
wr %l4, PSR_ET, %psr
358
WRITE_PAUSE
359
call sun4m_nmi
360
nop
361
st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000
362
WRITE_PAUSE
363
ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending
364
WRITE_PAUSE
365
RESTORE_ALL
366
367
.globl smp4d_ticker
368
/* SMP per-cpu ticker interrupts are handled specially. */
369
smp4d_ticker:
370
SAVE_ALL
371
or %l0, PSR_PIL, %g2
372
sethi %hi(CC_ICLR), %o0
373
sethi %hi(1 << 14), %o1
374
or %o0, %lo(CC_ICLR), %o0
375
stha %o1, [%o0] ASI_M_MXCC /* Clear PIL 14 in MXCC's ICLR */
376
wr %g2, 0x0, %psr
377
WRITE_PAUSE
378
wr %g2, PSR_ET, %psr
379
WRITE_PAUSE
380
call smp4d_percpu_timer_interrupt
381
add %sp, STACKFRAME_SZ, %o0
382
wr %l0, PSR_ET, %psr
383
WRITE_PAUSE
384
RESTORE_ALL
385
386
.align 4
387
.globl linux_trap_ipi15_sun4d
388
linux_trap_ipi15_sun4d:
389
SAVE_ALL
390
sethi %hi(CC_BASE), %o4
391
sethi %hi(MXCC_ERR_ME|MXCC_ERR_PEW|MXCC_ERR_ASE|MXCC_ERR_PEE), %o2
392
or %o4, (CC_EREG - CC_BASE), %o0
393
ldda [%o0] ASI_M_MXCC, %o0
394
andcc %o0, %o2, %g0
395
bne 1f
396
sethi %hi(BB_STAT2), %o2
397
lduba [%o2] ASI_M_CTL, %o2
398
andcc %o2, BB_STAT2_MASK, %g0
399
bne 2f
400
or %o4, (CC_ICLR - CC_BASE), %o0
401
sethi %hi(1 << 15), %o1
402
stha %o1, [%o0] ASI_M_MXCC /* Clear PIL 15 in MXCC's ICLR */
403
or %l0, PSR_PIL, %l4
404
wr %l4, 0x0, %psr
405
WRITE_PAUSE
406
wr %l4, PSR_ET, %psr
407
WRITE_PAUSE
408
call smp4d_cross_call_irq
409
nop
410
b ret_trap_lockless_ipi
411
clr %l6
412
413
1: /* MXCC error */
414
2: /* BB error */
415
/* Disable PIL 15 */
416
set CC_IMSK, %l4
417
lduha [%l4] ASI_M_MXCC, %l5
418
sethi %hi(1 << 15), %l7
419
or %l5, %l7, %l5
420
stha %l5, [%l4] ASI_M_MXCC
421
/* FIXME */
422
1: b,a 1b
423
424
#ifdef CONFIG_SPARC_LEON
425
.globl smpleon_ipi
426
.extern leon_ipi_interrupt
427
/* SMP per-cpu IPI interrupts are handled specially. */
428
smpleon_ipi:
429
SAVE_ALL
430
or %l0, PSR_PIL, %g2
431
wr %g2, 0x0, %psr
432
WRITE_PAUSE
433
wr %g2, PSR_ET, %psr
434
WRITE_PAUSE
435
call leonsmp_ipi_interrupt
436
add %sp, STACKFRAME_SZ, %o1 ! pt_regs
437
wr %l0, PSR_ET, %psr
438
WRITE_PAUSE
439
RESTORE_ALL
440
441
.align 4
442
.globl linux_trap_ipi15_leon
443
linux_trap_ipi15_leon:
444
SAVE_ALL
445
or %l0, PSR_PIL, %l4
446
wr %l4, 0x0, %psr
447
WRITE_PAUSE
448
wr %l4, PSR_ET, %psr
449
WRITE_PAUSE
450
call leon_cross_call_irq
451
nop
452
b ret_trap_lockless_ipi
453
clr %l6
454
455
#endif /* CONFIG_SPARC_LEON */
456
457
#endif /* CONFIG_SMP */
458
459
/* This routine handles illegal instructions and privileged
460
* instruction attempts from user code.
461
*/
462
.align 4
463
.globl bad_instruction
464
bad_instruction:
465
sethi %hi(0xc1f80000), %l4
466
ld [%l1], %l5
467
sethi %hi(0x81d80000), %l7
468
and %l5, %l4, %l5
469
cmp %l5, %l7
470
be 1f
471
SAVE_ALL
472
473
wr %l0, PSR_ET, %psr ! re-enable traps
474
WRITE_PAUSE
475
476
add %sp, STACKFRAME_SZ, %o0
477
mov %l1, %o1
478
mov %l2, %o2
479
call do_illegal_instruction
480
mov %l0, %o3
481
482
RESTORE_ALL
483
484
1: /* unimplemented flush - just skip */
485
jmpl %l2, %g0
486
rett %l2 + 4
487
488
.align 4
489
.globl priv_instruction
490
priv_instruction:
491
SAVE_ALL
492
493
wr %l0, PSR_ET, %psr
494
WRITE_PAUSE
495
496
add %sp, STACKFRAME_SZ, %o0
497
mov %l1, %o1
498
mov %l2, %o2
499
call do_priv_instruction
500
mov %l0, %o3
501
502
RESTORE_ALL
503
504
/* This routine handles unaligned data accesses. */
505
.align 4
506
.globl mna_handler
507
mna_handler:
508
andcc %l0, PSR_PS, %g0
509
be mna_fromuser
510
nop
511
512
SAVE_ALL
513
514
wr %l0, PSR_ET, %psr
515
WRITE_PAUSE
516
517
ld [%l1], %o1
518
call kernel_unaligned_trap
519
add %sp, STACKFRAME_SZ, %o0
520
521
RESTORE_ALL
522
523
mna_fromuser:
524
SAVE_ALL
525
526
wr %l0, PSR_ET, %psr ! re-enable traps
527
WRITE_PAUSE
528
529
ld [%l1], %o1
530
call user_unaligned_trap
531
add %sp, STACKFRAME_SZ, %o0
532
533
RESTORE_ALL
534
535
/* This routine handles floating point disabled traps. */
536
.align 4
537
.globl fpd_trap_handler
538
fpd_trap_handler:
539
SAVE_ALL
540
541
wr %l0, PSR_ET, %psr ! re-enable traps
542
WRITE_PAUSE
543
544
add %sp, STACKFRAME_SZ, %o0
545
mov %l1, %o1
546
mov %l2, %o2
547
call do_fpd_trap
548
mov %l0, %o3
549
550
RESTORE_ALL
551
552
/* This routine handles Floating Point Exceptions. */
553
.align 4
554
.globl fpe_trap_handler
555
fpe_trap_handler:
556
set fpsave_magic, %l5
557
cmp %l1, %l5
558
be 1f
559
sethi %hi(fpsave), %l5
560
or %l5, %lo(fpsave), %l5
561
cmp %l1, %l5
562
bne 2f
563
sethi %hi(fpsave_catch2), %l5
564
or %l5, %lo(fpsave_catch2), %l5
565
wr %l0, 0x0, %psr
566
WRITE_PAUSE
567
jmp %l5
568
rett %l5 + 4
569
1:
570
sethi %hi(fpsave_catch), %l5
571
or %l5, %lo(fpsave_catch), %l5
572
wr %l0, 0x0, %psr
573
WRITE_PAUSE
574
jmp %l5
575
rett %l5 + 4
576
577
2:
578
SAVE_ALL
579
580
wr %l0, PSR_ET, %psr ! re-enable traps
581
WRITE_PAUSE
582
583
add %sp, STACKFRAME_SZ, %o0
584
mov %l1, %o1
585
mov %l2, %o2
586
call do_fpe_trap
587
mov %l0, %o3
588
589
RESTORE_ALL
590
591
/* This routine handles Tag Overflow Exceptions. */
592
.align 4
593
.globl do_tag_overflow
594
do_tag_overflow:
595
SAVE_ALL
596
597
wr %l0, PSR_ET, %psr ! re-enable traps
598
WRITE_PAUSE
599
600
add %sp, STACKFRAME_SZ, %o0
601
mov %l1, %o1
602
mov %l2, %o2
603
call handle_tag_overflow
604
mov %l0, %o3
605
606
RESTORE_ALL
607
608
/* This routine handles Watchpoint Exceptions. */
609
.align 4
610
.globl do_watchpoint
611
do_watchpoint:
612
SAVE_ALL
613
614
wr %l0, PSR_ET, %psr ! re-enable traps
615
WRITE_PAUSE
616
617
add %sp, STACKFRAME_SZ, %o0
618
mov %l1, %o1
619
mov %l2, %o2
620
call handle_watchpoint
621
mov %l0, %o3
622
623
RESTORE_ALL
624
625
/* This routine handles Register Access Exceptions. */
626
.align 4
627
.globl do_reg_access
628
do_reg_access:
629
SAVE_ALL
630
631
wr %l0, PSR_ET, %psr ! re-enable traps
632
WRITE_PAUSE
633
634
add %sp, STACKFRAME_SZ, %o0
635
mov %l1, %o1
636
mov %l2, %o2
637
call handle_reg_access
638
mov %l0, %o3
639
640
RESTORE_ALL
641
642
/* This routine handles Co-Processor Disabled Exceptions. */
643
.align 4
644
.globl do_cp_disabled
645
do_cp_disabled:
646
SAVE_ALL
647
648
wr %l0, PSR_ET, %psr ! re-enable traps
649
WRITE_PAUSE
650
651
add %sp, STACKFRAME_SZ, %o0
652
mov %l1, %o1
653
mov %l2, %o2
654
call handle_cp_disabled
655
mov %l0, %o3
656
657
RESTORE_ALL
658
659
/* This routine handles Co-Processor Exceptions. */
660
.align 4
661
.globl do_cp_exception
662
do_cp_exception:
663
SAVE_ALL
664
665
wr %l0, PSR_ET, %psr ! re-enable traps
666
WRITE_PAUSE
667
668
add %sp, STACKFRAME_SZ, %o0
669
mov %l1, %o1
670
mov %l2, %o2
671
call handle_cp_exception
672
mov %l0, %o3
673
674
RESTORE_ALL
675
676
/* This routine handles Hardware Divide By Zero Exceptions. */
677
.align 4
678
.globl do_hw_divzero
679
do_hw_divzero:
680
SAVE_ALL
681
682
wr %l0, PSR_ET, %psr ! re-enable traps
683
WRITE_PAUSE
684
685
add %sp, STACKFRAME_SZ, %o0
686
mov %l1, %o1
687
mov %l2, %o2
688
call handle_hw_divzero
689
mov %l0, %o3
690
691
RESTORE_ALL
692
693
.align 4
694
.globl do_flush_windows
695
do_flush_windows:
696
SAVE_ALL
697
698
wr %l0, PSR_ET, %psr
699
WRITE_PAUSE
700
701
andcc %l0, PSR_PS, %g0
702
bne dfw_kernel
703
nop
704
705
call flush_user_windows
706
nop
707
708
/* Advance over the trap instruction. */
709
ld [%sp + STACKFRAME_SZ + PT_NPC], %l1
710
add %l1, 0x4, %l2
711
st %l1, [%sp + STACKFRAME_SZ + PT_PC]
712
st %l2, [%sp + STACKFRAME_SZ + PT_NPC]
713
714
RESTORE_ALL
715
716
.globl flush_patch_one
717
718
/* We get these for debugging routines using __builtin_return_address() */
719
dfw_kernel:
720
flush_patch_one:
721
FLUSH_ALL_KERNEL_WINDOWS
722
723
/* Advance over the trap instruction. */
724
ld [%sp + STACKFRAME_SZ + PT_NPC], %l1
725
add %l1, 0x4, %l2
726
st %l1, [%sp + STACKFRAME_SZ + PT_PC]
727
st %l2, [%sp + STACKFRAME_SZ + PT_NPC]
728
729
RESTORE_ALL
730
731
/* The getcc software trap. The user wants the condition codes from
732
* the %psr in register %g1.
733
*/
734
735
.align 4
736
.globl getcc_trap_handler
737
getcc_trap_handler:
738
srl %l0, 20, %g1 ! give user
739
and %g1, 0xf, %g1 ! only ICC bits in %psr
740
jmp %l2 ! advance over trap instruction
741
rett %l2 + 0x4 ! like this...
742
743
/* The setcc software trap. The user has condition codes in %g1
744
* that it would like placed in the %psr. Be careful not to flip
745
* any unintentional bits!
746
*/
747
748
.align 4
749
.globl setcc_trap_handler
750
setcc_trap_handler:
751
sll %g1, 0x14, %l4
752
set PSR_ICC, %l5
753
andn %l0, %l5, %l0 ! clear ICC bits in %psr
754
and %l4, %l5, %l4 ! clear non-ICC bits in user value
755
or %l4, %l0, %l4 ! or them in... mix mix mix
756
757
wr %l4, 0x0, %psr ! set new %psr
758
WRITE_PAUSE ! TI scumbags...
759
760
jmp %l2 ! advance over trap instruction
761
rett %l2 + 0x4 ! like this...
762
763
.align 4
764
.globl linux_trap_nmi_sun4c
765
linux_trap_nmi_sun4c:
766
SAVE_ALL
767
768
/* Ugh, we need to clear the IRQ line. This is now
769
* a very sun4c specific trap handler...
770
*/
771
sethi %hi(interrupt_enable), %l5
772
ld [%l5 + %lo(interrupt_enable)], %l5
773
ldub [%l5], %l6
774
andn %l6, INTS_ENAB, %l6
775
stb %l6, [%l5]
776
777
/* Now it is safe to re-enable traps without recursion. */
778
or %l0, PSR_PIL, %l0
779
wr %l0, PSR_ET, %psr
780
WRITE_PAUSE
781
782
/* Now call the c-code with the pt_regs frame ptr and the
783
* memory error registers as arguments. The ordering chosen
784
* here is due to unlatching semantics.
785
*/
786
sethi %hi(AC_SYNC_ERR), %o0
787
add %o0, 0x4, %o0
788
lda [%o0] ASI_CONTROL, %o2 ! sync vaddr
789
sub %o0, 0x4, %o0
790
lda [%o0] ASI_CONTROL, %o1 ! sync error
791
add %o0, 0xc, %o0
792
lda [%o0] ASI_CONTROL, %o4 ! async vaddr
793
sub %o0, 0x4, %o0
794
lda [%o0] ASI_CONTROL, %o3 ! async error
795
call sparc_lvl15_nmi
796
add %sp, STACKFRAME_SZ, %o0
797
798
RESTORE_ALL
799
800
.align 4
801
.globl invalid_segment_patch1_ff
802
.globl invalid_segment_patch2_ff
803
invalid_segment_patch1_ff: cmp %l4, 0xff
804
invalid_segment_patch2_ff: mov 0xff, %l3
805
806
.align 4
807
.globl invalid_segment_patch1_1ff
808
.globl invalid_segment_patch2_1ff
809
invalid_segment_patch1_1ff: cmp %l4, 0x1ff
810
invalid_segment_patch2_1ff: mov 0x1ff, %l3
811
812
.align 4
813
.globl num_context_patch1_16, num_context_patch2_16
814
num_context_patch1_16: mov 0x10, %l7
815
num_context_patch2_16: mov 0x10, %l7
816
817
.align 4
818
.globl vac_linesize_patch_32
819
vac_linesize_patch_32: subcc %l7, 32, %l7
820
821
.align 4
822
.globl vac_hwflush_patch1_on, vac_hwflush_patch2_on
823
824
/*
825
* Ugly, but we can't use hardware flushing on the sun4 and we'd require
826
* two instructions (Anton)
827
*/
828
vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7
829
830
vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG
831
832
.globl invalid_segment_patch1, invalid_segment_patch2
833
.globl num_context_patch1
834
.globl vac_linesize_patch, vac_hwflush_patch1
835
.globl vac_hwflush_patch2
836
837
.align 4
838
.globl sun4c_fault
839
840
! %l0 = %psr
841
! %l1 = %pc
842
! %l2 = %npc
843
! %l3 = %wim
844
! %l7 = 1 for textfault
845
! We want error in %l5, vaddr in %l6
846
sun4c_fault:
847
sethi %hi(AC_SYNC_ERR), %l4
848
add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6
849
lda [%l6] ASI_CONTROL, %l5 ! Address
850
lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit
851
852
andn %l5, 0xfff, %l5 ! Encode all info into l7
853
srl %l6, 14, %l4
854
855
and %l4, 2, %l4
856
or %l5, %l4, %l4
857
858
or %l4, %l7, %l7 ! l7 = [addr,write,txtfault]
859
860
andcc %l0, PSR_PS, %g0
861
be sun4c_fault_fromuser
862
andcc %l7, 1, %g0 ! Text fault?
863
864
be 1f
865
sethi %hi(KERNBASE), %l4
866
867
mov %l1, %l5 ! PC
868
869
1:
870
cmp %l5, %l4
871
blu sun4c_fault_fromuser
872
sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4
873
874
/* If the kernel references a bum kernel pointer, or a pte which
875
* points to a non existent page in ram, we will run this code
876
* _forever_ and lock up the machine!!!!! So we must check for
877
* this condition, the AC_SYNC_ERR bits are what we must examine.
878
* Also a parity error would make this happen as well. So we just
879
* check that we are in fact servicing a tlb miss and not some
880
* other type of fault for the kernel.
881
*/
882
andcc %l6, 0x80, %g0
883
be sun4c_fault_fromuser
884
and %l5, %l4, %l5
885
886
/* Test for NULL pte_t * in vmalloc area. */
887
sethi %hi(VMALLOC_START), %l4
888
cmp %l5, %l4
889
blu,a invalid_segment_patch1
890
lduXa [%l5] ASI_SEGMAP, %l4
891
892
sethi %hi(swapper_pg_dir), %l4
893
srl %l5, SUN4C_PGDIR_SHIFT, %l6
894
or %l4, %lo(swapper_pg_dir), %l4
895
sll %l6, 2, %l6
896
ld [%l4 + %l6], %l4
897
andcc %l4, PAGE_MASK, %g0
898
be sun4c_fault_fromuser
899
lduXa [%l5] ASI_SEGMAP, %l4
900
901
invalid_segment_patch1:
902
cmp %l4, 0x7f
903
bne 1f
904
sethi %hi(sun4c_kfree_ring), %l4
905
or %l4, %lo(sun4c_kfree_ring), %l4
906
ld [%l4 + 0x18], %l3
907
deccc %l3 ! do we have a free entry?
908
bcs,a 2f ! no, unmap one.
909
sethi %hi(sun4c_kernel_ring), %l4
910
911
st %l3, [%l4 + 0x18] ! sun4c_kfree_ring.num_entries--
912
913
ld [%l4 + 0x00], %l6 ! entry = sun4c_kfree_ring.ringhd.next
914
st %l5, [%l6 + 0x08] ! entry->vaddr = address
915
916
ld [%l6 + 0x00], %l3 ! next = entry->next
917
ld [%l6 + 0x04], %l7 ! entry->prev
918
919
st %l7, [%l3 + 0x04] ! next->prev = entry->prev
920
st %l3, [%l7 + 0x00] ! entry->prev->next = next
921
922
sethi %hi(sun4c_kernel_ring), %l4
923
or %l4, %lo(sun4c_kernel_ring), %l4
924
! head = &sun4c_kernel_ring.ringhd
925
926
ld [%l4 + 0x00], %l7 ! head->next
927
928
st %l4, [%l6 + 0x04] ! entry->prev = head
929
st %l7, [%l6 + 0x00] ! entry->next = head->next
930
st %l6, [%l7 + 0x04] ! head->next->prev = entry
931
932
st %l6, [%l4 + 0x00] ! head->next = entry
933
934
ld [%l4 + 0x18], %l3
935
inc %l3 ! sun4c_kernel_ring.num_entries++
936
st %l3, [%l4 + 0x18]
937
b 4f
938
ld [%l6 + 0x08], %l5
939
940
2:
941
or %l4, %lo(sun4c_kernel_ring), %l4
942
! head = &sun4c_kernel_ring.ringhd
943
944
ld [%l4 + 0x04], %l6 ! entry = head->prev
945
946
ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr
947
948
! Flush segment from the cache.
949
sethi %hi((64 * 1024)), %l7
950
9:
951
vac_hwflush_patch1:
952
vac_linesize_patch:
953
subcc %l7, 16, %l7
954
bne 9b
955
vac_hwflush_patch2:
956
sta %g0, [%l3 + %l7] ASI_FLUSHSEG
957
958
st %l5, [%l6 + 0x08] ! entry->vaddr = address
959
960
ld [%l6 + 0x00], %l5 ! next = entry->next
961
ld [%l6 + 0x04], %l7 ! entry->prev
962
963
st %l7, [%l5 + 0x04] ! next->prev = entry->prev
964
st %l5, [%l7 + 0x00] ! entry->prev->next = next
965
st %l4, [%l6 + 0x04] ! entry->prev = head
966
967
ld [%l4 + 0x00], %l7 ! head->next
968
969
st %l7, [%l6 + 0x00] ! entry->next = head->next
970
st %l6, [%l7 + 0x04] ! head->next->prev = entry
971
st %l6, [%l4 + 0x00] ! head->next = entry
972
973
mov %l3, %l5 ! address = tmp
974
975
4:
976
num_context_patch1:
977
mov 0x08, %l7
978
979
ld [%l6 + 0x08], %l4
980
ldub [%l6 + 0x0c], %l3
981
or %l4, %l3, %l4 ! encode new vaddr/pseg into l4
982
983
sethi %hi(AC_CONTEXT), %l3
984
lduba [%l3] ASI_CONTROL, %l6
985
986
/* Invalidate old mapping, instantiate new mapping,
987
* for each context. Registers l6/l7 are live across
988
* this loop.
989
*/
990
3: deccc %l7
991
sethi %hi(AC_CONTEXT), %l3
992
stba %l7, [%l3] ASI_CONTROL
993
invalid_segment_patch2:
994
mov 0x7f, %l3
995
stXa %l3, [%l5] ASI_SEGMAP
996
andn %l4, 0x1ff, %l3
997
bne 3b
998
stXa %l4, [%l3] ASI_SEGMAP
999
1000
sethi %hi(AC_CONTEXT), %l3
1001
stba %l6, [%l3] ASI_CONTROL
1002
1003
andn %l4, 0x1ff, %l5
1004
1005
1:
1006
sethi %hi(VMALLOC_START), %l4
1007
cmp %l5, %l4
1008
1009
bgeu 1f
1010
mov 1 << (SUN4C_REAL_PGDIR_SHIFT - PAGE_SHIFT), %l7
1011
1012
sethi %hi(KERNBASE), %l6
1013
1014
sub %l5, %l6, %l4
1015
srl %l4, PAGE_SHIFT, %l4
1016
sethi %hi((SUN4C_PAGE_KERNEL & 0xf4000000)), %l3
1017
or %l3, %l4, %l3
1018
1019
sethi %hi(PAGE_SIZE), %l4
1020
1021
2:
1022
sta %l3, [%l5] ASI_PTE
1023
deccc %l7
1024
inc %l3
1025
bne 2b
1026
add %l5, %l4, %l5
1027
1028
b 7f
1029
sethi %hi(sun4c_kernel_faults), %l4
1030
1031
1:
1032
srl %l5, SUN4C_PGDIR_SHIFT, %l3
1033
sethi %hi(swapper_pg_dir), %l4
1034
or %l4, %lo(swapper_pg_dir), %l4
1035
sll %l3, 2, %l3
1036
ld [%l4 + %l3], %l4
1037
and %l4, PAGE_MASK, %l4
1038
1039
srl %l5, (PAGE_SHIFT - 2), %l6
1040
and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6
1041
add %l6, %l4, %l6
1042
1043
sethi %hi(PAGE_SIZE), %l4
1044
1045
2:
1046
ld [%l6], %l3
1047
deccc %l7
1048
sta %l3, [%l5] ASI_PTE
1049
add %l6, 0x4, %l6
1050
bne 2b
1051
add %l5, %l4, %l5
1052
1053
sethi %hi(sun4c_kernel_faults), %l4
1054
7:
1055
ld [%l4 + %lo(sun4c_kernel_faults)], %l3
1056
inc %l3
1057
st %l3, [%l4 + %lo(sun4c_kernel_faults)]
1058
1059
/* Restore condition codes */
1060
wr %l0, 0x0, %psr
1061
WRITE_PAUSE
1062
jmp %l1
1063
rett %l2
1064
1065
sun4c_fault_fromuser:
1066
SAVE_ALL
1067
nop
1068
1069
mov %l7, %o1 ! Decode the info from %l7
1070
mov %l7, %o2
1071
and %o1, 1, %o1 ! arg2 = text_faultp
1072
mov %l7, %o3
1073
and %o2, 2, %o2 ! arg3 = writep
1074
andn %o3, 0xfff, %o3 ! arg4 = faulting address
1075
1076
wr %l0, PSR_ET, %psr
1077
WRITE_PAUSE
1078
1079
call do_sun4c_fault
1080
add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr
1081
1082
RESTORE_ALL
1083
1084
.align 4
1085
.globl srmmu_fault
1086
srmmu_fault:
1087
mov 0x400, %l5
1088
mov 0x300, %l4
1089
1090
lda [%l5] ASI_M_MMUREGS, %l6 ! read sfar first
1091
lda [%l4] ASI_M_MMUREGS, %l5 ! read sfsr last
1092
1093
andn %l6, 0xfff, %l6
1094
srl %l5, 6, %l5 ! and encode all info into l7
1095
1096
and %l5, 2, %l5
1097
or %l5, %l6, %l6
1098
1099
or %l6, %l7, %l7 ! l7 = [addr,write,txtfault]
1100
1101
SAVE_ALL
1102
1103
mov %l7, %o1
1104
mov %l7, %o2
1105
and %o1, 1, %o1 ! arg2 = text_faultp
1106
mov %l7, %o3
1107
and %o2, 2, %o2 ! arg3 = writep
1108
andn %o3, 0xfff, %o3 ! arg4 = faulting address
1109
1110
wr %l0, PSR_ET, %psr
1111
WRITE_PAUSE
1112
1113
call do_sparc_fault
1114
add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr
1115
1116
RESTORE_ALL
1117
1118
.align 4
1119
.globl sys_nis_syscall
1120
sys_nis_syscall:
1121
mov %o7, %l5
1122
add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg
1123
call c_sys_nis_syscall
1124
mov %l5, %o7
1125
1126
.align 4
1127
.globl sys_execve
1128
sys_execve:
1129
mov %o7, %l5
1130
add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg
1131
call sparc_execve
1132
mov %l5, %o7
1133
1134
.globl sunos_execv
1135
sunos_execv:
1136
st %g0, [%sp + STACKFRAME_SZ + PT_I2]
1137
1138
call sparc_execve
1139
add %sp, STACKFRAME_SZ, %o0
1140
1141
b ret_sys_call
1142
ld [%sp + STACKFRAME_SZ + PT_I0], %o0
1143
1144
.align 4
1145
.globl sys_sparc_pipe
1146
sys_sparc_pipe:
1147
mov %o7, %l5
1148
add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg
1149
call sparc_pipe
1150
mov %l5, %o7
1151
1152
.align 4
1153
.globl sys_sigaltstack
1154
sys_sigaltstack:
1155
mov %o7, %l5
1156
mov %fp, %o2
1157
call do_sigaltstack
1158
mov %l5, %o7
1159
1160
.align 4
1161
.globl sys_sigstack
1162
sys_sigstack:
1163
mov %o7, %l5
1164
mov %fp, %o2
1165
call do_sys_sigstack
1166
mov %l5, %o7
1167
1168
.align 4
1169
.globl sys_sigreturn
1170
sys_sigreturn:
1171
call do_sigreturn
1172
add %sp, STACKFRAME_SZ, %o0
1173
1174
ld [%curptr + TI_FLAGS], %l5
1175
andcc %l5, _TIF_SYSCALL_TRACE, %g0
1176
be 1f
1177
nop
1178
1179
call syscall_trace
1180
nop
1181
1182
1:
1183
/* We don't want to muck with user registers like a
1184
* normal syscall, just return.
1185
*/
1186
RESTORE_ALL
1187
1188
.align 4
1189
.globl sys_rt_sigreturn
1190
sys_rt_sigreturn:
1191
call do_rt_sigreturn
1192
add %sp, STACKFRAME_SZ, %o0
1193
1194
ld [%curptr + TI_FLAGS], %l5
1195
andcc %l5, _TIF_SYSCALL_TRACE, %g0
1196
be 1f
1197
nop
1198
1199
add %sp, STACKFRAME_SZ, %o0
1200
call syscall_trace
1201
mov 1, %o1
1202
1203
1:
1204
/* We are returning to a signal handler. */
1205
RESTORE_ALL
1206
1207
/* Now that we have a real sys_clone, sys_fork() is
1208
* implemented in terms of it. Our _real_ implementation
1209
* of SunOS vfork() will use sys_vfork().
1210
*
1211
* XXX These three should be consolidated into mostly shared
1212
* XXX code just like on sparc64... -DaveM
1213
*/
1214
.align 4
1215
.globl sys_fork, flush_patch_two
1216
sys_fork:
1217
mov %o7, %l5
1218
flush_patch_two:
1219
FLUSH_ALL_KERNEL_WINDOWS;
1220
ld [%curptr + TI_TASK], %o4
1221
rd %psr, %g4
1222
WRITE_PAUSE
1223
mov SIGCHLD, %o0 ! arg0: clone flags
1224
rd %wim, %g5
1225
WRITE_PAUSE
1226
mov %fp, %o1 ! arg1: usp
1227
std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
1228
add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr
1229
mov 0, %o3
1230
call sparc_do_fork
1231
mov %l5, %o7
1232
1233
/* Whee, kernel threads! */
1234
.globl sys_clone, flush_patch_three
1235
sys_clone:
1236
mov %o7, %l5
1237
flush_patch_three:
1238
FLUSH_ALL_KERNEL_WINDOWS;
1239
ld [%curptr + TI_TASK], %o4
1240
rd %psr, %g4
1241
WRITE_PAUSE
1242
1243
/* arg0,1: flags,usp -- loaded already */
1244
cmp %o1, 0x0 ! Is new_usp NULL?
1245
rd %wim, %g5
1246
WRITE_PAUSE
1247
be,a 1f
1248
mov %fp, %o1 ! yes, use callers usp
1249
andn %o1, 7, %o1 ! no, align to 8 bytes
1250
1:
1251
std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
1252
add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr
1253
mov 0, %o3
1254
call sparc_do_fork
1255
mov %l5, %o7
1256
1257
/* Whee, real vfork! */
1258
.globl sys_vfork, flush_patch_four
1259
sys_vfork:
1260
flush_patch_four:
1261
FLUSH_ALL_KERNEL_WINDOWS;
1262
ld [%curptr + TI_TASK], %o4
1263
rd %psr, %g4
1264
WRITE_PAUSE
1265
rd %wim, %g5
1266
WRITE_PAUSE
1267
std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
1268
sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0
1269
mov %fp, %o1
1270
or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
1271
sethi %hi(sparc_do_fork), %l1
1272
mov 0, %o3
1273
jmpl %l1 + %lo(sparc_do_fork), %g0
1274
add %sp, STACKFRAME_SZ, %o2
1275
1276
.align 4
1277
linux_sparc_ni_syscall:
1278
sethi %hi(sys_ni_syscall), %l7
1279
b syscall_is_too_hard
1280
or %l7, %lo(sys_ni_syscall), %l7
1281
1282
linux_fast_syscall:
1283
andn %l7, 3, %l7
1284
mov %i0, %o0
1285
mov %i1, %o1
1286
mov %i2, %o2
1287
jmpl %l7 + %g0, %g0
1288
mov %i3, %o3
1289
1290
linux_syscall_trace:
1291
add %sp, STACKFRAME_SZ, %o0
1292
call syscall_trace
1293
mov 0, %o1
1294
cmp %o0, 0
1295
bne 3f
1296
mov -ENOSYS, %o0
1297
mov %i0, %o0
1298
mov %i1, %o1
1299
mov %i2, %o2
1300
mov %i3, %o3
1301
b 2f
1302
mov %i4, %o4
1303
1304
.globl ret_from_fork
1305
ret_from_fork:
1306
call schedule_tail
1307
ld [%g3 + TI_TASK], %o0
1308
b ret_sys_call
1309
ld [%sp + STACKFRAME_SZ + PT_I0], %o0
1310
1311
/* Linux native system calls enter here... */
1312
.align 4
1313
.globl linux_sparc_syscall
1314
linux_sparc_syscall:
1315
sethi %hi(PSR_SYSCALL), %l4
1316
or %l0, %l4, %l0
1317
/* Direct access to user regs, must faster. */
1318
cmp %g1, NR_syscalls
1319
bgeu linux_sparc_ni_syscall
1320
sll %g1, 2, %l4
1321
ld [%l7 + %l4], %l7
1322
andcc %l7, 1, %g0
1323
bne linux_fast_syscall
1324
/* Just do first insn from SAVE_ALL in the delay slot */
1325
1326
syscall_is_too_hard:
1327
SAVE_ALL_HEAD
1328
rd %wim, %l3
1329
1330
wr %l0, PSR_ET, %psr
1331
mov %i0, %o0
1332
mov %i1, %o1
1333
mov %i2, %o2
1334
1335
ld [%curptr + TI_FLAGS], %l5
1336
mov %i3, %o3
1337
andcc %l5, _TIF_SYSCALL_TRACE, %g0
1338
mov %i4, %o4
1339
bne linux_syscall_trace
1340
mov %i0, %l5
1341
2:
1342
call %l7
1343
mov %i5, %o5
1344
1345
3:
1346
st %o0, [%sp + STACKFRAME_SZ + PT_I0]
1347
1348
ret_sys_call:
1349
ld [%curptr + TI_FLAGS], %l6
1350
cmp %o0, -ERESTART_RESTARTBLOCK
1351
ld [%sp + STACKFRAME_SZ + PT_PSR], %g3
1352
set PSR_C, %g2
1353
bgeu 1f
1354
andcc %l6, _TIF_SYSCALL_TRACE, %g0
1355
1356
/* System call success, clear Carry condition code. */
1357
andn %g3, %g2, %g3
1358
clr %l6
1359
st %g3, [%sp + STACKFRAME_SZ + PT_PSR]
1360
bne linux_syscall_trace2
1361
ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */
1362
add %l1, 0x4, %l2 /* npc = npc+4 */
1363
st %l1, [%sp + STACKFRAME_SZ + PT_PC]
1364
b ret_trap_entry
1365
st %l2, [%sp + STACKFRAME_SZ + PT_NPC]
1366
1:
1367
/* System call failure, set Carry condition code.
1368
* Also, get abs(errno) to return to the process.
1369
*/
1370
sub %g0, %o0, %o0
1371
or %g3, %g2, %g3
1372
st %o0, [%sp + STACKFRAME_SZ + PT_I0]
1373
mov 1, %l6
1374
st %g3, [%sp + STACKFRAME_SZ + PT_PSR]
1375
bne linux_syscall_trace2
1376
ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */
1377
add %l1, 0x4, %l2 /* npc = npc+4 */
1378
st %l1, [%sp + STACKFRAME_SZ + PT_PC]
1379
b ret_trap_entry
1380
st %l2, [%sp + STACKFRAME_SZ + PT_NPC]
1381
1382
linux_syscall_trace2:
1383
add %sp, STACKFRAME_SZ, %o0
1384
mov 1, %o1
1385
call syscall_trace
1386
add %l1, 0x4, %l2 /* npc = npc+4 */
1387
st %l1, [%sp + STACKFRAME_SZ + PT_PC]
1388
b ret_trap_entry
1389
st %l2, [%sp + STACKFRAME_SZ + PT_NPC]
1390
1391
1392
/* Saving and restoring the FPU state is best done from lowlevel code.
1393
*
1394
* void fpsave(unsigned long *fpregs, unsigned long *fsr,
1395
* void *fpqueue, unsigned long *fpqdepth)
1396
*/
1397
1398
.globl fpsave
1399
fpsave:
1400
st %fsr, [%o1] ! this can trap on us if fpu is in bogon state
1401
ld [%o1], %g1
1402
set 0x2000, %g4
1403
andcc %g1, %g4, %g0
1404
be 2f
1405
mov 0, %g2
1406
1407
/* We have an fpqueue to save. */
1408
1:
1409
std %fq, [%o2]
1410
fpsave_magic:
1411
st %fsr, [%o1]
1412
ld [%o1], %g3
1413
andcc %g3, %g4, %g0
1414
add %g2, 1, %g2
1415
bne 1b
1416
add %o2, 8, %o2
1417
1418
2:
1419
st %g2, [%o3]
1420
1421
std %f0, [%o0 + 0x00]
1422
std %f2, [%o0 + 0x08]
1423
std %f4, [%o0 + 0x10]
1424
std %f6, [%o0 + 0x18]
1425
std %f8, [%o0 + 0x20]
1426
std %f10, [%o0 + 0x28]
1427
std %f12, [%o0 + 0x30]
1428
std %f14, [%o0 + 0x38]
1429
std %f16, [%o0 + 0x40]
1430
std %f18, [%o0 + 0x48]
1431
std %f20, [%o0 + 0x50]
1432
std %f22, [%o0 + 0x58]
1433
std %f24, [%o0 + 0x60]
1434
std %f26, [%o0 + 0x68]
1435
std %f28, [%o0 + 0x70]
1436
retl
1437
std %f30, [%o0 + 0x78]
1438
1439
/* Thanks for Theo Deraadt and the authors of the Sprite/netbsd/openbsd
1440
* code for pointing out this possible deadlock, while we save state
1441
* above we could trap on the fsr store so our low level fpu trap
1442
* code has to know how to deal with this.
1443
*/
1444
fpsave_catch:
1445
b fpsave_magic + 4
1446
st %fsr, [%o1]
1447
1448
fpsave_catch2:
1449
b fpsave + 4
1450
st %fsr, [%o1]
1451
1452
/* void fpload(unsigned long *fpregs, unsigned long *fsr); */
1453
1454
.globl fpload
1455
fpload:
1456
ldd [%o0 + 0x00], %f0
1457
ldd [%o0 + 0x08], %f2
1458
ldd [%o0 + 0x10], %f4
1459
ldd [%o0 + 0x18], %f6
1460
ldd [%o0 + 0x20], %f8
1461
ldd [%o0 + 0x28], %f10
1462
ldd [%o0 + 0x30], %f12
1463
ldd [%o0 + 0x38], %f14
1464
ldd [%o0 + 0x40], %f16
1465
ldd [%o0 + 0x48], %f18
1466
ldd [%o0 + 0x50], %f20
1467
ldd [%o0 + 0x58], %f22
1468
ldd [%o0 + 0x60], %f24
1469
ldd [%o0 + 0x68], %f26
1470
ldd [%o0 + 0x70], %f28
1471
ldd [%o0 + 0x78], %f30
1472
ld [%o1], %fsr
1473
retl
1474
nop
1475
1476
/* __ndelay and __udelay take two arguments:
1477
* 0 - nsecs or usecs to delay
1478
* 1 - per_cpu udelay_val (loops per jiffy)
1479
*
1480
* Note that ndelay gives HZ times higher resolution but has a 10ms
1481
* limit. udelay can handle up to 1s.
1482
*/
1483
.globl __ndelay
1484
__ndelay:
1485
save %sp, -STACKFRAME_SZ, %sp
1486
mov %i0, %o0
1487
call .umul ! round multiplier up so large ns ok
1488
mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ)
1489
call .umul
1490
mov %i1, %o1 ! udelay_val
1491
ba delay_continue
1492
mov %o1, %o0 ! >>32 later for better resolution
1493
1494
.globl __udelay
1495
__udelay:
1496
save %sp, -STACKFRAME_SZ, %sp
1497
mov %i0, %o0
1498
sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok
1499
call .umul
1500
or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000
1501
call .umul
1502
mov %i1, %o1 ! udelay_val
1503
sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32,
1504
or %g0, %lo(0x028f4b62), %l0
1505
addcc %o0, %l0, %o0 ! 2**32 * 0.009 999
1506
bcs,a 3f
1507
add %o1, 0x01, %o1
1508
3:
1509
call .umul
1510
mov HZ, %o0 ! >>32 earlier for wider range
1511
1512
delay_continue:
1513
cmp %o0, 0x0
1514
1:
1515
bne 1b
1516
subcc %o0, 1, %o0
1517
1518
ret
1519
restore
1520
1521
/* Handle a software breakpoint */
1522
/* We have to inform parent that child has stopped */
1523
.align 4
1524
.globl breakpoint_trap
1525
breakpoint_trap:
1526
rd %wim,%l3
1527
SAVE_ALL
1528
wr %l0, PSR_ET, %psr
1529
WRITE_PAUSE
1530
1531
st %i0, [%sp + STACKFRAME_SZ + PT_G0] ! for restarting syscalls
1532
call sparc_breakpoint
1533
add %sp, STACKFRAME_SZ, %o0
1534
1535
RESTORE_ALL
1536
1537
#ifdef CONFIG_KGDB
1538
.align 4
1539
.globl kgdb_trap_low
1540
.type kgdb_trap_low,#function
1541
kgdb_trap_low:
1542
rd %wim,%l3
1543
SAVE_ALL
1544
wr %l0, PSR_ET, %psr
1545
WRITE_PAUSE
1546
1547
call kgdb_trap
1548
add %sp, STACKFRAME_SZ, %o0
1549
1550
RESTORE_ALL
1551
.size kgdb_trap_low,.-kgdb_trap_low
1552
#endif
1553
1554
.align 4
1555
.globl flush_patch_exception
1556
flush_patch_exception:
1557
FLUSH_ALL_KERNEL_WINDOWS;
1558
ldd [%o0], %o6
1559
jmpl %o7 + 0xc, %g0 ! see asm-sparc/processor.h
1560
mov 1, %g1 ! signal EFAULT condition
1561
1562
.align 4
1563
.globl kill_user_windows, kuw_patch1_7win
1564
.globl kuw_patch1
1565
kuw_patch1_7win: sll %o3, 6, %o3
1566
1567
/* No matter how much overhead this routine has in the worst
1568
* case scenerio, it is several times better than taking the
1569
* traps with the old method of just doing flush_user_windows().
1570
*/
1571
kill_user_windows:
1572
ld [%g6 + TI_UWINMASK], %o0 ! get current umask
1573
orcc %g0, %o0, %g0 ! if no bits set, we are done
1574
be 3f ! nothing to do
1575
rd %psr, %o5 ! must clear interrupts
1576
or %o5, PSR_PIL, %o4 ! or else that could change
1577
wr %o4, 0x0, %psr ! the uwinmask state
1578
WRITE_PAUSE ! burn them cycles
1579
1:
1580
ld [%g6 + TI_UWINMASK], %o0 ! get consistent state
1581
orcc %g0, %o0, %g0 ! did an interrupt come in?
1582
be 4f ! yep, we are done
1583
rd %wim, %o3 ! get current wim
1584
srl %o3, 1, %o4 ! simulate a save
1585
kuw_patch1:
1586
sll %o3, 7, %o3 ! compute next wim
1587
or %o4, %o3, %o3 ! result
1588
andncc %o0, %o3, %o0 ! clean this bit in umask
1589
bne kuw_patch1 ! not done yet
1590
srl %o3, 1, %o4 ! begin another save simulation
1591
wr %o3, 0x0, %wim ! set the new wim
1592
st %g0, [%g6 + TI_UWINMASK] ! clear uwinmask
1593
4:
1594
wr %o5, 0x0, %psr ! re-enable interrupts
1595
WRITE_PAUSE ! burn baby burn
1596
3:
1597
retl ! return
1598
st %g0, [%g6 + TI_W_SAVED] ! no windows saved
1599
1600
.align 4
1601
.globl restore_current
1602
restore_current:
1603
LOAD_CURRENT(g6, o0)
1604
retl
1605
nop
1606
1607
#ifdef CONFIG_PCIC_PCI
1608
#include <asm/pcic.h>
1609
1610
.align 4
1611
.globl linux_trap_ipi15_pcic
1612
linux_trap_ipi15_pcic:
1613
rd %wim, %l3
1614
SAVE_ALL
1615
1616
/*
1617
* First deactivate NMI
1618
* or we cannot drop ET, cannot get window spill traps.
1619
* The busy loop is necessary because the PIO error
1620
* sometimes does not go away quickly and we trap again.
1621
*/
1622
sethi %hi(pcic_regs), %o1
1623
ld [%o1 + %lo(pcic_regs)], %o2
1624
1625
! Get pending status for printouts later.
1626
ld [%o2 + PCI_SYS_INT_PENDING], %o0
1627
1628
mov PCI_SYS_INT_PENDING_CLEAR_ALL, %o1
1629
stb %o1, [%o2 + PCI_SYS_INT_PENDING_CLEAR]
1630
1:
1631
ld [%o2 + PCI_SYS_INT_PENDING], %o1
1632
andcc %o1, ((PCI_SYS_INT_PENDING_PIO|PCI_SYS_INT_PENDING_PCI)>>24), %g0
1633
bne 1b
1634
nop
1635
1636
or %l0, PSR_PIL, %l4
1637
wr %l4, 0x0, %psr
1638
WRITE_PAUSE
1639
wr %l4, PSR_ET, %psr
1640
WRITE_PAUSE
1641
1642
call pcic_nmi
1643
add %sp, STACKFRAME_SZ, %o1 ! struct pt_regs *regs
1644
RESTORE_ALL
1645
1646
.globl pcic_nmi_trap_patch
1647
pcic_nmi_trap_patch:
1648
sethi %hi(linux_trap_ipi15_pcic), %l3
1649
jmpl %l3 + %lo(linux_trap_ipi15_pcic), %g0
1650
rd %psr, %l0
1651
.word 0
1652
1653
#endif /* CONFIG_PCIC_PCI */
1654
1655
.globl flushw_all
1656
flushw_all:
1657
save %sp, -0x40, %sp
1658
save %sp, -0x40, %sp
1659
save %sp, -0x40, %sp
1660
save %sp, -0x40, %sp
1661
save %sp, -0x40, %sp
1662
save %sp, -0x40, %sp
1663
save %sp, -0x40, %sp
1664
restore
1665
restore
1666
restore
1667
restore
1668
restore
1669
restore
1670
ret
1671
restore
1672
1673
/* End of entry.S */
1674
1675