1 /* SPDX-License-Identifier: GPL-2.0 */ !! 1 /* $Id: entry.S,v 1.170 2001/11/13 00:57:05 davem Exp $ 2 /* !! 2 * arch/sparc/kernel/entry.S: Sparc trap low-level entry points. 3 * S390 low-level entry points. << 4 * 3 * 5 * Copyright IBM Corp. 1999, 2012 !! 4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 6 * Author(s): Martin Schwidefsky (schwidefs !! 5 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) 7 * Hartmut Penner (hp@de.ibm.com !! 6 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) 8 * Denis Joseph Barrow (djbarrow !! 7 * Copyright (C) 1996-1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz) >> 8 * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) 9 */ 9 */ 10 10 11 #include <linux/export.h> !! 11 #include <linux/config.h> 12 #include <linux/init.h> !! 12 #include <linux/errno.h> 13 #include <linux/linkage.h> !! 13 14 #include <asm/asm-extable.h> !! 14 #include <asm/head.h> 15 #include <asm/alternative.h> !! 15 #include <asm/asi.h> 16 #include <asm/processor.h> !! 16 #include <asm/smp.h> 17 #include <asm/cache.h> !! 17 #include <asm/kgdb.h> 18 #include <asm/dwarf.h> !! 18 #include <asm/contregs.h> 19 #include <asm/errno.h> << 20 #include <asm/ptrace.h> 19 #include <asm/ptrace.h> 21 #include <asm/thread_info.h> !! 20 #include <asm/asm_offsets.h> 22 #include <asm/asm-offsets.h> !! 21 #include <asm/psr.h> 23 #include <asm/unistd.h> !! 22 #include <asm/cprefix.h> >> 23 #include <asm/vaddrs.h> >> 24 #include <asm/memreg.h> 24 #include <asm/page.h> 25 #include <asm/page.h> 25 #include <asm/sigp.h> !! 26 #ifdef CONFIG_SUN4 26 #include <asm/irq.h> !! 27 #include <asm/pgtsun4.h> 27 #include <asm/fpu-insn.h> << 28 #include <asm/setup.h> << 29 #include <asm/nmi.h> << 30 #include <asm/nospec-insn.h> << 31 #include <asm/lowcore.h> << 32 << 33 _LPP_OFFSET = __LC_LPP << 34 << 35 .macro STBEAR address << 36 ALTERNATIVE "nop", ".insn s,0xb2010000 << 37 .endm << 38 << 39 .macro LBEAR address << 40 ALTERNATIVE "nop", ".insn s,0xb2000000 << 41 .endm << 42 << 43 .macro LPSWEY address, lpswe << 44 ALTERNATIVE_2 "b \lpswe;nopr", \ << 45 ".insn siy,0xeb0000000071,\add << 46 __stringify(.insn siy,0xeb0000 << 47 ALT_LOWCORE << 48 .endm << 49 << 50 .macro MBEAR reg, lowcore << 51 ALTERNATIVE "brcl 0,0", __stringify(mv << 52 ALT_FACILITY(193) << 53 .endm << 54 << 55 .macro CHECK_STACK savearea, lowcore << 56 #ifdef CONFIG_CHECK_STACK << 57 tml %r15,THREAD_SIZE - CONFIG_STAC << 58 la %r14,\savearea(\lowcore) << 59 jz stack_overflow << 60 #endif << 61 .endm << 62 << 63 .macro CHECK_VMAP_STACK savearea, low << 64 #ifdef CONFIG_VMAP_STACK << 65 lgr %r14,%r15 << 66 nill %r14,0x10000 - THREAD_SIZE << 67 oill %r14,STACK_INIT_OFFSET << 68 clg %r14,__LC_KERNEL_STACK(\lowcor << 69 je \oklabel << 70 clg %r14,__LC_ASYNC_STACK(\lowcore << 71 je \oklabel << 72 clg %r14,__LC_MCCK_STACK(\lowcore) << 73 je \oklabel << 74 clg %r14,__LC_NODAT_STACK(\lowcore << 75 je \oklabel << 76 clg %r14,__LC_RESTART_STACK(\lowco << 77 je \oklabel << 78 la %r14,\savearea(\lowcore) << 79 j stack_overflow << 80 #else 28 #else 81 j \oklabel !! 29 #include <asm/pgtsun4c.h> 82 #endif 30 #endif 83 .endm !! 31 #include <asm/winmacro.h> >> 32 #include <asm/signal.h> >> 33 #include <asm/obio.h> >> 34 #include <asm/mxcc.h> >> 35 #include <asm/thread_info.h> 84 36 85 /* !! 37 #include <asm/asmmacro.h> 86 * The TSTMSK macro generates a test-u !! 38 87 * calculating the memory offset for t !! 39 #define curptr g6 88 * Mask value can be any constant. Th !! 40 89 * value to calculate the memory offse !! 41 #define NR_SYSCALLS 272 /* Each OS is different... */ 90 * instruction. !! 42 91 */ !! 43 /* These are just handy. */ 92 .macro TSTMSK addr, mask, size=8, byte !! 44 #define _SV save %sp, -STACKFRAME_SZ, %sp 93 .if (\bytepos < \size) && (\ma !! 45 #define _RS restore 94 .if (\mask & 0xff) !! 46 95 .error "Mask e !! 47 #define FLUSH_ALL_KERNEL_WINDOWS \ 96 .endif !! 48 _SV; _SV; _SV; _SV; _SV; _SV; _SV; \ 97 TSTMSK \addr, "(\mask !! 49 _RS; _RS; _RS; _RS; _RS; _RS; _RS; 98 .exitm !! 50 99 .endif !! 51 /* First, KGDB low level things. This is a rewrite 100 .ifeq \mask !! 52 * of the routines found in the sparc-stub.c asm() statement 101 .error "Mask must not !! 53 * from the gdb distribution. This is also dual-purpose 102 .endif !! 54 * as a software trap for userlevel programs. 103 off = \size - \bytepos - 1 !! 55 */ 104 tm off+\addr, \mask !! 56 .data 105 .endm !! 57 .align 4 106 !! 58 107 .macro BPOFF !! 59 in_trap_handler: 108 ALTERNATIVE "nop", ".insn rrf,0xb2e800 !! 60 .word 0 109 .endm !! 61 110 !! 62 .text 111 .macro BPON !! 63 .align 4 112 ALTERNATIVE "nop", ".insn rrf,0xb2e800 << 113 .endm << 114 << 115 .macro BPENTER tif_ptr,tif_mask << 116 ALTERNATIVE "TSTMSK \tif_ptr,\tif_mask << 117 "j .+12; nop; nop", ALT_SP << 118 .endm << 119 << 120 .macro BPEXIT tif_ptr,tif_mask << 121 TSTMSK \tif_ptr,\tif_mask << 122 ALTERNATIVE "jz .+8; .insn rrf,0xb2e8 << 123 "jnz .+8; .insn rrf,0xb2e8 << 124 .endm << 125 << 126 #if IS_ENABLED(CONFIG_KVM) << 127 .macro SIEEXIT sie_control,lowcore << 128 lg %r9,\sie_control << 129 ni __SIE_PROG0C+3(%r9),0xfe << 130 lctlg %c1,%c1,__LC_KERNEL_ASCE(\lowc << 131 lg %r9,__LC_CURRENT(\lowcore) << 132 mvi __TI_sie(%r9),0 << 133 larl %r9,sie_exit << 134 .endm << 135 #endif << 136 << 137 .macro STACKLEAK_ERASE << 138 #ifdef CONFIG_GCC_PLUGIN_STACKLEAK << 139 brasl %r14,stackleak_erase_on_task_s << 140 #endif << 141 .endm << 142 64 143 GEN_BR_THUNK %r14 !! 65 #if 0 /* kgdb is dropped from 2.5.33 */ >> 66 ! This function is called when any SPARC trap (except window overflow or >> 67 ! underflow) occurs. It makes sure that the invalid register window is still >> 68 ! available before jumping into C code. It will also restore the world if you >> 69 ! return from handle_exception. >> 70 >> 71 .globl C_LABEL(trap_low) >> 72 C_LABEL(trap_low): >> 73 rd %wim, %l3 >> 74 SAVE_ALL >> 75 >> 76 sethi %hi(in_trap_handler), %l4 >> 77 ld [%lo(in_trap_handler) + %l4], %l5 >> 78 inc %l5 >> 79 st %l5, [%lo(in_trap_handler) + %l4] >> 80 >> 81 /* Make sure kgdb sees the same state we just saved. */ >> 82 LOAD_PT_GLOBALS(sp) >> 83 LOAD_PT_INS(sp) >> 84 ld [%sp + STACKFRAME_SZ + PT_Y], %l4 >> 85 ld [%sp + STACKFRAME_SZ + PT_WIM], %l3 >> 86 ld [%sp + STACKFRAME_SZ + PT_PSR], %l0 >> 87 ld [%sp + STACKFRAME_SZ + PT_PC], %l1 >> 88 ld [%sp + STACKFRAME_SZ + PT_NPC], %l2 >> 89 rd %tbr, %l5 /* Never changes... */ >> 90 >> 91 /* Make kgdb exception frame. */ >> 92 sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals >> 93 ! + hidden arg + arg spill >> 94 ! + doubleword alignment >> 95 ! + registers[72] local var >> 96 SAVE_KGDB_GLOBALS(sp) >> 97 SAVE_KGDB_INS(sp) >> 98 SAVE_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2) >> 99 >> 100 /* We are increasing PIL, so two writes. */ >> 101 or %l0, PSR_PIL, %l0 >> 102 wr %l0, 0, %psr >> 103 WRITE_PAUSE >> 104 wr %l0, PSR_ET, %psr >> 105 WRITE_PAUSE >> 106 >> 107 call C_LABEL(handle_exception) >> 108 add %sp, STACKFRAME_SZ, %o0 ! Pass address of registers >> 109 >> 110 /* Load new kgdb register set. */ >> 111 LOAD_KGDB_GLOBALS(sp) >> 112 LOAD_KGDB_INS(sp) >> 113 LOAD_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2) >> 114 wr %l4, 0x0, %y >> 115 >> 116 sethi %hi(in_trap_handler), %l4 >> 117 ld [%lo(in_trap_handler) + %l4], %l5 >> 118 dec %l5 >> 119 st %l5, [%lo(in_trap_handler) + %l4] 144 120 145 .section .kprobes.text, "ax" !! 121 add %sp,(16+1+6+1+72)*4,%sp ! Undo the kgdb trap frame. 146 .Ldummy: !! 122 >> 123 /* Now take what kgdb did and place it into the pt_regs >> 124 * frame which SparcLinux RESTORE_ALL understands., >> 125 */ >> 126 STORE_PT_INS(sp) >> 127 STORE_PT_GLOBALS(sp) >> 128 STORE_PT_YREG(sp, g2) >> 129 STORE_PT_PRIV(sp, l0, l1, l2) >> 130 >> 131 RESTORE_ALL >> 132 #endif >> 133 >> 134 #ifdef CONFIG_BLK_DEV_FD >> 135 .text >> 136 .align 4 >> 137 .globl C_LABEL(floppy_hardint) >> 138 C_LABEL(floppy_hardint): 147 /* 139 /* 148 * The following nop exists only in or !! 140 * This code cannot touch registers %l0 %l1 and %l2 149 * symbol starts at the beginning of t !! 141 * because SAVE_ALL depends on their values. It depends 150 * In that case there would be several !! 142 * on %l3 also, but we regenerate it before a call. 151 * E.g. objdump would take an arbitrar !! 143 * Other registers are: 152 * the code. !! 144 * %l3 -- base address of fdc registers 153 * With the added nop in between this !! 145 * %l4 -- pdma_vaddr >> 146 * %l5 -- scratch for ld/st address >> 147 * %l6 -- pdma_size >> 148 * %l7 -- scratch [floppy byte, ld/st address, aux. data] 154 */ 149 */ 155 nop 0 << 156 150 157 /* !! 151 /* Do we have work to do? */ 158 * Scheduler resume function, called by __swit !! 152 sethi %hi(C_LABEL(doing_pdma)), %l7 159 * gpr2 = (task_struct *)prev !! 153 ld [%l7 + %lo(C_LABEL(doing_pdma))], %l7 160 * gpr3 = (task_struct *)next !! 154 cmp %l7, 0 161 * Returns: !! 155 be floppy_dosoftint 162 * gpr2 = prev !! 156 nop >> 157 >> 158 /* Load fdc register base */ >> 159 sethi %hi(C_LABEL(fdc_status)), %l3 >> 160 ld [%l3 + %lo(C_LABEL(fdc_status))], %l3 >> 161 >> 162 /* Setup register addresses */ >> 163 sethi %hi(C_LABEL(pdma_vaddr)), %l5 ! transfer buffer >> 164 ld [%l5 + %lo(C_LABEL(pdma_vaddr))], %l4 >> 165 sethi %hi(C_LABEL(pdma_size)), %l5 ! bytes to go >> 166 ld [%l5 + %lo(C_LABEL(pdma_size))], %l6 >> 167 next_byte: >> 168 ldub [%l3], %l7 >> 169 >> 170 andcc %l7, 0x80, %g0 ! Does fifo still have data >> 171 bz floppy_fifo_emptied ! fifo has been emptied... >> 172 andcc %l7, 0x20, %g0 ! in non-dma mode still? >> 173 bz floppy_overrun ! nope, overrun >> 174 andcc %l7, 0x40, %g0 ! 0=write 1=read >> 175 bz floppy_write >> 176 sub %l6, 0x1, %l6 >> 177 >> 178 /* Ok, actually read this byte */ >> 179 ldub [%l3 + 1], %l7 >> 180 orcc %g0, %l6, %g0 >> 181 stb %l7, [%l4] >> 182 bne next_byte >> 183 add %l4, 0x1, %l4 >> 184 >> 185 b floppy_tdone >> 186 nop >> 187 >> 188 floppy_write: >> 189 /* Ok, actually write this byte */ >> 190 ldub [%l4], %l7 >> 191 orcc %g0, %l6, %g0 >> 192 stb %l7, [%l3 + 1] >> 193 bne next_byte >> 194 add %l4, 0x1, %l4 >> 195 >> 196 /* fall through... */ >> 197 floppy_tdone: >> 198 sethi %hi(C_LABEL(pdma_vaddr)), %l5 >> 199 st %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))] >> 200 sethi %hi(C_LABEL(pdma_size)), %l5 >> 201 st %l6, [%l5 + %lo(C_LABEL(pdma_size))] >> 202 /* Flip terminal count pin */ >> 203 set C_LABEL(auxio_register), %l7 >> 204 ld [%l7], %l7 >> 205 >> 206 set C_LABEL(sparc_cpu_model), %l5 >> 207 ld [%l5], %l5 >> 208 subcc %l5, 1, %g0 /* enum { sun4c = 1 }; */ >> 209 be 1f >> 210 ldub [%l7], %l5 >> 211 >> 212 or %l5, 0xc2, %l5 >> 213 stb %l5, [%l7] >> 214 andn %l5, 0x02, %l5 >> 215 b 2f >> 216 nop >> 217 >> 218 1: >> 219 or %l5, 0xf4, %l5 >> 220 stb %l5, [%l7] >> 221 andn %l5, 0x04, %l5 >> 222 >> 223 2: >> 224 /* Kill some time so the bits set */ >> 225 WRITE_PAUSE >> 226 WRITE_PAUSE >> 227 >> 228 stb %l5, [%l7] >> 229 >> 230 /* Prevent recursion */ >> 231 sethi %hi(C_LABEL(doing_pdma)), %l7 >> 232 b floppy_dosoftint >> 233 st %g0, [%l7 + %lo(C_LABEL(doing_pdma))] >> 234 >> 235 /* We emptied the FIFO, but we haven't read everything >> 236 * as of yet. Store the current transfer address and >> 237 * bytes left to read so we can continue when the next >> 238 * fast IRQ comes in. >> 239 */ >> 240 floppy_fifo_emptied: >> 241 sethi %hi(C_LABEL(pdma_vaddr)), %l5 >> 242 st %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))] >> 243 sethi %hi(C_LABEL(pdma_size)), %l7 >> 244 st %l6, [%l7 + %lo(C_LABEL(pdma_size))] >> 245 >> 246 /* Restore condition codes */ >> 247 wr %l0, 0x0, %psr >> 248 WRITE_PAUSE >> 249 >> 250 jmp %l1 >> 251 rett %l2 >> 252 >> 253 floppy_overrun: >> 254 sethi %hi(C_LABEL(pdma_vaddr)), %l5 >> 255 st %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))] >> 256 sethi %hi(C_LABEL(pdma_size)), %l5 >> 257 st %l6, [%l5 + %lo(C_LABEL(pdma_size))] >> 258 /* Prevent recursion */ >> 259 sethi %hi(C_LABEL(doing_pdma)), %l7 >> 260 st %g0, [%l7 + %lo(C_LABEL(doing_pdma))] >> 261 >> 262 /* fall through... */ >> 263 floppy_dosoftint: >> 264 rd %wim, %l3 >> 265 SAVE_ALL >> 266 >> 267 /* Set all IRQs off. */ >> 268 or %l0, PSR_PIL, %l4 >> 269 wr %l4, 0x0, %psr >> 270 WRITE_PAUSE >> 271 wr %l4, PSR_ET, %psr >> 272 WRITE_PAUSE >> 273 >> 274 mov 11, %o0 ! floppy irq level (unused anyway) >> 275 mov %g0, %o1 ! devid is not used in fast interrupts >> 276 call C_LABEL(sparc_floppy_irq) >> 277 add %sp, STACKFRAME_SZ, %o2 ! struct pt_regs *regs >> 278 >> 279 RESTORE_ALL >> 280 >> 281 #endif /* (CONFIG_BLK_DEV_FD) */ >> 282 >> 283 /* Bad trap handler */ >> 284 .globl bad_trap_handler >> 285 bad_trap_handler: >> 286 SAVE_ALL >> 287 >> 288 wr %l0, PSR_ET, %psr >> 289 WRITE_PAUSE >> 290 >> 291 mov %l7, %o0 ! trap number >> 292 mov %l0, %o1 ! psr >> 293 call C_LABEL(do_hw_interrupt) >> 294 mov %l1, %o2 ! pc >> 295 >> 296 RESTORE_ALL >> 297 >> 298 /* For now all IRQ's not registered get sent here. handler_irq() will >> 299 * see if a routine is registered to handle this interrupt and if not >> 300 * it will say so on the console. 163 */ 301 */ 164 SYM_FUNC_START(__switch_to_asm) << 165 stmg %r6,%r15,__SF_GPRS(%r15) << 166 lghi %r4,__TASK_stack << 167 lghi %r1,__TASK_thread << 168 llill %r5,STACK_INIT_OFFSET << 169 stg %r15,__THREAD_ksp(%r1,%r2) << 170 lg %r15,0(%r4,%r3) << 171 agr %r15,%r5 << 172 GET_LC %r13 << 173 stg %r3,__LC_CURRENT(%r13) << 174 stg %r15,__LC_KERNEL_STACK(%r13) << 175 lg %r15,__THREAD_ksp(%r1,%r3) << 176 aghi %r3,__TASK_pid << 177 mvc __LC_CURRENT_PID(4,%r13),0(%r3 << 178 ALTERNATIVE "nop", "lpp _LPP_OFFSET(%r << 179 lmg %r6,%r15,__SF_GPRS(%r15) << 180 BR_EX %r14 << 181 SYM_FUNC_END(__switch_to_asm) << 182 302 183 #if IS_ENABLED(CONFIG_KVM) !! 303 .align 4 184 /* !! 304 .globl real_irq_entry, patch_handler_irq 185 * __sie64a calling convention: !! 305 real_irq_entry: 186 * %r2 pointer to sie control block phys !! 306 SAVE_ALL 187 * %r3 pointer to sie control block virt !! 307 188 * %r4 guest register save area !! 308 #ifdef CONFIG_SMP 189 * %r5 guest asce !! 309 .globl patchme_maybe_smp_msg 190 */ !! 310 191 SYM_FUNC_START(__sie64a) !! 311 cmp %l7, 12 192 stmg %r6,%r14,__SF_GPRS(%r15) !! 312 patchme_maybe_smp_msg: 193 GET_LC %r13 !! 313 bgu maybe_smp4m_msg 194 lg %r14,__LC_CURRENT(%r13) !! 314 nop 195 stg %r2,__SF_SIE_CONTROL_PHYS(%r15 << 196 stg %r3,__SF_SIE_CONTROL(%r15) << 197 stg %r4,__SF_SIE_SAVEAREA(%r15) << 198 stg %r5,__SF_SIE_GUEST_ASCE(%r15) << 199 xc __SF_SIE_REASON(8,%r15),__SF_S << 200 mvc __SF_SIE_FLAGS(8,%r15),__TI_fl << 201 lmg %r0,%r13,0(%r4) << 202 mvi __TI_sie(%r14),1 << 203 lctlg %c1,%c1,__SF_SIE_GUEST_ASCE(%r << 204 lg %r14,__SF_SIE_CONTROL(%r15) << 205 oi __SIE_PROG0C+3(%r14),1 << 206 tm __SIE_PROG20+3(%r14),3 << 207 jnz .Lsie_skip << 208 lg %r14,__SF_SIE_CONTROL_PHYS(%r1 << 209 BPEXIT __SF_SIE_FLAGS(%r15),_TIF_ISOL << 210 .Lsie_entry: << 211 sie 0(%r14) << 212 # Let the next instruction be NOP to avoid tri << 213 # and handling it in a guest as result of the << 214 nopr 7 << 215 .Lsie_leave: << 216 BPOFF << 217 BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOL << 218 .Lsie_skip: << 219 lg %r14,__SF_SIE_CONTROL(%r15) << 220 ni __SIE_PROG0C+3(%r14),0xfe << 221 GET_LC %r14 << 222 lctlg %c1,%c1,__LC_KERNEL_ASCE(%r14) << 223 lg %r14,__LC_CURRENT(%r14) << 224 mvi __TI_sie(%r14),0 << 225 # some program checks are suppressing. C code << 226 # will rewind the PSW by the ILC, which is oft << 227 # are some corner cases (e.g. runtime instrume << 228 # Other instructions between __sie64a and .Lsi << 229 # interrupts. So lets use 3 nops as a landing << 230 .Lrewind_pad6: << 231 nopr 7 << 232 .Lrewind_pad4: << 233 nopr 7 << 234 .Lrewind_pad2: << 235 nopr 7 << 236 SYM_INNER_LABEL(sie_exit, SYM_L_GLOBAL) << 237 lg %r14,__SF_SIE_SAVEAREA(%r15) << 238 stmg %r0,%r13,0(%r14) << 239 xgr %r0,%r0 << 240 xgr %r1,%r1 << 241 xgr %r3,%r3 << 242 xgr %r4,%r4 << 243 xgr %r5,%r5 << 244 lmg %r6,%r14,__SF_GPRS(%r15) << 245 lg %r2,__SF_SIE_REASON(%r15) << 246 BR_EX %r14 << 247 .Lsie_fault: << 248 lghi %r14,-EFAULT << 249 stg %r14,__SF_SIE_REASON(%r15) << 250 j sie_exit << 251 << 252 EX_TABLE(.Lrewind_pad6,.Lsie_fault) << 253 EX_TABLE(.Lrewind_pad4,.Lsie_fault) << 254 EX_TABLE(.Lrewind_pad2,.Lsie_fault) << 255 EX_TABLE(sie_exit,.Lsie_fault) << 256 SYM_FUNC_END(__sie64a) << 257 EXPORT_SYMBOL(__sie64a) << 258 EXPORT_SYMBOL(sie_exit) << 259 #endif 315 #endif 260 316 261 /* !! 317 real_irq_continue: 262 * SVC interrupt handler routine. System calls !! 318 or %l0, PSR_PIL, %g2 263 * are entered with interrupts disabled. !! 319 wr %g2, 0x0, %psr 264 */ !! 320 WRITE_PAUSE >> 321 wr %g2, PSR_ET, %psr >> 322 WRITE_PAUSE >> 323 mov %l7, %o0 ! irq level >> 324 patch_handler_irq: >> 325 call C_LABEL(handler_irq) >> 326 add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr >> 327 or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq >> 328 wr %g2, PSR_ET, %psr ! keep ET up >> 329 WRITE_PAUSE >> 330 >> 331 RESTORE_ALL >> 332 >> 333 #ifdef CONFIG_SMP >> 334 /* SMP per-cpu ticker interrupts are handled specially. */ >> 335 smp4m_ticker: >> 336 bne real_irq_continue+4 >> 337 or %l0, PSR_PIL, %g2 >> 338 wr %g2, 0x0, %psr >> 339 WRITE_PAUSE >> 340 wr %g2, PSR_ET, %psr >> 341 WRITE_PAUSE >> 342 call C_LABEL(smp4m_percpu_timer_interrupt) >> 343 add %sp, STACKFRAME_SZ, %o0 >> 344 wr %l0, PSR_ET, %psr >> 345 WRITE_PAUSE >> 346 RESTORE_ALL >> 347 >> 348 /* Here is where we check for possible SMP IPI passed to us >> 349 * on some level other than 15 which is the NMI and only used >> 350 * for cross calls. That has a separate entry point below. >> 351 */ >> 352 maybe_smp4m_msg: >> 353 GET_PROCESSOR_MID(o3, o2) >> 354 set C_LABEL(sun4m_interrupts), %l5 >> 355 ld [%l5], %o5 >> 356 sethi %hi(0x60000000), %o4 >> 357 sll %o3, 12, %o3 >> 358 ld [%o5 + %o3], %o1 >> 359 andcc %o1, %o4, %g0 >> 360 be,a smp4m_ticker >> 361 cmp %l7, 14 >> 362 sethi %hi(0x40000000), %o2 >> 363 add %o5, %o3, %o5 >> 364 andcc %o1, %o2, %g0 >> 365 be,a 1f >> 366 sethi %hi(0x20000000), %o2 >> 367 1: >> 368 st %o2, [%o5 + 0x4] >> 369 WRITE_PAUSE >> 370 ld [%o5], %g0 >> 371 WRITE_PAUSE >> 372 or %l0, PSR_PIL, %l4 >> 373 wr %l4, 0x0, %psr >> 374 WRITE_PAUSE >> 375 wr %l4, PSR_ET, %psr >> 376 WRITE_PAUSE >> 377 srl %o2, (16+14), %o2 >> 378 tst %o2 >> 379 bne 2f >> 380 nop >> 381 call C_LABEL(smp_reschedule_irq) >> 382 add %o7, 8, %o7 >> 383 2: >> 384 call C_LABEL(smp_stop_cpu_irq) >> 385 nop >> 386 RESTORE_ALL >> 387 >> 388 .align 4 >> 389 .globl linux_trap_ipi15_sun4m >> 390 linux_trap_ipi15_sun4m: >> 391 SAVE_ALL >> 392 sethi %hi(0x80000000), %o2 >> 393 GET_PROCESSOR_MID(o0, o1) >> 394 set C_LABEL(sun4m_interrupts), %l5 >> 395 ld [%l5], %o5 >> 396 sll %o0, 12, %o0 >> 397 add %o5, %o0, %o5 >> 398 ld [%o5], %o3 >> 399 andcc %o3, %o2, %g0 >> 400 be 1f ! Must be an NMI async memory error >> 401 st %o2, [%o5 + 4] >> 402 WRITE_PAUSE >> 403 ld [%o5], %g0 >> 404 WRITE_PAUSE >> 405 or %l0, PSR_PIL, %l4 >> 406 wr %l4, 0x0, %psr >> 407 WRITE_PAUSE >> 408 wr %l4, PSR_ET, %psr >> 409 WRITE_PAUSE >> 410 call C_LABEL(smp4m_cross_call_irq) >> 411 nop >> 412 b ret_trap_lockless_ipi >> 413 clr %l6 >> 414 1: >> 415 /* NMI async memory error handling. */ >> 416 sethi %hi(0x80000000), %l4 >> 417 sethi %hi(0x4000), %o3 >> 418 sub %o5, %o0, %o5 >> 419 add %o5, %o3, %l5 >> 420 st %l4, [%l5 + 0xc] >> 421 WRITE_PAUSE >> 422 ld [%l5], %g0 >> 423 WRITE_PAUSE >> 424 or %l0, PSR_PIL, %l4 >> 425 wr %l4, 0x0, %psr >> 426 WRITE_PAUSE >> 427 wr %l4, PSR_ET, %psr >> 428 WRITE_PAUSE >> 429 call C_LABEL(sun4m_nmi) >> 430 nop >> 431 st %l4, [%l5 + 0x8] >> 432 WRITE_PAUSE >> 433 ld [%l5], %g0 >> 434 WRITE_PAUSE >> 435 RESTORE_ALL >> 436 >> 437 .globl smp4d_ticker >> 438 /* SMP per-cpu ticker interrupts are handled specially. */ >> 439 smp4d_ticker: >> 440 SAVE_ALL >> 441 or %l0, PSR_PIL, %g2 >> 442 sethi %hi(CC_ICLR), %o0 >> 443 sethi %hi(1 << 14), %o1 >> 444 or %o0, %lo(CC_ICLR), %o0 >> 445 stha %o1, [%o0] ASI_M_MXCC /* Clear PIL 14 in MXCC's ICLR */ >> 446 wr %g2, 0x0, %psr >> 447 WRITE_PAUSE >> 448 wr %g2, PSR_ET, %psr >> 449 WRITE_PAUSE >> 450 call C_LABEL(smp4d_percpu_timer_interrupt) >> 451 add %sp, STACKFRAME_SZ, %o0 >> 452 wr %l0, PSR_ET, %psr >> 453 WRITE_PAUSE >> 454 RESTORE_ALL >> 455 >> 456 .align 4 >> 457 .globl linux_trap_ipi15_sun4d >> 458 linux_trap_ipi15_sun4d: >> 459 SAVE_ALL >> 460 sethi %hi(CC_BASE), %o4 >> 461 sethi %hi(MXCC_ERR_ME|MXCC_ERR_PEW|MXCC_ERR_ASE|MXCC_ERR_PEE), %o2 >> 462 or %o4, (CC_EREG - CC_BASE), %o0 >> 463 ldda [%o0] ASI_M_MXCC, %o0 >> 464 andcc %o0, %o2, %g0 >> 465 bne 1f >> 466 sethi %hi(BB_STAT2), %o2 >> 467 lduba [%o2] ASI_M_CTL, %o2 >> 468 andcc %o2, BB_STAT2_MASK, %g0 >> 469 bne 2f >> 470 or %o4, (CC_ICLR - CC_BASE), %o0 >> 471 sethi %hi(1 << 15), %o1 >> 472 stha %o1, [%o0] ASI_M_MXCC /* Clear PIL 15 in MXCC's ICLR */ >> 473 or %l0, PSR_PIL, %l4 >> 474 wr %l4, 0x0, %psr >> 475 WRITE_PAUSE >> 476 wr %l4, PSR_ET, %psr >> 477 WRITE_PAUSE >> 478 call C_LABEL(smp4d_cross_call_irq) >> 479 nop >> 480 b ret_trap_lockless_ipi >> 481 clr %l6 >> 482 >> 483 1: /* MXCC error */ >> 484 2: /* BB error */ >> 485 /* Disable PIL 15 */ >> 486 set CC_IMSK, %l4 >> 487 lduha [%l4] ASI_M_MXCC, %l5 >> 488 sethi %hi(1 << 15), %l7 >> 489 or %l5, %l7, %l5 >> 490 stha %l5, [%l4] ASI_M_MXCC >> 491 /* FIXME */ >> 492 1: b,a 1b 265 493 266 SYM_CODE_START(system_call) !! 494 #endif /* CONFIG_SMP */ 267 STMG_LC %r8,%r15,__LC_SAVE_AREA << 268 GET_LC %r13 << 269 stpt __LC_SYS_ENTER_TIMER(%r13) << 270 BPOFF << 271 lghi %r14,0 << 272 .Lsysc_per: << 273 STBEAR __LC_LAST_BREAK(%r13) << 274 lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13) << 275 lg %r15,__LC_KERNEL_STACK(%r13) << 276 xc __SF_BACKCHAIN(8,%r15),__SF_BA << 277 stmg %r0,%r7,STACK_FRAME_OVERHEAD+_ << 278 # clear user controlled register to pr << 279 xgr %r0,%r0 << 280 xgr %r1,%r1 << 281 xgr %r4,%r4 << 282 xgr %r5,%r5 << 283 xgr %r6,%r6 << 284 xgr %r7,%r7 << 285 xgr %r8,%r8 << 286 xgr %r9,%r9 << 287 xgr %r10,%r10 << 288 xgr %r11,%r11 << 289 la %r2,STACK_FRAME_OVERHEAD(%r15) << 290 mvc __PT_R8(64,%r2),__LC_SAVE_AREA << 291 MBEAR %r2,%r13 << 292 lgr %r3,%r14 << 293 brasl %r14,__do_syscall << 294 STACKLEAK_ERASE << 295 lctlg %c1,%c1,__LC_USER_ASCE(%r13) << 296 mvc __LC_RETURN_PSW(16,%r13),STACK << 297 BPON << 298 LBEAR STACK_FRAME_OVERHEAD+__PT_LAST << 299 stpt __LC_EXIT_TIMER(%r13) << 300 lmg %r0,%r15,STACK_FRAME_OVERHEAD+ << 301 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LP << 302 SYM_CODE_END(system_call) << 303 << 304 # << 305 # a new process exits the kernel with ret_from << 306 # << 307 SYM_CODE_START(ret_from_fork) << 308 lgr %r3,%r11 << 309 brasl %r14,__ret_from_fork << 310 STACKLEAK_ERASE << 311 GET_LC %r13 << 312 lctlg %c1,%c1,__LC_USER_ASCE(%r13) << 313 mvc __LC_RETURN_PSW(16,%r13),STACK << 314 BPON << 315 LBEAR STACK_FRAME_OVERHEAD+__PT_LAST << 316 stpt __LC_EXIT_TIMER(%r13) << 317 lmg %r0,%r15,STACK_FRAME_OVERHEAD+ << 318 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LP << 319 SYM_CODE_END(ret_from_fork) << 320 495 321 /* !! 496 /* This routine handles illegal instructions and privileged 322 * Program check handler routine !! 497 * instruction attempts from user code. 323 */ !! 498 */ >> 499 .align 4 >> 500 .globl bad_instruction >> 501 bad_instruction: >> 502 sethi %hi(0xc1f80000), %l4 >> 503 ld [%l1], %l5 >> 504 sethi %hi(0x81d80000), %l7 >> 505 and %l5, %l4, %l5 >> 506 cmp %l5, %l7 >> 507 be 1f >> 508 SAVE_ALL >> 509 >> 510 wr %l0, PSR_ET, %psr ! re-enable traps >> 511 WRITE_PAUSE >> 512 >> 513 add %sp, STACKFRAME_SZ, %o0 >> 514 mov %l1, %o1 >> 515 mov %l2, %o2 >> 516 call C_LABEL(do_illegal_instruction) >> 517 mov %l0, %o3 >> 518 >> 519 RESTORE_ALL >> 520 >> 521 1: /* unimplemented flush - just skip */ >> 522 jmpl %l2, %g0 >> 523 rett %l2 + 4 >> 524 >> 525 .align 4 >> 526 .globl priv_instruction >> 527 priv_instruction: >> 528 SAVE_ALL >> 529 >> 530 wr %l0, PSR_ET, %psr >> 531 WRITE_PAUSE >> 532 >> 533 add %sp, STACKFRAME_SZ, %o0 >> 534 mov %l1, %o1 >> 535 mov %l2, %o2 >> 536 call C_LABEL(do_priv_instruction) >> 537 mov %l0, %o3 >> 538 >> 539 RESTORE_ALL >> 540 >> 541 /* This routine handles unaligned data accesses. */ >> 542 .align 4 >> 543 .globl mna_handler >> 544 mna_handler: >> 545 andcc %l0, PSR_PS, %g0 >> 546 be mna_fromuser >> 547 nop >> 548 >> 549 SAVE_ALL >> 550 >> 551 wr %l0, PSR_ET, %psr >> 552 WRITE_PAUSE >> 553 >> 554 ld [%l1], %o1 >> 555 call C_LABEL(kernel_unaligned_trap) >> 556 add %sp, STACKFRAME_SZ, %o0 >> 557 >> 558 RESTORE_ALL >> 559 >> 560 mna_fromuser: >> 561 SAVE_ALL >> 562 >> 563 wr %l0, PSR_ET, %psr ! re-enable traps >> 564 WRITE_PAUSE >> 565 >> 566 ld [%l1], %o1 >> 567 call C_LABEL(user_unaligned_trap) >> 568 add %sp, STACKFRAME_SZ, %o0 >> 569 >> 570 RESTORE_ALL >> 571 >> 572 /* This routine handles floating point disabled traps. */ >> 573 .align 4 >> 574 .globl fpd_trap_handler >> 575 fpd_trap_handler: >> 576 SAVE_ALL >> 577 >> 578 wr %l0, PSR_ET, %psr ! re-enable traps >> 579 WRITE_PAUSE >> 580 >> 581 add %sp, STACKFRAME_SZ, %o0 >> 582 mov %l1, %o1 >> 583 mov %l2, %o2 >> 584 call C_LABEL(do_fpd_trap) >> 585 mov %l0, %o3 >> 586 >> 587 RESTORE_ALL >> 588 >> 589 /* This routine handles Floating Point Exceptions. */ >> 590 .align 4 >> 591 .globl fpe_trap_handler >> 592 fpe_trap_handler: >> 593 set fpsave_magic, %l5 >> 594 cmp %l1, %l5 >> 595 be 1f >> 596 sethi %hi(C_LABEL(fpsave)), %l5 >> 597 or %l5, %lo(C_LABEL(fpsave)), %l5 >> 598 cmp %l1, %l5 >> 599 bne 2f >> 600 sethi %hi(fpsave_catch2), %l5 >> 601 or %l5, %lo(fpsave_catch2), %l5 >> 602 wr %l0, 0x0, %psr >> 603 WRITE_PAUSE >> 604 jmp %l5 >> 605 rett %l5 + 4 >> 606 1: >> 607 sethi %hi(fpsave_catch), %l5 >> 608 or %l5, %lo(fpsave_catch), %l5 >> 609 wr %l0, 0x0, %psr >> 610 WRITE_PAUSE >> 611 jmp %l5 >> 612 rett %l5 + 4 >> 613 >> 614 2: >> 615 SAVE_ALL >> 616 >> 617 wr %l0, PSR_ET, %psr ! re-enable traps >> 618 WRITE_PAUSE >> 619 >> 620 add %sp, STACKFRAME_SZ, %o0 >> 621 mov %l1, %o1 >> 622 mov %l2, %o2 >> 623 call C_LABEL(do_fpe_trap) >> 624 mov %l0, %o3 >> 625 >> 626 RESTORE_ALL >> 627 >> 628 /* This routine handles Tag Overflow Exceptions. */ >> 629 .align 4 >> 630 .globl do_tag_overflow >> 631 do_tag_overflow: >> 632 SAVE_ALL >> 633 >> 634 wr %l0, PSR_ET, %psr ! re-enable traps >> 635 WRITE_PAUSE >> 636 >> 637 add %sp, STACKFRAME_SZ, %o0 >> 638 mov %l1, %o1 >> 639 mov %l2, %o2 >> 640 call C_LABEL(handle_tag_overflow) >> 641 mov %l0, %o3 >> 642 >> 643 RESTORE_ALL >> 644 >> 645 /* This routine handles Watchpoint Exceptions. */ >> 646 .align 4 >> 647 .globl do_watchpoint >> 648 do_watchpoint: >> 649 SAVE_ALL >> 650 >> 651 wr %l0, PSR_ET, %psr ! re-enable traps >> 652 WRITE_PAUSE >> 653 >> 654 add %sp, STACKFRAME_SZ, %o0 >> 655 mov %l1, %o1 >> 656 mov %l2, %o2 >> 657 call C_LABEL(handle_watchpoint) >> 658 mov %l0, %o3 >> 659 >> 660 RESTORE_ALL >> 661 >> 662 /* This routine handles Register Access Exceptions. */ >> 663 .align 4 >> 664 .globl do_reg_access >> 665 do_reg_access: >> 666 SAVE_ALL >> 667 >> 668 wr %l0, PSR_ET, %psr ! re-enable traps >> 669 WRITE_PAUSE >> 670 >> 671 add %sp, STACKFRAME_SZ, %o0 >> 672 mov %l1, %o1 >> 673 mov %l2, %o2 >> 674 call C_LABEL(handle_reg_access) >> 675 mov %l0, %o3 >> 676 >> 677 RESTORE_ALL >> 678 >> 679 /* This routine handles Co-Processor Disabled Exceptions. */ >> 680 .align 4 >> 681 .globl do_cp_disabled >> 682 do_cp_disabled: >> 683 SAVE_ALL >> 684 >> 685 wr %l0, PSR_ET, %psr ! re-enable traps >> 686 WRITE_PAUSE >> 687 >> 688 add %sp, STACKFRAME_SZ, %o0 >> 689 mov %l1, %o1 >> 690 mov %l2, %o2 >> 691 call C_LABEL(handle_cp_disabled) >> 692 mov %l0, %o3 >> 693 >> 694 RESTORE_ALL >> 695 >> 696 /* This routine handles Co-Processor Exceptions. */ >> 697 .align 4 >> 698 .globl do_cp_exception >> 699 do_cp_exception: >> 700 SAVE_ALL >> 701 >> 702 wr %l0, PSR_ET, %psr ! re-enable traps >> 703 WRITE_PAUSE >> 704 >> 705 add %sp, STACKFRAME_SZ, %o0 >> 706 mov %l1, %o1 >> 707 mov %l2, %o2 >> 708 call C_LABEL(handle_cp_exception) >> 709 mov %l0, %o3 >> 710 >> 711 RESTORE_ALL >> 712 >> 713 /* This routine handles Hardware Divide By Zero Exceptions. */ >> 714 .align 4 >> 715 .globl do_hw_divzero >> 716 do_hw_divzero: >> 717 SAVE_ALL >> 718 >> 719 wr %l0, PSR_ET, %psr ! re-enable traps >> 720 WRITE_PAUSE >> 721 >> 722 add %sp, STACKFRAME_SZ, %o0 >> 723 mov %l1, %o1 >> 724 mov %l2, %o2 >> 725 call C_LABEL(handle_hw_divzero) >> 726 mov %l0, %o3 >> 727 >> 728 RESTORE_ALL >> 729 >> 730 .align 4 >> 731 .globl do_flush_windows >> 732 do_flush_windows: >> 733 SAVE_ALL >> 734 >> 735 wr %l0, PSR_ET, %psr >> 736 WRITE_PAUSE >> 737 >> 738 andcc %l0, PSR_PS, %g0 >> 739 bne dfw_kernel >> 740 nop >> 741 >> 742 call C_LABEL(flush_user_windows) >> 743 nop >> 744 >> 745 /* Advance over the trap instruction. */ >> 746 ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 >> 747 add %l1, 0x4, %l2 >> 748 st %l1, [%sp + STACKFRAME_SZ + PT_PC] >> 749 st %l2, [%sp + STACKFRAME_SZ + PT_NPC] >> 750 >> 751 RESTORE_ALL >> 752 >> 753 .globl flush_patch_one >> 754 >> 755 /* We get these for debugging routines using __builtin_return_address() */ >> 756 dfw_kernel: >> 757 flush_patch_one: >> 758 FLUSH_ALL_KERNEL_WINDOWS >> 759 >> 760 /* Advance over the trap instruction. */ >> 761 ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 >> 762 add %l1, 0x4, %l2 >> 763 st %l1, [%sp + STACKFRAME_SZ + PT_PC] >> 764 st %l2, [%sp + STACKFRAME_SZ + PT_NPC] 324 765 325 SYM_CODE_START(pgm_check_handler) !! 766 RESTORE_ALL 326 STMG_LC %r8,%r15,__LC_SAVE_AREA << 327 GET_LC %r13 << 328 stpt __LC_SYS_ENTER_TIMER(%r13) << 329 BPOFF << 330 lgr %r10,%r15 << 331 lmg %r8,%r9,__LC_PGM_OLD_PSW(%r13) << 332 tmhh %r8,0x0001 # comi << 333 jno .Lpgm_skip_asce << 334 lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13) << 335 j 3f # -> f << 336 .Lpgm_skip_asce: << 337 1: tmhh %r8,0x4000 # PER << 338 jnz 2f # -> e << 339 tm __LC_PGM_ILC+3(%r13),0x80 << 340 jnz .Lpgm_svcper # -> s << 341 2: CHECK_STACK __LC_SAVE_AREA,%r13 << 342 aghi %r15,-(STACK_FRAME_OVERHEAD + << 343 # CHECK_VMAP_STACK branches to stack_o << 344 CHECK_VMAP_STACK __LC_SAVE_AREA,%r13,4 << 345 3: lg %r15,__LC_KERNEL_STACK(%r13) << 346 4: la %r11,STACK_FRAME_OVERHEAD(%r15 << 347 xc __PT_FLAGS(8,%r11),__PT_FLAGS( << 348 xc __SF_BACKCHAIN(8,%r15),__SF_BA << 349 stmg %r0,%r7,__PT_R0(%r11) << 350 mvc __PT_R8(64,%r11),__LC_SAVE_ARE << 351 mvc __PT_LAST_BREAK(8,%r11),__LC_P << 352 stctg %c1,%c1,__PT_CR1(%r11) << 353 #if IS_ENABLED(CONFIG_KVM) << 354 ltg %r12,__LC_GMAP(%r13) << 355 jz 5f << 356 clc __GMAP_ASCE(8,%r12), __PT_CR1( << 357 jne 5f << 358 BPENTER __SF_SIE_FLAGS(%r10),_TIF_ISOL << 359 SIEEXIT __SF_SIE_CONTROL(%r10),%r13 << 360 #endif << 361 5: stmg %r8,%r9,__PT_PSW(%r11) << 362 # clear user controlled registers to p << 363 xgr %r0,%r0 << 364 xgr %r1,%r1 << 365 xgr %r3,%r3 << 366 xgr %r4,%r4 << 367 xgr %r5,%r5 << 368 xgr %r6,%r6 << 369 xgr %r7,%r7 << 370 lgr %r2,%r11 << 371 brasl %r14,__do_pgm_check << 372 tmhh %r8,0x0001 # retu << 373 jno .Lpgm_exit_kernel << 374 STACKLEAK_ERASE << 375 lctlg %c1,%c1,__LC_USER_ASCE(%r13) << 376 BPON << 377 stpt __LC_EXIT_TIMER(%r13) << 378 .Lpgm_exit_kernel: << 379 mvc __LC_RETURN_PSW(16,%r13),STACK << 380 LBEAR STACK_FRAME_OVERHEAD+__PT_LAST << 381 lmg %r0,%r15,STACK_FRAME_OVERHEAD+ << 382 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LP << 383 << 384 # << 385 # single stepped system call << 386 # << 387 .Lpgm_svcper: << 388 mvc __LC_RETURN_PSW(8,%r13),__LC_S << 389 larl %r14,.Lsysc_per << 390 stg %r14,__LC_RETURN_PSW+8(%r13) << 391 lghi %r14,1 << 392 LBEAR __LC_PGM_LAST_BREAK(%r13) << 393 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LP << 394 SYM_CODE_END(pgm_check_handler) << 395 767 396 /* !! 768 /* The getcc software trap. The user wants the condition codes from 397 * Interrupt handler macro used for external a !! 769 * the %psr in register %g1. 398 */ !! 770 */ 399 .macro INT_HANDLER name,lc_old_psw,handler !! 771 400 SYM_CODE_START(\name) !! 772 .align 4 401 STMG_LC %r8,%r15,__LC_SAVE_AREA !! 773 .globl getcc_trap_handler 402 GET_LC %r13 !! 774 getcc_trap_handler: 403 stckf __LC_INT_CLOCK(%r13) !! 775 srl %l0, 20, %g1 ! give user 404 stpt __LC_SYS_ENTER_TIMER(%r13) !! 776 and %g1, 0xf, %g1 ! only ICC bits in %psr 405 STBEAR __LC_LAST_BREAK(%r13) !! 777 jmp %l2 ! advance over trap instruction 406 BPOFF !! 778 rett %l2 + 0x4 ! like this... 407 lmg %r8,%r9,\lc_old_psw(%r13) !! 779 408 tmhh %r8,0x0001 !! 780 /* The setcc software trap. The user has condition codes in %g1 409 jnz 1f !! 781 * that it would like placed in the %psr. Be careful not to flip 410 #if IS_ENABLED(CONFIG_KVM) !! 782 * any unintentional bits! 411 lg %r10,__LC_CURRENT(%r13) !! 783 */ 412 tm __TI_sie(%r10),0xff !! 784 413 jz 0f !! 785 .align 4 414 BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOL !! 786 .globl setcc_trap_handler 415 SIEEXIT __SF_SIE_CONTROL(%r15),%r13 !! 787 setcc_trap_handler: 416 #endif !! 788 sll %g1, 0x14, %l4 417 0: CHECK_STACK __LC_SAVE_AREA,%r13 !! 789 set PSR_ICC, %l5 418 aghi %r15,-(STACK_FRAME_OVERHEAD + !! 790 andn %l0, %l5, %l0 ! clear ICC bits in %psr 419 j 2f !! 791 and %l4, %l5, %l4 ! clear non-ICC bits in user value 420 1: lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13) !! 792 or %l4, %l0, %l4 ! or them in... mix mix mix 421 lg %r15,__LC_KERNEL_STACK(%r13) !! 793 422 2: xc __SF_BACKCHAIN(8,%r15),__SF_BA !! 794 wr %l4, 0x0, %psr ! set new %psr 423 la %r11,STACK_FRAME_OVERHEAD(%r15 !! 795 WRITE_PAUSE ! TI scumbags... 424 stmg %r0,%r7,__PT_R0(%r11) !! 796 425 # clear user controlled registers to p !! 797 jmp %l2 ! advance over trap instruction 426 xgr %r0,%r0 !! 798 rett %l2 + 0x4 ! like this... 427 xgr %r1,%r1 !! 799 428 xgr %r3,%r3 !! 800 .align 4 429 xgr %r4,%r4 !! 801 .globl linux_trap_nmi_sun4c 430 xgr %r5,%r5 !! 802 linux_trap_nmi_sun4c: 431 xgr %r6,%r6 !! 803 SAVE_ALL 432 xgr %r7,%r7 << 433 xgr %r10,%r10 << 434 xc __PT_FLAGS(8,%r11),__PT_FLAGS( << 435 mvc __PT_R8(64,%r11),__LC_SAVE_ARE << 436 MBEAR %r11,%r13 << 437 stmg %r8,%r9,__PT_PSW(%r11) << 438 lgr %r2,%r11 # pass << 439 brasl %r14,\handler << 440 mvc __LC_RETURN_PSW(16,%r13),__PT_ << 441 tmhh %r8,0x0001 # retu << 442 jno 2f << 443 STACKLEAK_ERASE << 444 lctlg %c1,%c1,__LC_USER_ASCE(%r13) << 445 BPON << 446 stpt __LC_EXIT_TIMER(%r13) << 447 2: LBEAR __PT_LAST_BREAK(%r11) << 448 lmg %r0,%r15,__PT_R0(%r11) << 449 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LP << 450 SYM_CODE_END(\name) << 451 .endm << 452 804 453 INT_HANDLER ext_int_handler,__LC_EXT_OLD_PSW,d !! 805 /* Ugh, we need to clear the IRQ line. This is now 454 INT_HANDLER io_int_handler,__LC_IO_OLD_PSW,do_ !! 806 * a very sun4c specific trap handler... >> 807 */ >> 808 sethi %hi(C_LABEL(interrupt_enable)), %l5 >> 809 ld [%l5 + %lo(C_LABEL(interrupt_enable))], %l5 >> 810 ldub [%l5], %l6 >> 811 andn %l6, INTS_ENAB, %l6 >> 812 stb %l6, [%l5] >> 813 >> 814 /* Now it is safe to re-enable traps without recursion. */ >> 815 or %l0, PSR_PIL, %l0 >> 816 wr %l0, PSR_ET, %psr >> 817 WRITE_PAUSE >> 818 >> 819 /* Now call the c-code with the pt_regs frame ptr and the >> 820 * memory error registers as arguments. The ordering chosen >> 821 * here is due to unlatching semantics. >> 822 */ >> 823 sethi %hi(AC_SYNC_ERR), %o0 >> 824 add %o0, 0x4, %o0 >> 825 lda [%o0] ASI_CONTROL, %o2 ! sync vaddr >> 826 sub %o0, 0x4, %o0 >> 827 lda [%o0] ASI_CONTROL, %o1 ! sync error >> 828 add %o0, 0xc, %o0 >> 829 lda [%o0] ASI_CONTROL, %o4 ! async vaddr >> 830 sub %o0, 0x4, %o0 >> 831 lda [%o0] ASI_CONTROL, %o3 ! async error >> 832 call C_LABEL(sparc_lvl15_nmi) >> 833 add %sp, STACKFRAME_SZ, %o0 >> 834 >> 835 RESTORE_ALL >> 836 >> 837 .align 4 >> 838 .globl C_LABEL(invalid_segment_patch1_ff) >> 839 .globl C_LABEL(invalid_segment_patch2_ff) >> 840 C_LABEL(invalid_segment_patch1_ff): cmp %l4, 0xff >> 841 C_LABEL(invalid_segment_patch2_ff): mov 0xff, %l3 >> 842 >> 843 .align 4 >> 844 .globl C_LABEL(invalid_segment_patch1_1ff) >> 845 .globl C_LABEL(invalid_segment_patch2_1ff) >> 846 C_LABEL(invalid_segment_patch1_1ff): cmp %l4, 0x1ff >> 847 C_LABEL(invalid_segment_patch2_1ff): mov 0x1ff, %l3 >> 848 >> 849 .align 4 >> 850 .globl C_LABEL(num_context_patch1_16), C_LABEL(num_context_patch2_16) >> 851 C_LABEL(num_context_patch1_16): mov 0x10, %l7 >> 852 C_LABEL(num_context_patch2_16): mov 0x10, %l7 >> 853 >> 854 .align 4 >> 855 .globl C_LABEL(vac_linesize_patch_32) >> 856 C_LABEL(vac_linesize_patch_32): subcc %l7, 32, %l7 >> 857 >> 858 .align 4 >> 859 .globl C_LABEL(vac_hwflush_patch1_on), C_LABEL(vac_hwflush_patch2_on) 455 860 456 /* 861 /* 457 * Machine check handler routines !! 862 * Ugly, but we cant use hardware flushing on the sun4 and we'd require >> 863 * two instructions (Anton) 458 */ 864 */ 459 SYM_CODE_START(mcck_int_handler) !! 865 #ifdef CONFIG_SUN4 460 BPOFF !! 866 C_LABEL(vac_hwflush_patch1_on): nop 461 GET_LC %r13 !! 867 #else 462 lmg %r8,%r9,__LC_MCK_OLD_PSW(%r13) !! 868 C_LABEL(vac_hwflush_patch1_on): addcc %l7, -PAGE_SIZE, %l7 463 TSTMSK __LC_MCCK_CODE(%r13),MCCK_CODE !! 869 #endif 464 jo .Lmcck_panic # yes !! 870 465 TSTMSK __LC_MCCK_CODE(%r13),MCCK_CODE !! 871 C_LABEL(vac_hwflush_patch2_on): sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG 466 jno .Lmcck_panic # cont !! 872 467 ptlb !! 873 .globl C_LABEL(invalid_segment_patch1), C_LABEL(invalid_segment_patch2) 468 lay %r14,__LC_CPU_TIMER_SAVE_AREA( !! 874 .globl C_LABEL(num_context_patch1), C_LABEL(num_context_patch2) 469 mvc __LC_MCCK_ENTER_TIMER(8,%r13), !! 875 .globl C_LABEL(vac_linesize_patch), C_LABEL(vac_hwflush_patch1) 470 TSTMSK __LC_MCCK_CODE(%r13),MCCK_CODE !! 876 .globl C_LABEL(vac_hwflush_patch2) 471 jo 3f !! 877 472 la %r14,__LC_SYS_ENTER_TIMER(%r13 !! 878 .align 4 473 clc 0(8,%r14),__LC_EXIT_TIMER(%r13 !! 879 .globl sun4c_fault 474 jl 1f !! 880 475 la %r14,__LC_EXIT_TIMER(%r13) !! 881 ! %l0 = %psr 476 1: clc 0(8,%r14),__LC_LAST_UPDATE_TIM !! 882 ! %l1 = %pc 477 jl 2f !! 883 ! %l2 = %npc 478 la %r14,__LC_LAST_UPDATE_TIMER(%r !! 884 ! %l3 = %wim 479 2: spt 0(%r14) !! 885 ! %l7 = 1 for textfault 480 mvc __LC_MCCK_ENTER_TIMER(8,%r13), !! 886 ! We want error in %l5, vaddr in %l6 481 3: TSTMSK __LC_MCCK_CODE(%r13),MCCK_CODE !! 887 sun4c_fault: 482 jno .Lmcck_panic !! 888 #ifdef CONFIG_SUN4 483 tmhh %r8,0x0001 # inte !! 889 sethi %hi(C_LABEL(sun4c_memerr_reg)), %l4 484 jnz .Lmcck_user !! 890 ld [%l4+%lo(C_LABEL(sun4c_memerr_reg))], %l4 ! memerr ctrl reg addr 485 TSTMSK __LC_MCCK_CODE(%r13),MCCK_CODE !! 891 ld [%l4], %l6 ! memerr ctrl reg 486 jno .Lmcck_panic !! 892 ld [%l4 + 4], %l5 ! memerr vaddr reg 487 #if IS_ENABLED(CONFIG_KVM) !! 893 andcc %l6, 0x80, %g0 ! check for error type 488 lg %r10,__LC_CURRENT(%r13) !! 894 st %g0, [%l4 + 4] ! clear the error 489 tm __TI_sie(%r10),0xff !! 895 be 0f ! normal error 490 jz .Lmcck_user !! 896 sethi %hi(AC_BUS_ERROR), %l4 ! bus err reg addr 491 # Need to compare the address instead !! 897 492 # Otherwise there would be a race betw !! 898 call C_LABEL(prom_halt) ! something weird happened 493 # and entering SIE (or leaving and cle !! 899 ! what exactly did happen? 494 # would cause machine checks targeted !! 900 ! what should we do here? 495 # handled by the host. !! 901 496 larl %r14,.Lsie_entry !! 902 0: or %l4, %lo(AC_BUS_ERROR), %l4 ! bus err reg addr 497 clgrjl %r9,%r14, 4f !! 903 lduba [%l4] ASI_CONTROL, %l6 ! bus err reg 498 larl %r14,.Lsie_leave !! 904 499 clgrjhe %r9,%r14, 4f !! 905 cmp %l7, 1 ! text fault? 500 lg %r10,__LC_PCPU !! 906 be 1f ! yes 501 oi __PCPU_FLAGS+7(%r10), _CIF_MCC !! 907 nop 502 4: BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOL !! 908 503 SIEEXIT __SF_SIE_CONTROL(%r15),%r13 !! 909 ld [%l1], %l4 ! load instruction that caused fault 504 #endif !! 910 srl %l4, 21, %l4 505 .Lmcck_user: !! 911 andcc %l4, 1, %g0 ! store instruction? 506 lg %r15,__LC_MCCK_STACK(%r13) !! 912 507 la %r11,STACK_FRAME_OVERHEAD(%r15 !! 913 be 1f ! no 508 stctg %c1,%c1,__PT_CR1(%r11) !! 914 sethi %hi(SUN4C_SYNC_BADWRITE), %l4 ! yep 509 lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13) !! 915 ! %lo(SUN4C_SYNC_BADWRITE) = 0 510 xc __SF_BACKCHAIN(8,%r15),__SF_BA !! 916 or %l4, %l6, %l6 ! set write bit to emulate sun4c 511 lay %r14,__LC_GPREGS_SAVE_AREA(%r1 !! 917 1: 512 mvc __PT_R0(128,%r11),0(%r14) !! 918 #else 513 # clear user controlled registers to p !! 919 sethi %hi(AC_SYNC_ERR), %l4 514 xgr %r0,%r0 !! 920 add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6 515 xgr %r1,%r1 !! 921 lda [%l6] ASI_CONTROL, %l5 ! Address 516 xgr %r3,%r3 !! 922 lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit 517 xgr %r4,%r4 !! 923 #endif 518 xgr %r5,%r5 !! 924 519 xgr %r6,%r6 !! 925 andn %l5, 0xfff, %l5 ! Encode all info into l7 520 xgr %r7,%r7 !! 926 srl %l6, 14, %l4 521 xgr %r10,%r10 !! 927 522 stmg %r8,%r9,__PT_PSW(%r11) !! 928 and %l4, 2, %l4 523 xc __PT_FLAGS(8,%r11),__PT_FLAGS( !! 929 or %l5, %l4, %l4 524 xc __SF_BACKCHAIN(8,%r15),__SF_BA !! 930 525 lgr %r2,%r11 # pass !! 931 or %l4, %l7, %l7 ! l7 = [addr,write,txtfault] 526 brasl %r14,s390_do_machine_check !! 932 527 lctlg %c1,%c1,__PT_CR1(%r11) !! 933 andcc %l0, PSR_PS, %g0 528 lmg %r0,%r10,__PT_R0(%r11) !! 934 be sun4c_fault_fromuser 529 mvc __LC_RETURN_MCCK_PSW(16,%r13), !! 935 andcc %l7, 1, %g0 ! Text fault? 530 tm __LC_RETURN_MCCK_PSW+1(%r13),0 !! 936 531 jno 0f !! 937 be 1f 532 BPON !! 938 sethi %hi(KERNBASE), %l4 533 stpt __LC_EXIT_TIMER(%r13) !! 939 534 0: ALTERNATIVE "brcl 0,0", __stringify(la !! 940 mov %l1, %l5 ! PC 535 ALT_FACILITY(193) !! 941 536 LBEAR 0(%r12) !! 942 1: 537 lmg %r11,%r15,__PT_R11(%r11) !! 943 cmp %l5, %l4 538 LPSWEY __LC_RETURN_MCCK_PSW,__LC_RETU !! 944 blu sun4c_fault_fromuser >> 945 sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4 >> 946 >> 947 /* If the kernel references a bum kernel pointer, or a pte which >> 948 * points to a non existant page in ram, we will run this code >> 949 * _forever_ and lock up the machine!!!!! So we must check for >> 950 * this condition, the AC_SYNC_ERR bits are what we must examine. >> 951 * Also a parity error would make this happen as well. So we just >> 952 * check that we are in fact servicing a tlb miss and not some >> 953 * other type of fault for the kernel. >> 954 */ >> 955 andcc %l6, 0x80, %g0 >> 956 be sun4c_fault_fromuser >> 957 and %l5, %l4, %l5 >> 958 >> 959 /* Test for NULL pte_t * in vmalloc area. */ >> 960 sethi %hi(VMALLOC_START), %l4 >> 961 cmp %l5, %l4 >> 962 blu,a C_LABEL(invalid_segment_patch1) >> 963 lduXa [%l5] ASI_SEGMAP, %l4 >> 964 >> 965 sethi %hi(C_LABEL(swapper_pg_dir)), %l4 >> 966 srl %l5, SUN4C_PGDIR_SHIFT, %l6 >> 967 or %l4, %lo(C_LABEL(swapper_pg_dir)), %l4 >> 968 sll %l6, 2, %l6 >> 969 ld [%l4 + %l6], %l4 >> 970 #ifdef CONFIG_SUN4 >> 971 sethi %hi(PAGE_MASK), %l6 >> 972 andcc %l4, %l6, %g0 >> 973 #else >> 974 andcc %l4, PAGE_MASK, %g0 >> 975 #endif >> 976 be sun4c_fault_fromuser >> 977 lduXa [%l5] ASI_SEGMAP, %l4 >> 978 >> 979 C_LABEL(invalid_segment_patch1): >> 980 cmp %l4, 0x7f >> 981 bne 1f >> 982 sethi %hi(C_LABEL(sun4c_kfree_ring)), %l4 >> 983 or %l4, %lo(C_LABEL(sun4c_kfree_ring)), %l4 >> 984 ld [%l4 + 0x18], %l3 >> 985 deccc %l3 ! do we have a free entry? >> 986 bcs,a 2f ! no, unmap one. >> 987 sethi %hi(C_LABEL(sun4c_kernel_ring)), %l4 >> 988 >> 989 st %l3, [%l4 + 0x18] ! sun4c_kfree_ring.num_entries-- >> 990 >> 991 ld [%l4 + 0x00], %l6 ! entry = sun4c_kfree_ring.ringhd.next >> 992 st %l5, [%l6 + 0x08] ! entry->vaddr = address >> 993 >> 994 ld [%l6 + 0x00], %l3 ! next = entry->next >> 995 ld [%l6 + 0x04], %l7 ! entry->prev >> 996 >> 997 st %l7, [%l3 + 0x04] ! next->prev = entry->prev >> 998 st %l3, [%l7 + 0x00] ! entry->prev->next = next >> 999 >> 1000 sethi %hi(C_LABEL(sun4c_kernel_ring)), %l4 >> 1001 or %l4, %lo(C_LABEL(sun4c_kernel_ring)), %l4 >> 1002 ! head = &sun4c_kernel_ring.ringhd >> 1003 >> 1004 ld [%l4 + 0x00], %l7 ! head->next >> 1005 >> 1006 st %l4, [%l6 + 0x04] ! entry->prev = head >> 1007 st %l7, [%l6 + 0x00] ! entry->next = head->next >> 1008 st %l6, [%l7 + 0x04] ! head->next->prev = entry >> 1009 >> 1010 st %l6, [%l4 + 0x00] ! head->next = entry >> 1011 >> 1012 ld [%l4 + 0x18], %l3 >> 1013 inc %l3 ! sun4c_kernel_ring.num_entries++ >> 1014 st %l3, [%l4 + 0x18] >> 1015 b 4f >> 1016 ld [%l6 + 0x08], %l5 >> 1017 >> 1018 2: >> 1019 or %l4, %lo(C_LABEL(sun4c_kernel_ring)), %l4 >> 1020 ! head = &sun4c_kernel_ring.ringhd >> 1021 >> 1022 ld [%l4 + 0x04], %l6 ! entry = head->prev >> 1023 >> 1024 ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr >> 1025 >> 1026 ! Flush segment from the cache. >> 1027 #ifdef CONFIG_SUN4 >> 1028 sethi %hi((128 * 1024)), %l7 >> 1029 #else >> 1030 sethi %hi((64 * 1024)), %l7 >> 1031 #endif >> 1032 9: >> 1033 C_LABEL(vac_hwflush_patch1): >> 1034 C_LABEL(vac_linesize_patch): >> 1035 subcc %l7, 16, %l7 >> 1036 bne 9b >> 1037 C_LABEL(vac_hwflush_patch2): >> 1038 sta %g0, [%l3 + %l7] ASI_FLUSHSEG >> 1039 >> 1040 st %l5, [%l6 + 0x08] ! entry->vaddr = address >> 1041 >> 1042 ld [%l6 + 0x00], %l5 ! next = entry->next >> 1043 ld [%l6 + 0x04], %l7 ! entry->prev >> 1044 >> 1045 st %l7, [%l5 + 0x04] ! next->prev = entry->prev >> 1046 st %l5, [%l7 + 0x00] ! entry->prev->next = next >> 1047 st %l4, [%l6 + 0x04] ! entry->prev = head >> 1048 >> 1049 ld [%l4 + 0x00], %l7 ! head->next >> 1050 >> 1051 st %l7, [%l6 + 0x00] ! entry->next = head->next >> 1052 st %l6, [%l7 + 0x04] ! head->next->prev = entry >> 1053 st %l6, [%l4 + 0x00] ! head->next = entry >> 1054 >> 1055 mov %l3, %l5 ! address = tmp >> 1056 >> 1057 4: >> 1058 C_LABEL(num_context_patch1): >> 1059 mov 0x08, %l7 >> 1060 >> 1061 ld [%l6 + 0x08], %l4 >> 1062 ldub [%l6 + 0x0c], %l3 >> 1063 or %l4, %l3, %l4 ! encode new vaddr/pseg into l4 >> 1064 >> 1065 sethi %hi(AC_CONTEXT), %l3 >> 1066 lduba [%l3] ASI_CONTROL, %l6 >> 1067 >> 1068 /* Invalidate old mapping, instantiate new mapping, >> 1069 * for each context. Registers l6/l7 are live across >> 1070 * this loop. >> 1071 */ >> 1072 3: deccc %l7 >> 1073 sethi %hi(AC_CONTEXT), %l3 >> 1074 stba %l7, [%l3] ASI_CONTROL >> 1075 C_LABEL(invalid_segment_patch2): >> 1076 mov 0x7f, %l3 >> 1077 stXa %l3, [%l5] ASI_SEGMAP >> 1078 andn %l4, 0x1ff, %l3 >> 1079 bne 3b >> 1080 stXa %l4, [%l3] ASI_SEGMAP >> 1081 >> 1082 sethi %hi(AC_CONTEXT), %l3 >> 1083 stba %l6, [%l3] ASI_CONTROL >> 1084 >> 1085 andn %l4, 0x1ff, %l5 >> 1086 >> 1087 1: >> 1088 sethi %hi(VMALLOC_START), %l4 >> 1089 cmp %l5, %l4 >> 1090 >> 1091 bgeu 1f >> 1092 mov 1 << (SUN4C_REAL_PGDIR_SHIFT - PAGE_SHIFT), %l7 >> 1093 >> 1094 sethi %hi(KERNBASE), %l6 >> 1095 >> 1096 sub %l5, %l6, %l4 >> 1097 srl %l4, PAGE_SHIFT, %l4 >> 1098 sethi %hi((SUN4C_PAGE_KERNEL & 0xf4000000)), %l3 >> 1099 or %l3, %l4, %l3 >> 1100 >> 1101 sethi %hi(PAGE_SIZE), %l4 >> 1102 >> 1103 2: >> 1104 sta %l3, [%l5] ASI_PTE >> 1105 deccc %l7 >> 1106 inc %l3 >> 1107 bne 2b >> 1108 add %l5, %l4, %l5 >> 1109 >> 1110 b 7f >> 1111 sethi %hi(C_LABEL(sun4c_kernel_faults)), %l4 >> 1112 >> 1113 1: >> 1114 srl %l5, SUN4C_PGDIR_SHIFT, %l3 >> 1115 sethi %hi(C_LABEL(swapper_pg_dir)), %l4 >> 1116 or %l4, %lo(C_LABEL(swapper_pg_dir)), %l4 >> 1117 sll %l3, 2, %l3 >> 1118 ld [%l4 + %l3], %l4 >> 1119 #ifndef CONFIG_SUN4 >> 1120 and %l4, PAGE_MASK, %l4 >> 1121 #else >> 1122 sethi %hi(PAGE_MASK), %l6 >> 1123 and %l4, %l6, %l4 >> 1124 #endif >> 1125 >> 1126 srl %l5, (PAGE_SHIFT - 2), %l6 >> 1127 and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6 >> 1128 add %l6, %l4, %l6 >> 1129 >> 1130 sethi %hi(PAGE_SIZE), %l4 >> 1131 >> 1132 2: >> 1133 ld [%l6], %l3 >> 1134 deccc %l7 >> 1135 sta %l3, [%l5] ASI_PTE >> 1136 add %l6, 0x4, %l6 >> 1137 bne 2b >> 1138 add %l5, %l4, %l5 >> 1139 >> 1140 sethi %hi(C_LABEL(sun4c_kernel_faults)), %l4 >> 1141 7: >> 1142 ld [%l4 + %lo(C_LABEL(sun4c_kernel_faults))], %l3 >> 1143 inc %l3 >> 1144 st %l3, [%l4 + %lo(C_LABEL(sun4c_kernel_faults))] >> 1145 >> 1146 /* Restore condition codes */ >> 1147 wr %l0, 0x0, %psr >> 1148 WRITE_PAUSE >> 1149 jmp %l1 >> 1150 rett %l2 >> 1151 >> 1152 sun4c_fault_fromuser: >> 1153 SAVE_ALL >> 1154 nop >> 1155 >> 1156 mov %l7, %o1 ! Decode the info from %l7 >> 1157 mov %l7, %o2 >> 1158 and %o1, 1, %o1 ! arg2 = text_faultp >> 1159 mov %l7, %o3 >> 1160 and %o2, 2, %o2 ! arg3 = writep >> 1161 andn %o3, 0xfff, %o3 ! arg4 = faulting address >> 1162 >> 1163 wr %l0, PSR_ET, %psr >> 1164 WRITE_PAUSE >> 1165 >> 1166 call C_LABEL(do_sun4c_fault) >> 1167 add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr >> 1168 >> 1169 RESTORE_ALL >> 1170 >> 1171 .align 4 >> 1172 .globl C_LABEL(srmmu_fault) >> 1173 C_LABEL(srmmu_fault): >> 1174 mov 0x400, %l5 >> 1175 mov 0x300, %l4 >> 1176 >> 1177 lda [%l5] ASI_M_MMUREGS, %l6 ! read sfar first >> 1178 lda [%l4] ASI_M_MMUREGS, %l5 ! read sfsr last >> 1179 >> 1180 andn %l6, 0xfff, %l6 >> 1181 srl %l5, 6, %l5 ! and encode all info into l7 >> 1182 >> 1183 and %l5, 2, %l5 >> 1184 or %l5, %l6, %l6 >> 1185 >> 1186 or %l6, %l7, %l7 ! l7 = [addr,write,txtfault] >> 1187 >> 1188 SAVE_ALL >> 1189 >> 1190 mov %l7, %o1 >> 1191 mov %l7, %o2 >> 1192 and %o1, 1, %o1 ! arg2 = text_faultp >> 1193 mov %l7, %o3 >> 1194 and %o2, 2, %o2 ! arg3 = writep >> 1195 andn %o3, 0xfff, %o3 ! arg4 = faulting address >> 1196 >> 1197 wr %l0, PSR_ET, %psr >> 1198 WRITE_PAUSE >> 1199 >> 1200 call C_LABEL(do_sparc_fault) >> 1201 add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr >> 1202 >> 1203 RESTORE_ALL >> 1204 >> 1205 #ifdef CONFIG_SUNOS_EMUL >> 1206 /* SunOS uses syscall zero as the 'indirect syscall' it looks >> 1207 * like indir_syscall(scall_num, arg0, arg1, arg2...); etc. >> 1208 * This is complete brain damage. >> 1209 */ >> 1210 .globl C_LABEL(sunos_indir) >> 1211 C_LABEL(sunos_indir): >> 1212 mov %o7, %l4 >> 1213 cmp %o0, NR_SYSCALLS >> 1214 blu,a 1f >> 1215 sll %o0, 0x2, %o0 >> 1216 >> 1217 sethi %hi(C_LABEL(sunos_nosys)), %l6 >> 1218 b 2f >> 1219 or %l6, %lo(C_LABEL(sunos_nosys)), %l6 >> 1220 >> 1221 1: >> 1222 set C_LABEL(sunos_sys_table), %l7 >> 1223 ld [%l7 + %o0], %l6 >> 1224 >> 1225 2: >> 1226 mov %o1, %o0 >> 1227 mov %o2, %o1 >> 1228 mov %o3, %o2 >> 1229 mov %o4, %o3 >> 1230 mov %o5, %o4 >> 1231 call %l6 >> 1232 mov %l4, %o7 >> 1233 #endif >> 1234 >> 1235 .align 4 >> 1236 .globl C_LABEL(sys_nis_syscall) >> 1237 C_LABEL(sys_nis_syscall): >> 1238 mov %o7, %l5 >> 1239 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg >> 1240 call C_LABEL(c_sys_nis_syscall) >> 1241 mov %l5, %o7 >> 1242 >> 1243 .align 4 >> 1244 .globl C_LABEL(sys_ptrace) >> 1245 C_LABEL(sys_ptrace): >> 1246 call C_LABEL(do_ptrace) >> 1247 add %sp, STACKFRAME_SZ, %o0 >> 1248 >> 1249 ld [%curptr + TI_FLAGS], %l5 >> 1250 andcc %l5, _TIF_SYSCALL_TRACE, %g0 >> 1251 be 1f >> 1252 nop >> 1253 >> 1254 call C_LABEL(syscall_trace) >> 1255 nop >> 1256 >> 1257 1: >> 1258 RESTORE_ALL >> 1259 >> 1260 .align 4 >> 1261 .globl C_LABEL(sys_execve) >> 1262 C_LABEL(sys_execve): >> 1263 mov %o7, %l5 >> 1264 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg >> 1265 call C_LABEL(sparc_execve) >> 1266 mov %l5, %o7 >> 1267 >> 1268 .align 4 >> 1269 .globl C_LABEL(sys_pipe) >> 1270 C_LABEL(sys_pipe): >> 1271 mov %o7, %l5 >> 1272 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg >> 1273 call C_LABEL(sparc_pipe) >> 1274 mov %l5, %o7 >> 1275 >> 1276 .align 4 >> 1277 .globl C_LABEL(sys_sigaltstack) >> 1278 C_LABEL(sys_sigaltstack): >> 1279 mov %o7, %l5 >> 1280 mov %fp, %o2 >> 1281 call C_LABEL(do_sigaltstack) >> 1282 mov %l5, %o7 >> 1283 >> 1284 .align 4 >> 1285 .globl C_LABEL(sys_sigstack) >> 1286 C_LABEL(sys_sigstack): >> 1287 mov %o7, %l5 >> 1288 mov %fp, %o2 >> 1289 call C_LABEL(do_sys_sigstack) >> 1290 mov %l5, %o7 >> 1291 >> 1292 .align 4 >> 1293 .globl C_LABEL(sys_sigpause) >> 1294 C_LABEL(sys_sigpause): >> 1295 /* Note: %o0 already has correct value... */ >> 1296 call C_LABEL(do_sigpause) >> 1297 add %sp, STACKFRAME_SZ, %o1 >> 1298 >> 1299 ld [%curptr + TI_FLAGS], %l5 >> 1300 andcc %l5, _TIF_SYSCALL_TRACE, %g0 >> 1301 be 1f >> 1302 nop >> 1303 >> 1304 call C_LABEL(syscall_trace) >> 1305 nop >> 1306 >> 1307 1: >> 1308 /* We are returning to a signal handler. */ >> 1309 RESTORE_ALL >> 1310 >> 1311 .align 4 >> 1312 .globl C_LABEL(sys_sigsuspend) >> 1313 C_LABEL(sys_sigsuspend): >> 1314 call C_LABEL(do_sigsuspend) >> 1315 add %sp, STACKFRAME_SZ, %o0 >> 1316 >> 1317 ld [%curptr + TI_FLAGS], %l5 >> 1318 andcc %l5, _TIF_SYSCALL_TRACE, %g0 >> 1319 be 1f >> 1320 nop >> 1321 >> 1322 call C_LABEL(syscall_trace) >> 1323 nop >> 1324 >> 1325 1: >> 1326 /* We are returning to a signal handler. */ >> 1327 RESTORE_ALL >> 1328 >> 1329 .align 4 >> 1330 .globl C_LABEL(sys_rt_sigsuspend) >> 1331 C_LABEL(sys_rt_sigsuspend): >> 1332 /* Note: %o0, %o1 already have correct value... */ >> 1333 call C_LABEL(do_rt_sigsuspend) >> 1334 add %sp, STACKFRAME_SZ, %o2 >> 1335 >> 1336 ld [%curptr + TI_FLAGS], %l5 >> 1337 andcc %l5, _TIF_SYSCALL_TRACE, %g0 >> 1338 be 1f >> 1339 nop >> 1340 >> 1341 call C_LABEL(syscall_trace) >> 1342 nop >> 1343 >> 1344 1: >> 1345 /* We are returning to a signal handler. */ >> 1346 RESTORE_ALL >> 1347 >> 1348 .align 4 >> 1349 .globl C_LABEL(sys_sigreturn) >> 1350 C_LABEL(sys_sigreturn): >> 1351 call C_LABEL(do_sigreturn) >> 1352 add %sp, STACKFRAME_SZ, %o0 >> 1353 >> 1354 ld [%curptr + TI_FLAGS], %l5 >> 1355 andcc %l5, _TIF_SYSCALL_TRACE, %g0 >> 1356 be 1f >> 1357 nop >> 1358 >> 1359 call C_LABEL(syscall_trace) >> 1360 nop >> 1361 >> 1362 1: >> 1363 /* We don't want to muck with user registers like a >> 1364 * normal syscall, just return. >> 1365 */ >> 1366 RESTORE_ALL >> 1367 >> 1368 .align 4 >> 1369 .globl C_LABEL(sys_rt_sigreturn) >> 1370 C_LABEL(sys_rt_sigreturn): >> 1371 call C_LABEL(do_rt_sigreturn) >> 1372 add %sp, STACKFRAME_SZ, %o0 >> 1373 >> 1374 ld [%curptr + TI_FLAGS], %l5 >> 1375 andcc %l5, _TIF_SYSCALL_TRACE, %g0 >> 1376 be 1f >> 1377 nop >> 1378 >> 1379 call C_LABEL(syscall_trace) >> 1380 nop >> 1381 >> 1382 1: >> 1383 /* We are returning to a signal handler. */ >> 1384 RESTORE_ALL >> 1385 >> 1386 /* Now that we have a real sys_clone, sys_fork() is >> 1387 * implemented in terms of it. Our _real_ implementation >> 1388 * of SunOS vfork() will use sys_vfork(). >> 1389 * >> 1390 * XXX These three should be consolidated into mostly shared >> 1391 * XXX code just like on sparc64... -DaveM >> 1392 */ >> 1393 .align 4 >> 1394 .globl C_LABEL(sys_fork), flush_patch_two >> 1395 C_LABEL(sys_fork): >> 1396 mov %o7, %l5 >> 1397 flush_patch_two: >> 1398 FLUSH_ALL_KERNEL_WINDOWS; >> 1399 ld [%curptr + TI_TASK], %o4 >> 1400 rd %psr, %g4 >> 1401 WRITE_PAUSE >> 1402 mov SIGCHLD, %o0 ! arg0: clone flags >> 1403 rd %wim, %g5 >> 1404 WRITE_PAUSE >> 1405 mov %fp, %o1 ! arg1: usp >> 1406 std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] >> 1407 add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr >> 1408 mov 0, %o3 >> 1409 call C_LABEL(sparc_do_fork) >> 1410 mov %l5, %o7 >> 1411 >> 1412 /* Whee, kernel threads! */ >> 1413 .globl C_LABEL(sys_clone), flush_patch_three >> 1414 C_LABEL(sys_clone): >> 1415 mov %o7, %l5 >> 1416 flush_patch_three: >> 1417 FLUSH_ALL_KERNEL_WINDOWS; >> 1418 ld [%curptr + TI_TASK], %o4 >> 1419 rd %psr, %g4 >> 1420 WRITE_PAUSE >> 1421 >> 1422 /* arg0,1: flags,usp -- loaded already */ >> 1423 cmp %o1, 0x0 ! Is new_usp NULL? >> 1424 rd %wim, %g5 >> 1425 WRITE_PAUSE >> 1426 be,a 1f >> 1427 mov %fp, %o1 ! yes, use callers usp >> 1428 andn %o1, 7, %o1 ! no, align to 8 bytes >> 1429 1: >> 1430 std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] >> 1431 add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr >> 1432 mov 0, %o3 >> 1433 call C_LABEL(sparc_do_fork) >> 1434 mov %l5, %o7 >> 1435 >> 1436 /* Whee, real vfork! */ >> 1437 .globl C_LABEL(sys_vfork), flush_patch_four >> 1438 C_LABEL(sys_vfork): >> 1439 flush_patch_four: >> 1440 FLUSH_ALL_KERNEL_WINDOWS; >> 1441 ld [%curptr + TI_TASK], %o4 >> 1442 rd %psr, %g4 >> 1443 WRITE_PAUSE >> 1444 rd %wim, %g5 >> 1445 WRITE_PAUSE >> 1446 std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] >> 1447 sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0 >> 1448 mov %fp, %o1 >> 1449 or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0 >> 1450 sethi %hi(C_LABEL(sparc_do_fork)), %l1 >> 1451 mov 0, %o3 >> 1452 jmpl %l1 + %lo(C_LABEL(sparc_do_fork)), %g0 >> 1453 add %sp, STACKFRAME_SZ, %o2 >> 1454 >> 1455 .align 4 >> 1456 linux_sparc_ni_syscall: >> 1457 sethi %hi(C_LABEL(sys_ni_syscall)), %l7 >> 1458 b syscall_is_too_hard >> 1459 or %l7, %lo(C_LABEL(sys_ni_syscall)), %l7 >> 1460 >> 1461 linux_fast_syscall: >> 1462 andn %l7, 3, %l7 >> 1463 mov %i0, %o0 >> 1464 mov %i1, %o1 >> 1465 mov %i2, %o2 >> 1466 jmpl %l7 + %g0, %g0 >> 1467 mov %i3, %o3 >> 1468 >> 1469 linux_syscall_trace: >> 1470 call C_LABEL(syscall_trace) >> 1471 nop >> 1472 mov %i0, %o0 >> 1473 mov %i1, %o1 >> 1474 mov %i2, %o2 >> 1475 mov %i3, %o3 >> 1476 b 2f >> 1477 mov %i4, %o4 >> 1478 >> 1479 .globl C_LABEL(ret_from_fork) >> 1480 C_LABEL(ret_from_fork): >> 1481 call schedule_tail >> 1482 mov %g3, %o0 >> 1483 b C_LABEL(ret_sys_call) >> 1484 ld [%sp + STACKFRAME_SZ + PT_I0], %o0 >> 1485 >> 1486 /* Linux native and SunOS system calls enter here... */ >> 1487 .align 4 >> 1488 .globl linux_sparc_syscall >> 1489 linux_sparc_syscall: >> 1490 /* Direct access to user regs, must faster. */ >> 1491 cmp %g1, NR_SYSCALLS >> 1492 bgeu linux_sparc_ni_syscall >> 1493 sll %g1, 2, %l4 >> 1494 ld [%l7 + %l4], %l7 >> 1495 andcc %l7, 1, %g0 >> 1496 bne linux_fast_syscall >> 1497 /* Just do first insn from SAVE_ALL in the delay slot */ >> 1498 >> 1499 .globl syscall_is_too_hard >> 1500 syscall_is_too_hard: >> 1501 SAVE_ALL_HEAD >> 1502 rd %wim, %l3 >> 1503 >> 1504 wr %l0, PSR_ET, %psr >> 1505 mov %i0, %o0 >> 1506 mov %i1, %o1 >> 1507 mov %i2, %o2 >> 1508 >> 1509 ld [%curptr + TI_FLAGS], %l5 >> 1510 mov %i3, %o3 >> 1511 andcc %l5, _TIF_SYSCALL_TRACE, %g0 >> 1512 mov %i4, %o4 >> 1513 bne linux_syscall_trace >> 1514 mov %i0, %l5 >> 1515 2: >> 1516 call %l7 >> 1517 mov %i5, %o5 >> 1518 >> 1519 st %o0, [%sp + STACKFRAME_SZ + PT_I0] >> 1520 >> 1521 .globl C_LABEL(ret_sys_call) >> 1522 C_LABEL(ret_sys_call): >> 1523 ld [%curptr + TI_FLAGS], %l6 >> 1524 cmp %o0, -ENOIOCTLCMD >> 1525 ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 >> 1526 set PSR_C, %g2 >> 1527 bgeu 1f >> 1528 andcc %l6, _TIF_SYSCALL_TRACE, %g0 >> 1529 >> 1530 /* System call success, clear Carry condition code. */ >> 1531 andn %g3, %g2, %g3 >> 1532 clr %l6 >> 1533 st %g3, [%sp + STACKFRAME_SZ + PT_PSR] >> 1534 bne linux_syscall_trace2 >> 1535 ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */ >> 1536 add %l1, 0x4, %l2 /* npc = npc+4 */ >> 1537 st %l1, [%sp + STACKFRAME_SZ + PT_PC] >> 1538 b ret_trap_entry >> 1539 st %l2, [%sp + STACKFRAME_SZ + PT_NPC] >> 1540 1: >> 1541 /* System call failure, set Carry condition code. >> 1542 * Also, get abs(errno) to return to the process. >> 1543 */ >> 1544 sub %g0, %o0, %o0 >> 1545 or %g3, %g2, %g3 >> 1546 st %o0, [%sp + STACKFRAME_SZ + PT_I0] >> 1547 mov 1, %l6 >> 1548 st %g3, [%sp + STACKFRAME_SZ + PT_PSR] >> 1549 bne linux_syscall_trace2 >> 1550 ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */ >> 1551 add %l1, 0x4, %l2 /* npc = npc+4 */ >> 1552 st %l1, [%sp + STACKFRAME_SZ + PT_PC] >> 1553 b ret_trap_entry >> 1554 st %l2, [%sp + STACKFRAME_SZ + PT_NPC] >> 1555 >> 1556 linux_syscall_trace2: >> 1557 call C_LABEL(syscall_trace) >> 1558 add %l1, 0x4, %l2 /* npc = npc+4 */ >> 1559 st %l1, [%sp + STACKFRAME_SZ + PT_PC] >> 1560 b ret_trap_entry >> 1561 st %l2, [%sp + STACKFRAME_SZ + PT_NPC] >> 1562 539 1563 540 .Lmcck_panic: << 541 /* 1564 /* 542 * Iterate over all possible CPU addre !! 1565 * Solaris system calls and indirect system calls enter here. 543 * and stop each CPU using signal proc !! 1566 * 544 * to allow just one CPU-stopper and p !! 1567 * I have named the solaris indirect syscalls like that because 545 * stopping each other while leaving t !! 1568 * it seems like Solaris has some fast path syscalls that can 546 */ !! 1569 * be handled as indirect system calls. - mig 547 lhi %r5,0 !! 1570 */ 548 lhi %r6,1 << 549 larl %r7,stop_lock << 550 cs %r5,%r6,0(%r7) # sing << 551 jnz 4f << 552 larl %r7,this_cpu << 553 stap 0(%r7) # this << 554 lh %r4,0(%r7) << 555 nilh %r4,0 << 556 lhi %r0,1 << 557 sll %r0,16 # CPU << 558 lhi %r3,0 # next << 559 0: cr %r3,%r4 << 560 je 2f << 561 1: sigp %r1,%r3,SIGP_STOP # stop << 562 brc SIGP_CC_BUSY,1b << 563 2: ahi %r3,1 << 564 brct %r0,0b << 565 3: sigp %r1,%r4,SIGP_STOP # stop << 566 brc SIGP_CC_BUSY,3b << 567 4: j 4b << 568 SYM_CODE_END(mcck_int_handler) << 569 << 570 SYM_CODE_START(restart_int_handler) << 571 ALTERNATIVE "nop", "lpp _LPP_OFFSET", << 572 stg %r15,__LC_SAVE_AREA_RESTART << 573 TSTMSK __LC_RESTART_FLAGS,RESTART_FLA << 574 jz 0f << 575 lctlg %c0,%c15,__LC_CREGS_SAVE_AREA << 576 0: larl %r15,daton_psw << 577 lpswe 0(%r15) << 578 .Ldaton: << 579 GET_LC %r15 << 580 lg %r15,__LC_RESTART_STACK(%r15) << 581 xc STACK_FRAME_OVERHEAD(__PT_SIZE << 582 stmg %r0,%r14,STACK_FRAME_OVERHEAD+ << 583 GET_LC %r13 << 584 mvc STACK_FRAME_OVERHEAD+__PT_R15( << 585 mvc STACK_FRAME_OVERHEAD+__PT_PSW( << 586 xc 0(STACK_FRAME_OVERHEAD,%r15),0 << 587 lg %r1,__LC_RESTART_FN(%r13) << 588 lg %r2,__LC_RESTART_DATA(%r13) << 589 lgf %r3,__LC_RESTART_SOURCE(%r13) << 590 ltgr %r3,%r3 << 591 jm 1f << 592 0: sigp %r4,%r3,SIGP_SENSE << 593 brc 10,0b << 594 1: basr %r14,%r1 << 595 stap __SF_EMPTY(%r15) << 596 llgh %r3,__SF_EMPTY(%r15) << 597 2: sigp %r4,%r3,SIGP_STOP << 598 brc 2,2b << 599 3: j 3b << 600 SYM_CODE_END(restart_int_handler) << 601 << 602 __INIT << 603 SYM_CODE_START(early_pgm_check_handler) << 604 STMG_LC %r8,%r15,__LC_SAVE_AREA << 605 GET_LC %r13 << 606 aghi %r15,-(STACK_FRAME_OVERHEAD+__ << 607 la %r11,STACK_FRAME_OVERHEAD(%r15 << 608 xc __SF_BACKCHAIN(8,%r15),__SF_BA << 609 stmg %r0,%r7,__PT_R0(%r11) << 610 mvc __PT_PSW(16,%r11),__LC_PGM_OLD << 611 mvc __PT_R8(64,%r11),__LC_SAVE_ARE << 612 lgr %r2,%r11 << 613 brasl %r14,__do_early_pgm_check << 614 mvc __LC_RETURN_PSW(16,%r13),STACK << 615 lmg %r0,%r15,STACK_FRAME_OVERHEAD+ << 616 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LP << 617 SYM_CODE_END(early_pgm_check_handler) << 618 __FINIT << 619 1571 620 .section .kprobes.text, "ax" !! 1572 linux_syscall_for_solaris: >> 1573 sethi %hi(sys_call_table), %l7 >> 1574 b linux_sparc_syscall >> 1575 or %l7, %lo(sys_call_table), %l7 >> 1576 >> 1577 .align 4 >> 1578 .globl solaris_syscall >> 1579 solaris_syscall: >> 1580 cmp %g1,59 >> 1581 be linux_syscall_for_solaris >> 1582 cmp %g1,2 >> 1583 be linux_syscall_for_solaris >> 1584 cmp %g1,42 >> 1585 be linux_syscall_for_solaris >> 1586 cmp %g1,119 >> 1587 be,a linux_syscall_for_solaris >> 1588 mov 2, %g1 >> 1589 1: >> 1590 SAVE_ALL_HEAD >> 1591 rd %wim, %l3 >> 1592 >> 1593 wr %l0, PSR_ET, %psr >> 1594 nop >> 1595 nop >> 1596 mov %i0, %l5 >> 1597 >> 1598 call C_LABEL(do_solaris_syscall) >> 1599 add %sp, STACKFRAME_SZ, %o0 >> 1600 >> 1601 st %o0, [%sp + STACKFRAME_SZ + PT_I0] >> 1602 set PSR_C, %g2 >> 1603 cmp %o0, -ENOIOCTLCMD >> 1604 bgeu 1f >> 1605 ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 >> 1606 >> 1607 /* System call success, clear Carry condition code. */ >> 1608 andn %g3, %g2, %g3 >> 1609 clr %l6 >> 1610 b 2f >> 1611 st %g3, [%sp + STACKFRAME_SZ + PT_PSR] >> 1612 >> 1613 1: >> 1614 /* System call failure, set Carry condition code. >> 1615 * Also, get abs(errno) to return to the process. >> 1616 */ >> 1617 sub %g0, %o0, %o0 >> 1618 mov 1, %l6 >> 1619 st %o0, [%sp + STACKFRAME_SZ + PT_I0] >> 1620 or %g3, %g2, %g3 >> 1621 st %g3, [%sp + STACKFRAME_SZ + PT_PSR] >> 1622 >> 1623 /* Advance the pc and npc over the trap instruction. >> 1624 * If the npc is unaligned (has a 1 in the lower byte), it means >> 1625 * the kernel does not want us to play magic (ie, skipping over >> 1626 * traps). Mainly when the Solaris code wants to set some PC and >> 1627 * nPC (setcontext). >> 1628 */ >> 1629 2: >> 1630 ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */ >> 1631 andcc %l1, 1, %g0 >> 1632 bne 1f >> 1633 add %l1, 0x4, %l2 /* npc = npc+4 */ >> 1634 st %l1, [%sp + STACKFRAME_SZ + PT_PC] >> 1635 b ret_trap_entry >> 1636 st %l2, [%sp + STACKFRAME_SZ + PT_NPC] >> 1637 >> 1638 /* kernel knows what it is doing, fixup npc and continue */ >> 1639 1: >> 1640 sub %l1, 1, %l1 >> 1641 b ret_trap_entry >> 1642 st %l1, [%sp + STACKFRAME_SZ + PT_NPC] >> 1643 >> 1644 #ifndef CONFIG_SUNOS_EMUL >> 1645 .align 4 >> 1646 .globl sunos_syscall >> 1647 sunos_syscall: >> 1648 SAVE_ALL_HEAD >> 1649 rd %wim, %l3 >> 1650 wr %l0, PSR_ET, %psr >> 1651 nop >> 1652 nop >> 1653 mov %i0, %l5 >> 1654 call C_LABEL(do_sunos_syscall) >> 1655 add %sp, STACKFRAME_SZ, %o0 >> 1656 #endif 621 1657 622 #if defined(CONFIG_CHECK_STACK) || defined(CON !! 1658 /* {net, open}bsd system calls enter here... */ 623 /* !! 1659 .align 4 624 * The synchronous or the asynchronous stack o !! 1660 .globl bsd_syscall 625 * No need to properly save the registers, we !! 1661 bsd_syscall: 626 * Setup a pt_regs so that show_trace can prov !! 1662 /* Direct access to user regs, must faster. */ >> 1663 cmp %g1, NR_SYSCALLS >> 1664 blu,a 1f >> 1665 sll %g1, 2, %l4 >> 1666 >> 1667 set C_LABEL(sys_ni_syscall), %l7 >> 1668 b bsd_is_too_hard >> 1669 nop >> 1670 >> 1671 1: >> 1672 ld [%l7 + %l4], %l7 >> 1673 >> 1674 .globl bsd_is_too_hard >> 1675 bsd_is_too_hard: >> 1676 rd %wim, %l3 >> 1677 SAVE_ALL >> 1678 >> 1679 wr %l0, PSR_ET, %psr >> 1680 WRITE_PAUSE >> 1681 >> 1682 2: >> 1683 mov %i0, %o0 >> 1684 mov %i1, %o1 >> 1685 mov %i2, %o2 >> 1686 mov %i0, %l5 >> 1687 mov %i3, %o3 >> 1688 mov %i4, %o4 >> 1689 call %l7 >> 1690 mov %i5, %o5 >> 1691 >> 1692 st %o0, [%sp + STACKFRAME_SZ + PT_I0] >> 1693 set PSR_C, %g2 >> 1694 cmp %o0, -ENOIOCTLCMD >> 1695 bgeu 1f >> 1696 ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 >> 1697 >> 1698 /* System call success, clear Carry condition code. */ >> 1699 andn %g3, %g2, %g3 >> 1700 clr %l6 >> 1701 b 2f >> 1702 st %g3, [%sp + STACKFRAME_SZ + PT_PSR] >> 1703 >> 1704 1: >> 1705 /* System call failure, set Carry condition code. >> 1706 * Also, get abs(errno) to return to the process. >> 1707 */ >> 1708 sub %g0, %o0, %o0 >> 1709 #if 0 /* XXX todo XXX */ >> 1710 sethi %hi(C_LABEL(bsd_xlatb_rorl), %o3 >> 1711 or %o3, %lo(C_LABEL(bsd_xlatb_rorl)), %o3 >> 1712 sll %o0, 2, %o0 >> 1713 ld [%o3 + %o0], %o0 >> 1714 #endif >> 1715 mov 1, %l6 >> 1716 st %o0, [%sp + STACKFRAME_SZ + PT_I0] >> 1717 or %g3, %g2, %g3 >> 1718 st %g3, [%sp + STACKFRAME_SZ + PT_PSR] >> 1719 >> 1720 /* Advance the pc and npc over the trap instruction. */ >> 1721 2: >> 1722 ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */ >> 1723 add %l1, 0x4, %l2 /* npc = npc+4 */ >> 1724 st %l1, [%sp + STACKFRAME_SZ + PT_PC] >> 1725 b ret_trap_entry >> 1726 st %l2, [%sp + STACKFRAME_SZ + PT_NPC] >> 1727 >> 1728 /* Saving and restoring the FPU state is best done from lowlevel code. >> 1729 * >> 1730 * void fpsave(unsigned long *fpregs, unsigned long *fsr, >> 1731 * void *fpqueue, unsigned long *fpqdepth) 627 */ 1732 */ 628 SYM_CODE_START(stack_overflow) !! 1733 629 GET_LC %r15 !! 1734 .globl C_LABEL(fpsave) 630 lg %r15,__LC_NODAT_STACK(%r15) # !! 1735 C_LABEL(fpsave): 631 la %r11,STACK_FRAME_OVERHEAD(%r15 !! 1736 st %fsr, [%o1] ! this can trap on us if fpu is in bogon state 632 stmg %r0,%r7,__PT_R0(%r11) !! 1737 ld [%o1], %g1 633 stmg %r8,%r9,__PT_PSW(%r11) !! 1738 set 0x2000, %g4 634 mvc __PT_R8(64,%r11),0(%r14) !! 1739 andcc %g1, %g4, %g0 635 stg %r10,__PT_ORIG_GPR2(%r11) # st !! 1740 be 2f 636 xc __SF_BACKCHAIN(8,%r15),__SF_BA !! 1741 mov 0, %g2 637 lgr %r2,%r11 # pass !! 1742 638 jg kernel_stack_overflow !! 1743 /* We have an fpqueue to save. */ 639 SYM_CODE_END(stack_overflow) !! 1744 1: 640 #endif !! 1745 std %fq, [%o2] 641 !! 1746 fpsave_magic: 642 .section .data, "aw" !! 1747 st %fsr, [%o1] 643 .balign 4 !! 1748 ld [%o1], %g3 644 SYM_DATA_LOCAL(stop_lock, .long 0) !! 1749 andcc %g3, %g4, %g0 645 SYM_DATA_LOCAL(this_cpu, .short 0) !! 1750 add %g2, 1, %g2 646 .balign 8 !! 1751 bne 1b 647 SYM_DATA_START_LOCAL(daton_psw) !! 1752 add %o2, 8, %o2 648 .quad PSW_KERNEL_BITS !! 1753 649 .quad .Ldaton !! 1754 2: 650 SYM_DATA_END(daton_psw) !! 1755 st %g2, [%o3] 651 !! 1756 652 .section .rodata, "a" !! 1757 std %f0, [%o0 + 0x00] 653 .balign 8 !! 1758 std %f2, [%o0 + 0x08] 654 #define SYSCALL(esame,emu) .quad __s390x_ !! 1759 std %f4, [%o0 + 0x10] 655 SYM_DATA_START(sys_call_table) !! 1760 std %f6, [%o0 + 0x18] 656 #include "asm/syscall_table.h" !! 1761 std %f8, [%o0 + 0x20] 657 SYM_DATA_END(sys_call_table) !! 1762 std %f10, [%o0 + 0x28] 658 #undef SYSCALL !! 1763 std %f12, [%o0 + 0x30] 659 !! 1764 std %f14, [%o0 + 0x38] 660 #ifdef CONFIG_COMPAT !! 1765 std %f16, [%o0 + 0x40] 661 !! 1766 std %f18, [%o0 + 0x48] 662 #define SYSCALL(esame,emu) .quad __s390_ !! 1767 std %f20, [%o0 + 0x50] 663 SYM_DATA_START(sys_call_table_emu) !! 1768 std %f22, [%o0 + 0x58] 664 #include "asm/syscall_table.h" !! 1769 std %f24, [%o0 + 0x60] 665 SYM_DATA_END(sys_call_table_emu) !! 1770 std %f26, [%o0 + 0x68] 666 #undef SYSCALL !! 1771 std %f28, [%o0 + 0x70] >> 1772 retl >> 1773 std %f30, [%o0 + 0x78] >> 1774 >> 1775 /* Thanks for Theo Deraadt and the authors of the Sprite/netbsd/openbsd >> 1776 * code for pointing out this possible deadlock, while we save state >> 1777 * above we could trap on the fsr store so our low level fpu trap >> 1778 * code has to know how to deal with this. >> 1779 */ >> 1780 fpsave_catch: >> 1781 b fpsave_magic + 4 >> 1782 st %fsr, [%o1] >> 1783 >> 1784 fpsave_catch2: >> 1785 b C_LABEL(fpsave) + 4 >> 1786 st %fsr, [%o1] >> 1787 >> 1788 /* void fpload(unsigned long *fpregs, unsigned long *fsr); */ >> 1789 >> 1790 .globl C_LABEL(fpload) >> 1791 C_LABEL(fpload): >> 1792 ldd [%o0 + 0x00], %f0 >> 1793 ldd [%o0 + 0x08], %f2 >> 1794 ldd [%o0 + 0x10], %f4 >> 1795 ldd [%o0 + 0x18], %f6 >> 1796 ldd [%o0 + 0x20], %f8 >> 1797 ldd [%o0 + 0x28], %f10 >> 1798 ldd [%o0 + 0x30], %f12 >> 1799 ldd [%o0 + 0x38], %f14 >> 1800 ldd [%o0 + 0x40], %f16 >> 1801 ldd [%o0 + 0x48], %f18 >> 1802 ldd [%o0 + 0x50], %f20 >> 1803 ldd [%o0 + 0x58], %f22 >> 1804 ldd [%o0 + 0x60], %f24 >> 1805 ldd [%o0 + 0x68], %f26 >> 1806 ldd [%o0 + 0x70], %f28 >> 1807 ldd [%o0 + 0x78], %f30 >> 1808 ld [%o1], %fsr >> 1809 retl >> 1810 nop >> 1811 >> 1812 .globl C_LABEL(ndelay) >> 1813 C_LABEL(ndelay): >> 1814 save %sp, -STACKFRAME_SZ, %sp >> 1815 mov %i0, %o0 >> 1816 call .umul >> 1817 mov 5, %o1 >> 1818 ba delay_continue >> 1819 nop >> 1820 >> 1821 .globl C_LABEL(udelay) >> 1822 C_LABEL(udelay): >> 1823 save %sp, -STACKFRAME_SZ, %sp >> 1824 mov %i0, %o0 >> 1825 sethi %hi(0x10c6), %o1 >> 1826 call .umul >> 1827 or %o1, %lo(0x10c6), %o1 >> 1828 delay_continue: >> 1829 #ifndef CONFIG_SMP >> 1830 sethi %hi(C_LABEL(loops_per_jiffy)), %o3 >> 1831 call .umul >> 1832 ld [%o3 + %lo(C_LABEL(loops_per_jiffy))], %o1 >> 1833 #else >> 1834 GET_PROCESSOR_OFFSET(o4, o2) >> 1835 set C_LABEL(cpu_data), %o3 >> 1836 call .umul >> 1837 ld [%o3 + %o4], %o1 667 #endif 1838 #endif >> 1839 call .umul >> 1840 mov 100, %o0 >> 1841 >> 1842 cmp %o0, 0x0 >> 1843 1: >> 1844 bne 1b >> 1845 subcc %o0, 1, %o0 >> 1846 >> 1847 ret >> 1848 restore >> 1849 >> 1850 /* Handle a software breakpoint */ >> 1851 /* We have to inform parent that child has stopped */ >> 1852 .align 4 >> 1853 .globl breakpoint_trap >> 1854 breakpoint_trap: >> 1855 rd %wim,%l3 >> 1856 SAVE_ALL >> 1857 wr %l0, PSR_ET, %psr >> 1858 WRITE_PAUSE >> 1859 >> 1860 st %i0, [%sp + STACKFRAME_SZ + PT_G0] ! for restarting syscalls >> 1861 call C_LABEL(sparc_breakpoint) >> 1862 add %sp, STACKFRAME_SZ, %o0 >> 1863 >> 1864 RESTORE_ALL >> 1865 >> 1866 .align 4 >> 1867 .globl C_LABEL(__handle_exception), flush_patch_exception >> 1868 C_LABEL(__handle_exception): >> 1869 flush_patch_exception: >> 1870 FLUSH_ALL_KERNEL_WINDOWS; >> 1871 ldd [%o0], %o6 >> 1872 jmpl %o7 + 0xc, %g0 ! see asm-sparc/processor.h >> 1873 mov 1, %g1 ! signal EFAULT condition >> 1874 >> 1875 .align 4 >> 1876 .globl C_LABEL(kill_user_windows), kuw_patch1_7win >> 1877 .globl kuw_patch1 >> 1878 kuw_patch1_7win: sll %o3, 6, %o3 >> 1879 >> 1880 /* No matter how much overhead this routine has in the worst >> 1881 * case scenerio, it is several times better than taking the >> 1882 * traps with the old method of just doing flush_user_windows(). >> 1883 */ >> 1884 C_LABEL(kill_user_windows): >> 1885 ld [%g6 + TI_UWINMASK], %o0 ! get current umask >> 1886 orcc %g0, %o0, %g0 ! if no bits set, we are done >> 1887 be 3f ! nothing to do >> 1888 rd %psr, %o5 ! must clear interrupts >> 1889 or %o5, PSR_PIL, %o4 ! or else that could change >> 1890 wr %o4, 0x0, %psr ! the uwinmask state >> 1891 WRITE_PAUSE ! burn them cycles >> 1892 1: >> 1893 ld [%g6 + TI_UWINMASK], %o0 ! get consistent state >> 1894 orcc %g0, %o0, %g0 ! did an interrupt come in? >> 1895 be 4f ! yep, we are done >> 1896 rd %wim, %o3 ! get current wim >> 1897 srl %o3, 1, %o4 ! simulate a save >> 1898 kuw_patch1: >> 1899 sll %o3, 7, %o3 ! compute next wim >> 1900 or %o4, %o3, %o3 ! result >> 1901 andncc %o0, %o3, %o0 ! clean this bit in umask >> 1902 bne kuw_patch1 ! not done yet >> 1903 srl %o3, 1, %o4 ! begin another save simulation >> 1904 wr %o3, 0x0, %wim ! set the new wim >> 1905 st %g0, [%g6 + TI_UWINMASK] ! clear uwinmask >> 1906 4: >> 1907 wr %o5, 0x0, %psr ! re-enable interrupts >> 1908 WRITE_PAUSE ! burn baby burn >> 1909 3: >> 1910 ld [%g6 + TI_TASK], %o4 >> 1911 retl ! return >> 1912 st %g0, [%o4 + AOFF_task_thread + AOFF_thread_w_saved] ! no windows saved >> 1913 >> 1914 .align 4 >> 1915 .globl C_LABEL(restore_current) >> 1916 C_LABEL(restore_current): >> 1917 LOAD_CURRENT(g6, o0) >> 1918 retl >> 1919 nop >> 1920 >> 1921 #ifdef CONFIG_PCI >> 1922 #include <asm/pcic.h> >> 1923 >> 1924 .align 4 >> 1925 .globl linux_trap_ipi15_pcic >> 1926 linux_trap_ipi15_pcic: >> 1927 rd %wim, %l3 >> 1928 SAVE_ALL >> 1929 >> 1930 /* >> 1931 * First deactivate NMI >> 1932 * or we cannot drop ET, cannot get window spill traps. >> 1933 * The busy loop is necessary because the PIO error >> 1934 * sometimes does not go away quickly and we trap again. >> 1935 */ >> 1936 sethi %hi(C_LABEL(pcic_regs)), %o1 >> 1937 ld [%o1 + %lo(C_LABEL(pcic_regs))], %o2 >> 1938 >> 1939 ! Get pending status for printouts later. >> 1940 ld [%o2 + PCI_SYS_INT_PENDING], %o0 >> 1941 >> 1942 mov PCI_SYS_INT_PENDING_CLEAR_ALL, %o1 >> 1943 stb %o1, [%o2 + PCI_SYS_INT_PENDING_CLEAR] >> 1944 1: >> 1945 ld [%o2 + PCI_SYS_INT_PENDING], %o1 >> 1946 andcc %o1, ((PCI_SYS_INT_PENDING_PIO|PCI_SYS_INT_PENDING_PCI)>>24), %g0 >> 1947 bne 1b >> 1948 nop >> 1949 >> 1950 or %l0, PSR_PIL, %l4 >> 1951 wr %l4, 0x0, %psr >> 1952 WRITE_PAUSE >> 1953 wr %l4, PSR_ET, %psr >> 1954 WRITE_PAUSE >> 1955 >> 1956 call C_LABEL(pcic_nmi) >> 1957 add %sp, STACKFRAME_SZ, %o1 ! struct pt_regs *regs >> 1958 RESTORE_ALL >> 1959 >> 1960 .globl C_LABEL(pcic_nmi_trap_patch) >> 1961 C_LABEL(pcic_nmi_trap_patch): >> 1962 sethi %hi(linux_trap_ipi15_pcic), %l3 >> 1963 jmpl %l3 + %lo(linux_trap_ipi15_pcic), %g0 >> 1964 rd %psr, %l0 >> 1965 .word 0 >> 1966 >> 1967 #endif /* CONFIG_PCI */ >> 1968 >> 1969 /* End of entry.S */
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.