cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

entry.S (28628B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/* arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
      3 *
      4 * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
      5 * Copyright (C) 1996 Eddie C. Dost   (ecd@skynet.be)
      6 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
      7 * Copyright (C) 1996-1999 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
      8 * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au)
      9 */
     10
     11#include <linux/linkage.h>
     12#include <linux/errno.h>
     13#include <linux/pgtable.h>
     14
     15#include <asm/head.h>
     16#include <asm/asi.h>
     17#include <asm/smp.h>
     18#include <asm/contregs.h>
     19#include <asm/ptrace.h>
     20#include <asm/asm-offsets.h>
     21#include <asm/psr.h>
     22#include <asm/vaddrs.h>
     23#include <asm/page.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#include <asm/export.h>
     34
     35#define curptr      g6
     36
     37/* These are just handy. */
     38#define _SV	save	%sp, -STACKFRAME_SZ, %sp
     39#define _RS     restore 
     40
     41#define FLUSH_ALL_KERNEL_WINDOWS \
     42	_SV; _SV; _SV; _SV; _SV; _SV; _SV; \
     43	_RS; _RS; _RS; _RS; _RS; _RS; _RS;
     44
     45	.text
     46
     47#ifdef CONFIG_KGDB
     48	.align	4
     49	.globl		arch_kgdb_breakpoint
     50	.type		arch_kgdb_breakpoint,#function
     51arch_kgdb_breakpoint:
     52	ta		0x7d
     53	retl
     54	 nop
     55	.size		arch_kgdb_breakpoint,.-arch_kgdb_breakpoint
     56#endif
     57
     58#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
     59	.align	4
     60	.globl	floppy_hardint
     61floppy_hardint:
     62	/*
     63	 * This code cannot touch registers %l0 %l1 and %l2
     64	 * because SAVE_ALL depends on their values. It depends
     65	 * on %l3 also, but we regenerate it before a call.
     66	 * Other registers are:
     67	 * %l3 -- base address of fdc registers
     68	 * %l4 -- pdma_vaddr
     69	 * %l5 -- scratch for ld/st address
     70	 * %l6 -- pdma_size
     71	 * %l7 -- scratch [floppy byte, ld/st address, aux. data]
     72	 */
     73
     74	/* Do we have work to do? */
     75	sethi	%hi(doing_pdma), %l7
     76	ld	[%l7 + %lo(doing_pdma)], %l7
     77	cmp	%l7, 0
     78	be	floppy_dosoftint
     79	 nop
     80
     81	/* Load fdc register base */
     82	sethi	%hi(fdc_status), %l3
     83	ld	[%l3 + %lo(fdc_status)], %l3
     84
     85	/* Setup register addresses */
     86	sethi	%hi(pdma_vaddr), %l5	! transfer buffer
     87	ld	[%l5 + %lo(pdma_vaddr)], %l4
     88	sethi	%hi(pdma_size), %l5	! bytes to go
     89	ld	[%l5 + %lo(pdma_size)], %l6
     90next_byte:
     91  	ldub	[%l3], %l7
     92
     93	andcc	%l7, 0x80, %g0		! Does fifo still have data
     94	bz	floppy_fifo_emptied	! fifo has been emptied...
     95	 andcc	%l7, 0x20, %g0		! in non-dma mode still?
     96	bz	floppy_overrun		! nope, overrun
     97	 andcc	%l7, 0x40, %g0		! 0=write 1=read
     98	bz	floppy_write
     99	 sub	%l6, 0x1, %l6
    100
    101	/* Ok, actually read this byte */
    102	ldub	[%l3 + 1], %l7
    103	orcc	%g0, %l6, %g0
    104	stb	%l7, [%l4]
    105	bne	next_byte
    106	 add	%l4, 0x1, %l4
    107
    108	b	floppy_tdone
    109	 nop
    110
    111floppy_write:
    112	/* Ok, actually write this byte */
    113	ldub	[%l4], %l7
    114	orcc	%g0, %l6, %g0
    115	stb	%l7, [%l3 + 1]
    116	bne	next_byte
    117	 add	%l4, 0x1, %l4
    118
    119	/* fall through... */
    120floppy_tdone:
    121	sethi	%hi(pdma_vaddr), %l5
    122	st	%l4, [%l5 + %lo(pdma_vaddr)]
    123	sethi	%hi(pdma_size), %l5
    124	st	%l6, [%l5 + %lo(pdma_size)]
    125	/* Flip terminal count pin */
    126	set	auxio_register, %l7
    127	ld	[%l7], %l7
    128
    129	ldub	[%l7], %l5
    130
    131	or	%l5, 0xc2, %l5
    132	stb	%l5, [%l7]
    133	andn    %l5, 0x02, %l5
    134
    1352:
    136	/* Kill some time so the bits set */
    137	WRITE_PAUSE
    138	WRITE_PAUSE
    139
    140	stb     %l5, [%l7]
    141
    142	/* Prevent recursion */
    143	sethi	%hi(doing_pdma), %l7
    144	b	floppy_dosoftint
    145	 st	%g0, [%l7 + %lo(doing_pdma)]
    146
    147	/* We emptied the FIFO, but we haven't read everything
    148	 * as of yet.  Store the current transfer address and
    149	 * bytes left to read so we can continue when the next
    150	 * fast IRQ comes in.
    151	 */
    152floppy_fifo_emptied:
    153	sethi	%hi(pdma_vaddr), %l5
    154	st	%l4, [%l5 + %lo(pdma_vaddr)]
    155	sethi	%hi(pdma_size), %l7
    156	st	%l6, [%l7 + %lo(pdma_size)]
    157
    158	/* Restore condition codes */
    159	wr	%l0, 0x0, %psr
    160	WRITE_PAUSE
    161
    162	jmp	%l1
    163	rett	%l2
    164
    165floppy_overrun:
    166	sethi	%hi(pdma_vaddr), %l5
    167	st	%l4, [%l5 + %lo(pdma_vaddr)]
    168	sethi	%hi(pdma_size), %l5
    169	st	%l6, [%l5 + %lo(pdma_size)]
    170	/* Prevent recursion */
    171	sethi	%hi(doing_pdma), %l7
    172	st	%g0, [%l7 + %lo(doing_pdma)]
    173
    174	/* fall through... */
    175floppy_dosoftint:
    176	rd	%wim, %l3
    177	SAVE_ALL
    178
    179	/* Set all IRQs off. */
    180	or	%l0, PSR_PIL, %l4
    181	wr	%l4, 0x0, %psr
    182	WRITE_PAUSE
    183	wr	%l4, PSR_ET, %psr
    184	WRITE_PAUSE
    185
    186	mov	11, %o0			! floppy irq level (unused anyway)
    187	mov	%g0, %o1		! devid is not used in fast interrupts
    188	call	sparc_floppy_irq
    189	 add	%sp, STACKFRAME_SZ, %o2	! struct pt_regs *regs
    190
    191	RESTORE_ALL
    192	
    193#endif /* (CONFIG_BLK_DEV_FD) */
    194
    195	/* Bad trap handler */
    196	.globl	bad_trap_handler
    197bad_trap_handler:
    198	SAVE_ALL
    199
    200	wr	%l0, PSR_ET, %psr
    201	WRITE_PAUSE
    202
    203	add	%sp, STACKFRAME_SZ, %o0	! pt_regs
    204	call	do_hw_interrupt
    205	 mov	%l7, %o1		! trap number
    206
    207	RESTORE_ALL
    208	
    209/* For now all IRQ's not registered get sent here. handler_irq() will
    210 * see if a routine is registered to handle this interrupt and if not
    211 * it will say so on the console.
    212 */
    213
    214	.align	4
    215	.globl	real_irq_entry, patch_handler_irq
    216real_irq_entry:
    217	SAVE_ALL
    218
    219#ifdef CONFIG_SMP
    220	.globl	patchme_maybe_smp_msg
    221
    222	cmp	%l7, 11
    223patchme_maybe_smp_msg:
    224	bgu	maybe_smp4m_msg
    225	 nop
    226#endif
    227
    228real_irq_continue:
    229	or	%l0, PSR_PIL, %g2
    230	wr	%g2, 0x0, %psr
    231	WRITE_PAUSE
    232	wr	%g2, PSR_ET, %psr
    233	WRITE_PAUSE
    234	mov	%l7, %o0		! irq level
    235patch_handler_irq:
    236	call	handler_irq
    237	 add	%sp, STACKFRAME_SZ, %o1	! pt_regs ptr
    238	or	%l0, PSR_PIL, %g2	! restore PIL after handler_irq
    239	wr	%g2, PSR_ET, %psr	! keep ET up
    240	WRITE_PAUSE
    241
    242	RESTORE_ALL
    243
    244#ifdef CONFIG_SMP
    245	/* SMP per-cpu ticker interrupts are handled specially. */
    246smp4m_ticker:
    247	bne	real_irq_continue+4
    248	 or	%l0, PSR_PIL, %g2
    249	wr	%g2, 0x0, %psr
    250	WRITE_PAUSE
    251	wr	%g2, PSR_ET, %psr
    252	WRITE_PAUSE
    253	call	smp4m_percpu_timer_interrupt
    254	 add	%sp, STACKFRAME_SZ, %o0
    255	wr	%l0, PSR_ET, %psr
    256	WRITE_PAUSE
    257	RESTORE_ALL
    258
    259#define GET_PROCESSOR4M_ID(reg)	\
    260	rd	%tbr, %reg;	\
    261	srl	%reg, 12, %reg;	\
    262	and	%reg, 3, %reg;
    263
    264	/* Here is where we check for possible SMP IPI passed to us
    265	 * on some level other than 15 which is the NMI and only used
    266	 * for cross calls.  That has a separate entry point below.
    267	 *
    268	 * IPIs are sent on Level 12, 13 and 14. See IRQ_IPI_*.
    269	 */
    270maybe_smp4m_msg:
    271	GET_PROCESSOR4M_ID(o3)
    272	sethi	%hi(sun4m_irq_percpu), %l5
    273	sll	%o3, 2, %o3
    274	or	%l5, %lo(sun4m_irq_percpu), %o5
    275	sethi	%hi(0x70000000), %o2	! Check all soft-IRQs
    276	ld	[%o5 + %o3], %o1
    277	ld	[%o1 + 0x00], %o3	! sun4m_irq_percpu[cpu]->pending
    278	andcc	%o3, %o2, %g0
    279	be,a	smp4m_ticker
    280	 cmp	%l7, 14
    281	/* Soft-IRQ IPI */
    282	st	%o2, [%o1 + 0x04]	! sun4m_irq_percpu[cpu]->clear=0x70000000
    283	WRITE_PAUSE
    284	ld	[%o1 + 0x00], %g0	! sun4m_irq_percpu[cpu]->pending
    285	WRITE_PAUSE
    286	or	%l0, PSR_PIL, %l4
    287	wr	%l4, 0x0, %psr
    288	WRITE_PAUSE
    289	wr	%l4, PSR_ET, %psr
    290	WRITE_PAUSE
    291	srl	%o3, 28, %o2		! shift for simpler checks below
    292maybe_smp4m_msg_check_single:
    293	andcc	%o2, 0x1, %g0
    294	beq,a	maybe_smp4m_msg_check_mask
    295	 andcc	%o2, 0x2, %g0
    296	call	smp_call_function_single_interrupt
    297	 nop
    298	andcc	%o2, 0x2, %g0
    299maybe_smp4m_msg_check_mask:
    300	beq,a	maybe_smp4m_msg_check_resched
    301	 andcc	%o2, 0x4, %g0
    302	call	smp_call_function_interrupt
    303	 nop
    304	andcc	%o2, 0x4, %g0
    305maybe_smp4m_msg_check_resched:
    306	/* rescheduling is done in RESTORE_ALL regardless, but incr stats */
    307	beq,a	maybe_smp4m_msg_out
    308	 nop
    309	call	smp_resched_interrupt
    310	 nop
    311maybe_smp4m_msg_out:
    312	RESTORE_ALL
    313
    314	.align	4
    315	.globl	linux_trap_ipi15_sun4m
    316linux_trap_ipi15_sun4m:
    317	SAVE_ALL
    318	sethi	%hi(0x80000000), %o2
    319	GET_PROCESSOR4M_ID(o0)
    320	sethi	%hi(sun4m_irq_percpu), %l5
    321	or	%l5, %lo(sun4m_irq_percpu), %o5
    322	sll	%o0, 2, %o0
    323	ld	[%o5 + %o0], %o5
    324	ld	[%o5 + 0x00], %o3	! sun4m_irq_percpu[cpu]->pending
    325	andcc	%o3, %o2, %g0
    326	be	sun4m_nmi_error		! Must be an NMI async memory error
    327	 st	%o2, [%o5 + 0x04]	! sun4m_irq_percpu[cpu]->clear=0x80000000
    328	WRITE_PAUSE
    329	ld	[%o5 + 0x00], %g0	! sun4m_irq_percpu[cpu]->pending
    330	WRITE_PAUSE
    331	or	%l0, PSR_PIL, %l4
    332	wr	%l4, 0x0, %psr
    333	WRITE_PAUSE
    334	wr	%l4, PSR_ET, %psr
    335	WRITE_PAUSE
    336	call	smp4m_cross_call_irq
    337	 nop
    338	b	ret_trap_lockless_ipi
    339	 clr	%l6
    340
    341	.globl	smp4d_ticker
    342	/* SMP per-cpu ticker interrupts are handled specially. */
    343smp4d_ticker:
    344	SAVE_ALL
    345	or	%l0, PSR_PIL, %g2
    346	sethi	%hi(CC_ICLR), %o0
    347	sethi	%hi(1 << 14), %o1
    348	or	%o0, %lo(CC_ICLR), %o0
    349	stha	%o1, [%o0] ASI_M_MXCC	/* Clear PIL 14 in MXCC's ICLR */
    350	wr	%g2, 0x0, %psr
    351	WRITE_PAUSE
    352	wr	%g2, PSR_ET, %psr
    353	WRITE_PAUSE
    354	call	smp4d_percpu_timer_interrupt
    355	 add	%sp, STACKFRAME_SZ, %o0
    356	wr	%l0, PSR_ET, %psr
    357	WRITE_PAUSE
    358	RESTORE_ALL
    359
    360	.align	4
    361	.globl	linux_trap_ipi15_sun4d
    362linux_trap_ipi15_sun4d:
    363	SAVE_ALL
    364	sethi	%hi(CC_BASE), %o4
    365	sethi	%hi(MXCC_ERR_ME|MXCC_ERR_PEW|MXCC_ERR_ASE|MXCC_ERR_PEE), %o2
    366	or	%o4, (CC_EREG - CC_BASE), %o0
    367	ldda	[%o0] ASI_M_MXCC, %o0
    368	andcc	%o0, %o2, %g0
    369	bne	1f
    370	 sethi	%hi(BB_STAT2), %o2
    371	lduba	[%o2] ASI_M_CTL, %o2
    372	andcc	%o2, BB_STAT2_MASK, %g0
    373	bne	2f
    374	 or	%o4, (CC_ICLR - CC_BASE), %o0
    375	sethi	%hi(1 << 15), %o1
    376	stha	%o1, [%o0] ASI_M_MXCC	/* Clear PIL 15 in MXCC's ICLR */
    377	or	%l0, PSR_PIL, %l4
    378	wr	%l4, 0x0, %psr
    379	WRITE_PAUSE
    380	wr	%l4, PSR_ET, %psr
    381	WRITE_PAUSE
    382	call	smp4d_cross_call_irq
    383	 nop
    384	b	ret_trap_lockless_ipi
    385	 clr	%l6
    386
    3871:	/* MXCC error */
    3882:	/* BB error */
    389	/* Disable PIL 15 */
    390	set	CC_IMSK, %l4
    391	lduha	[%l4] ASI_M_MXCC, %l5
    392	sethi	%hi(1 << 15), %l7
    393	or	%l5, %l7, %l5
    394	stha	%l5, [%l4] ASI_M_MXCC
    395	/* FIXME */
    3961:	b,a	1b
    397
    398	.globl	smpleon_ipi
    399	.extern leon_ipi_interrupt
    400	/* SMP per-cpu IPI interrupts are handled specially. */
    401smpleon_ipi:
    402        SAVE_ALL
    403	or	%l0, PSR_PIL, %g2
    404	wr	%g2, 0x0, %psr
    405	WRITE_PAUSE
    406	wr	%g2, PSR_ET, %psr
    407	WRITE_PAUSE
    408	call	leonsmp_ipi_interrupt
    409	 add	%sp, STACKFRAME_SZ, %o1 ! pt_regs
    410	wr	%l0, PSR_ET, %psr
    411	WRITE_PAUSE
    412	RESTORE_ALL
    413
    414	.align	4
    415	.globl	linux_trap_ipi15_leon
    416linux_trap_ipi15_leon:
    417	SAVE_ALL
    418	or	%l0, PSR_PIL, %l4
    419	wr	%l4, 0x0, %psr
    420	WRITE_PAUSE
    421	wr	%l4, PSR_ET, %psr
    422	WRITE_PAUSE
    423	call	leon_cross_call_irq
    424	 nop
    425	b	ret_trap_lockless_ipi
    426	 clr	%l6
    427
    428#endif /* CONFIG_SMP */
    429
    430	/* This routine handles illegal instructions and privileged
    431	 * instruction attempts from user code.
    432	 */
    433	.align	4
    434	.globl	bad_instruction
    435bad_instruction:
    436	sethi	%hi(0xc1f80000), %l4
    437	ld	[%l1], %l5
    438	sethi	%hi(0x81d80000), %l7
    439	and	%l5, %l4, %l5
    440	cmp	%l5, %l7
    441	be	1f
    442	SAVE_ALL
    443
    444	wr	%l0, PSR_ET, %psr		! re-enable traps
    445	WRITE_PAUSE
    446
    447	add	%sp, STACKFRAME_SZ, %o0
    448	mov	%l1, %o1
    449	mov	%l2, %o2
    450	call	do_illegal_instruction
    451	 mov	%l0, %o3
    452
    453	RESTORE_ALL
    454
    4551:	/* unimplemented flush - just skip */
    456	jmpl	%l2, %g0
    457	 rett	%l2 + 4
    458
    459	.align	4
    460	.globl	priv_instruction
    461priv_instruction:
    462	SAVE_ALL
    463
    464	wr	%l0, PSR_ET, %psr
    465	WRITE_PAUSE
    466
    467	add	%sp, STACKFRAME_SZ, %o0
    468	mov	%l1, %o1
    469	mov	%l2, %o2
    470	call	do_priv_instruction
    471	 mov	%l0, %o3
    472
    473	RESTORE_ALL
    474
    475	/* This routine handles unaligned data accesses. */
    476	.align	4
    477	.globl	mna_handler
    478mna_handler:
    479	andcc	%l0, PSR_PS, %g0
    480	be	mna_fromuser
    481	 nop
    482
    483	SAVE_ALL
    484
    485	wr	%l0, PSR_ET, %psr
    486	WRITE_PAUSE
    487
    488	ld	[%l1], %o1
    489	call	kernel_unaligned_trap
    490	 add	%sp, STACKFRAME_SZ, %o0
    491
    492	RESTORE_ALL
    493
    494mna_fromuser:
    495	SAVE_ALL
    496
    497	wr	%l0, PSR_ET, %psr		! re-enable traps
    498	WRITE_PAUSE
    499
    500	ld	[%l1], %o1
    501	call	user_unaligned_trap
    502	 add	%sp, STACKFRAME_SZ, %o0
    503
    504	RESTORE_ALL
    505
    506	/* This routine handles floating point disabled traps. */
    507	.align	4
    508	.globl	fpd_trap_handler
    509fpd_trap_handler:
    510	SAVE_ALL
    511
    512	wr	%l0, PSR_ET, %psr		! re-enable traps
    513	WRITE_PAUSE
    514
    515	add	%sp, STACKFRAME_SZ, %o0
    516	mov	%l1, %o1
    517	mov	%l2, %o2
    518	call	do_fpd_trap
    519	 mov	%l0, %o3
    520
    521	RESTORE_ALL
    522
    523	/* This routine handles Floating Point Exceptions. */
    524	.align	4
    525	.globl	fpe_trap_handler
    526fpe_trap_handler:
    527	set	fpsave_magic, %l5
    528	cmp	%l1, %l5
    529	be	1f
    530	 sethi	%hi(fpsave), %l5
    531	or	%l5, %lo(fpsave), %l5
    532	cmp	%l1, %l5
    533	bne	2f
    534	 sethi	%hi(fpsave_catch2), %l5
    535	or	%l5, %lo(fpsave_catch2), %l5
    536	wr	%l0, 0x0, %psr
    537	WRITE_PAUSE
    538	jmp	%l5
    539	 rett	%l5 + 4
    5401:	
    541	sethi	%hi(fpsave_catch), %l5
    542	or	%l5, %lo(fpsave_catch), %l5
    543	wr	%l0, 0x0, %psr
    544	WRITE_PAUSE
    545	jmp	%l5
    546	 rett	%l5 + 4
    547
    5482:
    549	SAVE_ALL
    550
    551	wr	%l0, PSR_ET, %psr		! re-enable traps
    552	WRITE_PAUSE
    553
    554	add	%sp, STACKFRAME_SZ, %o0
    555	mov	%l1, %o1
    556	mov	%l2, %o2
    557	call	do_fpe_trap
    558	 mov	%l0, %o3
    559
    560	RESTORE_ALL
    561
    562	/* This routine handles Tag Overflow Exceptions. */
    563	.align	4
    564	.globl	do_tag_overflow
    565do_tag_overflow:
    566	SAVE_ALL
    567
    568	wr	%l0, PSR_ET, %psr		! re-enable traps
    569	WRITE_PAUSE
    570
    571	add	%sp, STACKFRAME_SZ, %o0
    572	mov	%l1, %o1
    573	mov	%l2, %o2
    574	call	handle_tag_overflow
    575	 mov	%l0, %o3
    576
    577	RESTORE_ALL
    578
    579	/* This routine handles Watchpoint Exceptions. */
    580	.align	4
    581	.globl	do_watchpoint
    582do_watchpoint:
    583	SAVE_ALL
    584
    585	wr	%l0, PSR_ET, %psr		! re-enable traps
    586	WRITE_PAUSE
    587
    588	add	%sp, STACKFRAME_SZ, %o0
    589	mov	%l1, %o1
    590	mov	%l2, %o2
    591	call	handle_watchpoint
    592	 mov	%l0, %o3
    593
    594	RESTORE_ALL
    595
    596	/* This routine handles Register Access Exceptions. */
    597	.align	4
    598	.globl	do_reg_access
    599do_reg_access:
    600	SAVE_ALL
    601
    602	wr	%l0, PSR_ET, %psr		! re-enable traps
    603	WRITE_PAUSE
    604
    605	add	%sp, STACKFRAME_SZ, %o0
    606	mov	%l1, %o1
    607	mov	%l2, %o2
    608	call	handle_reg_access
    609	 mov	%l0, %o3
    610
    611	RESTORE_ALL
    612
    613	/* This routine handles Co-Processor Disabled Exceptions. */
    614	.align	4
    615	.globl	do_cp_disabled
    616do_cp_disabled:
    617	SAVE_ALL
    618
    619	wr	%l0, PSR_ET, %psr		! re-enable traps
    620	WRITE_PAUSE
    621
    622	add	%sp, STACKFRAME_SZ, %o0
    623	mov	%l1, %o1
    624	mov	%l2, %o2
    625	call	handle_cp_disabled
    626	 mov	%l0, %o3
    627
    628	RESTORE_ALL
    629
    630	/* This routine handles Co-Processor Exceptions. */
    631	.align	4
    632	.globl	do_cp_exception
    633do_cp_exception:
    634	SAVE_ALL
    635
    636	wr	%l0, PSR_ET, %psr		! re-enable traps
    637	WRITE_PAUSE
    638
    639	add	%sp, STACKFRAME_SZ, %o0
    640	mov	%l1, %o1
    641	mov	%l2, %o2
    642	call	handle_cp_exception
    643	 mov	%l0, %o3
    644
    645	RESTORE_ALL
    646
    647	/* This routine handles Hardware Divide By Zero Exceptions. */
    648	.align	4
    649	.globl	do_hw_divzero
    650do_hw_divzero:
    651	SAVE_ALL
    652
    653	wr	%l0, PSR_ET, %psr		! re-enable traps
    654	WRITE_PAUSE
    655
    656	add	%sp, STACKFRAME_SZ, %o0
    657	mov	%l1, %o1
    658	mov	%l2, %o2
    659	call	handle_hw_divzero
    660	 mov	%l0, %o3
    661
    662	RESTORE_ALL
    663
    664	.align	4
    665	.globl	do_flush_windows
    666do_flush_windows:
    667	SAVE_ALL
    668
    669	wr	%l0, PSR_ET, %psr
    670	WRITE_PAUSE
    671
    672	andcc	%l0, PSR_PS, %g0
    673	bne	dfw_kernel
    674	 nop
    675
    676	call	flush_user_windows
    677	 nop
    678
    679	/* Advance over the trap instruction. */
    680	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1
    681	add	%l1, 0x4, %l2
    682	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
    683	st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
    684
    685	RESTORE_ALL
    686
    687	.globl	flush_patch_one
    688
    689	/* We get these for debugging routines using __builtin_return_address() */
    690dfw_kernel:
    691flush_patch_one:
    692	FLUSH_ALL_KERNEL_WINDOWS
    693
    694	/* Advance over the trap instruction. */
    695	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1
    696	add	%l1, 0x4, %l2
    697	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
    698	st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
    699
    700	RESTORE_ALL
    701
    702	/* The getcc software trap.  The user wants the condition codes from
    703	 * the %psr in register %g1.
    704	 */
    705
    706	.align	4
    707	.globl	getcc_trap_handler
    708getcc_trap_handler:
    709	srl	%l0, 20, %g1	! give user
    710	and	%g1, 0xf, %g1	! only ICC bits in %psr
    711	jmp	%l2		! advance over trap instruction
    712	rett	%l2 + 0x4	! like this...
    713
    714	/* The setcc software trap.  The user has condition codes in %g1
    715	 * that it would like placed in the %psr.  Be careful not to flip
    716	 * any unintentional bits!
    717	 */
    718
    719	.align	4
    720	.globl	setcc_trap_handler
    721setcc_trap_handler:
    722	sll	%g1, 0x14, %l4
    723	set	PSR_ICC, %l5
    724	andn	%l0, %l5, %l0	! clear ICC bits in %psr
    725	and	%l4, %l5, %l4	! clear non-ICC bits in user value
    726	or	%l4, %l0, %l4	! or them in... mix mix mix
    727
    728	wr	%l4, 0x0, %psr	! set new %psr
    729	WRITE_PAUSE		! TI scumbags...
    730
    731	jmp	%l2		! advance over trap instruction
    732	rett	%l2 + 0x4	! like this...
    733
    734sun4m_nmi_error:
    735	/* NMI async memory error handling. */
    736	sethi	%hi(0x80000000), %l4
    737	sethi	%hi(sun4m_irq_global), %o5
    738	ld	[%o5 + %lo(sun4m_irq_global)], %l5
    739	st	%l4, [%l5 + 0x0c]	! sun4m_irq_global->mask_set=0x80000000
    740	WRITE_PAUSE
    741	ld	[%l5 + 0x00], %g0	! sun4m_irq_global->pending
    742	WRITE_PAUSE
    743	or	%l0, PSR_PIL, %l4
    744	wr	%l4, 0x0, %psr
    745	WRITE_PAUSE
    746	wr	%l4, PSR_ET, %psr
    747	WRITE_PAUSE
    748	call	sun4m_nmi
    749	 nop
    750	st	%l4, [%l5 + 0x08]	! sun4m_irq_global->mask_clear=0x80000000
    751	WRITE_PAUSE
    752	ld	[%l5 + 0x00], %g0	! sun4m_irq_global->pending
    753	WRITE_PAUSE
    754	RESTORE_ALL
    755
    756#ifndef CONFIG_SMP
    757	.align	4
    758	.globl	linux_trap_ipi15_sun4m
    759linux_trap_ipi15_sun4m:
    760	SAVE_ALL
    761
    762	ba	sun4m_nmi_error
    763	 nop
    764#endif /* CONFIG_SMP */
    765
    766	.align	4
    767	.globl	srmmu_fault
    768srmmu_fault:
    769	mov	0x400, %l5
    770	mov	0x300, %l4
    771
    772LEON_PI(lda	[%l5] ASI_LEON_MMUREGS, %l6)	! read sfar first
    773SUN_PI_(lda	[%l5] ASI_M_MMUREGS, %l6)	! read sfar first
    774
    775LEON_PI(lda	[%l4] ASI_LEON_MMUREGS, %l5)	! read sfsr last
    776SUN_PI_(lda	[%l4] ASI_M_MMUREGS, %l5)	! read sfsr last
    777
    778	andn	%l6, 0xfff, %l6
    779	srl	%l5, 6, %l5			! and encode all info into l7
    780
    781	and	%l5, 2, %l5
    782	or	%l5, %l6, %l6
    783
    784	or	%l6, %l7, %l7			! l7 = [addr,write,txtfault]
    785
    786	SAVE_ALL
    787
    788	mov	%l7, %o1
    789	mov	%l7, %o2
    790	and	%o1, 1, %o1		! arg2 = text_faultp
    791	mov	%l7, %o3
    792	and	%o2, 2, %o2		! arg3 = writep
    793	andn	%o3, 0xfff, %o3		! arg4 = faulting address
    794
    795	wr	%l0, PSR_ET, %psr
    796	WRITE_PAUSE
    797
    798	call	do_sparc_fault
    799	 add	%sp, STACKFRAME_SZ, %o0	! arg1 = pt_regs ptr
    800
    801	RESTORE_ALL
    802
    803	.align	4
    804sunos_execv:
    805	.globl	sunos_execv
    806	b	sys_execve
    807	 clr	%i2
    808
    809	.align	4
    810	.globl	sys_sigstack
    811sys_sigstack:
    812	mov	%o7, %l5
    813	mov	%fp, %o2
    814	call	do_sys_sigstack
    815	 mov	%l5, %o7
    816
    817	.align	4
    818	.globl	sys_sigreturn
    819sys_sigreturn:
    820	call	do_sigreturn
    821	 add	%sp, STACKFRAME_SZ, %o0
    822
    823	ld	[%curptr + TI_FLAGS], %l5
    824	andcc	%l5, _TIF_SYSCALL_TRACE, %g0
    825	be	1f
    826	 nop
    827
    828	call	syscall_trace
    829	 mov	1, %o1
    830
    8311:
    832	/* We don't want to muck with user registers like a
    833	 * normal syscall, just return.
    834	 */
    835	RESTORE_ALL
    836
    837	.align	4
    838	.globl	sys_rt_sigreturn
    839sys_rt_sigreturn:
    840	call	do_rt_sigreturn
    841	 add	%sp, STACKFRAME_SZ, %o0
    842
    843	ld	[%curptr + TI_FLAGS], %l5
    844	andcc	%l5, _TIF_SYSCALL_TRACE, %g0
    845	be	1f
    846	 nop
    847
    848	add	%sp, STACKFRAME_SZ, %o0
    849	call	syscall_trace
    850	 mov	1, %o1
    851
    8521:
    853	/* We are returning to a signal handler. */
    854	RESTORE_ALL
    855
    856	/* Now that we have a real sys_clone, sys_fork() is
    857	 * implemented in terms of it.  Our _real_ implementation
    858	 * of SunOS vfork() will use sys_vfork().
    859	 *
    860	 * XXX These three should be consolidated into mostly shared
    861	 * XXX code just like on sparc64... -DaveM
    862	 */
    863	.align	4
    864	.globl	sys_fork, flush_patch_two
    865sys_fork:
    866	mov	%o7, %l5
    867flush_patch_two:
    868	FLUSH_ALL_KERNEL_WINDOWS;
    869	ld	[%curptr + TI_TASK], %o4
    870	rd	%psr, %g4
    871	WRITE_PAUSE
    872	rd	%wim, %g5
    873	WRITE_PAUSE
    874	std	%g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
    875	add	%sp, STACKFRAME_SZ, %o0
    876	call	sparc_fork
    877	 mov	%l5, %o7
    878
    879	/* Whee, kernel threads! */
    880	.globl	sys_clone, flush_patch_three
    881sys_clone:
    882	mov	%o7, %l5
    883flush_patch_three:
    884	FLUSH_ALL_KERNEL_WINDOWS;
    885	ld	[%curptr + TI_TASK], %o4
    886	rd	%psr, %g4
    887	WRITE_PAUSE
    888	rd	%wim, %g5
    889	WRITE_PAUSE
    890	std	%g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
    891	add	%sp, STACKFRAME_SZ, %o0
    892	call	sparc_clone
    893	 mov	%l5, %o7
    894
    895	/* Whee, real vfork! */
    896	.globl	sys_vfork, flush_patch_four
    897sys_vfork:
    898flush_patch_four:
    899	FLUSH_ALL_KERNEL_WINDOWS;
    900	ld	[%curptr + TI_TASK], %o4
    901	rd	%psr, %g4
    902	WRITE_PAUSE
    903	rd	%wim, %g5
    904	WRITE_PAUSE
    905	std	%g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
    906	sethi	%hi(sparc_vfork), %l1
    907	jmpl	%l1 + %lo(sparc_vfork), %g0
    908	 add	%sp, STACKFRAME_SZ, %o0
    909
    910        .align  4
    911linux_sparc_ni_syscall:
    912	sethi   %hi(sys_ni_syscall), %l7
    913	b       do_syscall
    914	 or     %l7, %lo(sys_ni_syscall), %l7
    915
    916linux_syscall_trace:
    917	add	%sp, STACKFRAME_SZ, %o0
    918	call	syscall_trace
    919	 mov	0, %o1
    920	cmp	%o0, 0
    921	bne	3f
    922	 mov	-ENOSYS, %o0
    923
    924	/* Syscall tracing can modify the registers.  */
    925	ld	[%sp + STACKFRAME_SZ + PT_G1], %g1
    926	sethi	%hi(sys_call_table), %l7
    927	ld	[%sp + STACKFRAME_SZ + PT_I0], %i0
    928	or	%l7, %lo(sys_call_table), %l7
    929	ld	[%sp + STACKFRAME_SZ + PT_I1], %i1
    930	ld	[%sp + STACKFRAME_SZ + PT_I2], %i2
    931	ld	[%sp + STACKFRAME_SZ + PT_I3], %i3
    932	ld	[%sp + STACKFRAME_SZ + PT_I4], %i4
    933	ld	[%sp + STACKFRAME_SZ + PT_I5], %i5
    934	cmp	%g1, NR_syscalls
    935	bgeu	3f
    936	 mov	-ENOSYS, %o0
    937
    938	sll	%g1, 2, %l4
    939	mov	%i0, %o0
    940	ld	[%l7 + %l4], %l7
    941	mov	%i1, %o1
    942	mov	%i2, %o2
    943	mov	%i3, %o3
    944	b	2f
    945	 mov	%i4, %o4
    946
    947	.globl	ret_from_fork
    948ret_from_fork:
    949	call	schedule_tail
    950	 ld	[%g3 + TI_TASK], %o0
    951	b	ret_sys_call
    952	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
    953
    954	.globl	ret_from_kernel_thread
    955ret_from_kernel_thread:
    956	call	schedule_tail
    957	 ld	[%g3 + TI_TASK], %o0
    958	ld	[%sp + STACKFRAME_SZ + PT_G1], %l0
    959	call	%l0
    960	 ld	[%sp + STACKFRAME_SZ + PT_G2], %o0
    961	rd	%psr, %l1
    962	ld	[%sp + STACKFRAME_SZ + PT_PSR], %l0
    963	andn	%l0, PSR_CWP, %l0
    964	nop
    965	and	%l1, PSR_CWP, %l1
    966	or	%l0, %l1, %l0
    967	st	%l0, [%sp + STACKFRAME_SZ + PT_PSR]
    968	b	ret_sys_call
    969	 mov	0, %o0
    970
    971	/* Linux native system calls enter here... */
    972	.align	4
    973	.globl	linux_sparc_syscall
    974linux_sparc_syscall:
    975	sethi	%hi(PSR_SYSCALL), %l4
    976	or	%l0, %l4, %l0
    977	/* Direct access to user regs, must faster. */
    978	cmp	%g1, NR_syscalls
    979	bgeu	linux_sparc_ni_syscall
    980	 sll	%g1, 2, %l4
    981	ld	[%l7 + %l4], %l7
    982
    983do_syscall:
    984	SAVE_ALL_HEAD
    985	 rd	%wim, %l3
    986
    987	wr	%l0, PSR_ET, %psr
    988	mov	%i0, %o0
    989	mov	%i1, %o1
    990	mov	%i2, %o2
    991
    992	ld	[%curptr + TI_FLAGS], %l5
    993	mov	%i3, %o3
    994	andcc	%l5, _TIF_SYSCALL_TRACE, %g0
    995	mov	%i4, %o4
    996	bne	linux_syscall_trace
    997	 mov	%i0, %l6
    9982:
    999	call	%l7
   1000	 mov	%i5, %o5
   1001
   10023:
   1003	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
   1004
   1005ret_sys_call:
   1006	ld	[%curptr + TI_FLAGS], %l5
   1007	cmp	%o0, -ERESTART_RESTARTBLOCK
   1008	ld	[%sp + STACKFRAME_SZ + PT_PSR], %g3
   1009	set	PSR_C, %g2
   1010	bgeu	1f
   1011	 andcc	%l5, _TIF_SYSCALL_TRACE, %g0
   1012
   1013	/* System call success, clear Carry condition code. */
   1014	andn	%g3, %g2, %g3
   1015	st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]	
   1016	bne	linux_syscall_trace2
   1017	 ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */
   1018	add	%l1, 0x4, %l2			/* npc = npc+4 */
   1019	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
   1020	b	ret_trap_entry
   1021	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
   10221:
   1023	/* System call failure, set Carry condition code.
   1024	 * Also, get abs(errno) to return to the process.
   1025	 */
   1026	sub	%g0, %o0, %o0
   1027	or	%g3, %g2, %g3
   1028	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
   1029	st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]
   1030	bne	linux_syscall_trace2
   1031	 ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */
   1032	add	%l1, 0x4, %l2			/* npc = npc+4 */
   1033	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
   1034	b	ret_trap_entry
   1035	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
   1036
   1037linux_syscall_trace2:
   1038	add	%sp, STACKFRAME_SZ, %o0
   1039	mov	1, %o1
   1040	call	syscall_trace
   1041	 add	%l1, 0x4, %l2			/* npc = npc+4 */
   1042	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
   1043	b	ret_trap_entry
   1044	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
   1045
   1046
   1047/* Saving and restoring the FPU state is best done from lowlevel code.
   1048 *
   1049 * void fpsave(unsigned long *fpregs, unsigned long *fsr,
   1050 *             void *fpqueue, unsigned long *fpqdepth)
   1051 */
   1052
   1053	.globl	fpsave
   1054fpsave:
   1055	st	%fsr, [%o1]	! this can trap on us if fpu is in bogon state
   1056	ld	[%o1], %g1
   1057	set	0x2000, %g4
   1058	andcc	%g1, %g4, %g0
   1059	be	2f
   1060	 mov	0, %g2
   1061
   1062	/* We have an fpqueue to save. */
   10631:
   1064	std	%fq, [%o2]
   1065fpsave_magic:
   1066	st	%fsr, [%o1]
   1067	ld	[%o1], %g3
   1068	andcc	%g3, %g4, %g0
   1069	add	%g2, 1, %g2
   1070	bne	1b
   1071	 add	%o2, 8, %o2
   1072
   10732:
   1074	st	%g2, [%o3]
   1075
   1076	std	%f0, [%o0 + 0x00]
   1077	std	%f2, [%o0 + 0x08]
   1078	std	%f4, [%o0 + 0x10]
   1079	std	%f6, [%o0 + 0x18]
   1080	std	%f8, [%o0 + 0x20]
   1081	std	%f10, [%o0 + 0x28]
   1082	std	%f12, [%o0 + 0x30]
   1083	std	%f14, [%o0 + 0x38]
   1084	std	%f16, [%o0 + 0x40]
   1085	std	%f18, [%o0 + 0x48]
   1086	std	%f20, [%o0 + 0x50]
   1087	std	%f22, [%o0 + 0x58]
   1088	std	%f24, [%o0 + 0x60]
   1089	std	%f26, [%o0 + 0x68]
   1090	std	%f28, [%o0 + 0x70]
   1091	retl
   1092	 std	%f30, [%o0 + 0x78]
   1093
   1094	/* Thanks for Theo Deraadt and the authors of the Sprite/netbsd/openbsd
   1095	 * code for pointing out this possible deadlock, while we save state
   1096	 * above we could trap on the fsr store so our low level fpu trap
   1097	 * code has to know how to deal with this.
   1098	 */
   1099fpsave_catch:
   1100	b	fpsave_magic + 4
   1101	 st	%fsr, [%o1]
   1102
   1103fpsave_catch2:
   1104	b	fpsave + 4
   1105	 st	%fsr, [%o1]
   1106
   1107	/* void fpload(unsigned long *fpregs, unsigned long *fsr); */
   1108
   1109	.globl	fpload
   1110fpload:
   1111	ldd	[%o0 + 0x00], %f0
   1112	ldd	[%o0 + 0x08], %f2
   1113	ldd	[%o0 + 0x10], %f4
   1114	ldd	[%o0 + 0x18], %f6
   1115	ldd	[%o0 + 0x20], %f8
   1116	ldd	[%o0 + 0x28], %f10
   1117	ldd	[%o0 + 0x30], %f12
   1118	ldd	[%o0 + 0x38], %f14
   1119	ldd	[%o0 + 0x40], %f16
   1120	ldd	[%o0 + 0x48], %f18
   1121	ldd	[%o0 + 0x50], %f20
   1122	ldd	[%o0 + 0x58], %f22
   1123	ldd	[%o0 + 0x60], %f24
   1124	ldd	[%o0 + 0x68], %f26
   1125	ldd	[%o0 + 0x70], %f28
   1126	ldd	[%o0 + 0x78], %f30
   1127	ld	[%o1], %fsr
   1128	retl
   1129	 nop
   1130
   1131	/* __ndelay and __udelay take two arguments:
   1132	 * 0 - nsecs or usecs to delay
   1133	 * 1 - per_cpu udelay_val (loops per jiffy)
   1134	 *
   1135	 * Note that ndelay gives HZ times higher resolution but has a 10ms
   1136	 * limit.  udelay can handle up to 1s.
   1137	 */
   1138	.globl	__ndelay
   1139__ndelay:
   1140	save	%sp, -STACKFRAME_SZ, %sp
   1141	mov	%i0, %o0		! round multiplier up so large ns ok
   1142	mov	0x1ae, %o1		! 2**32 / (1 000 000 000 / HZ)
   1143	umul	%o0, %o1, %o0
   1144	rd	%y, %o1
   1145	mov	%i1, %o1		! udelay_val
   1146	umul	%o0, %o1, %o0
   1147	rd	%y, %o1
   1148	ba	delay_continue
   1149	 mov	%o1, %o0		! >>32 later for better resolution
   1150
   1151	.globl	__udelay
   1152__udelay:
   1153	save	%sp, -STACKFRAME_SZ, %sp
   1154	mov	%i0, %o0
   1155	sethi	%hi(0x10c7), %o1	! round multiplier up so large us ok
   1156	or	%o1, %lo(0x10c7), %o1	! 2**32 / 1 000 000
   1157	umul	%o0, %o1, %o0
   1158	rd	%y, %o1
   1159	mov	%i1, %o1		! udelay_val
   1160	umul	%o0, %o1, %o0
   1161	rd	%y, %o1
   1162	sethi	%hi(0x028f4b62), %l0	! Add in rounding constant * 2**32,
   1163	or	%g0, %lo(0x028f4b62), %l0
   1164	addcc	%o0, %l0, %o0		! 2**32 * 0.009 999
   1165	bcs,a	3f
   1166	 add	%o1, 0x01, %o1
   11673:
   1168	mov	HZ, %o0			! >>32 earlier for wider range
   1169	umul	%o0, %o1, %o0
   1170	rd	%y, %o1
   1171
   1172delay_continue:
   1173	cmp	%o0, 0x0
   11741:
   1175	bne	1b
   1176	 subcc	%o0, 1, %o0
   1177	
   1178	ret
   1179	restore
   1180EXPORT_SYMBOL(__udelay)
   1181EXPORT_SYMBOL(__ndelay)
   1182
   1183	/* Handle a software breakpoint */
   1184	/* We have to inform parent that child has stopped */
   1185	.align 4
   1186	.globl breakpoint_trap
   1187breakpoint_trap:
   1188	rd	%wim,%l3
   1189	SAVE_ALL
   1190	wr 	%l0, PSR_ET, %psr
   1191	WRITE_PAUSE
   1192
   1193	st	%i0, [%sp + STACKFRAME_SZ + PT_G0] ! for restarting syscalls
   1194	call	sparc_breakpoint
   1195	 add	%sp, STACKFRAME_SZ, %o0
   1196
   1197	RESTORE_ALL
   1198
   1199#ifdef CONFIG_KGDB
   1200	ENTRY(kgdb_trap_low)
   1201	rd	%wim,%l3
   1202	SAVE_ALL
   1203	wr 	%l0, PSR_ET, %psr
   1204	WRITE_PAUSE
   1205
   1206	mov	%l7, %o0		! trap_level
   1207	call	kgdb_trap
   1208	 add	%sp, STACKFRAME_SZ, %o1	! struct pt_regs *regs
   1209
   1210	RESTORE_ALL
   1211	ENDPROC(kgdb_trap_low)
   1212#endif
   1213
   1214	.align	4
   1215	.globl	flush_patch_exception
   1216flush_patch_exception:
   1217	FLUSH_ALL_KERNEL_WINDOWS;
   1218	ldd	[%o0], %o6
   1219	jmpl	%o7 + 0xc, %g0			! see asm-sparc/processor.h
   1220	 mov	1, %g1				! signal EFAULT condition
   1221
   1222	.align	4
   1223	.globl	kill_user_windows, kuw_patch1_7win
   1224	.globl	kuw_patch1
   1225kuw_patch1_7win:	sll	%o3, 6, %o3
   1226
   1227	/* No matter how much overhead this routine has in the worst
   1228	 * case scenario, it is several times better than taking the
   1229	 * traps with the old method of just doing flush_user_windows().
   1230	 */
   1231kill_user_windows:
   1232	ld	[%g6 + TI_UWINMASK], %o0	! get current umask
   1233	orcc	%g0, %o0, %g0			! if no bits set, we are done
   1234	be	3f				! nothing to do
   1235	 rd	%psr, %o5			! must clear interrupts
   1236	or	%o5, PSR_PIL, %o4		! or else that could change
   1237	wr	%o4, 0x0, %psr			! the uwinmask state
   1238	WRITE_PAUSE				! burn them cycles
   12391:
   1240	ld	[%g6 + TI_UWINMASK], %o0	! get consistent state
   1241	orcc	%g0, %o0, %g0			! did an interrupt come in?
   1242	be	4f				! yep, we are done
   1243	 rd	%wim, %o3			! get current wim
   1244	srl	%o3, 1, %o4			! simulate a save
   1245kuw_patch1:
   1246	sll	%o3, 7, %o3			! compute next wim
   1247	or	%o4, %o3, %o3			! result
   1248	andncc	%o0, %o3, %o0			! clean this bit in umask
   1249	bne	kuw_patch1			! not done yet
   1250	 srl	%o3, 1, %o4			! begin another save simulation
   1251	wr	%o3, 0x0, %wim			! set the new wim
   1252	st	%g0, [%g6 + TI_UWINMASK]	! clear uwinmask
   12534:
   1254	wr	%o5, 0x0, %psr			! re-enable interrupts
   1255	WRITE_PAUSE				! burn baby burn
   12563:
   1257	retl					! return
   1258	 st	%g0, [%g6 + TI_W_SAVED]		! no windows saved
   1259
   1260	.align	4
   1261	.globl	restore_current
   1262restore_current:
   1263	LOAD_CURRENT(g6, o0)
   1264	retl
   1265	 nop
   1266
   1267#ifdef CONFIG_PCIC_PCI
   1268#include <asm/pcic.h>
   1269
   1270	.align	4
   1271	.globl	linux_trap_ipi15_pcic
   1272linux_trap_ipi15_pcic:
   1273	rd	%wim, %l3
   1274	SAVE_ALL
   1275
   1276	/*
   1277	 * First deactivate NMI
   1278	 * or we cannot drop ET, cannot get window spill traps.
   1279	 * The busy loop is necessary because the PIO error
   1280	 * sometimes does not go away quickly and we trap again.
   1281	 */
   1282	sethi	%hi(pcic_regs), %o1
   1283	ld	[%o1 + %lo(pcic_regs)], %o2
   1284
   1285	! Get pending status for printouts later.
   1286	ld	[%o2 + PCI_SYS_INT_PENDING], %o0
   1287
   1288	mov	PCI_SYS_INT_PENDING_CLEAR_ALL, %o1
   1289	stb	%o1, [%o2 + PCI_SYS_INT_PENDING_CLEAR]
   12901:
   1291	ld	[%o2 + PCI_SYS_INT_PENDING], %o1
   1292	andcc	%o1, ((PCI_SYS_INT_PENDING_PIO|PCI_SYS_INT_PENDING_PCI)>>24), %g0
   1293	bne	1b
   1294	 nop
   1295
   1296	or	%l0, PSR_PIL, %l4
   1297	wr	%l4, 0x0, %psr
   1298	WRITE_PAUSE
   1299	wr	%l4, PSR_ET, %psr
   1300	WRITE_PAUSE
   1301
   1302	call	pcic_nmi
   1303	 add	%sp, STACKFRAME_SZ, %o1	! struct pt_regs *regs
   1304	RESTORE_ALL
   1305
   1306	.globl	pcic_nmi_trap_patch
   1307pcic_nmi_trap_patch:
   1308	sethi	%hi(linux_trap_ipi15_pcic), %l3
   1309	jmpl	%l3 + %lo(linux_trap_ipi15_pcic), %g0
   1310	 rd	%psr, %l0
   1311	.word	0
   1312
   1313#endif /* CONFIG_PCIC_PCI */
   1314
   1315	.globl	flushw_all
   1316flushw_all:
   1317	save	%sp, -0x40, %sp
   1318	save	%sp, -0x40, %sp
   1319	save	%sp, -0x40, %sp
   1320	save	%sp, -0x40, %sp
   1321	save	%sp, -0x40, %sp
   1322	save	%sp, -0x40, %sp
   1323	save	%sp, -0x40, %sp
   1324	restore
   1325	restore
   1326	restore
   1327	restore
   1328	restore
   1329	restore
   1330	ret
   1331	 restore
   1332
   1333#ifdef CONFIG_SMP
   1334ENTRY(hard_smp_processor_id)
   1335661:	rd		%tbr, %g1
   1336	srl		%g1, 12, %o0
   1337	and		%o0, 3, %o0
   1338	.section	.cpuid_patch, "ax"
   1339	/* Instruction location. */
   1340	.word		661b
   1341	/* SUN4D implementation. */
   1342	lda		[%g0] ASI_M_VIKING_TMP1, %o0
   1343	nop
   1344	nop
   1345	/* LEON implementation. */
   1346	rd		%asr17, %o0
   1347	srl		%o0, 0x1c, %o0
   1348	nop
   1349	.previous
   1350	retl
   1351	 nop
   1352ENDPROC(hard_smp_processor_id)
   1353#endif
   1354
   1355/* End of entry.S */