1 /* SPDX-License-Identifier: GPL-2.0-or-later * !! 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* !! 2 /* arch/sparc/kernel/entry.S: Sparc trap low-level entry points. 3 * Linux/PA-RISC Project (http://www.parisc-li << 4 * 3 * 5 * kernel entry points (interruptions, system !! 4 * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net) 6 * Copyright (C) 1999,2000 Philipp Rumpf !! 5 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) 7 * Copyright (C) 1999 SuSE GmbH Nuernberg !! 6 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) 8 * Copyright (C) 2000 Hewlett-Packard (John M !! 7 * Copyright (C) 1996-1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 9 * Copyright (C) 1999 Hewlett-Packard (Frank !! 8 * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) 10 */ 9 */ 11 10 12 #include <asm/asm-offsets.h> !! 11 #include <linux/export.h> 13 << 14 /* we have the following possibilities to act << 15 * - handle in assembly and use shadowed regi << 16 * - save registers to kernel stack and handl << 17 << 18 << 19 #include <asm/psw.h> << 20 #include <asm/cache.h> /* for L1_CACH << 21 #include <asm/assembly.h> /* for LDREG/S << 22 #include <asm/signal.h> << 23 #include <asm/unistd.h> << 24 #include <asm/ldcw.h> << 25 #include <asm/traps.h> << 26 #include <asm/thread_info.h> << 27 #include <asm/alternative.h> << 28 #include <asm/spinlock_types.h> << 29 << 30 #include <linux/linkage.h> 12 #include <linux/linkage.h> >> 13 #include <linux/errno.h> 31 #include <linux/pgtable.h> 14 #include <linux/pgtable.h> 32 15 33 #ifdef CONFIG_64BIT !! 16 #include <asm/head.h> 34 .level 2.0w !! 17 #include <asm/asi.h> 35 #else !! 18 #include <asm/smp.h> 36 .level 2.0 !! 19 #include <asm/contregs.h> 37 #endif !! 20 #include <asm/ptrace.h> 38 !! 21 #include <asm/asm-offsets.h> 39 /* !! 22 #include <asm/psr.h> 40 * We need seven instructions after a TLB inse !! 23 #include <asm/vaddrs.h> 41 * The PA8800/PA8900 processors are an excepti !! 24 #include <asm/page.h> 42 * The RFI changes both IAOQ_Back and IAOQ_Fro !! 25 #include <asm/winmacro.h> 43 */ !! 26 #include <asm/signal.h> 44 #ifdef CONFIG_64BIT !! 27 #include <asm/obio.h> 45 #define NUM_PIPELINE_INSNS 12 !! 28 #include <asm/mxcc.h> 46 #else !! 29 #include <asm/thread_info.h> 47 #define NUM_PIPELINE_INSNS 7 !! 30 #include <asm/param.h> 48 #endif !! 31 #include <asm/unistd.h> 49 << 50 /* Insert num nops */ << 51 .macro insert_nops num << 52 .rept \num << 53 nop << 54 .endr << 55 .endm << 56 << 57 /* Get aligned page_table_lock address << 58 .macro get_ptl reg << 59 mfctl %cr28,\reg << 60 .endm << 61 << 62 /* space_to_prot macro creates a prot << 63 << 64 #if (SPACEID_SHIFT) == 0 << 65 .macro space_to_prot spc prot << 66 depd,z \spc,62,31,\prot << 67 .endm << 68 #else << 69 .macro space_to_prot spc prot << 70 extrd,u \spc,(64 - (SPACEID_SHIFT)),32 << 71 .endm << 72 #endif << 73 /* << 74 * The "get_stack" macros are responsi << 75 * kernel stack value. << 76 * << 77 * If sr7 == 0 << 78 * Already using a kernel sta << 79 * get_stack_use_r30 macro to << 80 * on the stack, and store re << 81 * else << 82 * Need to set up a kernel st << 83 * get_stack_use_cr30 macro t << 84 * to the pt_regs structure c << 85 * task pointer pointed to by << 86 * pointer from the task stru << 87 * << 88 * Note that we use shadowed registers << 89 * we can save %r26 and %r29. %r26 is << 90 * %r8 (a shadowed register) which tem << 91 * either the fault type ("code") or t << 92 * to use a non-shadowed register to c << 93 * the rfir in virt_map. We use %r26 s << 94 * up being passed as the argument to << 95 * or handle_interruption. %r29 is use << 96 * the register save area, and once ag << 97 * be a non-shadowed register so that << 98 */ << 99 << 100 .macro get_stack_use_cr30 << 101 << 102 /* we save the registers in the task s << 103 << 104 copy %r30, %r17 << 105 mfctl %cr30, %r1 << 106 tophys %r1,%r9 /* task_struct << 107 LDREG TASK_STACK(%r9),%r30 << 108 ldo PT_SZ_ALGN(%r30),%r30 << 109 mtsp %r0,%sr7 /* clear sr7 a << 110 mtsp %r16,%sr3 << 111 ldo TASK_REGS(%r9),%r9 << 112 STREG %r17,PT_GR30(%r9) << 113 STREG %r29,PT_GR29(%r9) << 114 STREG %r26,PT_GR26(%r9) << 115 STREG %r16,PT_SR7(%r9) << 116 copy %r9,%r29 << 117 .endm << 118 << 119 .macro get_stack_use_r30 << 120 << 121 /* we put a struct pt_regs on the stac << 122 << 123 tophys %r30,%r9 << 124 copy %r30,%r1 << 125 ldo PT_SZ_ALGN(%r30),%r30 << 126 STREG %r1,PT_GR30(%r9) << 127 STREG %r29,PT_GR29(%r9) << 128 STREG %r26,PT_GR26(%r9) << 129 STREG %r16,PT_SR7(%r9) << 130 copy %r9,%r29 << 131 .endm << 132 << 133 .macro rest_stack << 134 LDREG PT_GR1(%r29), %r1 << 135 LDREG PT_GR30(%r29),%r30 << 136 LDREG PT_GR29(%r29),%r29 << 137 .endm << 138 << 139 /* default interruption handler << 140 * (calls traps.c:handle_interruption) << 141 .macro def code << 142 b intr_save << 143 ldi \code, %r8 << 144 .align 32 << 145 .endm << 146 << 147 /* Interrupt interruption handler << 148 * (calls irq.c:do_cpu_irq_mask) */ << 149 .macro extint code << 150 b intr_extint << 151 mfsp %sr7,%r16 << 152 .align 32 << 153 .endm << 154 << 155 .import os_hpmc, code << 156 << 157 /* HPMC handler */ << 158 .macro hpmc code << 159 nop /* must be a N << 160 load32 PA(os_hpmc), %r3 << 161 bv,n 0(%r3) << 162 nop << 163 .word 0 /* checksum (w << 164 .word 0 /* address of << 165 .word 0 /* length of h << 166 .endm << 167 << 168 /* << 169 * Performance Note: Instructions will << 170 * this part of the code later on, onc << 171 * that the tlb miss handlers are clos << 172 */ << 173 << 174 /* Register definitions for tlb miss h << 175 << 176 va = r8 /* virtual address for << 177 spc = r24 /* space for which the << 178 << 179 #ifndef CONFIG_64BIT << 180 << 181 /* << 182 * itlb miss interruption handler (par << 183 */ << 184 << 185 .macro itlb_11 code << 186 << 187 mfctl %pcsq, spc << 188 b itlb_miss_11 << 189 mfctl %pcoq, va << 190 << 191 .align 32 << 192 .endm << 193 #endif << 194 << 195 /* << 196 * itlb miss interruption handler (par << 197 */ << 198 << 199 .macro itlb_20 code << 200 mfctl %pcsq, spc << 201 #ifdef CONFIG_64BIT << 202 b itlb_miss_20w << 203 #else << 204 b itlb_miss_20 << 205 #endif << 206 mfctl %pcoq, va << 207 << 208 .align 32 << 209 .endm << 210 << 211 #ifndef CONFIG_64BIT << 212 /* << 213 * naitlb miss interruption handler (p << 214 */ << 215 << 216 .macro naitlb_11 code << 217 << 218 mfctl %isr,spc << 219 b naitlb_miss_11 << 220 mfctl %ior,va << 221 << 222 .align 32 << 223 .endm << 224 #endif << 225 << 226 /* << 227 * naitlb miss interruption handler (p << 228 */ << 229 << 230 .macro naitlb_20 code << 231 << 232 mfctl %isr,spc << 233 #ifdef CONFIG_64BIT << 234 b naitlb_miss_20w << 235 #else << 236 b naitlb_miss_20 << 237 #endif << 238 mfctl %ior,va << 239 << 240 .align 32 << 241 .endm << 242 << 243 #ifndef CONFIG_64BIT << 244 /* << 245 * dtlb miss interruption handler (par << 246 */ << 247 << 248 .macro dtlb_11 code << 249 32 250 mfctl %isr, spc !! 33 #include <asm/asmmacro.h> 251 b dtlb_miss_11 << 252 mfctl %ior, va << 253 34 254 .align 32 !! 35 #define curptr g6 255 .endm << 256 #endif << 257 36 258 /* !! 37 /* These are just handy. */ 259 * dtlb miss interruption handler (par !! 38 #define _SV save %sp, -STACKFRAME_SZ, %sp 260 */ !! 39 #define _RS restore 261 !! 40 262 .macro dtlb_20 code !! 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 >> 51 arch_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 >> 61 floppy_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 >> 90 next_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 >> 111 floppy_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... */ >> 120 floppy_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 263 134 264 mfctl %isr, spc !! 135 2: 265 #ifdef CONFIG_64BIT !! 136 /* Kill some time so the bits set */ 266 b dtlb_miss_20w !! 137 WRITE_PAUSE 267 #else !! 138 WRITE_PAUSE 268 b dtlb_miss_20 !! 139 269 #endif !! 140 stb %l5, [%l7] 270 mfctl %ior, va !! 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 */ >> 152 floppy_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 >> 165 floppy_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... */ >> 175 floppy_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 271 190 272 .align 32 !! 191 RESTORE_ALL 273 .endm << 274 192 275 #ifndef CONFIG_64BIT !! 193 #endif /* (CONFIG_BLK_DEV_FD) */ 276 /* nadtlb miss interruption handler (p << 277 194 278 .macro nadtlb_11 code !! 195 /* Bad trap handler */ 279 !! 196 .globl bad_trap_handler 280 mfctl %isr,spc !! 197 bad_trap_handler: 281 b nadtlb_miss_11 !! 198 SAVE_ALL 282 mfctl %ior,va << 283 << 284 .align 32 << 285 .endm << 286 #endif << 287 << 288 /* nadtlb miss interruption handler (p << 289 199 290 .macro nadtlb_20 code !! 200 wr %l0, PSR_ET, %psr >> 201 WRITE_PAUSE 291 202 292 mfctl %isr,spc !! 203 add %sp, STACKFRAME_SZ, %o0 ! pt_regs 293 #ifdef CONFIG_64BIT !! 204 call do_hw_interrupt 294 b nadtlb_miss_20w !! 205 mov %l7, %o1 ! trap number 295 #else << 296 b nadtlb_miss_20 << 297 #endif << 298 mfctl %ior,va << 299 206 300 .align 32 !! 207 RESTORE_ALL 301 .endm << 302 208 303 #ifndef CONFIG_64BIT !! 209 /* For now all IRQ's not registered get sent here. handler_irq() will 304 /* !! 210 * see if a routine is registered to handle this interrupt and if not 305 * dirty bit trap interruption handler !! 211 * it will say so on the console. 306 */ !! 212 */ 307 << 308 .macro dbit_11 code << 309 << 310 mfctl %isr,spc << 311 b dbit_trap_11 << 312 mfctl %ior,va << 313 << 314 .align 32 << 315 .endm << 316 #endif << 317 << 318 /* << 319 * dirty bit trap interruption handler << 320 */ << 321 << 322 .macro dbit_20 code << 323 << 324 mfctl %isr,spc << 325 #ifdef CONFIG_64BIT << 326 b dbit_trap_20w << 327 #else << 328 b dbit_trap_20 << 329 #endif << 330 mfctl %ior,va << 331 << 332 .align 32 << 333 .endm << 334 << 335 /* In LP64, the space contains part of << 336 * fault. We have to extract this and << 337 * zeroing the corresponding bits in t << 338 .macro space_adjust spc,va << 339 #ifdef CONFIG_64BIT << 340 extrd,u \spc,63,SPACEID_SHIFT, << 341 depd %r0,63,SPACEID_SHIFT,\ << 342 depd \tmp,31,SPACEID_SHIFT, << 343 #endif << 344 .endm << 345 << 346 .import swapper_pg_dir,code << 347 << 348 /* Get the pgd. For faults on space z << 349 * is simply swapper_pg_dir. For user << 350 * pgd is stored in %cr25 */ << 351 .macro get_pgd spc,re << 352 ldil L%PA(swapper_pg_dir),\ << 353 ldo R%PA(swapper_pg_dir)(\ << 354 or,COND(=) %r0,\spc,%r0 << 355 mfctl %cr25,\reg << 356 .endm << 357 << 358 /* << 359 space_check(spc,tmp,fault) << 360 << 361 spc - The space we saw the fau << 362 tmp - The place to store the c << 363 fault - Function to call on fa << 364 << 365 Only allow faults on different << 366 currently active one if we're << 367 << 368 */ << 369 .macro space_check spc,tm << 370 mfsp %sr7,\tmp << 371 /* check against %r0 which is same val << 372 or,COND(<>) %r0,\spc,%r0 /* use << 373 * as << 374 * che << 375 copy \spc,\tmp << 376 or,COND(=) %r0,\tmp,%r0 /* nul << 377 cmpb,COND(<>),n \tmp,\spc,\fault << 378 .endm << 379 << 380 /* Look up a PTE in a 2-Level scheme ( << 381 * level if the entry isn't present << 382 * << 383 * NOTE: we use ldw even for LP64, sin << 384 * can address up to 1TB << 385 */ << 386 .macro L2_ptep pmd,pte,index, << 387 #if CONFIG_PGTABLE_LEVELS == 3 << 388 extru_safe \va,31-ASM_PMD_SHIFT,A << 389 #else << 390 extru_safe \va,31-ASM_PGDIR_SHIFT << 391 #endif << 392 dep %r0,31,PAGE_SHIFT,\pmd << 393 #if CONFIG_PGTABLE_LEVELS < 3 << 394 copy %r0,\pte << 395 #endif << 396 ldw,s \index(\pmd),\pmd << 397 bb,>=,n \pmd,_PxD_PRESENT_BIT, << 398 dep %r0,31,PxD_FLAG_SHIFT, << 399 SHLREG \pmd,PxD_VALUE_SHIFT,\ << 400 extru_safe \va,31-PAGE_SHIFT,ASM_ << 401 dep %r0,31,PAGE_SHIFT,\pmd << 402 shladd \index,BITS_PER_PTE_EN << 403 .endm << 404 << 405 /* Look up PTE in a 3-Level scheme. */ << 406 .macro L3_ptep pgd,pte,index, << 407 #if CONFIG_PGTABLE_LEVELS == 3 << 408 copy %r0,\pte << 409 extrd,u \va,63-ASM_PGDIR_SHIFT << 410 ldw,s \index(\pgd),\pgd << 411 bb,>=,n \pgd,_PxD_PRESENT_BIT, << 412 shld \pgd,PxD_VALUE_SHIFT,\ << 413 #endif << 414 L2_ptep \pgd,\pte,\index,\va,\ << 415 .endm << 416 << 417 /* Acquire page_table_lock and check p << 418 .macro ptl_lock spc,pt << 419 #ifdef CONFIG_TLB_PTLOCK << 420 98: cmpib,COND(=),n 0,\spc,2f << 421 get_ptl \tmp << 422 1: LDCW 0(\tmp),\tmp1 << 423 cmpib,COND(=) 0,\tmp1,1b << 424 nop << 425 LDREG 0(\ptp),\pte << 426 bb,<,n \pte,_PAGE_PRESENT_BIT << 427 b \fault << 428 stw \tmp1,0(\tmp) << 429 99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, << 430 #endif << 431 2: LDREG 0(\ptp),\pte << 432 bb,>=,n \pte,_PAGE_PRESENT_BIT << 433 3: << 434 .endm << 435 << 436 /* Release page_table_lock if for user << 437 store to ensure all prior accesses << 438 releasing the lock. Note stw may no << 439 provide one extra nop when CONFIG_T << 440 .macro ptl_unlock spc,tm << 441 #ifdef CONFIG_TLB_PTLOCK << 442 98: get_ptl \tmp << 443 ldi __ARCH_SPIN_LOCK_UNLOC << 444 or,COND(=) %r0,\spc,%r0 << 445 stw,ma \tmp2,0(\tmp) << 446 99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, << 447 insert_nops NUM_PIPELINE_INSNS - 4 << 448 #else << 449 insert_nops NUM_PIPELINE_INSNS - 1 << 450 #endif << 451 .endm << 452 << 453 /* Set the _PAGE_ACCESSED bit of the P << 454 * don't needlessly dirty the cache li << 455 .macro update_accessed ptp,pt << 456 ldi _PAGE_ACCESSED,\tmp1 << 457 or \tmp1,\pte,\tmp << 458 and,COND(<>) \tmp1,\pte,%r0 << 459 STREG \tmp,0(\ptp) << 460 .endm << 461 << 462 /* Set the dirty bit (and accessed bit << 463 * clever, this is only used from the << 464 .macro update_dirty ptp,pt << 465 ldi _PAGE_ACCESSED|_PAGE_D << 466 or \tmp,\pte,\pte << 467 STREG \pte,0(\ptp) << 468 .endm << 469 << 470 /* We have (depending on the page size << 471 * - 38 to 52-bit Physical Page Number << 472 * - 12 to 26-bit page offset << 473 */ << 474 /* bitshift difference between a PFN ( << 475 * to a CPU TLB 4k PFN (4k => 12 bits << 476 #define PAGE_ADD_SHIFT (PAGE_ << 477 #define PAGE_ADD_HUGE_SHIFT (REAL_ << 478 #define PFN_START_BIT (63-ASM_PFN_PT << 479 << 480 /* Drop prot bits and convert to page << 481 .macro convert_for_tlb_insert << 482 #ifdef CONFIG_HUGETLB_PAGE << 483 copy \pte,\tmp << 484 extrd,u \tmp,PFN_START_BIT,PFN << 485 << 486 depdi _PAGE_SIZE_ENCODING_DE << 487 (63-58)+PAGE_A << 488 extrd,u,*= \tmp,_PAGE_HPAGE_BIT+3 << 489 depdi _HUGE_PAGE_SIZE_ENCODI << 490 (63-58)+PAGE_A << 491 #else /* Huge pages disabled */ << 492 extrd,u \pte,PFN_START_BIT,PFN << 493 depdi _PAGE_SIZE_ENCODING_DE << 494 (63-58)+PAGE_A << 495 #endif << 496 .endm << 497 << 498 /* Convert the pte and prot to tlb ins << 499 * this happens is quite subtle, read << 500 .macro make_insert_tlb spc,pt << 501 space_to_prot \spc \prot /* c << 502 /* The following is the real subtlety. << 503 * T <-> _PAGE_REFTRAP << 504 * D <-> _PAGE_DIRTY << 505 * B <-> _PAGE_DMB (memory break) << 506 * << 507 * Then incredible subtlety: The acces << 508 * _PAGE_GATEWAY, _PAGE_EXEC and _PAGE << 509 * See 3-14 of the parisc 2.0 manual << 510 * << 511 * Finally, _PAGE_READ goes in the top << 512 * trigger an access rights trap in us << 513 * tries to read an unreadable page */ << 514 #if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT << 515 /* need to drop DMB bit, as it's used << 516 depi 0,_PAGE_SPECIAL_BIT,1, << 517 #endif << 518 depd \pte,8,7,\prot << 519 << 520 /* PAGE_USER indicates the page can be << 521 * so deposit X1|11 to PL1|PL2 (rememb << 522 * contains _PAGE_READ) */ << 523 extrd,u,*= \pte,_PAGE_USER_BIT+32 << 524 depdi 7,11,3,\prot << 525 /* If we're a gateway page, drop PL2 b << 526 * to kernel privilege (so we can exec << 527 * Any privilege promotion page always << 528 extrd,u,*= \pte,_PAGE_GATEWAY_BIT << 529 depd %r0,11,2,\prot /* If << 530 << 531 /* Enforce uncacheable pages. << 532 * This should ONLY be use for MMIO on << 533 * Memory/DMA is cache coherent on all << 534 * (that means T-class is NOT supporte << 535 * on most of those machines only hand << 536 */ << 537 extrd,u,*= \pte,_PAGE_NO_CACHE_BI << 538 depdi 1,12,1,\prot << 539 << 540 /* Drop prot bits and convert to page << 541 convert_for_tlb_insert20 \pte \tmp << 542 .endm << 543 << 544 /* Identical macro to make_insert_tlb << 545 * makes the tlb entry for the differe << 546 * insertion instructions */ << 547 .macro make_insert_tlb_11 << 548 #if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT << 549 /* need to drop DMB bit, as it's used << 550 depi 0,_PAGE_SPECIAL_BIT,1, << 551 #endif << 552 zdep \spc,30,15,\prot << 553 dep \pte,8,7,\prot << 554 extru,= \pte,_PAGE_NO_CACHE_BI << 555 depi 1,12,1,\prot << 556 extru,= \pte,_PAGE_USER_BIT,1, << 557 depi 7,11,3,\prot /* Set << 558 extru,= \pte,_PAGE_GATEWAY_BIT << 559 depi 0,11,2,\prot /* If << 560 << 561 /* Get rid of prot bits and convert to << 562 << 563 depi 0,31,ASM_PFN_PTE_SHIFT << 564 SHRREG \pte,(ASM_PFN_PTE_SHIF << 565 .endm << 566 << 567 /* This is for ILP32 PA2.0 only. The << 568 * to extend into I/O space if the add << 569 * so we extend the f's into the top w << 570 * this case */ << 571 .macro f_extend pte,tm << 572 extrd,s \pte,42,4,\tmp << 573 addi,<> 1,\tmp,%r0 << 574 extrd,s \pte,63,25,\pte << 575 .endm << 576 << 577 /* The alias region is comprised of a << 578 * aligned to 8 MB. It is used to clea << 579 * using kernel virtual addresses cong << 580 * virtual address. << 581 * << 582 * To use the alias page, you set %r26 << 583 * entry (identifying the physical pag << 584 * the from tlb entry (or nothing if o << 585 * clear_user_page_asm) */ << 586 .macro do_alias spc,tm << 587 cmpib,COND(<>),n 0,\spc,\fault << 588 ldil L%(TMPALIAS_MAP_START) << 589 copy \va,\tmp1 << 590 depi_safe 0,31,TMPALIAS_SIZE_BIT << 591 cmpb,COND(<>),n \tmp,\tmp1,\fault << 592 mfctl %cr19,\tmp /* iir << 593 /* get the opcode (first six bits) int << 594 extrw,u \tmp,5,6,\tmp << 595 /* << 596 * Only setting the T bit prevents dat << 597 * Setting access rights to zero preve << 598 * << 599 * Note subtlety here: _PAGE_GATEWAY, << 600 * to type field and _PAGE_READ goes t << 601 */ << 602 ldi (_PAGE_REFTRAP|_PAGE_R << 603 /* << 604 * so if the opcode is one (i.e. this << 605 * instruction) nullify the next load << 606 * Otherwise this is a normal data ope << 607 */ << 608 cmpiclr,= 0x01,\tmp,%r0 << 609 ldi (_PAGE_DIRTY|_PAGE_REA << 610 .ifc \patype,20 << 611 depd,z \prot,8,7,\prot << 612 .else << 613 .ifc \patype,11 << 614 depw,z \prot,8,7,\prot << 615 .else << 616 .error "undefined PA type to do_alias" << 617 .endif << 618 .endif << 619 /* << 620 * OK, it is in the temp alias region, << 621 * Check "subtle" note in pacache.S re << 622 */ << 623 extrw,u,= \va,31-TMPALIAS_SIZE_B << 624 or,COND(tr) %r23,%r0,\pte << 625 or %r26,%r0,\pte << 626 << 627 /* convert phys addr in \pte (from r23 << 628 SHRREG \pte,PAGE_SHIFT+PAGE_A << 629 depi_safe _PAGE_SIZE_ENCODING_DE << 630 .endm << 631 << 632 << 633 /* << 634 * Fault_vectors are architecturally r << 635 * boundary << 636 */ << 637 << 638 .section .text.hot << 639 .align 2048 << 640 << 641 ENTRY(fault_vector_20) << 642 /* First vector is invalid (0) */ << 643 .ascii "cows can fly" << 644 .byte 0 << 645 .align 32 << 646 << 647 hpmc 1 << 648 def 2 << 649 def 3 << 650 extint 4 << 651 def 5 << 652 itlb_20 PARISC_ITLB_TRAP << 653 def 7 << 654 def 8 << 655 def 9 << 656 def 10 << 657 def 11 << 658 def 12 << 659 def 13 << 660 def 14 << 661 dtlb_20 15 << 662 naitlb_20 16 << 663 nadtlb_20 17 << 664 def 18 << 665 def 19 << 666 dbit_20 20 << 667 def 21 << 668 def 22 << 669 def 23 << 670 def 24 << 671 def 25 << 672 def 26 << 673 def 27 << 674 def 28 << 675 def 29 << 676 def 30 << 677 def 31 << 678 END(fault_vector_20) << 679 << 680 #ifndef CONFIG_64BIT << 681 << 682 .align 2048 << 683 << 684 ENTRY(fault_vector_11) << 685 /* First vector is invalid (0) */ << 686 .ascii "cows can fly" << 687 .byte 0 << 688 .align 32 << 689 << 690 hpmc 1 << 691 def 2 << 692 def 3 << 693 extint 4 << 694 def 5 << 695 itlb_11 PARISC_ITLB_TRAP << 696 def 7 << 697 def 8 << 698 def 9 << 699 def 10 << 700 def 11 << 701 def 12 << 702 def 13 << 703 def 14 << 704 dtlb_11 15 << 705 naitlb_11 16 << 706 nadtlb_11 17 << 707 def 18 << 708 def 19 << 709 dbit_11 20 << 710 def 21 << 711 def 22 << 712 def 23 << 713 def 24 << 714 def 25 << 715 def 26 << 716 def 27 << 717 def 28 << 718 def 29 << 719 def 30 << 720 def 31 << 721 END(fault_vector_11) << 722 << 723 #endif << 724 /* Fault vector is separately protecte << 725 .align PAGE_SIZE << 726 << 727 .import handle_interruption,co << 728 .import do_cpu_irq_mask,code << 729 213 730 /* !! 214 .align 4 731 * Child Returns here !! 215 .globl real_irq_entry, patch_handler_irq >> 216 real_irq_entry: >> 217 SAVE_ALL >> 218 >> 219 #ifdef CONFIG_SMP >> 220 .globl patchme_maybe_smp_msg >> 221 >> 222 cmp %l7, 11 >> 223 patchme_maybe_smp_msg: >> 224 bgu maybe_smp4m_msg >> 225 nop >> 226 #endif >> 227 >> 228 real_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 >> 235 patch_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. */ >> 246 smp4m_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. 732 * 267 * 733 * copy_thread moved args into task sa !! 268 * IPIs are sent on Level 12, 13 and 14. See IRQ_IPI_*. 734 */ 269 */ >> 270 maybe_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 >> 292 maybe_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 >> 299 maybe_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 >> 305 maybe_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 >> 311 maybe_smp4m_msg_out: >> 312 RESTORE_ALL >> 313 >> 314 .align 4 >> 315 .globl linux_trap_ipi15_sun4m >> 316 linux_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. */ >> 343 smp4d_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 >> 362 linux_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 >> 387 1: /* MXCC error */ >> 388 2: /* 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 */ >> 396 1: b,a 1b >> 397 >> 398 .globl smpleon_ipi >> 399 .extern leon_ipi_interrupt >> 400 /* SMP per-cpu IPI interrupts are handled specially. */ >> 401 smpleon_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 >> 416 linux_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 >> 435 bad_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 >> 455 1: /* unimplemented flush - just skip */ >> 456 jmpl %l2, %g0 >> 457 rett %l2 + 4 >> 458 >> 459 .align 4 >> 460 .globl priv_instruction >> 461 priv_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 >> 478 mna_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 >> 494 mna_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 >> 509 fpd_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 >> 526 fpe_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 >> 540 1: >> 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 735 547 736 ENTRY(ret_from_kernel_thread) !! 548 2: 737 /* Call schedule_tail first though */ !! 549 SAVE_ALL 738 BL schedule_tail, %r2 << 739 nop << 740 550 741 mfctl %cr30,%r1 /* task_struct !! 551 wr %l0, PSR_ET, %psr ! re-enable traps 742 LDREG TASK_PT_GR25(%r1), %r26 !! 552 WRITE_PAUSE 743 #ifdef CONFIG_64BIT << 744 LDREG TASK_PT_GR27(%r1), %r27 << 745 #endif << 746 LDREG TASK_PT_GR26(%r1), %r1 << 747 ble 0(%sr7, %r1) << 748 copy %r31, %r2 << 749 b finish_child_return << 750 nop << 751 END(ret_from_kernel_thread) << 752 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 >> 565 do_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 >> 582 do_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 >> 599 do_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 >> 616 do_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 >> 633 do_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 >> 650 do_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 >> 666 do_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() */ >> 690 dfw_kernel: >> 691 flush_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 >> 708 getcc_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 >> 721 setcc_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 >> 734 sun4m_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 >> 759 linux_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 >> 768 srmmu_fault: >> 769 mov 0x400, %l5 >> 770 mov 0x300, %l4 >> 771 >> 772 LEON_PI(lda [%l5] ASI_LEON_MMUREGS, %l6) ! read sfar first >> 773 SUN_PI_(lda [%l5] ASI_M_MMUREGS, %l6) ! read sfar first >> 774 >> 775 LEON_PI(lda [%l4] ASI_LEON_MMUREGS, %l5) ! read sfsr last >> 776 SUN_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 >> 804 sunos_execv: >> 805 .globl sunos_execv >> 806 b sys_execve >> 807 clr %i2 >> 808 >> 809 .align 4 >> 810 .globl sys_sigstack >> 811 sys_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 >> 819 sys_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 753 827 754 /* !! 828 call syscall_trace 755 * struct task_struct *_switch_to(stru !! 829 mov 1, %o1 756 * struct task_struct *next) << 757 * << 758 * switch kernel stacks and return pre << 759 ENTRY_CFI(_switch_to) << 760 STREG %r2, -RP_OFFSET(%r30) << 761 << 762 callee_save_float << 763 callee_save << 764 << 765 load32 _switch_to_ret, %r2 << 766 << 767 STREG %r2, TASK_PT_KPC(%r26) << 768 LDREG TASK_PT_KPC(%r25), %r2 << 769 << 770 STREG %r30, TASK_PT_KSP(%r26) << 771 LDREG TASK_PT_KSP(%r25), %r30 << 772 bv %r0(%r2) << 773 mtctl %r25,%cr30 << 774 << 775 ENTRY(_switch_to_ret) << 776 mtctl %r0, %cr0 /* Nee << 777 callee_rest << 778 callee_rest_float << 779 << 780 LDREG -RP_OFFSET(%r30), %r2 << 781 bv %r0(%r2) << 782 copy %r26, %r28 << 783 ENDPROC_CFI(_switch_to) << 784 830 785 /* !! 831 1: 786 * Common rfi return path for interrup !! 832 /* We don't want to muck with user registers like a 787 * sys_rt_sigreturn (sometimes). The !! 833 * normal syscall, just return. 788 * return via this path if the signal << 789 * was running; if the process was blo << 790 * normal syscall_exit path is used. << 791 * proceses exit via intr_restore. << 792 * << 793 * XXX If any syscalls that change a p << 794 * this way, then we will need to copy << 795 * adjust IASQ[0..1]. << 796 * << 797 */ 834 */ >> 835 RESTORE_ALL 798 836 799 .align PAGE_SIZE !! 837 .align 4 800 !! 838 .globl sys_rt_sigreturn 801 ENTRY_CFI(syscall_exit_rfi) !! 839 sys_rt_sigreturn: 802 mfctl %cr30,%r16 /* tas !! 840 call do_rt_sigreturn 803 ldo TASK_REGS(%r16),%r16 !! 841 add %sp, STACKFRAME_SZ, %o0 804 /* Force iaoq to userspace, as the use !! 842 805 * context via sigcontext. Also Filter !! 843 ld [%curptr + TI_FLAGS], %l5 806 */ !! 844 andcc %l5, _TIF_SYSCALL_TRACE, %g0 807 LDREG PT_IAOQ0(%r16),%r19 !! 845 be 1f 808 depi PRIV_USER,31,2,%r19 !! 846 nop 809 STREG %r19,PT_IAOQ0(%r16) !! 847 810 LDREG PT_IAOQ1(%r16),%r19 !! 848 add %sp, STACKFRAME_SZ, %o0 811 depi PRIV_USER,31,2,%r19 !! 849 call syscall_trace 812 STREG %r19,PT_IAOQ1(%r16) !! 850 mov 1, %o1 813 LDREG PT_PSW(%r16),%r19 << 814 load32 USER_PSW_MASK,%r1 << 815 #ifdef CONFIG_64BIT << 816 load32 USER_PSW_HI_MASK,%r20 << 817 depd %r20,31,32,%r1 << 818 #endif << 819 and %r19,%r1,%r19 /* Mask out bits << 820 load32 USER_PSW,%r1 << 821 or %r19,%r1,%r19 /* Make sure def << 822 STREG %r19,PT_PSW(%r16) << 823 851 824 /* !! 852 1: 825 * If we aren't being traced, we never !! 853 /* We are returning to a signal handler. */ 826 * (we don't store them in the sigcont !! 854 RESTORE_ALL 827 * to "proper" values now (otherwise w << 828 * whatever was last stored in the tas << 829 * be inconsistent if an interrupt occ << 830 * page). Note that we may be "trashin << 831 * them, but we don't support the user << 832 */ << 833 855 834 STREG %r0,PT_SR2(%r16) !! 856 /* Now that we have a real sys_clone, sys_fork() is 835 mfsp %sr3,%r19 !! 857 * implemented in terms of it. Our _real_ implementation 836 STREG %r19,PT_SR0(%r16) !! 858 * of SunOS vfork() will use sys_vfork(). 837 STREG %r19,PT_SR1(%r16) << 838 STREG %r19,PT_SR3(%r16) << 839 STREG %r19,PT_SR4(%r16) << 840 STREG %r19,PT_SR5(%r16) << 841 STREG %r19,PT_SR6(%r16) << 842 STREG %r19,PT_SR7(%r16) << 843 << 844 ENTRY(intr_return) << 845 /* check for reschedule */ << 846 mfctl %cr30,%r1 << 847 LDREG TASK_TI_FLAGS(%r1),%r19 /* sch << 848 bb,<,n %r19,31-TIF_NEED_RESCHED,intr_ << 849 << 850 .import do_notify_resume,code << 851 intr_check_sig: << 852 /* As above */ << 853 mfctl %cr30,%r1 << 854 LDREG TASK_TI_FLAGS(%r1),%r19 << 855 ldi (_TIF_USER_WORK_MASK & ~_TIF_N << 856 and,COND(<>) %r19, %r20, %r0 << 857 b,n intr_restore /* skip past i << 858 << 859 /* This check is critical to having LW << 860 * working. The IASQ is zero on the ga << 861 * page and we cannot deliver any sign << 862 * we get off the gateway page. << 863 * 859 * 864 * Only do signals if we are returning !! 860 * XXX These three should be consolidated into mostly shared 865 */ !! 861 * XXX code just like on sparc64... -DaveM 866 LDREG PT_IASQ0(%r16), %r20 << 867 cmpib,COND(=),n LINUX_GATEWAY_SPACE, % << 868 LDREG PT_IASQ1(%r16), %r20 << 869 cmpib,COND(=),n LINUX_GATEWAY_SPACE, % << 870 << 871 copy %r0, %r25 << 872 #ifdef CONFIG_64BIT << 873 ldo -16(%r30),%r29 << 874 #endif << 875 << 876 /* NOTE: We need to enable interrupts << 877 * signals. We used to do this earlier << 878 * stack overflows. */ << 879 ssm PSW_SM_I, %r0 << 880 << 881 BL do_notify_resume,%r2 << 882 copy %r16, %r26 << 883 << 884 b,n intr_check_sig << 885 << 886 intr_restore: << 887 copy %r16,%r29 << 888 ldo PT_FR31(%r29),%r1 << 889 rest_fp %r1 << 890 rest_general %r29 << 891 << 892 /* inverse of virt_map */ << 893 pcxt_ssm_bug << 894 rsm PSW_SM_QUIET,%r0 << 895 tophys_r1 %r29 << 896 << 897 /* Restore space id's and special cr's << 898 * structure pointed to by r29 << 899 */ 862 */ 900 rest_specials %r29 !! 863 .align 4 901 !! 864 .globl sys_fork, flush_patch_two 902 /* IMPORTANT: rest_stack restores r29 !! 865 sys_fork: 903 * It also restores r1 and r30. !! 866 mov %o7, %l5 904 */ !! 867 flush_patch_two: 905 rest_stack !! 868 FLUSH_ALL_KERNEL_WINDOWS; 906 !! 869 ld [%curptr + TI_TASK], %o4 907 rfi !! 870 rd %psr, %g4 908 nop !! 871 WRITE_PAUSE 909 !! 872 rd %wim, %g5 910 #ifndef CONFIG_PREEMPTION !! 873 WRITE_PAUSE 911 # define intr_do_preempt intr_restore !! 874 std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] 912 #endif /* !CONFIG_PREEMPTION */ !! 875 add %sp, STACKFRAME_SZ, %o0 913 !! 876 call sparc_fork 914 .import schedule,code !! 877 mov %l5, %o7 915 intr_do_resched: !! 878 916 /* Only call schedule on return to use !! 879 /* Whee, kernel threads! */ 917 * to kernel space, we may schedule if !! 880 .globl sys_clone, flush_patch_three 918 * we jump back to intr_restore. !! 881 sys_clone: 919 */ !! 882 mov %o7, %l5 920 LDREG PT_IASQ0(%r16), %r20 !! 883 flush_patch_three: 921 cmpib,COND(=) 0, %r20, intr_do_preem !! 884 FLUSH_ALL_KERNEL_WINDOWS; 922 nop !! 885 ld [%curptr + TI_TASK], %o4 923 LDREG PT_IASQ1(%r16), %r20 !! 886 rd %psr, %g4 924 cmpib,COND(=) 0, %r20, intr_do_preem !! 887 WRITE_PAUSE 925 nop !! 888 rd %wim, %g5 926 !! 889 WRITE_PAUSE 927 /* NOTE: We need to enable interrupts !! 890 std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] 928 * to do this earlier but it caused ke !! 891 add %sp, STACKFRAME_SZ, %o0 929 ssm PSW_SM_I, %r0 !! 892 call sparc_clone 930 !! 893 mov %l5, %o7 931 #ifdef CONFIG_64BIT !! 894 932 ldo -16(%r30),%r29 /* Ref !! 895 /* Whee, real vfork! */ 933 #endif !! 896 .globl sys_vfork, flush_patch_four 934 !! 897 sys_vfork: 935 ldil L%intr_check_sig, %r2 !! 898 flush_patch_four: 936 #ifndef CONFIG_64BIT !! 899 FLUSH_ALL_KERNEL_WINDOWS; 937 b schedule !! 900 ld [%curptr + TI_TASK], %o4 938 #else !! 901 rd %psr, %g4 939 load32 schedule, %r20 !! 902 WRITE_PAUSE 940 bv %r0(%r20) !! 903 rd %wim, %g5 941 #endif !! 904 WRITE_PAUSE 942 ldo R%intr_check_sig(%r2), %r2 !! 905 std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] 943 !! 906 sethi %hi(sparc_vfork), %l1 944 /* preempt the current task on returni !! 907 jmpl %l1 + %lo(sparc_vfork), %g0 945 * mode from an interrupt, iff need_re !! 908 add %sp, STACKFRAME_SZ, %o0 946 * and preempt_count is 0. otherwise, !! 909 947 * our merry way back to the current r !! 910 .align 4 948 */ !! 911 linux_sparc_ni_syscall: 949 #ifdef CONFIG_PREEMPTION !! 912 sethi %hi(sys_ni_syscall), %l7 950 .import preempt_schedule_irq,code !! 913 b do_syscall 951 intr_do_preempt: !! 914 or %l7, %lo(sys_ni_syscall), %l7 952 rsm PSW_SM_I, %r0 /* dis !! 915 953 !! 916 linux_syscall_trace: 954 /* current_thread_info()->preempt_coun !! 917 add %sp, STACKFRAME_SZ, %o0 955 mfctl %cr30, %r1 !! 918 call syscall_trace 956 ldw TI_PRE_COUNT(%r1), %r19 !! 919 mov 0, %o1 957 cmpib,<> 0, %r19, intr_restore !! 920 cmp %o0, 0 958 nop /* pre !! 921 bne 3f 959 !! 922 mov -ENOSYS, %o0 960 /* check if we interrupted a critical !! 923 961 LDREG PT_PSW(%r16), %r20 !! 924 /* Syscall tracing can modify the registers. */ 962 bb,<,n %r20, 31 - PSW_SM_I, intr_rest !! 925 ld [%sp + STACKFRAME_SZ + PT_G1], %g1 963 nop !! 926 sethi %hi(sys_call_table), %l7 964 !! 927 ld [%sp + STACKFRAME_SZ + PT_I0], %i0 965 /* ssm PSW_SM_I done later in intr_res !! 928 or %l7, %lo(sys_call_table), %l7 966 #ifdef CONFIG_MLONGCALLS !! 929 ld [%sp + STACKFRAME_SZ + PT_I1], %i1 967 ldil L%intr_restore, %r2 !! 930 ld [%sp + STACKFRAME_SZ + PT_I2], %i2 968 load32 preempt_schedule_irq, %r1 !! 931 ld [%sp + STACKFRAME_SZ + PT_I3], %i3 969 bv %r0(%r1) !! 932 ld [%sp + STACKFRAME_SZ + PT_I4], %i4 970 ldo R%intr_restore(%r2), %r2 !! 933 ld [%sp + STACKFRAME_SZ + PT_I5], %i5 971 #else !! 934 cmp %g1, NR_syscalls 972 ldil L%intr_restore, %r1 !! 935 bgeu 3f 973 BL preempt_schedule_irq, %r2 !! 936 mov -ENOSYS, %o0 974 ldo R%intr_restore(%r1), %r2 !! 937 975 #endif !! 938 sll %g1, 2, %l4 976 #endif /* CONFIG_PREEMPTION */ !! 939 mov %i0, %o0 977 !! 940 ld [%l7 + %l4], %l7 978 /* !! 941 mov %i1, %o1 979 * External interrupts. !! 942 mov %i2, %o2 980 */ !! 943 mov %i3, %o3 981 << 982 intr_extint: << 983 cmpib,COND(=),n 0,%r16,1f << 984 << 985 get_stack_use_cr30 << 986 b,n 2f << 987 << 988 1: << 989 get_stack_use_r30 << 990 2: << 991 save_specials %r29 << 992 virt_map << 993 save_general %r29 << 994 << 995 ldo PT_FR0(%r29), %r24 << 996 save_fp %r24 << 997 << 998 loadgp << 999 << 1000 copy %r29, %r26 /* arg0 is pt << 1001 copy %r29, %r16 /* save pt_re << 1002 << 1003 ldil L%intr_return, %r2 << 1004 << 1005 #ifdef CONFIG_64BIT << 1006 ldo -16(%r30),%r29 /* Reference << 1007 #endif << 1008 << 1009 b do_cpu_irq_mask << 1010 ldo R%intr_return(%r2), %r2 /* re << 1011 ENDPROC_CFI(syscall_exit_rfi) << 1012 << 1013 << 1014 /* Generic interruptions (illegal ins << 1015 << 1016 ENTRY_CFI(intr_save) /* for os_hpm << 1017 mfsp %sr7,%r16 << 1018 cmpib,COND(=),n 0,%r16,1f << 1019 get_stack_use_cr30 << 1020 b 2f 944 b 2f 1021 copy %r8,%r26 !! 945 mov %i4, %o4 1022 << 1023 1: << 1024 get_stack_use_r30 << 1025 copy %r8,%r26 << 1026 946 >> 947 .globl ret_from_fork >> 948 ret_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 >> 955 ret_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 >> 974 linux_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 >> 983 do_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 1027 2: 998 2: 1028 save_specials %r29 !! 999 call %l7 1029 !! 1000 mov %i5, %o5 1030 /* If this trap is a itlb miss, skip << 1031 cmpib,COND(=),n PARISC_ITLB_TR << 1032 << 1033 << 1034 mfctl %isr, %r16 << 1035 nop /* serialize mfctl on << 1036 mfctl %ior, %r17 << 1037 << 1038 << 1039 #ifdef CONFIG_64BIT << 1040 /* << 1041 * If the interrupted code was runnin << 1042 * clear the b bits (bits 0 & 1) in t << 1043 * save_specials left ipsw value in r << 1044 */ << 1045 extrd,u,*<> %r8,PSW_W_BIT,1,%r0 << 1046 depdi 0,1,2,%r17 << 1047 1001 1048 /* adjust isr/ior: get high bits from !! 1002 3: 1049 space_adjust %r16,%r17,%r1 !! 1003 st %o0, [%sp + STACKFRAME_SZ + PT_I0] 1050 #endif << 1051 STREG %r16, PT_ISR(%r29) << 1052 STREG %r17, PT_IOR(%r29) << 1053 << 1054 #if defined(CONFIG_64BIT) << 1055 b,n intr_save2 << 1056 1004 1057 skip_save_ior: !! 1005 ret_sys_call: 1058 /* We have a itlb miss, and when exec !! 1006 ld [%curptr + TI_FLAGS], %l5 1059 * need to adjust iasq/iaoq here in t !! 1007 cmp %o0, -ERESTART_RESTARTBLOCK 1060 * above. !! 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] >> 1022 1: >> 1023 /* System call failure, set Carry condition code. >> 1024 * Also, get abs(errno) to return to the process. 1061 */ 1025 */ 1062 bb,COND(>=),n %r8,PSW_W_BIT,intr_sa !! 1026 sub %g0, %o0, %o0 1063 LDREG PT_IASQ0(%r29), %r16 !! 1027 or %g3, %g2, %g3 1064 LDREG PT_IAOQ0(%r29), %r17 !! 1028 st %o0, [%sp + STACKFRAME_SZ + PT_I0] 1065 /* adjust iasq/iaoq */ !! 1029 st %g3, [%sp + STACKFRAME_SZ + PT_PSR] 1066 space_adjust %r16,%r17,%r1 !! 1030 bne linux_syscall_trace2 1067 STREG %r16, PT_IASQ0(%r29) !! 1031 ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */ 1068 STREG %r17, PT_IAOQ0(%r29) !! 1032 add %l1, 0x4, %l2 /* npc = npc+4 */ 1069 #else !! 1033 st %l1, [%sp + STACKFRAME_SZ + PT_PC] 1070 skip_save_ior: !! 1034 b ret_trap_entry 1071 #endif !! 1035 st %l2, [%sp + STACKFRAME_SZ + PT_NPC] 1072 !! 1036 1073 intr_save2: !! 1037 linux_syscall_trace2: 1074 virt_map !! 1038 add %sp, STACKFRAME_SZ, %o0 1075 save_general %r29 !! 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] 1076 1045 1077 ldo PT_FR0(%r29), %r25 << 1078 save_fp %r25 << 1079 << 1080 loadgp << 1081 1046 1082 copy %r29, %r25 /* ar !! 1047 /* Saving and restoring the FPU state is best done from lowlevel code. 1083 #ifdef CONFIG_64BIT !! 1048 * 1084 ldo -16(%r30),%r29 /* Re !! 1049 * void fpsave(unsigned long *fpregs, unsigned long *fsr, 1085 #endif !! 1050 * void *fpqueue, unsigned long *fpqdepth) >> 1051 */ 1086 1052 1087 ldil L%intr_check_sig, %r2 !! 1053 .globl fpsave 1088 copy %r25, %r16 /* sa !! 1054 fpsave: >> 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 1089 1061 1090 b handle_interruption !! 1062 /* We have an fpqueue to save. */ 1091 ldo R%intr_check_sig(%r2) !! 1063 1: 1092 ENDPROC_CFI(intr_save) !! 1064 std %fq, [%o2] >> 1065 fpsave_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 1093 1072 >> 1073 2: >> 1074 st %g2, [%o3] 1094 1075 1095 /* !! 1076 std %f0, [%o0 + 0x00] 1096 * Note for all tlb miss handlers: !! 1077 std %f2, [%o0 + 0x08] 1097 * !! 1078 std %f4, [%o0 + 0x10] 1098 * cr24 contains a pointer to the ker !! 1079 std %f6, [%o0 + 0x18] 1099 * page directory. !! 1080 std %f8, [%o0 + 0x20] 1100 * !! 1081 std %f10, [%o0 + 0x28] 1101 * cr25 contains a pointer to the cur !! 1082 std %f12, [%o0 + 0x30] 1102 * space page directory. !! 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 */ >> 1099 fpsave_catch: >> 1100 b fpsave_magic + 4 >> 1101 st %fsr, [%o1] >> 1102 >> 1103 fpsave_catch2: >> 1104 b fpsave + 4 >> 1105 st %fsr, [%o1] >> 1106 >> 1107 /* void fpload(unsigned long *fpregs, unsigned long *fsr); */ >> 1108 >> 1109 .globl fpload >> 1110 fpload: >> 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) 1103 * 1134 * 1104 * sr3 will contain the space id of t !! 1135 * Note that ndelay gives HZ times higher resolution but has a 10ms 1105 * of the current running thread whil !! 1136 * limit. udelay can handle up to 1s. 1106 * running in the kernel. << 1107 */ 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 >> 1167 3: >> 1168 mov HZ, %o0 ! >>32 earlier for wider range >> 1169 umul %o0, %o1, %o0 >> 1170 rd %y, %o1 1108 1171 1109 /* !! 1172 delay_continue: 1110 * register number allocations. Note !! 1173 cmp %o0, 0x0 1111 * in the shadowed registers !! 1174 1: 1112 */ !! 1175 bne 1b 1113 !! 1176 subcc %o0, 1, %o0 1114 t0 = r1 /* temporary register << 1115 va = r8 /* virtual address fo << 1116 t1 = r9 /* temporary register << 1117 pte = r16 /* pte/phys page # */ << 1118 prot = r17 /* prot bits */ << 1119 spc = r24 /* space for which th << 1120 ptp = r25 /* page directory/pag << 1121 << 1122 #ifdef CONFIG_64BIT << 1123 << 1124 dtlb_miss_20w: << 1125 space_adjust spc,va,t0 << 1126 get_pgd spc,ptp << 1127 space_check spc,t0,dtlb_fault << 1128 << 1129 L3_ptep ptp,pte,t0,va,dtlb_ch << 1130 << 1131 ptl_lock spc,ptp,pte,t0,t1,dtl << 1132 update_accessed ptp,pte,t0,t1 << 1133 << 1134 make_insert_tlb spc,pte,prot,t1 << 1135 << 1136 idtlbt pte,prot << 1137 << 1138 ptl_unlock spc,t0,t1 << 1139 rfir << 1140 nop << 1141 << 1142 dtlb_check_alias_20w: << 1143 do_alias spc,t0,t1,va,pte,prot << 1144 << 1145 idtlbt pte,prot << 1146 << 1147 insert_nops NUM_PIPELINE_INSNS - << 1148 rfir << 1149 nop << 1150 << 1151 nadtlb_miss_20w: << 1152 space_adjust spc,va,t0 << 1153 get_pgd spc,ptp << 1154 space_check spc,t0,nadtlb_fault << 1155 << 1156 L3_ptep ptp,pte,t0,va,nadtlb_ << 1157 << 1158 ptl_lock spc,ptp,pte,t0,t1,nad << 1159 update_accessed ptp,pte,t0,t1 << 1160 << 1161 make_insert_tlb spc,pte,prot,t1 << 1162 << 1163 idtlbt pte,prot << 1164 << 1165 ptl_unlock spc,t0,t1 << 1166 rfir << 1167 nop << 1168 << 1169 nadtlb_check_alias_20w: << 1170 do_alias spc,t0,t1,va,pte,prot << 1171 << 1172 idtlbt pte,prot << 1173 << 1174 insert_nops NUM_PIPELINE_INSNS - << 1175 rfir << 1176 nop << 1177 << 1178 #else << 1179 << 1180 dtlb_miss_11: << 1181 get_pgd spc,ptp << 1182 << 1183 space_check spc,t0,dtlb_fault << 1184 << 1185 L2_ptep ptp,pte,t0,va,dtlb_ch << 1186 << 1187 ptl_lock spc,ptp,pte,t0,t1,dtl << 1188 update_accessed ptp,pte,t0,t1 << 1189 << 1190 make_insert_tlb_11 spc,pte,prot << 1191 << 1192 mfsp %sr1,t1 /* Save sr1 << 1193 mtsp spc,%sr1 << 1194 << 1195 idtlba pte,(%sr1,va) << 1196 idtlbp prot,(%sr1,va) << 1197 << 1198 mtsp t1, %sr1 /* Re << 1199 << 1200 ptl_unlock spc,t0,t1 << 1201 rfir << 1202 nop << 1203 << 1204 dtlb_check_alias_11: << 1205 do_alias spc,t0,t1,va,pte,prot << 1206 << 1207 idtlba pte,(va) << 1208 idtlbp prot,(va) << 1209 << 1210 insert_nops NUM_PIPELINE_INSNS - << 1211 rfir << 1212 nop << 1213 << 1214 nadtlb_miss_11: << 1215 get_pgd spc,ptp << 1216 << 1217 space_check spc,t0,nadtlb_fault << 1218 << 1219 L2_ptep ptp,pte,t0,va,nadtlb_ << 1220 << 1221 ptl_lock spc,ptp,pte,t0,t1,nad << 1222 update_accessed ptp,pte,t0,t1 << 1223 << 1224 make_insert_tlb_11 spc,pte,prot << 1225 << 1226 mfsp %sr1,t1 /* Save sr1 << 1227 mtsp spc,%sr1 << 1228 << 1229 idtlba pte,(%sr1,va) << 1230 idtlbp prot,(%sr1,va) << 1231 << 1232 mtsp t1, %sr1 /* Re << 1233 << 1234 ptl_unlock spc,t0,t1 << 1235 rfir << 1236 nop << 1237 << 1238 nadtlb_check_alias_11: << 1239 do_alias spc,t0,t1,va,pte,prot << 1240 << 1241 idtlba pte,(va) << 1242 idtlbp prot,(va) << 1243 << 1244 insert_nops NUM_PIPELINE_INSNS - << 1245 rfir << 1246 nop << 1247 << 1248 dtlb_miss_20: << 1249 space_adjust spc,va,t0 << 1250 get_pgd spc,ptp << 1251 space_check spc,t0,dtlb_fault << 1252 << 1253 L2_ptep ptp,pte,t0,va,dtlb_ch << 1254 << 1255 ptl_lock spc,ptp,pte,t0,t1,dtl << 1256 update_accessed ptp,pte,t0,t1 << 1257 << 1258 make_insert_tlb spc,pte,prot,t1 << 1259 << 1260 f_extend pte,t1 << 1261 << 1262 idtlbt pte,prot << 1263 << 1264 ptl_unlock spc,t0,t1 << 1265 rfir << 1266 nop << 1267 << 1268 dtlb_check_alias_20: << 1269 do_alias spc,t0,t1,va,pte,prot << 1270 << 1271 idtlbt pte,prot << 1272 << 1273 insert_nops NUM_PIPELINE_INSNS - << 1274 rfir << 1275 nop << 1276 << 1277 nadtlb_miss_20: << 1278 get_pgd spc,ptp << 1279 << 1280 space_check spc,t0,nadtlb_fault << 1281 << 1282 L2_ptep ptp,pte,t0,va,nadtlb_ << 1283 << 1284 ptl_lock spc,ptp,pte,t0,t1,nad << 1285 update_accessed ptp,pte,t0,t1 << 1286 << 1287 make_insert_tlb spc,pte,prot,t1 << 1288 << 1289 f_extend pte,t1 << 1290 << 1291 idtlbt pte,prot << 1292 << 1293 ptl_unlock spc,t0,t1 << 1294 rfir << 1295 nop << 1296 << 1297 nadtlb_check_alias_20: << 1298 do_alias spc,t0,t1,va,pte,prot << 1299 << 1300 idtlbt pte,prot << 1301 << 1302 insert_nops NUM_PIPELINE_INSNS - << 1303 rfir << 1304 nop << 1305 << 1306 #endif << 1307 << 1308 nadtlb_emulate: << 1309 << 1310 /* << 1311 * Non-access misses can be caused by << 1312 * probei instructions. The kernel no << 1313 * Use of lpa and probe instructions << 1314 * with shadow registers, we defer ev << 1315 */ << 1316 b,n nadtlb_fault << 1317 << 1318 #ifdef CONFIG_64BIT << 1319 itlb_miss_20w: << 1320 << 1321 /* << 1322 * I miss is a little different, sinc << 1323 * on the gateway page which is in th << 1324 */ << 1325 << 1326 space_adjust spc,va,t0 << 1327 get_pgd spc,ptp << 1328 space_check spc,t0,itlb_fault << 1329 << 1330 L3_ptep ptp,pte,t0,va,itlb_fa << 1331 << 1332 ptl_lock spc,ptp,pte,t0,t1,itl << 1333 update_accessed ptp,pte,t0,t1 << 1334 << 1335 make_insert_tlb spc,pte,prot,t1 << 1336 << 1337 iitlbt pte,prot << 1338 << 1339 ptl_unlock spc,t0,t1 << 1340 rfir << 1341 nop << 1342 << 1343 naitlb_miss_20w: << 1344 << 1345 /* << 1346 * I miss is a little different, sinc << 1347 * on the gateway page which is in th << 1348 */ << 1349 << 1350 space_adjust spc,va,t0 << 1351 get_pgd spc,ptp << 1352 space_check spc,t0,naitlb_fault << 1353 << 1354 L3_ptep ptp,pte,t0,va,naitlb_ << 1355 << 1356 ptl_lock spc,ptp,pte,t0,t1,nai << 1357 update_accessed ptp,pte,t0,t1 << 1358 << 1359 make_insert_tlb spc,pte,prot,t1 << 1360 << 1361 iitlbt pte,prot << 1362 << 1363 ptl_unlock spc,t0,t1 << 1364 rfir << 1365 nop << 1366 << 1367 naitlb_check_alias_20w: << 1368 do_alias spc,t0,t1,va,pte,prot << 1369 << 1370 iitlbt pte,prot << 1371 << 1372 insert_nops NUM_PIPELINE_INSNS - << 1373 rfir << 1374 nop << 1375 << 1376 #else << 1377 << 1378 itlb_miss_11: << 1379 get_pgd spc,ptp << 1380 << 1381 space_check spc,t0,itlb_fault << 1382 << 1383 L2_ptep ptp,pte,t0,va,itlb_fa << 1384 << 1385 ptl_lock spc,ptp,pte,t0,t1,itl << 1386 update_accessed ptp,pte,t0,t1 << 1387 << 1388 make_insert_tlb_11 spc,pte,prot << 1389 << 1390 mfsp %sr1,t1 /* Save sr1 << 1391 mtsp spc,%sr1 << 1392 << 1393 iitlba pte,(%sr1,va) << 1394 iitlbp prot,(%sr1,va) << 1395 << 1396 mtsp t1, %sr1 /* Re << 1397 << 1398 ptl_unlock spc,t0,t1 << 1399 rfir << 1400 nop << 1401 << 1402 naitlb_miss_11: << 1403 get_pgd spc,ptp << 1404 << 1405 space_check spc,t0,naitlb_fault << 1406 << 1407 L2_ptep ptp,pte,t0,va,naitlb_ << 1408 << 1409 ptl_lock spc,ptp,pte,t0,t1,nai << 1410 update_accessed ptp,pte,t0,t1 << 1411 << 1412 make_insert_tlb_11 spc,pte,prot << 1413 << 1414 mfsp %sr1,t1 /* Save sr1 << 1415 mtsp spc,%sr1 << 1416 << 1417 iitlba pte,(%sr1,va) << 1418 iitlbp prot,(%sr1,va) << 1419 << 1420 mtsp t1, %sr1 /* Re << 1421 << 1422 ptl_unlock spc,t0,t1 << 1423 rfir << 1424 nop << 1425 << 1426 naitlb_check_alias_11: << 1427 do_alias spc,t0,t1,va,pte,prot << 1428 << 1429 iitlba pte,(%sr0, va) << 1430 iitlbp prot,(%sr0, va) << 1431 << 1432 insert_nops NUM_PIPELINE_INSNS - << 1433 rfir << 1434 nop << 1435 << 1436 << 1437 itlb_miss_20: << 1438 get_pgd spc,ptp << 1439 << 1440 space_check spc,t0,itlb_fault << 1441 << 1442 L2_ptep ptp,pte,t0,va,itlb_fa << 1443 << 1444 ptl_lock spc,ptp,pte,t0,t1,itl << 1445 update_accessed ptp,pte,t0,t1 << 1446 << 1447 make_insert_tlb spc,pte,prot,t1 << 1448 << 1449 f_extend pte,t1 << 1450 << 1451 iitlbt pte,prot << 1452 << 1453 ptl_unlock spc,t0,t1 << 1454 rfir << 1455 nop << 1456 << 1457 naitlb_miss_20: << 1458 get_pgd spc,ptp << 1459 << 1460 space_check spc,t0,naitlb_fault << 1461 << 1462 L2_ptep ptp,pte,t0,va,naitlb_ << 1463 << 1464 ptl_lock spc,ptp,pte,t0,t1,nai << 1465 update_accessed ptp,pte,t0,t1 << 1466 << 1467 make_insert_tlb spc,pte,prot,t1 << 1468 << 1469 f_extend pte,t1 << 1470 << 1471 iitlbt pte,prot << 1472 << 1473 ptl_unlock spc,t0,t1 << 1474 rfir << 1475 nop << 1476 << 1477 naitlb_check_alias_20: << 1478 do_alias spc,t0,t1,va,pte,prot << 1479 << 1480 iitlbt pte,prot << 1481 << 1482 insert_nops NUM_PIPELINE_INSNS - << 1483 rfir << 1484 nop << 1485 << 1486 #endif << 1487 << 1488 #ifdef CONFIG_64BIT << 1489 << 1490 dbit_trap_20w: << 1491 space_adjust spc,va,t0 << 1492 get_pgd spc,ptp << 1493 space_check spc,t0,dbit_fault << 1494 << 1495 L3_ptep ptp,pte,t0,va,dbit_fa << 1496 << 1497 ptl_lock spc,ptp,pte,t0,t1,dbi << 1498 update_dirty ptp,pte,t1 << 1499 << 1500 make_insert_tlb spc,pte,prot,t1 << 1501 << 1502 idtlbt pte,prot << 1503 << 1504 ptl_unlock spc,t0,t1 << 1505 rfir << 1506 nop << 1507 #else << 1508 << 1509 dbit_trap_11: << 1510 << 1511 get_pgd spc,ptp << 1512 << 1513 space_check spc,t0,dbit_fault << 1514 << 1515 L2_ptep ptp,pte,t0,va,dbit_fa << 1516 << 1517 ptl_lock spc,ptp,pte,t0,t1,dbi << 1518 update_dirty ptp,pte,t1 << 1519 << 1520 make_insert_tlb_11 spc,pte,prot << 1521 << 1522 mfsp %sr1,t1 /* Save sr1 << 1523 mtsp spc,%sr1 << 1524 << 1525 idtlba pte,(%sr1,va) << 1526 idtlbp prot,(%sr1,va) << 1527 << 1528 mtsp t1, %sr1 /* Resto << 1529 << 1530 ptl_unlock spc,t0,t1 << 1531 rfir << 1532 nop << 1533 << 1534 dbit_trap_20: << 1535 get_pgd spc,ptp << 1536 << 1537 space_check spc,t0,dbit_fault << 1538 << 1539 L2_ptep ptp,pte,t0,va,dbit_fa << 1540 << 1541 ptl_lock spc,ptp,pte,t0,t1,dbi << 1542 update_dirty ptp,pte,t1 << 1543 << 1544 make_insert_tlb spc,pte,prot,t1 << 1545 << 1546 f_extend pte,t1 << 1547 1177 1548 idtlbt pte,prot !! 1178 ret 1549 !! 1179 restore 1550 ptl_unlock spc,t0,t1 !! 1180 EXPORT_SYMBOL(__udelay) 1551 rfir !! 1181 EXPORT_SYMBOL(__ndelay) 1552 nop !! 1182 1553 #endif !! 1183 /* Handle a software breakpoint */ 1554 !! 1184 /* We have to inform parent that child has stopped */ 1555 .import handle_interruption,code !! 1185 .align 4 1556 !! 1186 .globl breakpoint_trap 1557 kernel_bad_space: !! 1187 breakpoint_trap: 1558 b intr_save !! 1188 rd %wim,%l3 1559 ldi 31,%r8 /* Use an unu !! 1189 SAVE_ALL 1560 !! 1190 wr %l0, PSR_ET, %psr 1561 dbit_fault: !! 1191 WRITE_PAUSE 1562 b intr_save !! 1192 1563 ldi 20,%r8 !! 1193 st %i0, [%sp + STACKFRAME_SZ + PT_G0] ! for restarting syscalls 1564 !! 1194 call sparc_breakpoint 1565 itlb_fault: !! 1195 add %sp, STACKFRAME_SZ, %o0 1566 b intr_save !! 1196 1567 ldi PARISC_ITLB_TRAP,%r8 !! 1197 RESTORE_ALL 1568 !! 1198 1569 nadtlb_fault: !! 1199 #ifdef CONFIG_KGDB 1570 b intr_save !! 1200 ENTRY(kgdb_trap_low) 1571 ldi 17,%r8 !! 1201 rd %wim,%l3 1572 !! 1202 SAVE_ALL 1573 naitlb_fault: !! 1203 wr %l0, PSR_ET, %psr 1574 b intr_save !! 1204 WRITE_PAUSE 1575 ldi 16,%r8 !! 1205 1576 !! 1206 mov %l7, %o0 ! trap_level 1577 dtlb_fault: !! 1207 call kgdb_trap 1578 b intr_save !! 1208 add %sp, STACKFRAME_SZ, %o1 ! struct pt_regs *regs 1579 ldi 15,%r8 !! 1209 1580 !! 1210 RESTORE_ALL 1581 /* Register saving semantics for syst !! 1211 ENDPROC(kgdb_trap_low) 1582 !! 1212 #endif 1583 %r1 clobbered by syste !! 1213 1584 %r2 saved in PT_REGS b !! 1214 .align 4 1585 %r3 - %r18 preserved by C cod !! 1215 .globl flush_patch_exception 1586 %r19 - %r20 saved in PT_REGS b !! 1216 flush_patch_exception: 1587 %r21 - %r22 non-standard sysca !! 1217 FLUSH_ALL_KERNEL_WINDOWS; 1588 stored in kernel s !! 1218 ldd [%o0], %o6 1589 %r23 - %r26 arg3-arg0, saved i !! 1219 jmpl %o7 + 0xc, %g0 ! see asm-sparc/processor.h 1590 %r27 - %r30 saved in PT_REGS b !! 1220 mov 1, %g1 ! signal EFAULT condition 1591 %r31 syscall return poi !! 1221 1592 */ !! 1222 .align 4 1593 !! 1223 .globl kill_user_windows, kuw_patch1_7win 1594 /* Floating point registers (FIXME: w !! 1224 .globl kuw_patch1 1595 !! 1225 kuw_patch1_7win: sll %o3, 6, %o3 1596 %fr0 - %fr3 status/exception, !! 1226 1597 %fr4 - %fr7 arguments !! 1227 /* No matter how much overhead this routine has in the worst 1598 %fr8 - %fr11 not preserved by C !! 1228 * case scenario, it is several times better than taking the 1599 %fr12 - %fr21 preserved by C cod !! 1229 * traps with the old method of just doing flush_user_windows(). 1600 %fr22 - %fr31 not preserved by C !! 1230 */ 1601 */ !! 1231 kill_user_windows: 1602 !! 1232 ld [%g6 + TI_UWINMASK], %o0 ! get current umask 1603 .macro reg_save regs !! 1233 orcc %g0, %o0, %g0 ! if no bits set, we are done 1604 STREG %r3, PT_GR3(\regs) !! 1234 be 3f ! nothing to do 1605 STREG %r4, PT_GR4(\regs) !! 1235 rd %psr, %o5 ! must clear interrupts 1606 STREG %r5, PT_GR5(\regs) !! 1236 or %o5, PSR_PIL, %o4 ! or else that could change 1607 STREG %r6, PT_GR6(\regs) !! 1237 wr %o4, 0x0, %psr ! the uwinmask state 1608 STREG %r7, PT_GR7(\regs) !! 1238 WRITE_PAUSE ! burn them cycles 1609 STREG %r8, PT_GR8(\regs) << 1610 STREG %r9, PT_GR9(\regs) << 1611 STREG %r10,PT_GR10(\regs) << 1612 STREG %r11,PT_GR11(\regs) << 1613 STREG %r12,PT_GR12(\regs) << 1614 STREG %r13,PT_GR13(\regs) << 1615 STREG %r14,PT_GR14(\regs) << 1616 STREG %r15,PT_GR15(\regs) << 1617 STREG %r16,PT_GR16(\regs) << 1618 STREG %r17,PT_GR17(\regs) << 1619 STREG %r18,PT_GR18(\regs) << 1620 .endm << 1621 << 1622 .macro reg_restore regs << 1623 LDREG PT_GR3(\regs), %r3 << 1624 LDREG PT_GR4(\regs), %r4 << 1625 LDREG PT_GR5(\regs), %r5 << 1626 LDREG PT_GR6(\regs), %r6 << 1627 LDREG PT_GR7(\regs), %r7 << 1628 LDREG PT_GR8(\regs), %r8 << 1629 LDREG PT_GR9(\regs), %r9 << 1630 LDREG PT_GR10(\regs),%r10 << 1631 LDREG PT_GR11(\regs),%r11 << 1632 LDREG PT_GR12(\regs),%r12 << 1633 LDREG PT_GR13(\regs),%r13 << 1634 LDREG PT_GR14(\regs),%r14 << 1635 LDREG PT_GR15(\regs),%r15 << 1636 LDREG PT_GR16(\regs),%r16 << 1637 LDREG PT_GR17(\regs),%r17 << 1638 LDREG PT_GR18(\regs),%r18 << 1639 .endm << 1640 << 1641 .macro fork_like name << 1642 ENTRY_CFI(sys_\name\()_wrapper) << 1643 mfctl %cr30,%r1 << 1644 ldo TASK_REGS(%r1),%r1 << 1645 reg_save %r1 << 1646 mfctl %cr27, %r28 << 1647 ldil L%sys_\name, %r31 << 1648 be R%sys_\name(%sr4,%r31) << 1649 STREG %r28, PT_CR27(%r1) << 1650 ENDPROC_CFI(sys_\name\()_wrapper) << 1651 .endm << 1652 << 1653 fork_like clone << 1654 fork_like clone3 << 1655 fork_like fork << 1656 fork_like vfork << 1657 << 1658 /* Set the return value for the child << 1659 ENTRY(child_return) << 1660 BL schedule_tail, %r2 << 1661 nop << 1662 finish_child_return: << 1663 mfctl %cr30,%r1 << 1664 ldo TASK_REGS(%r1),%r1 /* g << 1665 << 1666 LDREG PT_CR27(%r1), %r3 << 1667 mtctl %r3, %cr27 << 1668 reg_restore %r1 << 1669 b syscall_exit << 1670 copy %r0,%r28 << 1671 END(child_return) << 1672 << 1673 ENTRY_CFI(sys_rt_sigreturn_wrapper) << 1674 mfctl %cr30,%r26 << 1675 ldo TASK_REGS(%r26),%r26 /* ge << 1676 /* Don't save regs, we are going to r << 1677 STREG %r2, -RP_OFFSET(%r30) << 1678 #ifdef CONFIG_64BIT << 1679 ldo FRAME_SIZE(%r30), %r30 << 1680 BL sys_rt_sigreturn,%r2 << 1681 ldo -16(%r30),%r29 /* Re << 1682 #else << 1683 BL sys_rt_sigreturn,%r2 << 1684 ldo FRAME_SIZE(%r30), %r30 << 1685 #endif << 1686 << 1687 ldo -FRAME_SIZE(%r30), %r30 << 1688 LDREG -RP_OFFSET(%r30), %r2 << 1689 << 1690 /* FIXME: I think we need to restore << 1691 mfctl %cr30,%r1 << 1692 ldo TASK_REGS(%r1),%r1 /* ge << 1693 reg_restore %r1 << 1694 << 1695 /* If the signal was received while t << 1696 * syscall, then r2 will take us to s << 1697 * take us to syscall_exit_rfi and on << 1698 */ << 1699 bv %r0(%r2) << 1700 LDREG PT_GR28(%r1),%r28 /* reload << 1701 ENDPROC_CFI(sys_rt_sigreturn_wrapper) << 1702 << 1703 ENTRY(syscall_exit) << 1704 /* NOTE: Not all syscalls exit this w << 1705 * via syscall_exit_rfi if the signal << 1706 * was running. << 1707 */ << 1708 << 1709 /* save return value now */ << 1710 mfctl %cr30, %r1 << 1711 STREG %r28,TASK_PT_GR28(%r1) << 1712 << 1713 /* Seems to me that dp could be wrong << 1714 * calling a module, and nothing got << 1715 */ << 1716 loadgp << 1717 << 1718 syscall_check_resched: << 1719 << 1720 /* check for reschedule */ << 1721 mfctl %cr30,%r19 << 1722 LDREG TASK_TI_FLAGS(%r19),%r19 << 1723 bb,<,n %r19, 31-TIF_NEED_RESCHED, sy << 1724 << 1725 .import do_signal,code << 1726 syscall_check_sig: << 1727 mfctl %cr30,%r19 << 1728 LDREG TASK_TI_FLAGS(%r19),%r19 << 1729 ldi (_TIF_USER_WORK_MASK & ~_TIF_ << 1730 and,COND(<>) %r19, %r26, %r0 << 1731 b,n syscall_restore /* skip past << 1732 << 1733 syscall_do_signal: << 1734 /* Save callee-save registers (for si << 1735 * FIXME: After this point the proces << 1736 * consistent with all the relevant s << 1737 * before the syscall. We need to ve << 1738 */ << 1739 mfctl %cr30,%r1 << 1740 ldo TASK_REGS(%r1), %r26 << 1741 reg_save %r26 << 1742 << 1743 #ifdef CONFIG_64BIT << 1744 ldo -16(%r30),%r29 << 1745 #endif << 1746 << 1747 BL do_notify_resume,%r2 << 1748 ldi 1, %r25 << 1749 << 1750 mfctl %cr30,%r1 << 1751 ldo TASK_REGS(%r1), %r20 << 1752 reg_restore %r20 << 1753 << 1754 b,n syscall_check_sig << 1755 << 1756 syscall_restore: << 1757 mfctl %cr30,%r1 << 1758 << 1759 /* Are we being ptraced? */ << 1760 LDREG TASK_TI_FLAGS(%r1),%r19 << 1761 ldi _TIF_SINGLESTEP|_TIF_BLOCKSTE << 1762 and,COND(=) %r19,%r2,%r0 << 1763 b,n syscall_restore_rfi << 1764 << 1765 ldo TASK_PT_FR31(%r1),%r19 << 1766 rest_fp %r19 << 1767 << 1768 LDREG TASK_PT_SAR(%r1),%r19 << 1769 mtsar %r19 << 1770 << 1771 LDREG TASK_PT_GR2(%r1),%r2 << 1772 LDREG TASK_PT_GR19(%r1),%r19 << 1773 LDREG TASK_PT_GR20(%r1),%r20 << 1774 LDREG TASK_PT_GR21(%r1),%r21 << 1775 LDREG TASK_PT_GR22(%r1),%r22 << 1776 LDREG TASK_PT_GR23(%r1),%r23 << 1777 LDREG TASK_PT_GR24(%r1),%r24 << 1778 LDREG TASK_PT_GR25(%r1),%r25 << 1779 LDREG TASK_PT_GR26(%r1),%r26 << 1780 LDREG TASK_PT_GR27(%r1),%r27 /* << 1781 LDREG TASK_PT_GR28(%r1),%r28 /* << 1782 LDREG TASK_PT_GR29(%r1),%r29 << 1783 LDREG TASK_PT_GR31(%r1),%r31 /* << 1784 << 1785 /* NOTE: We use rsm/ssm pair to make << 1786 LDREG TASK_PT_GR30(%r1),%r1 << 1787 rsm PSW_SM_I, %r0 << 1788 copy %r1,%r30 << 1789 mfsp %sr3,%r1 << 1790 mtsp %r1,%sr7 << 1791 ssm PSW_SM_I, %r0 << 1792 << 1793 /* Set sr2 to zero for userspace sysc << 1794 mtsp %r0,%sr2 << 1795 mtsp %r1,%sr4 << 1796 mtsp %r1,%sr5 << 1797 mtsp %r1,%sr6 << 1798 << 1799 depi PRIV_USER,31,2,%r31 /* en << 1800 << 1801 #ifdef CONFIG_64BIT << 1802 /* decide whether to reset the wide m << 1803 * << 1804 * For a syscall, the W bit is stored << 1805 * of sp. Extract it and reset W if << 1806 extrd,u,*<> %r30,63,1,%r1 << 1807 rsm PSW_SM_W, %r0 << 1808 /* now reset the lowest bit of sp if << 1809 xor %r30,%r1,%r30 << 1810 #endif << 1811 be,n 0(%sr3,%r31) << 1812 << 1813 /* We have to return via an RFI, so t << 1814 * appropriately. << 1815 * This sets up pt_regs so we can ret << 1816 * the most efficient way of doing th << 1817 */ << 1818 syscall_restore_rfi: << 1819 ldo -1(%r0),%r2 << 1820 mtctl %r2,%cr0 << 1821 LDREG TASK_PT_PSW(%r1),%r2 << 1822 ldi 0x0b,%r20 << 1823 depi -1,13,1,%r20 << 1824 << 1825 /* The values of SINGLESTEP_BIT and B << 1826 * set in thread_info.h and converted << 1827 * numbers in asm-offsets.c */ << 1828 << 1829 /* if ((%r19.SINGLESTEP_BIT)) { %r20. << 1830 extru,= %r19,TIF_SINGLESTEP_PA_BIT,1, << 1831 depi -1,27,1,%r20 << 1832 << 1833 /* if ((%r19.BLOCKSTEP_BIT)) { %r20.7 << 1834 extru,= %r19,TIF_BLOCKSTEP_PA_BIT,1,% << 1835 depi -1,7,1,%r20 << 1836 << 1837 STREG %r20,TASK_PT_PSW(%r1) << 1838 << 1839 /* Always store space registers, sinc << 1840 << 1841 mfsp %sr3,%r25 << 1842 STREG %r25,TASK_PT_SR3(%r1) << 1843 STREG %r25,TASK_PT_SR4(%r1) << 1844 STREG %r25,TASK_PT_SR5(%r1) << 1845 STREG %r25,TASK_PT_SR6(%r1) << 1846 STREG %r25,TASK_PT_SR7(%r1) << 1847 STREG %r25,TASK_PT_IASQ0(%r1) << 1848 STREG %r25,TASK_PT_IASQ1(%r1) << 1849 << 1850 /* XXX W bit??? */ << 1851 /* Now if old D bit is clear, it mean << 1852 * on syscall entry, so do that now. << 1853 * calls, or if someone attached to u << 1854 * We could make this more efficient << 1855 * then we wouldn't be able to use th << 1856 * It is only for traced processes an << 1857 * an issue. << 1858 */ << 1859 bb,< %r2,30,pt_regs_ok << 1860 ldo TASK_REGS(%r1),%r25 << 1861 reg_save %r25 << 1862 << 1863 /* Save the current sr */ << 1864 mfsp %sr0,%r2 << 1865 STREG %r2,TASK_PT_SR0(%r1) << 1866 << 1867 /* Save the scratch sr */ << 1868 mfsp %sr1,%r2 << 1869 STREG %r2,TASK_PT_SR1(%r1) << 1870 << 1871 /* sr2 should be set to zero for user << 1872 STREG %r0,TASK_PT_SR2(%r1) << 1873 << 1874 LDREG TASK_PT_GR31(%r1),%r2 << 1875 depi PRIV_USER,31,2,%r2 /* en << 1876 STREG %r2,TASK_PT_IAOQ0(%r1) << 1877 ldo 4(%r2),%r2 << 1878 STREG %r2,TASK_PT_IAOQ1(%r1) << 1879 b intr_restore << 1880 copy %r25,%r16 << 1881 << 1882 pt_regs_ok: << 1883 LDREG TASK_PT_IAOQ0(%r1),%r2 << 1884 depi PRIV_USER,31,2,%r2 /* en << 1885 STREG %r2,TASK_PT_IAOQ0(%r1) << 1886 LDREG TASK_PT_IAOQ1(%r1),%r2 << 1887 depi PRIV_USER,31,2,%r2 << 1888 STREG %r2,TASK_PT_IAOQ1(%r1) << 1889 b intr_restore << 1890 copy %r25,%r16 << 1891 << 1892 syscall_do_resched: << 1893 load32 syscall_check_resched,%r2 /* << 1894 load32 schedule,%r19 << 1895 bv %r0(%r19) /* ju << 1896 #ifdef CONFIG_64BIT << 1897 ldo -16(%r30),%r29 /* Re << 1898 #else << 1899 nop << 1900 #endif << 1901 END(syscall_exit) << 1902 << 1903 << 1904 #ifdef CONFIG_FUNCTION_TRACER << 1905 << 1906 .import ftrace_function_trampoline,co << 1907 .align L1_CACHE_BYTES << 1908 ENTRY_CFI(mcount, caller) << 1909 _mcount: << 1910 .export _mcount,data << 1911 /* << 1912 * The 64bit mcount() function pointe << 1913 * first two are free. We optimize i << 1914 * calling mcount(), and 2 instructio << 1915 * have all on one L1 cacheline. << 1916 */ << 1917 ldi 0, %arg3 << 1918 b ftrace_function_trampoline << 1919 copy %r3, %arg2 /* caller ori << 1920 ftrace_stub: << 1921 .globl ftrace_stub << 1922 .type ftrace_stub, @function << 1923 #ifdef CONFIG_64BIT << 1924 bve (%rp) << 1925 #else << 1926 bv %r0(%rp) << 1927 #endif << 1928 nop << 1929 #ifdef CONFIG_64BIT << 1930 .dword mcount << 1931 .dword 0 /* code in head.S puts value << 1932 #endif << 1933 ENDPROC_CFI(mcount) << 1934 << 1935 #ifdef CONFIG_DYNAMIC_FTRACE << 1936 << 1937 #ifdef CONFIG_64BIT << 1938 #define FTRACE_FRAME_SIZE (2*FRAME_SIZE) << 1939 #else << 1940 #define FTRACE_FRAME_SIZE FRAME_SIZE << 1941 #endif << 1942 ENTRY_CFI(ftrace_caller, caller,frame=FTRACE_ << 1943 ftrace_caller: << 1944 .global ftrace_caller << 1945 << 1946 STREG %r3, -FTRACE_FRAME_SIZE+1*REG << 1947 ldo -FTRACE_FRAME_SIZE(%sp), %r3 << 1948 STREG %rp, -RP_OFFSET(%r3) << 1949 << 1950 /* Offset 0 is already allocated for << 1951 STREG %r23, 2*REG_SZ(%r3) << 1952 STREG %r24, 3*REG_SZ(%r3) << 1953 STREG %r25, 4*REG_SZ(%r3) << 1954 STREG %r26, 5*REG_SZ(%r3) << 1955 STREG %r28, 6*REG_SZ(%r3) << 1956 STREG %r29, 7*REG_SZ(%r3) << 1957 #ifdef CONFIG_64BIT << 1958 STREG %r19, 8*REG_SZ(%r3) << 1959 STREG %r20, 9*REG_SZ(%r3) << 1960 STREG %r21, 10*REG_SZ(%r3) << 1961 STREG %r22, 11*REG_SZ(%r3) << 1962 STREG %r27, 12*REG_SZ(%r3) << 1963 STREG %r31, 13*REG_SZ(%r3) << 1964 loadgp << 1965 ldo -16(%sp),%r29 << 1966 #endif << 1967 LDREG 0(%r3), %r25 << 1968 copy %rp, %r26 << 1969 ldo -8(%r25), %r25 << 1970 ldi 0, %r23 /* no pt_regs << 1971 b,l ftrace_function_trampoline, % << 1972 copy %r3, %r24 << 1973 << 1974 LDREG -RP_OFFSET(%r3), %rp << 1975 LDREG 2*REG_SZ(%r3), %r23 << 1976 LDREG 3*REG_SZ(%r3), %r24 << 1977 LDREG 4*REG_SZ(%r3), %r25 << 1978 LDREG 5*REG_SZ(%r3), %r26 << 1979 LDREG 6*REG_SZ(%r3), %r28 << 1980 LDREG 7*REG_SZ(%r3), %r29 << 1981 #ifdef CONFIG_64BIT << 1982 LDREG 8*REG_SZ(%r3), %r19 << 1983 LDREG 9*REG_SZ(%r3), %r20 << 1984 LDREG 10*REG_SZ(%r3), %r21 << 1985 LDREG 11*REG_SZ(%r3), %r22 << 1986 LDREG 12*REG_SZ(%r3), %r27 << 1987 LDREG 13*REG_SZ(%r3), %r31 << 1988 #endif << 1989 LDREG 1*REG_SZ(%r3), %r3 << 1990 << 1991 LDREGM -FTRACE_FRAME_SIZE(%sp), %r1 << 1992 /* Adjust return point to jump back t << 1993 ldo -4(%r1), %r1 << 1994 bv,n (%r1) << 1995 << 1996 ENDPROC_CFI(ftrace_caller) << 1997 << 1998 #ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS << 1999 ENTRY_CFI(ftrace_regs_caller,caller,frame=FTR << 2000 CALLS,SAVE_RP,SAVE_SP) << 2001 ftrace_regs_caller: << 2002 .global ftrace_regs_caller << 2003 << 2004 ldo -FTRACE_FRAME_SIZE(%sp), %r1 << 2005 STREG %rp, -RP_OFFSET(%r1) << 2006 << 2007 copy %sp, %r1 << 2008 ldo PT_SZ_ALGN(%sp), %sp << 2009 << 2010 STREG %rp, PT_GR2(%r1) << 2011 STREG %r3, PT_GR3(%r1) << 2012 STREG %r4, PT_GR4(%r1) << 2013 STREG %r5, PT_GR5(%r1) << 2014 STREG %r6, PT_GR6(%r1) << 2015 STREG %r7, PT_GR7(%r1) << 2016 STREG %r8, PT_GR8(%r1) << 2017 STREG %r9, PT_GR9(%r1) << 2018 STREG %r10, PT_GR10(%r1) << 2019 STREG %r11, PT_GR11(%r1) << 2020 STREG %r12, PT_GR12(%r1) << 2021 STREG %r13, PT_GR13(%r1) << 2022 STREG %r14, PT_GR14(%r1) << 2023 STREG %r15, PT_GR15(%r1) << 2024 STREG %r16, PT_GR16(%r1) << 2025 STREG %r17, PT_GR17(%r1) << 2026 STREG %r18, PT_GR18(%r1) << 2027 STREG %r19, PT_GR19(%r1) << 2028 STREG %r20, PT_GR20(%r1) << 2029 STREG %r21, PT_GR21(%r1) << 2030 STREG %r22, PT_GR22(%r1) << 2031 STREG %r23, PT_GR23(%r1) << 2032 STREG %r24, PT_GR24(%r1) << 2033 STREG %r25, PT_GR25(%r1) << 2034 STREG %r26, PT_GR26(%r1) << 2035 STREG %r27, PT_GR27(%r1) << 2036 STREG %r28, PT_GR28(%r1) << 2037 STREG %r29, PT_GR29(%r1) << 2038 STREG %r30, PT_GR30(%r1) << 2039 STREG %r31, PT_GR31(%r1) << 2040 mfctl %cr11, %r26 << 2041 STREG %r26, PT_SAR(%r1) << 2042 << 2043 copy %rp, %r26 << 2044 LDREG -FTRACE_FRAME_SIZE-PT_SZ_ALGN << 2045 ldo -8(%r25), %r25 << 2046 ldo -FTRACE_FRAME_SIZE(%r1), %arg << 2047 b,l ftrace_function_trampoline, % << 2048 copy %r1, %arg3 /* struct pt_regs << 2049 << 2050 ldo -PT_SZ_ALGN(%sp), %r1 << 2051 << 2052 LDREG PT_SAR(%r1), %rp << 2053 mtctl %rp, %cr11 << 2054 << 2055 LDREG PT_GR2(%r1), %rp << 2056 LDREG PT_GR3(%r1), %r3 << 2057 LDREG PT_GR4(%r1), %r4 << 2058 LDREG PT_GR5(%r1), %r5 << 2059 LDREG PT_GR6(%r1), %r6 << 2060 LDREG PT_GR7(%r1), %r7 << 2061 LDREG PT_GR8(%r1), %r8 << 2062 LDREG PT_GR9(%r1), %r9 << 2063 LDREG PT_GR10(%r1),%r10 << 2064 LDREG PT_GR11(%r1),%r11 << 2065 LDREG PT_GR12(%r1),%r12 << 2066 LDREG PT_GR13(%r1),%r13 << 2067 LDREG PT_GR14(%r1),%r14 << 2068 LDREG PT_GR15(%r1),%r15 << 2069 LDREG PT_GR16(%r1),%r16 << 2070 LDREG PT_GR17(%r1),%r17 << 2071 LDREG PT_GR18(%r1),%r18 << 2072 LDREG PT_GR19(%r1),%r19 << 2073 LDREG PT_GR20(%r1),%r20 << 2074 LDREG PT_GR21(%r1),%r21 << 2075 LDREG PT_GR22(%r1),%r22 << 2076 LDREG PT_GR23(%r1),%r23 << 2077 LDREG PT_GR24(%r1),%r24 << 2078 LDREG PT_GR25(%r1),%r25 << 2079 LDREG PT_GR26(%r1),%r26 << 2080 LDREG PT_GR27(%r1),%r27 << 2081 LDREG PT_GR28(%r1),%r28 << 2082 LDREG PT_GR29(%r1),%r29 << 2083 LDREG PT_GR30(%r1),%r30 << 2084 LDREG PT_GR31(%r1),%r31 << 2085 << 2086 ldo -PT_SZ_ALGN(%sp), %sp << 2087 LDREGM -FTRACE_FRAME_SIZE(%sp), %r1 << 2088 /* Adjust return point to jump back t << 2089 ldo -4(%r1), %r1 << 2090 bv,n (%r1) << 2091 << 2092 ENDPROC_CFI(ftrace_regs_caller) << 2093 << 2094 #endif << 2095 #endif << 2096 << 2097 #ifdef CONFIG_FUNCTION_GRAPH_TRACER << 2098 .align 8 << 2099 ENTRY_CFI(return_to_handler, caller,frame=FRA << 2100 .export parisc_return_to_handler,data << 2101 parisc_return_to_handler: << 2102 copy %r3,%r1 << 2103 STREG %r0,-RP_OFFSET(%sp) /* st << 2104 copy %sp,%r3 << 2105 STREGM %r1,FRAME_SIZE(%sp) << 2106 STREG %ret0,8(%r3) << 2107 STREG %ret1,16(%r3) << 2108 << 2109 #ifdef CONFIG_64BIT << 2110 loadgp << 2111 #endif << 2112 << 2113 /* call ftrace_return_to_handler(0) * << 2114 .import ftrace_return_to_handler,code << 2115 load32 ftrace_return_to_handler,%ret0 << 2116 load32 .Lftrace_ret,%r2 << 2117 #ifdef CONFIG_64BIT << 2118 ldo -16(%sp),%ret1 /* Re << 2119 bve (%ret0) << 2120 #else << 2121 bv %r0(%ret0) << 2122 #endif << 2123 ldi 0,%r26 << 2124 .Lftrace_ret: << 2125 copy %ret0,%rp << 2126 << 2127 /* restore original return values */ << 2128 LDREG 8(%r3),%ret0 << 2129 LDREG 16(%r3),%ret1 << 2130 << 2131 /* return from function */ << 2132 #ifdef CONFIG_64BIT << 2133 bve (%rp) << 2134 #else << 2135 bv %r0(%rp) << 2136 #endif << 2137 LDREGM -FRAME_SIZE(%sp),%r3 << 2138 ENDPROC_CFI(return_to_handler) << 2139 << 2140 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ << 2141 << 2142 #endif /* CONFIG_FUNCTION_TRACER */ << 2143 << 2144 #ifdef CONFIG_IRQSTACKS << 2145 /* void call_on_stack(unsigned long param1, v << 2146 unsigned long new_stack << 2147 ENTRY_CFI(call_on_stack, FRAME=2*FRAME_SIZE,C << 2148 ENTRY(_call_on_stack) << 2149 copy %sp, %r1 << 2150 << 2151 /* Regarding the HPPA calling convent << 2152 we assume the PIC register is not << 2153 CONFIG_64BIT, the argument pointer << 2154 argument region allocated for the << 2155 << 2156 /* Switch to new stack. We allocate << 2157 ldo 2*FRAME_SIZE(%arg2), %sp << 2158 # ifdef CONFIG_64BIT << 2159 /* Save previous stack pointer and re << 2160 STREG %rp, -FRAME_SIZE-RP_OFFSET(%s << 2161 /* Calls always use function descript << 2162 LDREG 16(%arg1), %arg1 << 2163 bve,l (%arg1), %rp << 2164 STREG %r1, -FRAME_SIZE-REG_SZ(%sp) << 2165 LDREG -FRAME_SIZE-RP_OFFSET(%sp), % << 2166 bve (%rp) << 2167 LDREG -FRAME_SIZE-REG_SZ(%sp), %sp << 2168 # else << 2169 /* Save previous stack pointer and re << 2170 STREG %r1, -FRAME_SIZE-REG_SZ(%sp) << 2171 STREG %rp, -FRAME_SIZE-RP_OFFSET(%s << 2172 /* Calls use function descriptor if P << 2173 bb,>=,n %arg1, 30, 1f << 2174 depwi 0,31,2, %arg1 << 2175 LDREG 0(%arg1), %arg1 << 2176 1: 1239 1: 2177 be,l 0(%sr4,%arg1), %sr0, %r31 !! 1240 ld [%g6 + TI_UWINMASK], %o0 ! get consistent state 2178 copy %r31, %rp !! 1241 orcc %g0, %o0, %g0 ! did an interrupt come in? 2179 LDREG -FRAME_SIZE-RP_OFFSET(%sp), % !! 1242 be 4f ! yep, we are done 2180 bv (%rp) !! 1243 rd %wim, %o3 ! get current wim 2181 LDREG -FRAME_SIZE-REG_SZ(%sp), %sp !! 1244 srl %o3, 1, %o4 ! simulate a save 2182 # endif /* CONFIG_64BIT */ !! 1245 kuw_patch1: 2183 ENDPROC_CFI(call_on_stack) !! 1246 sll %o3, 7, %o3 ! compute next wim 2184 #endif /* CONFIG_IRQSTACKS */ !! 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 >> 1253 4: >> 1254 wr %o5, 0x0, %psr ! re-enable interrupts >> 1255 WRITE_PAUSE ! burn baby burn >> 1256 3: >> 1257 retl ! return >> 1258 st %g0, [%g6 + TI_W_SAVED] ! no windows saved 2185 1259 2186 ENTRY_CFI(get_register) !! 1260 .align 4 2187 /* !! 1261 .globl restore_current 2188 * get_register is used by the non ac !! 1262 restore_current: 2189 * copy the value of the general regi !! 1263 LOAD_CURRENT(g6, o0) 2190 * r1. This routine can't be used for !! 1264 retl 2191 * the rfir will restore the original !! 1265 nop 2192 * registers we put a -1 into r1 to i !! 1266 2193 * should not be used (the register b !! 1267 #ifdef CONFIG_PCIC_PCI 2194 * a -1 in it, but that is OK, it jus !! 1268 #include <asm/pcic.h> 2195 * to use the slow path instead). !! 1269 >> 1270 .align 4 >> 1271 .globl linux_trap_ipi15_pcic >> 1272 linux_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. 2196 */ 1281 */ 2197 blr %r8,%r0 !! 1282 sethi %hi(pcic_regs), %o1 2198 nop !! 1283 ld [%o1 + %lo(pcic_regs)], %o2 2199 bv %r0(%r25) /* r0 */ << 2200 copy %r0,%r1 << 2201 bv %r0(%r25) /* r1 - shadowed << 2202 ldi -1,%r1 << 2203 bv %r0(%r25) /* r2 */ << 2204 copy %r2,%r1 << 2205 bv %r0(%r25) /* r3 */ << 2206 copy %r3,%r1 << 2207 bv %r0(%r25) /* r4 */ << 2208 copy %r4,%r1 << 2209 bv %r0(%r25) /* r5 */ << 2210 copy %r5,%r1 << 2211 bv %r0(%r25) /* r6 */ << 2212 copy %r6,%r1 << 2213 bv %r0(%r25) /* r7 */ << 2214 copy %r7,%r1 << 2215 bv %r0(%r25) /* r8 - shadowed << 2216 ldi -1,%r1 << 2217 bv %r0(%r25) /* r9 - shadowed << 2218 ldi -1,%r1 << 2219 bv %r0(%r25) /* r10 */ << 2220 copy %r10,%r1 << 2221 bv %r0(%r25) /* r11 */ << 2222 copy %r11,%r1 << 2223 bv %r0(%r25) /* r12 */ << 2224 copy %r12,%r1 << 2225 bv %r0(%r25) /* r13 */ << 2226 copy %r13,%r1 << 2227 bv %r0(%r25) /* r14 */ << 2228 copy %r14,%r1 << 2229 bv %r0(%r25) /* r15 */ << 2230 copy %r15,%r1 << 2231 bv %r0(%r25) /* r16 - shadowe << 2232 ldi -1,%r1 << 2233 bv %r0(%r25) /* r17 - shadowe << 2234 ldi -1,%r1 << 2235 bv %r0(%r25) /* r18 */ << 2236 copy %r18,%r1 << 2237 bv %r0(%r25) /* r19 */ << 2238 copy %r19,%r1 << 2239 bv %r0(%r25) /* r20 */ << 2240 copy %r20,%r1 << 2241 bv %r0(%r25) /* r21 */ << 2242 copy %r21,%r1 << 2243 bv %r0(%r25) /* r22 */ << 2244 copy %r22,%r1 << 2245 bv %r0(%r25) /* r23 */ << 2246 copy %r23,%r1 << 2247 bv %r0(%r25) /* r24 - shadowe << 2248 ldi -1,%r1 << 2249 bv %r0(%r25) /* r25 - shadowe << 2250 ldi -1,%r1 << 2251 bv %r0(%r25) /* r26 */ << 2252 copy %r26,%r1 << 2253 bv %r0(%r25) /* r27 */ << 2254 copy %r27,%r1 << 2255 bv %r0(%r25) /* r28 */ << 2256 copy %r28,%r1 << 2257 bv %r0(%r25) /* r29 */ << 2258 copy %r29,%r1 << 2259 bv %r0(%r25) /* r30 */ << 2260 copy %r30,%r1 << 2261 bv %r0(%r25) /* r31 */ << 2262 copy %r31,%r1 << 2263 ENDPROC_CFI(get_register) << 2264 1284 >> 1285 ! Get pending status for printouts later. >> 1286 ld [%o2 + PCI_SYS_INT_PENDING], %o0 2265 1287 2266 ENTRY_CFI(set_register) !! 1288 mov PCI_SYS_INT_PENDING_CLEAR_ALL, %o1 2267 /* !! 1289 stb %o1, [%o2 + PCI_SYS_INT_PENDING_CLEAR] 2268 * set_register is used by the non ac !! 1290 1: 2269 * copy the value of r1 into the gene !! 1291 ld [%o2 + PCI_SYS_INT_PENDING], %o1 2270 * r8. !! 1292 andcc %o1, ((PCI_SYS_INT_PENDING_PIO|PCI_SYS_INT_PENDING_PCI)>>24), %g0 2271 */ !! 1293 bne 1b 2272 blr %r8,%r0 !! 1294 nop 2273 nop !! 1295 2274 bv %r0(%r25) /* r0 (silly, bu !! 1296 or %l0, PSR_PIL, %l4 2275 copy %r1,%r0 !! 1297 wr %l4, 0x0, %psr 2276 bv %r0(%r25) /* r1 */ !! 1298 WRITE_PAUSE 2277 copy %r1,%r1 !! 1299 wr %l4, PSR_ET, %psr 2278 bv %r0(%r25) /* r2 */ !! 1300 WRITE_PAUSE 2279 copy %r1,%r2 !! 1301 2280 bv %r0(%r25) /* r3 */ !! 1302 call pcic_nmi 2281 copy %r1,%r3 !! 1303 add %sp, STACKFRAME_SZ, %o1 ! struct pt_regs *regs 2282 bv %r0(%r25) /* r4 */ !! 1304 RESTORE_ALL 2283 copy %r1,%r4 !! 1305 2284 bv %r0(%r25) /* r5 */ !! 1306 .globl pcic_nmi_trap_patch 2285 copy %r1,%r5 !! 1307 pcic_nmi_trap_patch: 2286 bv %r0(%r25) /* r6 */ !! 1308 sethi %hi(linux_trap_ipi15_pcic), %l3 2287 copy %r1,%r6 !! 1309 jmpl %l3 + %lo(linux_trap_ipi15_pcic), %g0 2288 bv %r0(%r25) /* r7 */ !! 1310 rd %psr, %l0 2289 copy %r1,%r7 !! 1311 .word 0 2290 bv %r0(%r25) /* r8 */ !! 1312 2291 copy %r1,%r8 !! 1313 #endif /* CONFIG_PCIC_PCI */ 2292 bv %r0(%r25) /* r9 */ !! 1314 2293 copy %r1,%r9 !! 1315 .globl flushw_all 2294 bv %r0(%r25) /* r10 */ !! 1316 flushw_all: 2295 copy %r1,%r10 !! 1317 save %sp, -0x40, %sp 2296 bv %r0(%r25) /* r11 */ !! 1318 save %sp, -0x40, %sp 2297 copy %r1,%r11 !! 1319 save %sp, -0x40, %sp 2298 bv %r0(%r25) /* r12 */ !! 1320 save %sp, -0x40, %sp 2299 copy %r1,%r12 !! 1321 save %sp, -0x40, %sp 2300 bv %r0(%r25) /* r13 */ !! 1322 save %sp, -0x40, %sp 2301 copy %r1,%r13 !! 1323 save %sp, -0x40, %sp 2302 bv %r0(%r25) /* r14 */ !! 1324 restore 2303 copy %r1,%r14 !! 1325 restore 2304 bv %r0(%r25) /* r15 */ !! 1326 restore 2305 copy %r1,%r15 !! 1327 restore 2306 bv %r0(%r25) /* r16 */ !! 1328 restore 2307 copy %r1,%r16 !! 1329 restore 2308 bv %r0(%r25) /* r17 */ !! 1330 ret 2309 copy %r1,%r17 !! 1331 restore 2310 bv %r0(%r25) /* r18 */ !! 1332 2311 copy %r1,%r18 !! 1333 #ifdef CONFIG_SMP 2312 bv %r0(%r25) /* r19 */ !! 1334 ENTRY(hard_smp_processor_id) 2313 copy %r1,%r19 !! 1335 661: rd %tbr, %g1 2314 bv %r0(%r25) /* r20 */ !! 1336 srl %g1, 12, %o0 2315 copy %r1,%r20 !! 1337 and %o0, 3, %o0 2316 bv %r0(%r25) /* r21 */ !! 1338 .section .cpuid_patch, "ax" 2317 copy %r1,%r21 !! 1339 /* Instruction location. */ 2318 bv %r0(%r25) /* r22 */ !! 1340 .word 661b 2319 copy %r1,%r22 !! 1341 /* SUN4D implementation. */ 2320 bv %r0(%r25) /* r23 */ !! 1342 lda [%g0] ASI_M_VIKING_TMP1, %o0 2321 copy %r1,%r23 !! 1343 nop 2322 bv %r0(%r25) /* r24 */ !! 1344 nop 2323 copy %r1,%r24 !! 1345 /* LEON implementation. */ 2324 bv %r0(%r25) /* r25 */ !! 1346 rd %asr17, %o0 2325 copy %r1,%r25 !! 1347 srl %o0, 0x1c, %o0 2326 bv %r0(%r25) /* r26 */ !! 1348 nop 2327 copy %r1,%r26 !! 1349 .previous 2328 bv %r0(%r25) /* r27 */ !! 1350 retl 2329 copy %r1,%r27 !! 1351 nop 2330 bv %r0(%r25) /* r28 */ !! 1352 ENDPROC(hard_smp_processor_id) 2331 copy %r1,%r28 !! 1353 #endif 2332 bv %r0(%r25) /* r29 */ << 2333 copy %r1,%r29 << 2334 bv %r0(%r25) /* r30 */ << 2335 copy %r1,%r30 << 2336 bv %r0(%r25) /* r31 */ << 2337 copy %r1,%r31 << 2338 ENDPROC_CFI(set_register) << 2339 1354 >> 1355 /* 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.