1/* 2 * Linux/PA-RISC Project (http://www.parisc-linux.org/) 3 * 4 * kernel entry points (interruptions, system call wrappers) 5 * Copyright (C) 1999,2000 Philipp Rumpf 6 * Copyright (C) 1999 SuSE GmbH Nuernberg 7 * Copyright (C) 2000 Hewlett-Packard (John Marvin) 8 * Copyright (C) 1999 Hewlett-Packard (Frank Rowand) 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2, or (at your option) 13 * any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 */ 24 25#include <asm/asm-offsets.h> 26 27/* we have the following possibilities to act on an interruption: 28 * - handle in assembly and use shadowed registers only 29 * - save registers to kernel stack and handle in assembly or C */ 30 31 32#include <asm/psw.h> 33#include <asm/cache.h> /* for L1_CACHE_SHIFT */ 34#include <asm/assembly.h> /* for LDREG/STREG defines */ 35#include <asm/pgtable.h> 36#include <asm/signal.h> 37#include <asm/unistd.h> 38#include <asm/thread_info.h> 39 40#ifdef CONFIG_64BIT 41#define CMPIB cmpib,* 42#define CMPB cmpb,* 43#define COND(x) *x 44 45 .level 2.0w 46#else 47#define CMPIB cmpib, 48#define CMPB cmpb, 49#define COND(x) x 50 51 .level 2.0 52#endif 53 54 .import pa_dbit_lock,data 55 56 /* space_to_prot macro creates a prot id from a space id */ 57 58#if (SPACEID_SHIFT) == 0 59 .macro space_to_prot spc prot 60 depd,z \spc,62,31,\prot 61 .endm 62#else 63 .macro space_to_prot spc prot 64 extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot 65 .endm 66#endif 67 68 /* Switch to virtual mapping, trashing only %r1 */ 69 .macro virt_map 70 /* pcxt_ssm_bug */ 71 rsm PSW_SM_I, %r0 /* barrier for "Relied upon Translation */ 72 mtsp %r0, %sr4 73 mtsp %r0, %sr5 74 mfsp %sr7, %r1 75 or,= %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */ 76 mtsp %r1, %sr3 77 tovirt_r1 %r29 78 load32 KERNEL_PSW, %r1 79 80 rsm PSW_SM_QUIET,%r0 /* second "heavy weight" ctl op */ 81 mtsp %r0, %sr6 82 mtsp %r0, %sr7 83 mtctl %r0, %cr17 /* Clear IIASQ tail */ 84 mtctl %r0, %cr17 /* Clear IIASQ head */ 85 mtctl %r1, %ipsw 86 load32 4f, %r1 87 mtctl %r1, %cr18 /* Set IIAOQ tail */ 88 ldo 4(%r1), %r1 89 mtctl %r1, %cr18 /* Set IIAOQ head */ 90 rfir 91 nop 924: 93 .endm 94 95 /* 96 * The "get_stack" macros are responsible for determining the 97 * kernel stack value. 98 * 99 * For Faults: 100 * If sr7 == 0 101 * Already using a kernel stack, so call the 102 * get_stack_use_r30 macro to push a pt_regs structure 103 * on the stack, and store registers there. 104 * else 105 * Need to set up a kernel stack, so call the 106 * get_stack_use_cr30 macro to set up a pointer 107 * to the pt_regs structure contained within the 108 * task pointer pointed to by cr30. Set the stack 109 * pointer to point to the end of the task structure. 110 * 111 * For Interrupts: 112 * If sr7 == 0 113 * Already using a kernel stack, check to see if r30 114 * is already pointing to the per processor interrupt 115 * stack. If it is, call the get_stack_use_r30 macro 116 * to push a pt_regs structure on the stack, and store 117 * registers there. Otherwise, call get_stack_use_cr31 118 * to get a pointer to the base of the interrupt stack 119 * and push a pt_regs structure on that stack. 120 * else 121 * Need to set up a kernel stack, so call the 122 * get_stack_use_cr30 macro to set up a pointer 123 * to the pt_regs structure contained within the 124 * task pointer pointed to by cr30. Set the stack 125 * pointer to point to the end of the task structure. 126 * N.B: We don't use the interrupt stack for the 127 * first interrupt from userland, because signals/ 128 * resched's are processed when returning to userland, 129 * and we can sleep in those cases. 130 * 131 * Note that we use shadowed registers for temps until 132 * we can save %r26 and %r29. %r26 is used to preserve 133 * %r8 (a shadowed register) which temporarily contained 134 * either the fault type ("code") or the eirr. We need 135 * to use a non-shadowed register to carry the value over 136 * the rfir in virt_map. We use %r26 since this value winds 137 * up being passed as the argument to either do_cpu_irq_mask 138 * or handle_interruption. %r29 is used to hold a pointer 139 * the register save area, and once again, it needs to 140 * be a non-shadowed register so that it survives the rfir. 141 * 142 * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame. 143 */ 144 145 .macro get_stack_use_cr30 146 147 /* we save the registers in the task struct */ 148 149 mfctl %cr30, %r1 150 tophys %r1,%r9 151 LDREG TI_TASK(%r9), %r1 /* thread_info -> task_struct */ 152 tophys %r1,%r9 153 ldo TASK_REGS(%r9),%r9 154 STREG %r30, PT_GR30(%r9) 155 STREG %r29,PT_GR29(%r9) 156 STREG %r26,PT_GR26(%r9) 157 copy %r9,%r29 158 mfctl %cr30, %r1 159 ldo THREAD_SZ_ALGN(%r1), %r30 160 .endm 161 162 .macro get_stack_use_r30 163 164 /* we put a struct pt_regs on the stack and save the registers there */ 165 166 tophys %r30,%r9 167 STREG %r30,PT_GR30(%r9) 168 ldo PT_SZ_ALGN(%r30),%r30 169 STREG %r29,PT_GR29(%r9) 170 STREG %r26,PT_GR26(%r9) 171 copy %r9,%r29 172 .endm 173 174 .macro rest_stack 175 LDREG PT_GR1(%r29), %r1 176 LDREG PT_GR30(%r29),%r30 177 LDREG PT_GR29(%r29),%r29 178 .endm 179 180 /* default interruption handler 181 * (calls traps.c:handle_interruption) */ 182 .macro def code 183 b intr_save 184 ldi \code, %r8 185 .align 32 186 .endm 187 188 /* Interrupt interruption handler 189 * (calls irq.c:do_cpu_irq_mask) */ 190 .macro extint code 191 b intr_extint 192 mfsp %sr7,%r16 193 .align 32 194 .endm 195 196 .import os_hpmc, code 197 198 /* HPMC handler */ 199 .macro hpmc code 200 nop /* must be a NOP, will be patched later */ 201 load32 PA(os_hpmc), %r3 202 bv,n 0(%r3) 203 nop 204 .word 0 /* checksum (will be patched) */ 205 .word PA(os_hpmc) /* address of handler */ 206 .word 0 /* length of handler */ 207 .endm 208 209 /* 210 * Performance Note: Instructions will be moved up into 211 * this part of the code later on, once we are sure 212 * that the tlb miss handlers are close to final form. 213 */ 214 215 /* Register definitions for tlb miss handler macros */ 216 217 va = r8 /* virtual address for which the trap occured */ 218 spc = r24 /* space for which the trap occured */ 219 220#ifndef CONFIG_64BIT 221 222 /* 223 * itlb miss interruption handler (parisc 1.1 - 32 bit) 224 */ 225 226 .macro itlb_11 code 227 228 mfctl %pcsq, spc 229 b itlb_miss_11 230 mfctl %pcoq, va 231 232 .align 32 233 .endm 234#endif 235 236 /* 237 * itlb miss interruption handler (parisc 2.0) 238 */ 239 240 .macro itlb_20 code 241 mfctl %pcsq, spc 242#ifdef CONFIG_64BIT 243 b itlb_miss_20w 244#else 245 b itlb_miss_20 246#endif 247 mfctl %pcoq, va 248 249 .align 32 250 .endm 251 252#ifndef CONFIG_64BIT 253 /* 254 * naitlb miss interruption handler (parisc 1.1 - 32 bit) 255 * 256 * Note: naitlb misses will be treated 257 * as an ordinary itlb miss for now. 258 * However, note that naitlb misses 259 * have the faulting address in the 260 * IOR/ISR. 261 */ 262 263 .macro naitlb_11 code 264 265 mfctl %isr,spc 266 b itlb_miss_11 267 mfctl %ior,va 268 /* FIXME: If user causes a naitlb miss, the priv level may not be in 269 * lower bits of va, where the itlb miss handler is expecting them 270 */ 271 272 .align 32 273 .endm 274#endif 275 276 /* 277 * naitlb miss interruption handler (parisc 2.0) 278 * 279 * Note: naitlb misses will be treated 280 * as an ordinary itlb miss for now. 281 * However, note that naitlb misses 282 * have the faulting address in the 283 * IOR/ISR. 284 */ 285 286 .macro naitlb_20 code 287 288 mfctl %isr,spc 289#ifdef CONFIG_64BIT 290 b itlb_miss_20w 291#else 292 b itlb_miss_20 293#endif 294 mfctl %ior,va 295 /* FIXME: If user causes a naitlb miss, the priv level may not be in 296 * lower bits of va, where the itlb miss handler is expecting them 297 */ 298 299 .align 32 300 .endm 301 302#ifndef CONFIG_64BIT 303 /* 304 * dtlb miss interruption handler (parisc 1.1 - 32 bit) 305 */ 306 307 .macro dtlb_11 code 308 309 mfctl %isr, spc 310 b dtlb_miss_11 311 mfctl %ior, va 312 313 .align 32 314 .endm 315#endif 316 317 /* 318 * dtlb miss interruption handler (parisc 2.0) 319 */ 320 321 .macro dtlb_20 code 322 323 mfctl %isr, spc 324#ifdef CONFIG_64BIT 325 b dtlb_miss_20w 326#else 327 b dtlb_miss_20 328#endif 329 mfctl %ior, va 330 331 .align 32 332 .endm 333 334#ifndef CONFIG_64BIT 335 /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */ 336 337 .macro nadtlb_11 code 338 339 mfctl %isr,spc 340 b nadtlb_miss_11 341 mfctl %ior,va 342 343 .align 32 344 .endm 345#endif 346 347 /* nadtlb miss interruption handler (parisc 2.0) */ 348 349 .macro nadtlb_20 code 350 351 mfctl %isr,spc 352#ifdef CONFIG_64BIT 353 b nadtlb_miss_20w 354#else 355 b nadtlb_miss_20 356#endif 357 mfctl %ior,va 358 359 .align 32 360 .endm 361 362#ifndef CONFIG_64BIT 363 /* 364 * dirty bit trap interruption handler (parisc 1.1 - 32 bit) 365 */ 366 367 .macro dbit_11 code 368 369 mfctl %isr,spc 370 b dbit_trap_11 371 mfctl %ior,va 372 373 .align 32 374 .endm 375#endif 376 377 /* 378 * dirty bit trap interruption handler (parisc 2.0) 379 */ 380 381 .macro dbit_20 code 382 383 mfctl %isr,spc 384#ifdef CONFIG_64BIT 385 b dbit_trap_20w 386#else 387 b dbit_trap_20 388#endif 389 mfctl %ior,va 390 391 .align 32 392 .endm 393 394 /* The following are simple 32 vs 64 bit instruction 395 * abstractions for the macros */ 396 .macro EXTR reg1,start,length,reg2 397#ifdef CONFIG_64BIT 398 extrd,u \reg1,32+\start,\length,\reg2 399#else 400 extrw,u \reg1,\start,\length,\reg2 401#endif 402 .endm 403 404 .macro DEP reg1,start,length,reg2 405#ifdef CONFIG_64BIT 406 depd \reg1,32+\start,\length,\reg2 407#else 408 depw \reg1,\start,\length,\reg2 409#endif 410 .endm 411 412 .macro DEPI val,start,length,reg 413#ifdef CONFIG_64BIT 414 depdi \val,32+\start,\length,\reg 415#else 416 depwi \val,\start,\length,\reg 417#endif 418 .endm 419 420 /* In LP64, the space contains part of the upper 32 bits of the 421 * fault. We have to extract this and place it in the va, 422 * zeroing the corresponding bits in the space register */ 423 .macro space_adjust spc,va,tmp 424#ifdef CONFIG_64BIT 425 extrd,u \spc,63,SPACEID_SHIFT,\tmp 426 depd %r0,63,SPACEID_SHIFT,\spc 427 depd \tmp,31,SPACEID_SHIFT,\va 428#endif 429 .endm 430 431 .import swapper_pg_dir,code 432 433 /* Get the pgd. For faults on space zero (kernel space), this 434 * is simply swapper_pg_dir. For user space faults, the 435 * pgd is stored in %cr25 */ 436 .macro get_pgd spc,reg 437 ldil L%PA(swapper_pg_dir),\reg 438 ldo R%PA(swapper_pg_dir)(\reg),\reg 439 or,COND(=) %r0,\spc,%r0 440 mfctl %cr25,\reg 441 .endm 442 443 /* 444 space_check(spc,tmp,fault) 445 446 spc - The space we saw the fault with. 447 tmp - The place to store the current space. 448 fault - Function to call on failure. 449 450 Only allow faults on different spaces from the 451 currently active one if we're the kernel 452 453 */ 454 .macro space_check spc,tmp,fault 455 mfsp %sr7,\tmp 456 or,COND(<>) %r0,\spc,%r0 /* user may execute gateway page 457 * as kernel, so defeat the space 458 * check if it is */ 459 copy \spc,\tmp 460 or,COND(=) %r0,\tmp,%r0 /* nullify if executing as kernel */ 461 cmpb,COND(<>),n \tmp,\spc,\fault 462 .endm 463 464 /* Look up a PTE in a 2-Level scheme (faulting at each 465 * level if the entry isn't present 466 * 467 * NOTE: we use ldw even for LP64, since the short pointers 468 * can address up to 1TB 469 */ 470 .macro L2_ptep pmd,pte,index,va,fault 471#if PT_NLEVELS == 3 472 EXTR \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index 473#else 474 EXTR \va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index 475#endif 476 DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */ 477 copy %r0,\pte 478 ldw,s \index(\pmd),\pmd 479 bb,>=,n \pmd,_PxD_PRESENT_BIT,\fault 480 DEP %r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */ 481 copy \pmd,%r9 482 SHLREG %r9,PxD_VALUE_SHIFT,\pmd 483 EXTR \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index 484 DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */ 485 shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd 486 LDREG %r0(\pmd),\pte /* pmd is now pte */ 487 bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault 488 .endm 489 490 /* Look up PTE in a 3-Level scheme. 491 * 492 * Here we implement a Hybrid L2/L3 scheme: we allocate the 493 * first pmd adjacent to the pgd. This means that we can 494 * subtract a constant offset to get to it. The pmd and pgd 495 * sizes are arranged so that a single pmd covers 4GB (giving 496 * a full LP64 process access to 8TB) so our lookups are 497 * effectively L2 for the first 4GB of the kernel (i.e. for 498 * all ILP32 processes and all the kernel for machines with 499 * under 4GB of memory) */ 500 .macro L3_ptep pgd,pte,index,va,fault 501#if PT_NLEVELS == 3 /* we might have a 2-Level scheme, e.g. with 16kb page size */ 502 extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index 503 copy %r0,\pte 504 extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0 505 ldw,s \index(\pgd),\pgd 506 extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0 507 bb,>=,n \pgd,_PxD_PRESENT_BIT,\fault 508 extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0 509 shld \pgd,PxD_VALUE_SHIFT,\index 510 extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0 511 copy \index,\pgd 512 extrd,u,*<> \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0 513 ldo ASM_PGD_PMD_OFFSET(\pgd),\pgd 514#endif 515 L2_ptep \pgd,\pte,\index,\va,\fault 516 .endm 517 518 /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and 519 * don't needlessly dirty the cache line if it was already set */ 520 .macro update_ptep ptep,pte,tmp,tmp1 521 ldi _PAGE_ACCESSED,\tmp1 522 or \tmp1,\pte,\tmp 523 and,COND(<>) \tmp1,\pte,%r0 524 STREG \tmp,0(\ptep) 525 .endm 526 527 /* Set the dirty bit (and accessed bit). No need to be 528 * clever, this is only used from the dirty fault */ 529 .macro update_dirty ptep,pte,tmp 530 ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp 531 or \tmp,\pte,\pte 532 STREG \pte,0(\ptep) 533 .endm 534 535 /* Convert the pte and prot to tlb insertion values. How 536 * this happens is quite subtle, read below */ 537 .macro make_insert_tlb spc,pte,prot 538 space_to_prot \spc \prot /* create prot id from space */ 539 /* The following is the real subtlety. This is depositing 540 * T <-> _PAGE_REFTRAP 541 * D <-> _PAGE_DIRTY 542 * B <-> _PAGE_DMB (memory break) 543 * 544 * Then incredible subtlety: The access rights are 545 * _PAGE_GATEWAY _PAGE_EXEC _PAGE_READ 546 * See 3-14 of the parisc 2.0 manual 547 * 548 * Finally, _PAGE_READ goes in the top bit of PL1 (so we 549 * trigger an access rights trap in user space if the user 550 * tries to read an unreadable page */ 551 depd \pte,8,7,\prot 552 553 /* PAGE_USER indicates the page can be read with user privileges, 554 * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1 555 * contains _PAGE_READ */ 556 extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0 557 depdi 7,11,3,\prot 558 /* If we're a gateway page, drop PL2 back to zero for promotion 559 * to kernel privilege (so we can execute the page as kernel). 560 * Any privilege promotion page always denys read and write */ 561 extrd,u,*= \pte,_PAGE_GATEWAY_BIT+32,1,%r0 562 depd %r0,11,2,\prot /* If Gateway, Set PL2 to 0 */ 563 564 /* Enforce uncacheable pages. 565 * This should ONLY be use for MMIO on PA 2.0 machines. 566 * Memory/DMA is cache coherent on all PA2.0 machines we support 567 * (that means T-class is NOT supported) and the memory controllers 568 * on most of those machines only handles cache transactions. 569 */ 570 extrd,u,*= \pte,_PAGE_NO_CACHE_BIT+32,1,%r0 571 depi 1,12,1,\prot 572 573 /* Drop prot bits and convert to page addr for iitlbt and idtlbt */ 574 extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte 575 depdi _PAGE_SIZE_ENCODING_DEFAULT,63,63-58,\pte 576 .endm 577 578 /* Identical macro to make_insert_tlb above, except it 579 * makes the tlb entry for the differently formatted pa11 580 * insertion instructions */ 581 .macro make_insert_tlb_11 spc,pte,prot 582 zdep \spc,30,15,\prot 583 dep \pte,8,7,\prot 584 extru,= \pte,_PAGE_NO_CACHE_BIT,1,%r0 585 depi 1,12,1,\prot 586 extru,= \pte,_PAGE_USER_BIT,1,%r0 587 depi 7,11,3,\prot /* Set for user space (1 rsvd for read) */ 588 extru,= \pte,_PAGE_GATEWAY_BIT,1,%r0 589 depi 0,11,2,\prot /* If Gateway, Set PL2 to 0 */ 590 591 /* Get rid of prot bits and convert to page addr for iitlba */ 592 593 depi _PAGE_SIZE_ENCODING_DEFAULT,31,ASM_PFN_PTE_SHIFT,\pte 594 extru \pte,24,25,\pte 595 .endm 596 597 /* This is for ILP32 PA2.0 only. The TLB insertion needs 598 * to extend into I/O space if the address is 0xfXXXXXXX 599 * so we extend the f's into the top word of the pte in 600 * this case */ 601 .macro f_extend pte,tmp 602 extrd,s \pte,42,4,\tmp 603 addi,<> 1,\tmp,%r0 604 extrd,s \pte,63,25,\pte 605 .endm 606 607 /* The alias region is an 8MB aligned 16MB to do clear and 608 * copy user pages at addresses congruent with the user 609 * virtual address. 610 * 611 * To use the alias page, you set %r26 up with the to TLB 612 * entry (identifying the physical page) and %r23 up with 613 * the from tlb entry (or nothing if only a to entry---for 614 * clear_user_page_asm) */ 615 .macro do_alias spc,tmp,tmp1,va,pte,prot,fault 616 cmpib,COND(<>),n 0,\spc,\fault 617 ldil L%(TMPALIAS_MAP_START),\tmp 618#if defined(CONFIG_64BIT) && (TMPALIAS_MAP_START >= 0x80000000) 619 /* on LP64, ldi will sign extend into the upper 32 bits, 620 * which is behaviour we don't want */ 621 depdi 0,31,32,\tmp 622#endif 623 copy \va,\tmp1 624 DEPI 0,31,23,\tmp1 625 cmpb,COND(<>),n \tmp,\tmp1,\fault 626 ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot 627 depd,z \prot,8,7,\prot 628 /* 629 * OK, it is in the temp alias region, check whether "from" or "to". 630 * Check "subtle" note in pacache.S re: r23/r26. 631 */ 632#ifdef CONFIG_64BIT 633 extrd,u,*= \va,41,1,%r0 634#else 635 extrw,u,= \va,9,1,%r0 636#endif 637 or,COND(tr) %r23,%r0,\pte 638 or %r26,%r0,\pte 639 .endm 640 641 642 /* 643 * Align fault_vector_20 on 4K boundary so that both 644 * fault_vector_11 and fault_vector_20 are on the 645 * same page. This is only necessary as long as we 646 * write protect the kernel text, which we may stop 647 * doing once we use large page translations to cover 648 * the static part of the kernel address space. 649 */ 650 651 .export fault_vector_20 652 653 .text 654 655 .align 4096 656 657fault_vector_20: 658 /* First vector is invalid (0) */ 659 .ascii "cows can fly" 660 .byte 0 661 .align 32 662 663 hpmc 1 664 def 2 665 def 3 666 extint 4 667 def 5 668 itlb_20 6 669 def 7 670 def 8 671 def 9 672 def 10 673 def 11 674 def 12 675 def 13 676 def 14 677 dtlb_20 15 678#if 0 679 naitlb_20 16 680#else 681 def 16 682#endif 683 nadtlb_20 17 684 def 18 685 def 19 686 dbit_20 20 687 def 21 688 def 22 689 def 23 690 def 24 691 def 25 692 def 26 693 def 27 694 def 28 695 def 29 696 def 30 697 def 31 698 699#ifndef CONFIG_64BIT 700 701 .export fault_vector_11 702 703 .align 2048 704 705fault_vector_11: 706 /* First vector is invalid (0) */ 707 .ascii "cows can fly" 708 .byte 0 709 .align 32 710 711 hpmc 1 712 def 2 713 def 3 714 extint 4 715 def 5 716 itlb_11 6 717 def 7 718 def 8 719 def 9 720 def 10 721 def 11 722 def 12 723 def 13 724 def 14 725 dtlb_11 15 726#if 0 727 naitlb_11 16 728#else 729 def 16 730#endif 731 nadtlb_11 17 732 def 18 733 def 19 734 dbit_11 20 735 def 21 736 def 22 737 def 23 738 def 24 739 def 25 740 def 26 741 def 27 742 def 28 743 def 29 744 def 30 745 def 31 746 747#endif 748 749 .import handle_interruption,code 750 .import do_cpu_irq_mask,code 751 752 /* 753 * r26 = function to be called 754 * r25 = argument to pass in 755 * r24 = flags for do_fork() 756 * 757 * Kernel threads don't ever return, so they don't need 758 * a true register context. We just save away the arguments 759 * for copy_thread/ret_ to properly set up the child. 760 */ 761 762#define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */ 763#define CLONE_UNTRACED 0x00800000 764 765 .export __kernel_thread, code 766 .import do_fork 767__kernel_thread: 768 STREG %r2, -RP_OFFSET(%r30) 769 770 copy %r30, %r1 771 ldo PT_SZ_ALGN(%r30),%r30 772#ifdef CONFIG_64BIT 773 /* Yo, function pointers in wide mode are little structs... -PB */ 774 ldd 24(%r26), %r2 775 STREG %r2, PT_GR27(%r1) /* Store childs %dp */ 776 ldd 16(%r26), %r26 777 778 STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */ 779 copy %r0, %r22 /* user_tid */ 780#endif 781 STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ 782 STREG %r25, PT_GR25(%r1) 783 ldil L%CLONE_UNTRACED, %r26 784 ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */ 785 or %r26, %r24, %r26 /* will have kernel mappings. */ 786 ldi 1, %r25 /* stack_start, signals kernel thread */ 787 stw %r0, -52(%r30) /* user_tid */ 788#ifdef CONFIG_64BIT 789 ldo -16(%r30),%r29 /* Reference param save area */ 790#endif 791 BL do_fork, %r2 792 copy %r1, %r24 /* pt_regs */ 793 794 /* Parent Returns here */ 795 796 LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2 797 ldo -PT_SZ_ALGN(%r30), %r30 798 bv %r0(%r2) 799 nop 800 801 /* 802 * Child Returns here 803 * 804 * copy_thread moved args from temp save area set up above 805 * into task save area. 806 */ 807 808 .export ret_from_kernel_thread 809ret_from_kernel_thread: 810 811 /* Call schedule_tail first though */ 812 BL schedule_tail, %r2 813 nop 814 815 LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1 816 LDREG TASK_PT_GR25(%r1), %r26 817#ifdef CONFIG_64BIT 818 LDREG TASK_PT_GR27(%r1), %r27 819 LDREG TASK_PT_GR22(%r1), %r22 820#endif 821 LDREG TASK_PT_GR26(%r1), %r1 822 ble 0(%sr7, %r1) 823 copy %r31, %r2 824 825#ifdef CONFIG_64BIT 826 ldo -16(%r30),%r29 /* Reference param save area */ 827 loadgp /* Thread could have been in a module */ 828#endif 829#ifndef CONFIG_64BIT 830 b sys_exit 831#else 832 load32 sys_exit, %r1 833 bv %r0(%r1) 834#endif 835 ldi 0, %r26 836 837 .import sys_execve, code 838 .export __execve, code 839__execve: 840 copy %r2, %r15 841 copy %r30, %r16 842 ldo PT_SZ_ALGN(%r30), %r30 843 STREG %r26, PT_GR26(%r16) 844 STREG %r25, PT_GR25(%r16) 845 STREG %r24, PT_GR24(%r16) 846#ifdef CONFIG_64BIT 847 ldo -16(%r30),%r29 /* Reference param save area */ 848#endif 849 BL sys_execve, %r2 850 copy %r16, %r26 851 852 cmpib,=,n 0,%r28,intr_return /* forward */ 853 854 /* yes, this will trap and die. */ 855 copy %r15, %r2 856 copy %r16, %r30 857 bv %r0(%r2) 858 nop 859 860 .align 4 861 862 /* 863 * struct task_struct *_switch_to(struct task_struct *prev, 864 * struct task_struct *next) 865 * 866 * switch kernel stacks and return prev */ 867 .export _switch_to, code 868_switch_to: 869 STREG %r2, -RP_OFFSET(%r30) 870 871 callee_save_float 872 callee_save 873 874 load32 _switch_to_ret, %r2 875 876 STREG %r2, TASK_PT_KPC(%r26) 877 LDREG TASK_PT_KPC(%r25), %r2 878 879 STREG %r30, TASK_PT_KSP(%r26) 880 LDREG TASK_PT_KSP(%r25), %r30 881 LDREG TASK_THREAD_INFO(%r25), %r25 882 bv %r0(%r2) 883 mtctl %r25,%cr30 884 885_switch_to_ret: 886 mtctl %r0, %cr0 /* Needed for single stepping */ 887 callee_rest 888 callee_rest_float 889 890 LDREG -RP_OFFSET(%r30), %r2 891 bv %r0(%r2) 892 copy %r26, %r28 893 894 /* 895 * Common rfi return path for interruptions, kernel execve, and 896 * sys_rt_sigreturn (sometimes). The sys_rt_sigreturn syscall will 897 * return via this path if the signal was received when the process 898 * was running; if the process was blocked on a syscall then the 899 * normal syscall_exit path is used. All syscalls for traced 900 * proceses exit via intr_restore. 901 * 902 * XXX If any syscalls that change a processes space id ever exit 903 * this way, then we will need to copy %sr3 in to PT_SR[3..7], and 904 * adjust IASQ[0..1]. 905 * 906 */ 907 908 .align 4096 909 910 .export syscall_exit_rfi 911syscall_exit_rfi: 912 mfctl %cr30,%r16 913 LDREG TI_TASK(%r16), %r16 /* thread_info -> task_struct */ 914 ldo TASK_REGS(%r16),%r16 915 /* Force iaoq to userspace, as the user has had access to our current 916 * context via sigcontext. Also Filter the PSW for the same reason. 917 */ 918 LDREG PT_IAOQ0(%r16),%r19 919 depi 3,31,2,%r19 920 STREG %r19,PT_IAOQ0(%r16) 921 LDREG PT_IAOQ1(%r16),%r19 922 depi 3,31,2,%r19 923 STREG %r19,PT_IAOQ1(%r16) 924 LDREG PT_PSW(%r16),%r19 925 load32 USER_PSW_MASK,%r1 926#ifdef CONFIG_64BIT 927 load32 USER_PSW_HI_MASK,%r20 928 depd %r20,31,32,%r1 929#endif 930 and %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */ 931 load32 USER_PSW,%r1 932 or %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */ 933 STREG %r19,PT_PSW(%r16) 934 935 /* 936 * If we aren't being traced, we never saved space registers 937 * (we don't store them in the sigcontext), so set them 938 * to "proper" values now (otherwise we'll wind up restoring 939 * whatever was last stored in the task structure, which might 940 * be inconsistent if an interrupt occured while on the gateway 941 * page). Note that we may be "trashing" values the user put in 942 * them, but we don't support the user changing them. 943 */ 944 945 STREG %r0,PT_SR2(%r16) 946 mfsp %sr3,%r19 947 STREG %r19,PT_SR0(%r16) 948 STREG %r19,PT_SR1(%r16) 949 STREG %r19,PT_SR3(%r16) 950 STREG %r19,PT_SR4(%r16) 951 STREG %r19,PT_SR5(%r16) 952 STREG %r19,PT_SR6(%r16) 953 STREG %r19,PT_SR7(%r16) 954 955intr_return: 956 /* NOTE: Need to enable interrupts incase we schedule. */ 957 ssm PSW_SM_I, %r0 958 959 /* Check for software interrupts */ 960 961 .import irq_stat,data 962 963 load32 irq_stat,%r19 964#ifdef CONFIG_SMP 965 mfctl %cr30,%r1 966 ldw TI_CPU(%r1),%r1 /* get cpu # - int */ 967 /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount 968 ** irq_stat[] is defined using ____cacheline_aligned. 969 */ 970 SHLREG %r1,L1_CACHE_SHIFT,%r20 971 add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */ 972#endif /* CONFIG_SMP */ 973 974intr_check_resched: 975 976 /* check for reschedule */ 977 mfctl %cr30,%r1 978 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */ 979 bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */ 980 981intr_check_sig: 982 /* As above */ 983 mfctl %cr30,%r1 984 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_SIGPENDING */ 985 bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */ 986 987intr_restore: 988 copy %r16,%r29 989 ldo PT_FR31(%r29),%r1 990 rest_fp %r1 991 rest_general %r29 992 993 /* inverse of virt_map */ 994 pcxt_ssm_bug 995 rsm PSW_SM_QUIET,%r0 /* prepare for rfi */ 996 tophys_r1 %r29 997 998 /* Restore space id's and special cr's from PT_REGS 999 * structure pointed to by r29 1000 */ 1001 rest_specials %r29 1002 1003 /* IMPORTANT: rest_stack restores r29 last (we are using it)! 1004 * It also restores r1 and r30. 1005 */ 1006 rest_stack 1007 1008 rfi 1009 nop 1010 nop 1011 nop 1012 nop 1013 nop 1014 nop 1015 nop 1016 nop 1017 1018#ifndef CONFIG_PREEMPT 1019# define intr_do_preempt intr_restore 1020#endif /* !CONFIG_PREEMPT */ 1021 1022 .import schedule,code 1023intr_do_resched: 1024 /* Only call schedule on return to userspace. If we're returning 1025 * to kernel space, we may schedule if CONFIG_PREEMPT, otherwise 1026 * we jump back to intr_restore. 1027 */ 1028 LDREG PT_IASQ0(%r16), %r20 1029 CMPIB= 0, %r20, intr_do_preempt 1030 nop 1031 LDREG PT_IASQ1(%r16), %r20 1032 CMPIB= 0, %r20, intr_do_preempt 1033 nop 1034 1035#ifdef CONFIG_64BIT 1036 ldo -16(%r30),%r29 /* Reference param save area */ 1037#endif 1038 1039 ldil L%intr_check_sig, %r2 1040#ifndef CONFIG_64BIT 1041 b schedule 1042#else 1043 load32 schedule, %r20 1044 bv %r0(%r20) 1045#endif 1046 ldo R%intr_check_sig(%r2), %r2 1047 1048 /* preempt the current task on returning to kernel 1049 * mode from an interrupt, iff need_resched is set, 1050 * and preempt_count is 0. otherwise, we continue on 1051 * our merry way back to the current running task. 1052 */ 1053#ifdef CONFIG_PREEMPT 1054 .import preempt_schedule_irq,code 1055intr_do_preempt: 1056 rsm PSW_SM_I, %r0 /* disable interrupts */ 1057 1058 /* current_thread_info()->preempt_count */ 1059 mfctl %cr30, %r1 1060 LDREG TI_PRE_COUNT(%r1), %r19 1061 CMPIB<> 0, %r19, intr_restore /* if preempt_count > 0 */ 1062 nop /* prev insn branched backwards */ 1063 1064 /* check if we interrupted a critical path */ 1065 LDREG PT_PSW(%r16), %r20 1066 bb,<,n %r20, 31 - PSW_SM_I, intr_restore 1067 nop 1068 1069 BL preempt_schedule_irq, %r2 1070 nop 1071 1072 b,n intr_restore /* ssm PSW_SM_I done by intr_restore */ 1073#endif /* CONFIG_PREEMPT */ 1074 1075 .import do_signal,code 1076intr_do_signal: 1077 /* 1078 This check is critical to having LWS 1079 working. The IASQ is zero on the gateway 1080 page and we cannot deliver any signals until 1081 we get off the gateway page. 1082 1083 Only do signals if we are returning to user space 1084 */ 1085 LDREG PT_IASQ0(%r16), %r20 1086 CMPIB= 0,%r20,intr_restore /* backward */ 1087 nop 1088 LDREG PT_IASQ1(%r16), %r20 1089 CMPIB= 0,%r20,intr_restore /* backward */ 1090 nop 1091 1092 copy %r0, %r24 /* unsigned long in_syscall */ 1093 copy %r16, %r25 /* struct pt_regs *regs */ 1094#ifdef CONFIG_64BIT 1095 ldo -16(%r30),%r29 /* Reference param save area */ 1096#endif 1097 1098 BL do_signal,%r2 1099 copy %r0, %r26 /* sigset_t *oldset = NULL */ 1100 1101 b intr_check_sig 1102 nop 1103 1104 /* 1105 * External interrupts. 1106 */ 1107 1108intr_extint: 1109 CMPIB=,n 0,%r16,1f 1110 get_stack_use_cr30 1111 b,n 3f 1112 11131: 1114#if 0 /* Interrupt Stack support not working yet! */ 1115 mfctl %cr31,%r1 1116 copy %r30,%r17 1117 /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/ 1118#ifdef CONFIG_64BIT 1119 depdi 0,63,15,%r17 1120#else 1121 depi 0,31,15,%r17 1122#endif 1123 CMPB=,n %r1,%r17,2f 1124 get_stack_use_cr31 1125 b,n 3f 1126#endif 11272: 1128 get_stack_use_r30 1129 11303: 1131 save_specials %r29 1132 virt_map 1133 save_general %r29 1134 1135 ldo PT_FR0(%r29), %r24 1136 save_fp %r24 1137 1138 loadgp 1139 1140 copy %r29, %r26 /* arg0 is pt_regs */ 1141 copy %r29, %r16 /* save pt_regs */ 1142 1143 ldil L%intr_return, %r2 1144 1145#ifdef CONFIG_64BIT 1146 ldo -16(%r30),%r29 /* Reference param save area */ 1147#endif 1148 1149 b do_cpu_irq_mask 1150 ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */ 1151 1152 1153 /* Generic interruptions (illegal insn, unaligned, page fault, etc) */ 1154 1155 .export intr_save, code /* for os_hpmc */ 1156 1157intr_save: 1158 mfsp %sr7,%r16 1159 CMPIB=,n 0,%r16,1f 1160 get_stack_use_cr30 1161 b 2f 1162 copy %r8,%r26 1163 11641: 1165 get_stack_use_r30 1166 copy %r8,%r26 1167 11682: 1169 save_specials %r29 1170 1171 /* If this trap is a itlb miss, skip saving/adjusting isr/ior */ 1172 1173 /* 1174 * FIXME: 1) Use a #define for the hardwired "6" below (and in 1175 * traps.c. 1176 * 2) Once we start executing code above 4 Gb, we need 1177 * to adjust iasq/iaoq here in the same way we 1178 * adjust isr/ior below. 1179 */ 1180 1181 CMPIB=,n 6,%r26,skip_save_ior 1182 1183 1184 mfctl %cr20, %r16 /* isr */ 1185 nop /* serialize mfctl on PA 2.0 to avoid 4 cycle penalty */ 1186 mfctl %cr21, %r17 /* ior */ 1187 1188 1189#ifdef CONFIG_64BIT 1190 /* 1191 * If the interrupted code was running with W bit off (32 bit), 1192 * clear the b bits (bits 0 & 1) in the ior. 1193 * save_specials left ipsw value in r8 for us to test. 1194 */ 1195 extrd,u,*<> %r8,PSW_W_BIT,1,%r0 1196 depdi 0,1,2,%r17 1197 1198 /* 1199 * FIXME: This code has hardwired assumptions about the split 1200 * between space bits and offset bits. This will change 1201 * when we allow alternate page sizes. 1202 */ 1203 1204 /* adjust isr/ior. */ 1205 extrd,u %r16,63,SPACEID_SHIFT,%r1 /* get high bits from isr for ior */ 1206 depd %r1,31,SPACEID_SHIFT,%r17 /* deposit them into ior */ 1207 depdi 0,63,SPACEID_SHIFT,%r16 /* clear them from isr */ 1208#endif 1209 STREG %r16, PT_ISR(%r29) 1210 STREG %r17, PT_IOR(%r29) 1211 1212 1213skip_save_ior: 1214 virt_map 1215 save_general %r29 1216 1217 ldo PT_FR0(%r29), %r25 1218 save_fp %r25 1219 1220 loadgp 1221 1222 copy %r29, %r25 /* arg1 is pt_regs */ 1223#ifdef CONFIG_64BIT 1224 ldo -16(%r30),%r29 /* Reference param save area */ 1225#endif 1226 1227 ldil L%intr_check_sig, %r2 1228 copy %r25, %r16 /* save pt_regs */ 1229 1230 b handle_interruption 1231 ldo R%intr_check_sig(%r2), %r2 1232 1233 1234 /* 1235 * Note for all tlb miss handlers: 1236 * 1237 * cr24 contains a pointer to the kernel address space 1238 * page directory. 1239 * 1240 * cr25 contains a pointer to the current user address 1241 * space page directory. 1242 * 1243 * sr3 will contain the space id of the user address space 1244 * of the current running thread while that thread is 1245 * running in the kernel. 1246 */ 1247 1248 /* 1249 * register number allocations. Note that these are all 1250 * in the shadowed registers 1251 */ 1252 1253 t0 = r1 /* temporary register 0 */ 1254 va = r8 /* virtual address for which the trap occured */ 1255 t1 = r9 /* temporary register 1 */ 1256 pte = r16 /* pte/phys page # */ 1257 prot = r17 /* prot bits */ 1258 spc = r24 /* space for which the trap occured */ 1259 ptp = r25 /* page directory/page table pointer */ 1260 1261#ifdef CONFIG_64BIT 1262 1263dtlb_miss_20w: 1264 space_adjust spc,va,t0 1265 get_pgd spc,ptp 1266 space_check spc,t0,dtlb_fault 1267 1268 L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w 1269 1270 update_ptep ptp,pte,t0,t1 1271 1272 make_insert_tlb spc,pte,prot 1273 1274 idtlbt pte,prot 1275 1276 rfir 1277 nop 1278 1279dtlb_check_alias_20w: 1280 do_alias spc,t0,t1,va,pte,prot,dtlb_fault 1281 1282 idtlbt pte,prot 1283 1284 rfir 1285 nop 1286 1287nadtlb_miss_20w: 1288 space_adjust spc,va,t0 1289 get_pgd spc,ptp 1290 space_check spc,t0,nadtlb_fault 1291 1292 L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w 1293 1294 update_ptep ptp,pte,t0,t1 1295 1296 make_insert_tlb spc,pte,prot 1297 1298 idtlbt pte,prot 1299 1300 rfir 1301 nop 1302 1303nadtlb_check_flush_20w: 1304 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate 1305 1306 /* Insert a "flush only" translation */ 1307 1308 depdi,z 7,7,3,prot 1309 depdi 1,10,1,prot 1310 1311 /* Get rid of prot bits and convert to page addr for idtlbt */ 1312 1313 depdi 0,63,12,pte 1314 extrd,u pte,56,52,pte 1315 idtlbt pte,prot 1316 1317 rfir 1318 nop 1319 1320#else 1321 1322dtlb_miss_11: 1323 get_pgd spc,ptp 1324 1325 space_check spc,t0,dtlb_fault 1326 1327 L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 1328 1329 update_ptep ptp,pte,t0,t1 1330 1331 make_insert_tlb_11 spc,pte,prot 1332 1333 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ 1334 mtsp spc,%sr1 1335 1336 idtlba pte,(%sr1,va) 1337 idtlbp prot,(%sr1,va) 1338 1339 mtsp t0, %sr1 /* Restore sr1 */ 1340 1341 rfir 1342 nop 1343 1344dtlb_check_alias_11: 1345 1346 /* Check to see if fault is in the temporary alias region */ 1347 1348 cmpib,<>,n 0,spc,dtlb_fault /* forward */ 1349 ldil L%(TMPALIAS_MAP_START),t0 1350 copy va,t1 1351 depwi 0,31,23,t1 1352 cmpb,<>,n t0,t1,dtlb_fault /* forward */ 1353 ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot 1354 depw,z prot,8,7,prot 1355 1356 /* 1357 * OK, it is in the temp alias region, check whether "from" or "to". 1358 * Check "subtle" note in pacache.S re: r23/r26. 1359 */ 1360 1361 extrw,u,= va,9,1,r0 1362 or,tr %r23,%r0,pte /* If "from" use "from" page */ 1363 or %r26,%r0,pte /* else "to", use "to" page */ 1364 1365 idtlba pte,(va) 1366 idtlbp prot,(va) 1367 1368 rfir 1369 nop 1370 1371nadtlb_miss_11: 1372 get_pgd spc,ptp 1373 1374 space_check spc,t0,nadtlb_fault 1375 1376 L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11 1377 1378 update_ptep ptp,pte,t0,t1 1379 1380 make_insert_tlb_11 spc,pte,prot 1381 1382 1383 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ 1384 mtsp spc,%sr1 1385 1386 idtlba pte,(%sr1,va) 1387 idtlbp prot,(%sr1,va) 1388 1389 mtsp t0, %sr1 /* Restore sr1 */ 1390 1391 rfir 1392 nop 1393 1394nadtlb_check_flush_11: 1395 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate 1396 1397 /* Insert a "flush only" translation */ 1398 1399 zdepi 7,7,3,prot 1400 depi 1,10,1,prot 1401 1402 /* Get rid of prot bits and convert to page addr for idtlba */ 1403 1404 depi 0,31,12,pte 1405 extru pte,24,25,pte 1406 1407 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ 1408 mtsp spc,%sr1 1409 1410 idtlba pte,(%sr1,va) 1411 idtlbp prot,(%sr1,va) 1412 1413 mtsp t0, %sr1 /* Restore sr1 */ 1414 1415 rfir 1416 nop 1417 1418dtlb_miss_20: 1419 space_adjust spc,va,t0 1420 get_pgd spc,ptp 1421 space_check spc,t0,dtlb_fault 1422 1423 L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 1424 1425 update_ptep ptp,pte,t0,t1 1426 1427 make_insert_tlb spc,pte,prot 1428 1429 f_extend pte,t0 1430 1431 idtlbt pte,prot 1432 1433 rfir 1434 nop 1435 1436dtlb_check_alias_20: 1437 do_alias spc,t0,t1,va,pte,prot,dtlb_fault 1438 1439 idtlbt pte,prot 1440 1441 rfir 1442 nop 1443 1444nadtlb_miss_20: 1445 get_pgd spc,ptp 1446 1447 space_check spc,t0,nadtlb_fault 1448 1449 L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20 1450 1451 update_ptep ptp,pte,t0,t1 1452 1453 make_insert_tlb spc,pte,prot 1454 1455 f_extend pte,t0 1456 1457 idtlbt pte,prot 1458 1459 rfir 1460 nop 1461 1462nadtlb_check_flush_20: 1463 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate 1464 1465 /* Insert a "flush only" translation */ 1466 1467 depdi,z 7,7,3,prot 1468 depdi 1,10,1,prot 1469 1470 /* Get rid of prot bits and convert to page addr for idtlbt */ 1471 1472 depdi 0,63,12,pte 1473 extrd,u pte,56,32,pte 1474 idtlbt pte,prot 1475 1476 rfir 1477 nop 1478#endif 1479 1480nadtlb_emulate: 1481 1482 /* 1483 * Non access misses can be caused by fdc,fic,pdc,lpa,probe and 1484 * probei instructions. We don't want to fault for these 1485 * instructions (not only does it not make sense, it can cause 1486 * deadlocks, since some flushes are done with the mmap 1487 * semaphore held). If the translation doesn't exist, we can't 1488 * insert a translation, so have to emulate the side effects 1489 * of the instruction. Since we don't insert a translation 1490 * we can get a lot of faults during a flush loop, so it makes 1491 * sense to try to do it here with minimum overhead. We only 1492 * emulate fdc,fic,pdc,probew,prober instructions whose base 1493 * and index registers are not shadowed. We defer everything 1494 * else to the "slow" path. 1495 */ 1496 1497 mfctl %cr19,%r9 /* Get iir */ 1498 1499 /* PA 2.0 Arch Ref. Book pg 382 has a good description of the insn bits. 1500 Checks for fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw */ 1501 1502 /* Checks for fdc,fdce,pdc,"fic,4f" only */ 1503 ldi 0x280,%r16 1504 and %r9,%r16,%r17 1505 cmpb,<>,n %r16,%r17,nadtlb_probe_check 1506 bb,>=,n %r9,26,nadtlb_nullify /* m bit not set, just nullify */ 1507 BL get_register,%r25 1508 extrw,u %r9,15,5,%r8 /* Get index register # */ 1509 CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ 1510 copy %r1,%r24 1511 BL get_register,%r25 1512 extrw,u %r9,10,5,%r8 /* Get base register # */ 1513 CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ 1514 BL set_register,%r25 1515 add,l %r1,%r24,%r1 /* doesn't affect c/b bits */ 1516 1517nadtlb_nullify: 1518 mfctl %ipsw,%r8 1519 ldil L%PSW_N,%r9 1520 or %r8,%r9,%r8 /* Set PSW_N */ 1521 mtctl %r8,%ipsw 1522 1523 rfir 1524 nop 1525 1526 /* 1527 When there is no translation for the probe address then we 1528 must nullify the insn and return zero in the target regsiter. 1529 This will indicate to the calling code that it does not have 1530 write/read privileges to this address. 1531 1532 This should technically work for prober and probew in PA 1.1, 1533 and also probe,r and probe,w in PA 2.0 1534 1535 WARNING: USE ONLY NON-SHADOW REGISTERS WITH PROBE INSN! 1536 THE SLOW-PATH EMULATION HAS NOT BEEN WRITTEN YET. 1537 1538 */ 1539nadtlb_probe_check: 1540 ldi 0x80,%r16 1541 and %r9,%r16,%r17 1542 cmpb,<>,n %r16,%r17,nadtlb_fault /* Must be probe,[rw]*/ 1543 BL get_register,%r25 /* Find the target register */ 1544 extrw,u %r9,31,5,%r8 /* Get target register */ 1545 CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ 1546 BL set_register,%r25 1547 copy %r0,%r1 /* Write zero to target register */ 1548 b nadtlb_nullify /* Nullify return insn */ 1549 nop 1550 1551 1552#ifdef CONFIG_64BIT 1553itlb_miss_20w: 1554 1555 /* 1556 * I miss is a little different, since we allow users to fault 1557 * on the gateway page which is in the kernel address space. 1558 */ 1559 1560 space_adjust spc,va,t0 1561 get_pgd spc,ptp 1562 space_check spc,t0,itlb_fault 1563 1564 L3_ptep ptp,pte,t0,va,itlb_fault 1565 1566 update_ptep ptp,pte,t0,t1 1567 1568 make_insert_tlb spc,pte,prot 1569 1570 iitlbt pte,prot 1571 1572 rfir 1573 nop 1574 1575#else 1576 1577itlb_miss_11: 1578 get_pgd spc,ptp 1579 1580 space_check spc,t0,itlb_fault 1581 1582 L2_ptep ptp,pte,t0,va,itlb_fault 1583 1584 update_ptep ptp,pte,t0,t1 1585 1586 make_insert_tlb_11 spc,pte,prot 1587 1588 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ 1589 mtsp spc,%sr1 1590 1591 iitlba pte,(%sr1,va) 1592 iitlbp prot,(%sr1,va) 1593 1594 mtsp t0, %sr1 /* Restore sr1 */ 1595 1596 rfir 1597 nop 1598 1599itlb_miss_20: 1600 get_pgd spc,ptp 1601 1602 space_check spc,t0,itlb_fault 1603 1604 L2_ptep ptp,pte,t0,va,itlb_fault 1605 1606 update_ptep ptp,pte,t0,t1 1607 1608 make_insert_tlb spc,pte,prot 1609 1610 f_extend pte,t0 1611 1612 iitlbt pte,prot 1613 1614 rfir 1615 nop 1616 1617#endif 1618 1619#ifdef CONFIG_64BIT 1620 1621dbit_trap_20w: 1622 space_adjust spc,va,t0 1623 get_pgd spc,ptp 1624 space_check spc,t0,dbit_fault 1625 1626 L3_ptep ptp,pte,t0,va,dbit_fault 1627 1628#ifdef CONFIG_SMP 1629 CMPIB=,n 0,spc,dbit_nolock_20w 1630 load32 PA(pa_dbit_lock),t0 1631 1632dbit_spin_20w: 1633 LDCW 0(t0),t1 1634 cmpib,= 0,t1,dbit_spin_20w 1635 nop 1636 1637dbit_nolock_20w: 1638#endif 1639 update_dirty ptp,pte,t1 1640 1641 make_insert_tlb spc,pte,prot 1642 1643 idtlbt pte,prot 1644#ifdef CONFIG_SMP 1645 CMPIB=,n 0,spc,dbit_nounlock_20w 1646 ldi 1,t1 1647 stw t1,0(t0) 1648 1649dbit_nounlock_20w: 1650#endif 1651 1652 rfir 1653 nop 1654#else 1655 1656dbit_trap_11: 1657 1658 get_pgd spc,ptp 1659 1660 space_check spc,t0,dbit_fault 1661 1662 L2_ptep ptp,pte,t0,va,dbit_fault 1663 1664#ifdef CONFIG_SMP 1665 CMPIB=,n 0,spc,dbit_nolock_11 1666 load32 PA(pa_dbit_lock),t0 1667 1668dbit_spin_11: 1669 LDCW 0(t0),t1 1670 cmpib,= 0,t1,dbit_spin_11 1671 nop 1672 1673dbit_nolock_11: 1674#endif 1675 update_dirty ptp,pte,t1 1676 1677 make_insert_tlb_11 spc,pte,prot 1678 1679 mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ 1680 mtsp spc,%sr1 1681 1682 idtlba pte,(%sr1,va) 1683 idtlbp prot,(%sr1,va) 1684 1685 mtsp t1, %sr1 /* Restore sr1 */ 1686#ifdef CONFIG_SMP 1687 CMPIB=,n 0,spc,dbit_nounlock_11 1688 ldi 1,t1 1689 stw t1,0(t0) 1690 1691dbit_nounlock_11: 1692#endif 1693 1694 rfir 1695 nop 1696 1697dbit_trap_20: 1698 get_pgd spc,ptp 1699 1700 space_check spc,t0,dbit_fault 1701 1702 L2_ptep ptp,pte,t0,va,dbit_fault 1703 1704#ifdef CONFIG_SMP 1705 CMPIB=,n 0,spc,dbit_nolock_20 1706 load32 PA(pa_dbit_lock),t0 1707 1708dbit_spin_20: 1709 LDCW 0(t0),t1 1710 cmpib,= 0,t1,dbit_spin_20 1711 nop 1712 1713dbit_nolock_20: 1714#endif 1715 update_dirty ptp,pte,t1 1716 1717 make_insert_tlb spc,pte,prot 1718 1719 f_extend pte,t1 1720 1721 idtlbt pte,prot 1722 1723#ifdef CONFIG_SMP 1724 CMPIB=,n 0,spc,dbit_nounlock_20 1725 ldi 1,t1 1726 stw t1,0(t0) 1727 1728dbit_nounlock_20: 1729#endif 1730 1731 rfir 1732 nop 1733#endif 1734 1735 .import handle_interruption,code 1736 1737kernel_bad_space: 1738 b intr_save 1739 ldi 31,%r8 /* Use an unused code */ 1740 1741dbit_fault: 1742 b intr_save 1743 ldi 20,%r8 1744 1745itlb_fault: 1746 b intr_save 1747 ldi 6,%r8 1748 1749nadtlb_fault: 1750 b intr_save 1751 ldi 17,%r8 1752 1753dtlb_fault: 1754 b intr_save 1755 ldi 15,%r8 1756 1757 /* Register saving semantics for system calls: 1758 1759 %r1 clobbered by system call macro in userspace 1760 %r2 saved in PT_REGS by gateway page 1761 %r3 - %r18 preserved by C code (saved by signal code) 1762 %r19 - %r20 saved in PT_REGS by gateway page 1763 %r21 - %r22 non-standard syscall args 1764 stored in kernel stack by gateway page 1765 %r23 - %r26 arg3-arg0, saved in PT_REGS by gateway page 1766 %r27 - %r30 saved in PT_REGS by gateway page 1767 %r31 syscall return pointer 1768 */ 1769 1770 /* Floating point registers (FIXME: what do we do with these?) 1771 1772 %fr0 - %fr3 status/exception, not preserved 1773 %fr4 - %fr7 arguments 1774 %fr8 - %fr11 not preserved by C code 1775 %fr12 - %fr21 preserved by C code 1776 %fr22 - %fr31 not preserved by C code 1777 */ 1778 1779 .macro reg_save regs 1780 STREG %r3, PT_GR3(\regs) 1781 STREG %r4, PT_GR4(\regs) 1782 STREG %r5, PT_GR5(\regs) 1783 STREG %r6, PT_GR6(\regs) 1784 STREG %r7, PT_GR7(\regs) 1785 STREG %r8, PT_GR8(\regs) 1786 STREG %r9, PT_GR9(\regs) 1787 STREG %r10,PT_GR10(\regs) 1788 STREG %r11,PT_GR11(\regs) 1789 STREG %r12,PT_GR12(\regs) 1790 STREG %r13,PT_GR13(\regs) 1791 STREG %r14,PT_GR14(\regs) 1792 STREG %r15,PT_GR15(\regs) 1793 STREG %r16,PT_GR16(\regs) 1794 STREG %r17,PT_GR17(\regs) 1795 STREG %r18,PT_GR18(\regs) 1796 .endm 1797 1798 .macro reg_restore regs 1799 LDREG PT_GR3(\regs), %r3 1800 LDREG PT_GR4(\regs), %r4 1801 LDREG PT_GR5(\regs), %r5 1802 LDREG PT_GR6(\regs), %r6 1803 LDREG PT_GR7(\regs), %r7 1804 LDREG PT_GR8(\regs), %r8 1805 LDREG PT_GR9(\regs), %r9 1806 LDREG PT_GR10(\regs),%r10 1807 LDREG PT_GR11(\regs),%r11 1808 LDREG PT_GR12(\regs),%r12 1809 LDREG PT_GR13(\regs),%r13 1810 LDREG PT_GR14(\regs),%r14 1811 LDREG PT_GR15(\regs),%r15 1812 LDREG PT_GR16(\regs),%r16 1813 LDREG PT_GR17(\regs),%r17 1814 LDREG PT_GR18(\regs),%r18 1815 .endm 1816 1817 .export sys_fork_wrapper 1818 .export child_return 1819sys_fork_wrapper: 1820 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 1821 ldo TASK_REGS(%r1),%r1 1822 reg_save %r1 1823 mfctl %cr27, %r3 1824 STREG %r3, PT_CR27(%r1) 1825 1826 STREG %r2,-RP_OFFSET(%r30) 1827 ldo FRAME_SIZE(%r30),%r30 1828#ifdef CONFIG_64BIT 1829 ldo -16(%r30),%r29 /* Reference param save area */ 1830#endif 1831 1832 /* These are call-clobbered registers and therefore 1833 also syscall-clobbered (we hope). */ 1834 STREG %r2,PT_GR19(%r1) /* save for child */ 1835 STREG %r30,PT_GR21(%r1) 1836 1837 LDREG PT_GR30(%r1),%r25 1838 copy %r1,%r24 1839 BL sys_clone,%r2 1840 ldi SIGCHLD,%r26 1841 1842 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 1843wrapper_exit: 1844 ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */ 1845 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 1846 ldo TASK_REGS(%r1),%r1 /* get pt regs */ 1847 1848 LDREG PT_CR27(%r1), %r3 1849 mtctl %r3, %cr27 1850 reg_restore %r1 1851 1852 /* strace expects syscall # to be preserved in r20 */ 1853 ldi __NR_fork,%r20 1854 bv %r0(%r2) 1855 STREG %r20,PT_GR20(%r1) 1856 1857 /* Set the return value for the child */ 1858child_return: 1859 BL schedule_tail, %r2 1860 nop 1861 1862 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1 1863 LDREG TASK_PT_GR19(%r1),%r2 1864 b wrapper_exit 1865 copy %r0,%r28 1866 1867 1868 .export sys_clone_wrapper 1869sys_clone_wrapper: 1870 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 1871 ldo TASK_REGS(%r1),%r1 /* get pt regs */ 1872 reg_save %r1 1873 mfctl %cr27, %r3 1874 STREG %r3, PT_CR27(%r1) 1875 1876 STREG %r2,-RP_OFFSET(%r30) 1877 ldo FRAME_SIZE(%r30),%r30 1878#ifdef CONFIG_64BIT 1879 ldo -16(%r30),%r29 /* Reference param save area */ 1880#endif 1881 1882 /* WARNING - Clobbers r19 and r21, userspace must save these! */ 1883 STREG %r2,PT_GR19(%r1) /* save for child */ 1884 STREG %r30,PT_GR21(%r1) 1885 BL sys_clone,%r2 1886 copy %r1,%r24 1887 1888 b wrapper_exit 1889 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 1890 1891 .export sys_vfork_wrapper 1892sys_vfork_wrapper: 1893 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 1894 ldo TASK_REGS(%r1),%r1 /* get pt regs */ 1895 reg_save %r1 1896 mfctl %cr27, %r3 1897 STREG %r3, PT_CR27(%r1) 1898 1899 STREG %r2,-RP_OFFSET(%r30) 1900 ldo FRAME_SIZE(%r30),%r30 1901#ifdef CONFIG_64BIT 1902 ldo -16(%r30),%r29 /* Reference param save area */ 1903#endif 1904 1905 STREG %r2,PT_GR19(%r1) /* save for child */ 1906 STREG %r30,PT_GR21(%r1) 1907 1908 BL sys_vfork,%r2 1909 copy %r1,%r26 1910 1911 b wrapper_exit 1912 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 1913 1914 1915 .macro execve_wrapper execve 1916 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 1917 ldo TASK_REGS(%r1),%r1 /* get pt regs */ 1918 1919 /* 1920 * Do we need to save/restore r3-r18 here? 1921 * I don't think so. why would new thread need old 1922 * threads registers? 1923 */ 1924 1925 /* %arg0 - %arg3 are already saved for us. */ 1926 1927 STREG %r2,-RP_OFFSET(%r30) 1928 ldo FRAME_SIZE(%r30),%r30 1929#ifdef CONFIG_64BIT 1930 ldo -16(%r30),%r29 /* Reference param save area */ 1931#endif 1932 BL \execve,%r2 1933 copy %r1,%arg0 1934 1935 ldo -FRAME_SIZE(%r30),%r30 1936 LDREG -RP_OFFSET(%r30),%r2 1937 1938 /* If exec succeeded we need to load the args */ 1939 1940 ldo -1024(%r0),%r1 1941 cmpb,>>= %r28,%r1,error_\execve 1942 copy %r2,%r19 1943 1944error_\execve: 1945 bv %r0(%r19) 1946 nop 1947 .endm 1948 1949 .export sys_execve_wrapper 1950 .import sys_execve 1951 1952sys_execve_wrapper: 1953 execve_wrapper sys_execve 1954 1955#ifdef CONFIG_64BIT 1956 .export sys32_execve_wrapper 1957 .import sys32_execve 1958 1959sys32_execve_wrapper: 1960 execve_wrapper sys32_execve 1961#endif 1962 1963 .export sys_rt_sigreturn_wrapper 1964sys_rt_sigreturn_wrapper: 1965 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 1966 ldo TASK_REGS(%r26),%r26 /* get pt regs */ 1967 /* Don't save regs, we are going to restore them from sigcontext. */ 1968 STREG %r2, -RP_OFFSET(%r30) 1969#ifdef CONFIG_64BIT 1970 ldo FRAME_SIZE(%r30), %r30 1971 BL sys_rt_sigreturn,%r2 1972 ldo -16(%r30),%r29 /* Reference param save area */ 1973#else 1974 BL sys_rt_sigreturn,%r2 1975 ldo FRAME_SIZE(%r30), %r30 1976#endif 1977 1978 ldo -FRAME_SIZE(%r30), %r30 1979 LDREG -RP_OFFSET(%r30), %r2 1980 1981 /* FIXME: I think we need to restore a few more things here. */ 1982 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 1983 ldo TASK_REGS(%r1),%r1 /* get pt regs */ 1984 reg_restore %r1 1985 1986 /* If the signal was received while the process was blocked on a 1987 * syscall, then r2 will take us to syscall_exit; otherwise r2 will 1988 * take us to syscall_exit_rfi and on to intr_return. 1989 */ 1990 bv %r0(%r2) 1991 LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */ 1992 1993 .export sys_sigaltstack_wrapper 1994sys_sigaltstack_wrapper: 1995 /* Get the user stack pointer */ 1996 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 1997 ldo TASK_REGS(%r1),%r24 /* get pt regs */ 1998 LDREG TASK_PT_GR30(%r24),%r24 1999 STREG %r2, -RP_OFFSET(%r30) 2000#ifdef CONFIG_64BIT 2001 ldo FRAME_SIZE(%r30), %r30 2002 b,l do_sigaltstack,%r2 2003 ldo -16(%r30),%r29 /* Reference param save area */ 2004#else 2005 bl do_sigaltstack,%r2 2006 ldo FRAME_SIZE(%r30), %r30 2007#endif 2008 2009 ldo -FRAME_SIZE(%r30), %r30 2010 LDREG -RP_OFFSET(%r30), %r2 2011 bv %r0(%r2) 2012 nop 2013 2014#ifdef CONFIG_64BIT 2015 .export sys32_sigaltstack_wrapper 2016sys32_sigaltstack_wrapper: 2017 /* Get the user stack pointer */ 2018 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r24 2019 LDREG TASK_PT_GR30(%r24),%r24 2020 STREG %r2, -RP_OFFSET(%r30) 2021 ldo FRAME_SIZE(%r30), %r30 2022 b,l do_sigaltstack32,%r2 2023 ldo -16(%r30),%r29 /* Reference param save area */ 2024 2025 ldo -FRAME_SIZE(%r30), %r30 2026 LDREG -RP_OFFSET(%r30), %r2 2027 bv %r0(%r2) 2028 nop 2029#endif 2030 2031 .export sys_rt_sigsuspend_wrapper 2032sys_rt_sigsuspend_wrapper: 2033 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 2034 ldo TASK_REGS(%r1),%r24 2035 reg_save %r24 2036 2037 STREG %r2, -RP_OFFSET(%r30) 2038#ifdef CONFIG_64BIT 2039 ldo FRAME_SIZE(%r30), %r30 2040 b,l sys_rt_sigsuspend,%r2 2041 ldo -16(%r30),%r29 /* Reference param save area */ 2042#else 2043 bl sys_rt_sigsuspend,%r2 2044 ldo FRAME_SIZE(%r30), %r30 2045#endif 2046 2047 ldo -FRAME_SIZE(%r30), %r30 2048 LDREG -RP_OFFSET(%r30), %r2 2049 2050 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 2051 ldo TASK_REGS(%r1),%r1 2052 reg_restore %r1 2053 2054 bv %r0(%r2) 2055 nop 2056 2057 .export syscall_exit 2058syscall_exit: 2059 2060 /* NOTE: HP-UX syscalls also come through here 2061 * after hpux_syscall_exit fixes up return 2062 * values. */ 2063 2064 /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit 2065 * via syscall_exit_rfi if the signal was received while the process 2066 * was running. 2067 */ 2068 2069 /* save return value now */ 2070 2071 mfctl %cr30, %r1 2072 LDREG TI_TASK(%r1),%r1 2073 STREG %r28,TASK_PT_GR28(%r1) 2074 2075#ifdef CONFIG_HPUX 2076 2077/* <linux/personality.h> cannot be easily included */ 2078#define PER_HPUX 0x10 2079 LDREG TASK_PERSONALITY(%r1),%r19 2080 2081 /* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */ 2082 ldo -PER_HPUX(%r19), %r19 2083 CMPIB<>,n 0,%r19,1f 2084 2085 /* Save other hpux returns if personality is PER_HPUX */ 2086 STREG %r22,TASK_PT_GR22(%r1) 2087 STREG %r29,TASK_PT_GR29(%r1) 20881: 2089 2090#endif /* CONFIG_HPUX */ 2091 2092 /* Seems to me that dp could be wrong here, if the syscall involved 2093 * calling a module, and nothing got round to restoring dp on return. 2094 */ 2095 loadgp 2096 2097syscall_check_bh: 2098 2099 /* Check for software interrupts */ 2100 2101 .import irq_stat,data 2102 2103 load32 irq_stat,%r19 2104 2105#ifdef CONFIG_SMP 2106 /* sched.h: int processor */ 2107 /* %r26 is used as scratch register to index into irq_stat[] */ 2108 ldw TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */ 2109 2110 /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */ 2111 SHLREG %r26,L1_CACHE_SHIFT,%r20 2112 add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */ 2113#endif /* CONFIG_SMP */ 2114 2115syscall_check_resched: 2116 2117 /* check for reschedule */ 2118 2119 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */ 2120 bb,<,n %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */ 2121 2122syscall_check_sig: 2123 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* get ti flags */ 2124 bb,<,n %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */ 2125 2126syscall_restore: 2127 /* Are we being ptraced? */ 2128 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 2129 2130 LDREG TASK_PTRACE(%r1), %r19 2131 bb,< %r19,31,syscall_restore_rfi 2132 nop 2133 2134 ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */ 2135 rest_fp %r19 2136 2137 LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */ 2138 mtsar %r19 2139 2140 LDREG TASK_PT_GR2(%r1),%r2 /* restore user rp */ 2141 LDREG TASK_PT_GR19(%r1),%r19 2142 LDREG TASK_PT_GR20(%r1),%r20 2143 LDREG TASK_PT_GR21(%r1),%r21 2144 LDREG TASK_PT_GR22(%r1),%r22 2145 LDREG TASK_PT_GR23(%r1),%r23 2146 LDREG TASK_PT_GR24(%r1),%r24 2147 LDREG TASK_PT_GR25(%r1),%r25 2148 LDREG TASK_PT_GR26(%r1),%r26 2149 LDREG TASK_PT_GR27(%r1),%r27 /* restore user dp */ 2150 LDREG TASK_PT_GR28(%r1),%r28 /* syscall return value */ 2151 LDREG TASK_PT_GR29(%r1),%r29 2152 LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */ 2153 2154 /* NOTE: We use rsm/ssm pair to make this operation atomic */ 2155 rsm PSW_SM_I, %r0 2156 LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */ 2157 mfsp %sr3,%r1 /* Get users space id */ 2158 mtsp %r1,%sr7 /* Restore sr7 */ 2159 ssm PSW_SM_I, %r0 2160 2161 /* Set sr2 to zero for userspace syscalls to work. */ 2162 mtsp %r0,%sr2 2163 mtsp %r1,%sr4 /* Restore sr4 */ 2164 mtsp %r1,%sr5 /* Restore sr5 */ 2165 mtsp %r1,%sr6 /* Restore sr6 */ 2166 2167 depi 3,31,2,%r31 /* ensure return to user mode. */ 2168 2169#ifdef CONFIG_64BIT 2170 /* decide whether to reset the wide mode bit 2171 * 2172 * For a syscall, the W bit is stored in the lowest bit 2173 * of sp. Extract it and reset W if it is zero */ 2174 extrd,u,*<> %r30,63,1,%r1 2175 rsm PSW_SM_W, %r0 2176 /* now reset the lowest bit of sp if it was set */ 2177 xor %r30,%r1,%r30 2178#endif 2179 be,n 0(%sr3,%r31) /* return to user space */ 2180 2181 /* We have to return via an RFI, so that PSW T and R bits can be set 2182 * appropriately. 2183 * This sets up pt_regs so we can return via intr_restore, which is not 2184 * the most efficient way of doing things, but it works. 2185 */ 2186syscall_restore_rfi: 2187 ldo -1(%r0),%r2 /* Set recovery cntr to -1 */ 2188 mtctl %r2,%cr0 /* for immediate trap */ 2189 LDREG TASK_PT_PSW(%r1),%r2 /* Get old PSW */ 2190 ldi 0x0b,%r20 /* Create new PSW */ 2191 depi -1,13,1,%r20 /* C, Q, D, and I bits */ 2192 2193 /* The values of PA_SINGLESTEP_BIT and PA_BLOCKSTEP_BIT are 2194 * set in include/linux/ptrace.h and converted to PA bitmap 2195 * numbers in asm-offsets.c */ 2196 2197 /* if ((%r19.PA_SINGLESTEP_BIT)) { %r20.27=1} */ 2198 extru,= %r19,PA_SINGLESTEP_BIT,1,%r0 2199 depi -1,27,1,%r20 /* R bit */ 2200 2201 /* if ((%r19.PA_BLOCKSTEP_BIT)) { %r20.7=1} */ 2202 extru,= %r19,PA_BLOCKSTEP_BIT,1,%r0 2203 depi -1,7,1,%r20 /* T bit */ 2204 2205 STREG %r20,TASK_PT_PSW(%r1) 2206 2207 /* Always store space registers, since sr3 can be changed (e.g. fork) */ 2208 2209 mfsp %sr3,%r25 2210 STREG %r25,TASK_PT_SR3(%r1) 2211 STREG %r25,TASK_PT_SR4(%r1) 2212 STREG %r25,TASK_PT_SR5(%r1) 2213 STREG %r25,TASK_PT_SR6(%r1) 2214 STREG %r25,TASK_PT_SR7(%r1) 2215 STREG %r25,TASK_PT_IASQ0(%r1) 2216 STREG %r25,TASK_PT_IASQ1(%r1) 2217 2218 /* XXX W bit??? */ 2219 /* Now if old D bit is clear, it means we didn't save all registers 2220 * on syscall entry, so do that now. This only happens on TRACEME 2221 * calls, or if someone attached to us while we were on a syscall. 2222 * We could make this more efficient by not saving r3-r18, but 2223 * then we wouldn't be able to use the common intr_restore path. 2224 * It is only for traced processes anyway, so performance is not 2225 * an issue. 2226 */ 2227 bb,< %r2,30,pt_regs_ok /* Branch if D set */ 2228 ldo TASK_REGS(%r1),%r25 2229 reg_save %r25 /* Save r3 to r18 */ 2230 2231 /* Save the current sr */ 2232 mfsp %sr0,%r2 2233 STREG %r2,TASK_PT_SR0(%r1) 2234 2235 /* Save the scratch sr */ 2236 mfsp %sr1,%r2 2237 STREG %r2,TASK_PT_SR1(%r1) 2238 2239 /* sr2 should be set to zero for userspace syscalls */ 2240 STREG %r0,TASK_PT_SR2(%r1) 2241 2242pt_regs_ok: 2243 LDREG TASK_PT_GR31(%r1),%r2 2244 depi 3,31,2,%r2 /* ensure return to user mode. */ 2245 STREG %r2,TASK_PT_IAOQ0(%r1) 2246 ldo 4(%r2),%r2 2247 STREG %r2,TASK_PT_IAOQ1(%r1) 2248 copy %r25,%r16 2249 b intr_restore 2250 nop 2251 2252 .import schedule,code 2253syscall_do_resched: 2254 BL schedule,%r2 2255#ifdef CONFIG_64BIT 2256 ldo -16(%r30),%r29 /* Reference param save area */ 2257#else 2258 nop 2259#endif 2260 b syscall_check_bh /* if resched, we start over again */ 2261 nop 2262 2263 .import do_signal,code 2264syscall_do_signal: 2265 /* Save callee-save registers (for sigcontext). 2266 FIXME: After this point the process structure should be 2267 consistent with all the relevant state of the process 2268 before the syscall. We need to verify this. */ 2269 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 2270 ldo TASK_REGS(%r1), %r25 /* struct pt_regs *regs */ 2271 reg_save %r25 2272 2273 ldi 1, %r24 /* unsigned long in_syscall */ 2274 2275#ifdef CONFIG_64BIT 2276 ldo -16(%r30),%r29 /* Reference param save area */ 2277#endif 2278 BL do_signal,%r2 2279 copy %r0, %r26 /* sigset_t *oldset = NULL */ 2280 2281 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 2282 ldo TASK_REGS(%r1), %r20 /* reload pt_regs */ 2283 reg_restore %r20 2284 2285 b,n syscall_check_sig 2286 2287 /* 2288 * get_register is used by the non access tlb miss handlers to 2289 * copy the value of the general register specified in r8 into 2290 * r1. This routine can't be used for shadowed registers, since 2291 * the rfir will restore the original value. So, for the shadowed 2292 * registers we put a -1 into r1 to indicate that the register 2293 * should not be used (the register being copied could also have 2294 * a -1 in it, but that is OK, it just means that we will have 2295 * to use the slow path instead). 2296 */ 2297 2298get_register: 2299 blr %r8,%r0 2300 nop 2301 bv %r0(%r25) /* r0 */ 2302 copy %r0,%r1 2303 bv %r0(%r25) /* r1 - shadowed */ 2304 ldi -1,%r1 2305 bv %r0(%r25) /* r2 */ 2306 copy %r2,%r1 2307 bv %r0(%r25) /* r3 */ 2308 copy %r3,%r1 2309 bv %r0(%r25) /* r4 */ 2310 copy %r4,%r1 2311 bv %r0(%r25) /* r5 */ 2312 copy %r5,%r1 2313 bv %r0(%r25) /* r6 */ 2314 copy %r6,%r1 2315 bv %r0(%r25) /* r7 */ 2316 copy %r7,%r1 2317 bv %r0(%r25) /* r8 - shadowed */ 2318 ldi -1,%r1 2319 bv %r0(%r25) /* r9 - shadowed */ 2320 ldi -1,%r1 2321 bv %r0(%r25) /* r10 */ 2322 copy %r10,%r1 2323 bv %r0(%r25) /* r11 */ 2324 copy %r11,%r1 2325 bv %r0(%r25) /* r12 */ 2326 copy %r12,%r1 2327 bv %r0(%r25) /* r13 */ 2328 copy %r13,%r1 2329 bv %r0(%r25) /* r14 */ 2330 copy %r14,%r1 2331 bv %r0(%r25) /* r15 */ 2332 copy %r15,%r1 2333 bv %r0(%r25) /* r16 - shadowed */ 2334 ldi -1,%r1 2335 bv %r0(%r25) /* r17 - shadowed */ 2336 ldi -1,%r1 2337 bv %r0(%r25) /* r18 */ 2338 copy %r18,%r1 2339 bv %r0(%r25) /* r19 */ 2340 copy %r19,%r1 2341 bv %r0(%r25) /* r20 */ 2342 copy %r20,%r1 2343 bv %r0(%r25) /* r21 */ 2344 copy %r21,%r1 2345 bv %r0(%r25) /* r22 */ 2346 copy %r22,%r1 2347 bv %r0(%r25) /* r23 */ 2348 copy %r23,%r1 2349 bv %r0(%r25) /* r24 - shadowed */ 2350 ldi -1,%r1 2351 bv %r0(%r25) /* r25 - shadowed */ 2352 ldi -1,%r1 2353 bv %r0(%r25) /* r26 */ 2354 copy %r26,%r1 2355 bv %r0(%r25) /* r27 */ 2356 copy %r27,%r1 2357 bv %r0(%r25) /* r28 */ 2358 copy %r28,%r1 2359 bv %r0(%r25) /* r29 */ 2360 copy %r29,%r1 2361 bv %r0(%r25) /* r30 */ 2362 copy %r30,%r1 2363 bv %r0(%r25) /* r31 */ 2364 copy %r31,%r1 2365 2366 /* 2367 * set_register is used by the non access tlb miss handlers to 2368 * copy the value of r1 into the general register specified in 2369 * r8. 2370 */ 2371 2372set_register: 2373 blr %r8,%r0 2374 nop 2375 bv %r0(%r25) /* r0 (silly, but it is a place holder) */ 2376 copy %r1,%r0 2377 bv %r0(%r25) /* r1 */ 2378 copy %r1,%r1 2379 bv %r0(%r25) /* r2 */ 2380 copy %r1,%r2 2381 bv %r0(%r25) /* r3 */ 2382 copy %r1,%r3 2383 bv %r0(%r25) /* r4 */ 2384 copy %r1,%r4 2385 bv %r0(%r25) /* r5 */ 2386 copy %r1,%r5 2387 bv %r0(%r25) /* r6 */ 2388 copy %r1,%r6 2389 bv %r0(%r25) /* r7 */ 2390 copy %r1,%r7 2391 bv %r0(%r25) /* r8 */ 2392 copy %r1,%r8 2393 bv %r0(%r25) /* r9 */ 2394 copy %r1,%r9 2395 bv %r0(%r25) /* r10 */ 2396 copy %r1,%r10 2397 bv %r0(%r25) /* r11 */ 2398 copy %r1,%r11 2399 bv %r0(%r25) /* r12 */ 2400 copy %r1,%r12 2401 bv %r0(%r25) /* r13 */ 2402 copy %r1,%r13 2403 bv %r0(%r25) /* r14 */ 2404 copy %r1,%r14 2405 bv %r0(%r25) /* r15 */ 2406 copy %r1,%r15 2407 bv %r0(%r25) /* r16 */ 2408 copy %r1,%r16 2409 bv %r0(%r25) /* r17 */ 2410 copy %r1,%r17 2411 bv %r0(%r25) /* r18 */ 2412 copy %r1,%r18 2413 bv %r0(%r25) /* r19 */ 2414 copy %r1,%r19 2415 bv %r0(%r25) /* r20 */ 2416 copy %r1,%r20 2417 bv %r0(%r25) /* r21 */ 2418 copy %r1,%r21 2419 bv %r0(%r25) /* r22 */ 2420 copy %r1,%r22 2421 bv %r0(%r25) /* r23 */ 2422 copy %r1,%r23 2423 bv %r0(%r25) /* r24 */ 2424 copy %r1,%r24 2425 bv %r0(%r25) /* r25 */ 2426 copy %r1,%r25 2427 bv %r0(%r25) /* r26 */ 2428 copy %r1,%r26 2429 bv %r0(%r25) /* r27 */ 2430 copy %r1,%r27 2431 bv %r0(%r25) /* r28 */ 2432 copy %r1,%r28 2433 bv %r0(%r25) /* r29 */ 2434 copy %r1,%r29 2435 bv %r0(%r25) /* r30 */ 2436 copy %r1,%r30 2437 bv %r0(%r25) /* r31 */ 2438 copy %r1,%r31 2439