2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
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)
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)
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.
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.
25 #include <linux/config.h>
26 #include <asm/offsets.h>
28 /* we have the following possibilities to act on an interruption:
29 * - handle in assembly and use shadowed registers only
30 * - save registers to kernel stack and handle in assembly or C */
33 #include <asm/assembly.h> /* for LDREG/STREG defines */
34 #include <asm/pgtable.h>
36 #include <asm/signal.h>
37 #include <asm/unistd.h>
38 #include <asm/thread_info.h>
54 .import pa_dbit_lock,data
56 /* space_to_prot macro creates a prot id from a space id */
58 #if (SPACEID_SHIFT) == 0
59 .macro space_to_prot spc prot
60 depd,z \spc,62,31,\prot
63 .macro space_to_prot spc prot
64 extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot
68 /* Switch to virtual mapping, trashing only %r1 */
73 or,= %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */
79 ldil L%KERNEL_PSW, %r1
80 ldo R%KERNEL_PSW(%r1), %r1
82 mtctl %r0, %cr17 /* Clear IIASQ tail */
83 mtctl %r0, %cr17 /* Clear IIASQ head */
86 mtctl %r1, %cr18 /* Set IIAOQ tail */
88 mtctl %r1, %cr18 /* Set IIAOQ head */
95 * The "get_stack" macros are responsible for determining the
100 * Already using a kernel stack, so call the
101 * get_stack_use_r30 macro to push a pt_regs structure
102 * on the stack, and store registers there.
104 * Need to set up a kernel stack, so call the
105 * get_stack_use_cr30 macro to set up a pointer
106 * to the pt_regs structure contained within the
107 * task pointer pointed to by cr30. Set the stack
108 * pointer to point to the end of the task structure.
112 * Already using a kernel stack, check to see if r30
113 * is already pointing to the per processor interrupt
114 * stack. If it is, call the get_stack_use_r30 macro
115 * to push a pt_regs structure on the stack, and store
116 * registers there. Otherwise, call get_stack_use_cr31
117 * to get a pointer to the base of the interrupt stack
118 * and push a pt_regs structure on that stack.
120 * Need to set up a kernel stack, so call the
121 * get_stack_use_cr30 macro to set up a pointer
122 * to the pt_regs structure contained within the
123 * task pointer pointed to by cr30. Set the stack
124 * pointer to point to the end of the task structure.
125 * N.B: We don't use the interrupt stack for the
126 * first interrupt from userland, because signals/
127 * resched's are processed when returning to userland,
128 * and we can sleep in those cases.
130 * Note that we use shadowed registers for temps until
131 * we can save %r26 and %r29. %r26 is used to preserve
132 * %r8 (a shadowed register) which temporarily contained
133 * either the fault type ("code") or the eirr. We need
134 * to use a non-shadowed register to carry the value over
135 * the rfir in virt_map. We use %r26 since this value winds
136 * up being passed as the argument to either do_cpu_irq_mask
137 * or handle_interruption. %r29 is used to hold a pointer
138 * the register save area, and once again, it needs to
139 * be a non-shadowed register so that it survives the rfir.
141 * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame.
144 .macro get_stack_use_cr30
146 /* we save the registers in the task struct */
150 LDREG TI_TASK(%r9), %r1 /* thread_info -> task_struct */
152 ldo TASK_REGS(%r9),%r9
153 STREG %r30, PT_GR30(%r9)
154 STREG %r29,PT_GR29(%r9)
155 STREG %r26,PT_GR26(%r9)
158 ldo THREAD_SZ_ALGN(%r1), %r30
161 .macro get_stack_use_r30
163 /* we put a struct pt_regs on the stack and save the registers there */
166 STREG %r30,PT_GR30(%r9)
167 ldo PT_SZ_ALGN(%r30),%r30
168 STREG %r29,PT_GR29(%r9)
169 STREG %r26,PT_GR26(%r9)
174 LDREG PT_GR1(%r29), %r1
175 LDREG PT_GR30(%r29),%r30
176 LDREG PT_GR29(%r29),%r29
179 /* default interruption handler
180 * (calls traps.c:handle_interruption) */
187 /* Interrupt interruption handler
188 * (calls irq.c:do_cpu_irq_mask) */
195 .import os_hpmc, code
199 nop /* must be a NOP, will be patched later */
200 ldil L%PA(os_hpmc), %r3
201 ldo R%PA(os_hpmc)(%r3), %r3
204 .word 0 /* checksum (will be patched) */
205 .word PA(os_hpmc) /* address of handler */
206 .word 0 /* length of handler */
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.
215 /* Register definitions for tlb miss handler macros */
217 va = r8 /* virtual address for which the trap occured */
218 spc = r24 /* space for which the trap occured */
223 * itlb miss interruption handler (parisc 1.1 - 32 bit)
237 * itlb miss interruption handler (parisc 2.0)
254 * naitlb miss interruption handler (parisc 1.1 - 32 bit)
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
263 .macro naitlb_11 code
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
277 * naitlb miss interruption handler (parisc 2.0)
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
286 .macro naitlb_20 code
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
304 * dtlb miss interruption handler (parisc 1.1 - 32 bit)
318 * dtlb miss interruption handler (parisc 2.0)
335 /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */
337 .macro nadtlb_11 code
347 /* nadtlb miss interruption handler (parisc 2.0) */
349 .macro nadtlb_20 code
364 * dirty bit trap interruption handler (parisc 1.1 - 32 bit)
378 * dirty bit trap interruption handler (parisc 2.0)
394 /* The following are simple 32 vs 64 bit instruction
395 * abstractions for the macros */
396 .macro EXTR reg1,start,length,reg2
398 extrd,u \reg1,32+\start,\length,\reg2
400 extrw,u \reg1,\start,\length,\reg2
404 .macro DEP reg1,start,length,reg2
406 depd \reg1,32+\start,\length,\reg2
408 depw \reg1,\start,\length,\reg2
412 .macro DEPI val,start,length,reg
414 depdi \val,32+\start,\length,\reg
416 depwi \val,\start,\length,\reg
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
425 extrd,u \spc,63,SPACEID_SHIFT,\tmp
426 depd %r0,63,SPACEID_SHIFT,\spc
427 depd \tmp,31,SPACEID_SHIFT,\va
431 .import swapper_pg_dir,code
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
443 /* Only allow faults on different spaces from the
444 * currently active one if we're the kernel */
445 .macro space_check spc,tmp,fault
447 or,COND(<>) %r0,\spc,%r0 /* user may execute gateway page
448 * as kernel, so defeat the space
451 or,COND(=) %r0,\tmp,%r0 /* nullify if executing as kernel */
452 cmpb,COND(<>),n \tmp,\spc,\fault
455 /* Look up a PTE in a 2-Level scheme (faulting at each
456 * level if the entry isn't present
458 * NOTE: we use ldw even for LP64, since the short pointers
459 * can address up to 1TB
461 .macro L2_ptep pmd,pte,index,va,fault
463 EXTR \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index
465 EXTR \va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
467 DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */
469 ldw,s \index(\pmd),\pmd
470 bb,>=,n \pmd,_PxD_PRESENT_BIT,\fault
471 DEP %r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
474 shld %r9,PxD_VALUE_SHIFT,\pmd
476 shlw %r9,PxD_VALUE_SHIFT,\pmd
478 EXTR \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
479 DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */
480 shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd
481 LDREG %r0(\pmd),\pte /* pmd is now pte */
482 bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault
485 /* Look up PTE in a 3-Level scheme.
487 * Here we implement a Hybrid L2/L3 scheme: we allocate the
488 * first pmd adjacent to the pgd. This means that we can
489 * subtract a constant offset to get to it. The pmd and pgd
490 * sizes are arranged so that a single pmd covers 4GB (giving
491 * a full LP64 process access to 8TB) so our lookups are
492 * effectively L2 for the first 4GB of the kernel (i.e. for
493 * all ILP32 processes and all the kernel for machines with
494 * under 4GB of memory) */
495 .macro L3_ptep pgd,pte,index,va,fault
496 extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
498 extrd,u,*= \va,31,32,%r0
499 ldw,s \index(\pgd),\pgd
500 extrd,u,*= \va,31,32,%r0
501 bb,>=,n \pgd,_PxD_PRESENT_BIT,\fault
502 extrd,u,*= \va,31,32,%r0
503 shld \pgd,PxD_VALUE_SHIFT,\index
504 extrd,u,*= \va,31,32,%r0
506 extrd,u,*<> \va,31,32,%r0
507 ldo ASM_PGD_PMD_OFFSET(\pgd),\pgd
508 L2_ptep \pgd,\pte,\index,\va,\fault
511 /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and
512 * don't needlessly dirty the cache line if it was already set */
513 .macro update_ptep ptep,pte,tmp,tmp1
514 ldi _PAGE_ACCESSED,\tmp1
516 and,COND(<>) \tmp1,\pte,%r0
520 /* Set the dirty bit (and accessed bit). No need to be
521 * clever, this is only used from the dirty fault */
522 .macro update_dirty ptep,pte,tmp
523 ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp
528 /* Convert the pte and prot to tlb insertion values. How
529 * this happens is quite subtle, read below */
530 .macro make_insert_tlb spc,pte,prot
531 space_to_prot \spc \prot /* create prot id from space */
532 /* The following is the real subtlety. This is depositing
533 * T <-> _PAGE_REFTRAP
535 * B <-> _PAGE_DMB (memory break)
537 * Then incredible subtlety: The access rights are
538 * _PAGE_GATEWAY _PAGE_EXEC _PAGE_READ
539 * See 3-14 of the parisc 2.0 manual
541 * Finally, _PAGE_READ goes in the top bit of PL1 (so we
542 * trigger an access rights trap in user space if the user
543 * tries to read an unreadable page */
546 /* PAGE_USER indicates the page can be read with user privileges,
547 * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1
548 * contains _PAGE_READ */
549 extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0
551 /* If we're a gateway page, drop PL2 back to zero for promotion
552 * to kernel privilege (so we can execute the page as kernel).
553 * Any privilege promotion page always denys read and write */
554 extrd,u,*= \pte,_PAGE_GATEWAY_BIT+32,1,%r0
555 depd %r0,11,2,\prot /* If Gateway, Set PL2 to 0 */
557 /* Get rid of prot bits and convert to page addr for iitlbt */
559 depd %r0,63,PAGE_SHIFT,\pte
560 extrd,u \pte,56,32,\pte
563 /* Identical macro to make_insert_tlb above, except it
564 * makes the tlb entry for the differently formatted pa11
565 * insertion instructions */
566 .macro make_insert_tlb_11 spc,pte,prot
567 zdep \spc,30,15,\prot
569 extru,= \pte,_PAGE_NO_CACHE_BIT,1,%r0
571 extru,= \pte,_PAGE_USER_BIT,1,%r0
572 depi 7,11,3,\prot /* Set for user space (1 rsvd for read) */
573 extru,= \pte,_PAGE_GATEWAY_BIT,1,%r0
574 depi 0,11,2,\prot /* If Gateway, Set PL2 to 0 */
576 /* Get rid of prot bits and convert to page addr for iitlba */
579 extru \pte,24,25,\pte
583 /* This is for ILP32 PA2.0 only. The TLB insertion needs
584 * to extend into I/O space if the address is 0xfXXXXXXX
585 * so we extend the f's into the top word of the pte in
587 .macro f_extend pte,tmp
588 extrd,s \pte,42,4,\tmp
590 extrd,s \pte,63,25,\pte
593 /* The alias region is an 8MB aligned 16MB to do clear and
594 * copy user pages at addresses congruent with the user
597 * To use the alias page, you set %r26 up with the to TLB
598 * entry (identifying the physical page) and %r23 up with
599 * the from tlb entry (or nothing if only a to entry---for
600 * clear_user_page_asm) */
601 .macro do_alias spc,tmp,tmp1,va,pte,prot,fault
602 cmpib,COND(<>),n 0,\spc,\fault
603 ldil L%(TMPALIAS_MAP_START),\tmp
604 #if defined(__LP64__) && (TMPALIAS_MAP_START >= 0x80000000)
605 /* on LP64, ldi will sign extend into the upper 32 bits,
606 * which is behaviour we don't want */
611 cmpb,COND(<>),n \tmp,\tmp1,\fault
612 ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot
613 depd,z \prot,8,7,\prot
615 * OK, it is in the temp alias region, check whether "from" or "to".
616 * Check "subtle" note in pacache.S re: r23/r26.
619 extrd,u,*= \va,41,1,%r0
621 extrw,u,= \va,9,1,%r0
623 or,COND(tr) %r23,%r0,\pte
629 * Align fault_vector_20 on 4K boundary so that both
630 * fault_vector_11 and fault_vector_20 are on the
631 * same page. This is only necessary as long as we
632 * write protect the kernel text, which we may stop
633 * doing once we use large page translations to cover
634 * the static part of the kernel address space.
637 .export fault_vector_20
644 /* First vector is invalid (0) */
645 .ascii "cows can fly"
687 .export fault_vector_11
692 /* First vector is invalid (0) */
693 .ascii "cows can fly"
735 .import handle_interruption,code
736 .import do_cpu_irq_mask,code
739 * r26 = function to be called
740 * r25 = argument to pass in
741 * r24 = flags for do_fork()
743 * Kernel threads don't ever return, so they don't need
744 * a true register context. We just save away the arguments
745 * for copy_thread/ret_ to properly set up the child.
748 #define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */
749 #define CLONE_UNTRACED 0x00800000
751 .export __kernel_thread, code
754 STREG %r2, -RP_OFFSET(%r30)
757 ldo PT_SZ_ALGN(%r30),%r30
759 /* Yo, function pointers in wide mode are little structs... -PB */
761 STREG %r2, PT_GR27(%r1) /* Store childs %dp */
764 STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */
765 copy %r0, %r22 /* user_tid */
767 STREG %r26, PT_GR26(%r1) /* Store function & argument for child */
768 STREG %r25, PT_GR25(%r1)
769 ldil L%CLONE_UNTRACED, %r26
770 ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */
771 or %r26, %r24, %r26 /* will have kernel mappings. */
772 ldi 1, %r25 /* stack_start, signals kernel thread */
773 stw %r0, -52(%r30) /* user_tid */
775 ldo -16(%r30),%r29 /* Reference param save area */
778 copy %r1, %r24 /* pt_regs */
780 /* Parent Returns here */
782 LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2
783 ldo -PT_SZ_ALGN(%r30), %r30
790 * copy_thread moved args from temp save area set up above
791 * into task save area.
794 .export ret_from_kernel_thread
795 ret_from_kernel_thread:
797 /* Call schedule_tail first though */
798 BL schedule_tail, %r2
801 LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1
802 LDREG TASK_PT_GR25(%r1), %r26
804 LDREG TASK_PT_GR27(%r1), %r27
805 LDREG TASK_PT_GR22(%r1), %r22
807 LDREG TASK_PT_GR26(%r1), %r1
812 ldo -16(%r30),%r29 /* Reference param save area */
813 loadgp /* Thread could have been in a module */
818 .import sys_execve, code
819 .export __execve, code
823 ldo PT_SZ_ALGN(%r30), %r30
824 STREG %r26, PT_GR26(%r16)
825 STREG %r25, PT_GR25(%r16)
826 STREG %r24, PT_GR24(%r16)
828 ldo -16(%r30),%r29 /* Reference param save area */
833 cmpib,=,n 0,%r28,intr_return /* forward */
835 /* yes, this will trap and die. */
844 * struct task_struct *_switch_to(struct task_struct *prev,
845 * struct task_struct *next)
847 * switch kernel stacks and return prev */
848 .export _switch_to, code
850 STREG %r2, -RP_OFFSET(%r30)
854 ldil L%_switch_to_ret, %r2
855 ldo R%_switch_to_ret(%r2), %r2
857 STREG %r2, TASK_PT_KPC(%r26)
858 LDREG TASK_PT_KPC(%r25), %r2
860 STREG %r30, TASK_PT_KSP(%r26)
861 LDREG TASK_PT_KSP(%r25), %r30
862 LDREG TASK_THREAD_INFO(%r25), %r25
867 mtctl %r0, %cr0 /* Needed for single stepping */
870 LDREG -RP_OFFSET(%r30), %r2
875 * Common rfi return path for interruptions, kernel execve, and
876 * sys_rt_sigreturn (sometimes). The sys_rt_sigreturn syscall will
877 * return via this path if the signal was received when the process
878 * was running; if the process was blocked on a syscall then the
879 * normal syscall_exit path is used. All syscalls for traced
880 * proceses exit via intr_restore.
882 * XXX If any syscalls that change a processes space id ever exit
883 * this way, then we will need to copy %sr3 in to PT_SR[3..7], and
886 * Note that the following code uses a "relied upon translation".
887 * See the parisc ACD for details. The ssm is necessary due to a
893 .export syscall_exit_rfi
896 LDREG TI_TASK(%r16), %r16 /* thread_info -> task_struct */
897 ldo TASK_REGS(%r16),%r16
898 /* Force iaoq to userspace, as the user has had access to our current
899 * context via sigcontext. Also Filter the PSW for the same reason.
901 LDREG PT_IAOQ0(%r16),%r19
903 STREG %r19,PT_IAOQ0(%r16)
904 LDREG PT_IAOQ1(%r16),%r19
906 STREG %r19,PT_IAOQ1(%r16)
907 LDREG PT_PSW(%r16),%r19
908 ldil L%USER_PSW_MASK,%r1
909 ldo R%USER_PSW_MASK(%r1),%r1
911 ldil L%USER_PSW_HI_MASK,%r20
912 ldo R%USER_PSW_HI_MASK(%r20),%r20
915 and %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */
917 ldo R%USER_PSW(%r1),%r1
918 or %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */
919 STREG %r19,PT_PSW(%r16)
922 * If we aren't being traced, we never saved space registers
923 * (we don't store them in the sigcontext), so set them
924 * to "proper" values now (otherwise we'll wind up restoring
925 * whatever was last stored in the task structure, which might
926 * be inconsistent if an interrupt occured while on the gateway
927 * page) Note that we may be "trashing" values the user put in
928 * them, but we don't support the the user changing them.
931 STREG %r0,PT_SR2(%r16)
933 STREG %r19,PT_SR0(%r16)
934 STREG %r19,PT_SR1(%r16)
935 STREG %r19,PT_SR3(%r16)
936 STREG %r19,PT_SR4(%r16)
937 STREG %r19,PT_SR5(%r16)
938 STREG %r19,PT_SR6(%r16)
939 STREG %r19,PT_SR7(%r16)
944 /* Check for software interrupts */
946 .import irq_stat,data
949 ldo R%irq_stat(%r19),%r19
952 ldw TI_CPU(%r1),%r1 /* get cpu # - int */
953 /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
954 ** irq_stat[] is defined using ____cacheline_aligned.
961 add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */
962 #endif /* CONFIG_SMP */
964 LDREG IRQSTAT_SIRQ_PEND(%r19),%r20 /* hardirq.h: unsigned long */
965 cmpib,<>,n 0,%r20,intr_do_softirq /* forward */
969 /* check for reschedule */
971 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
972 bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
977 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_SIGPENDING */
978 bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
982 ldo PT_FR31(%r29),%r1
994 rsm (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0
1007 .import do_softirq,code
1011 ldo -16(%r30),%r29 /* Reference param save area */
1015 b intr_check_resched
1018 .import schedule,code
1020 /* Only do reschedule if we are returning to user space */
1021 LDREG PT_IASQ0(%r16), %r20
1022 CMPIB= 0,%r20,intr_restore /* backward */
1024 LDREG PT_IASQ1(%r16), %r20
1025 CMPIB= 0,%r20,intr_restore /* backward */
1029 ldo -16(%r30),%r29 /* Reference param save area */
1032 ldil L%intr_check_sig, %r2
1034 ldo R%intr_check_sig(%r2), %r2
1037 .import do_signal,code
1039 /* Only do signals if we are returning to user space */
1040 LDREG PT_IASQ0(%r16), %r20
1041 CMPIB= 0,%r20,intr_restore /* backward */
1043 LDREG PT_IASQ1(%r16), %r20
1044 CMPIB= 0,%r20,intr_restore /* backward */
1047 copy %r0, %r24 /* unsigned long in_syscall */
1048 copy %r16, %r25 /* struct pt_regs *regs */
1050 ldo -16(%r30),%r29 /* Reference param save area */
1054 copy %r0, %r26 /* sigset_t *oldset = NULL */
1060 * External interrupts.
1069 #if 0 /* Interrupt Stack support not working yet! */
1072 /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/
1090 ldo PT_FR0(%r29), %r24
1095 copy %r29, %r26 /* arg0 is pt_regs */
1096 copy %r29, %r16 /* save pt_regs */
1098 ldil L%intr_return, %r2
1101 ldo -16(%r30),%r29 /* Reference param save area */
1105 ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */
1108 /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
1110 .export intr_save, code /* for os_hpmc */
1126 /* If this trap is a itlb miss, skip saving/adjusting isr/ior */
1129 * FIXME: 1) Use a #define for the hardwired "6" below (and in
1131 * 2) Once we start executing code above 4 Gb, we need
1132 * to adjust iasq/iaoq here in the same way we
1133 * adjust isr/ior below.
1136 CMPIB=,n 6,%r26,skip_save_ior
1138 /* save_specials left ipsw value in r8 for us to test */
1140 mfctl %cr20, %r16 /* isr */
1141 mfctl %cr21, %r17 /* ior */
1145 * If the interrupted code was running with W bit off (32 bit),
1146 * clear the b bits (bits 0 & 1) in the ior.
1148 extrd,u,*<> %r8,PSW_W_BIT,1,%r0
1152 * FIXME: This code has hardwired assumptions about the split
1153 * between space bits and offset bits. This will change
1154 * when we allow alternate page sizes.
1157 /* adjust isr/ior. */
1159 extrd,u %r16,63,7,%r1 /* get high bits from isr for ior */
1160 depd %r1,31,7,%r17 /* deposit them into ior */
1161 depdi 0,63,7,%r16 /* clear them from isr */
1163 STREG %r16, PT_ISR(%r29)
1164 STREG %r17, PT_IOR(%r29)
1171 ldo PT_FR0(%r29), %r25
1176 copy %r29, %r25 /* arg1 is pt_regs */
1178 ldo -16(%r30),%r29 /* Reference param save area */
1181 ldil L%intr_check_sig, %r2
1182 copy %r25, %r16 /* save pt_regs */
1184 b handle_interruption
1185 ldo R%intr_check_sig(%r2), %r2
1189 * Note for all tlb miss handlers:
1191 * cr24 contains a pointer to the kernel address space
1194 * cr25 contains a pointer to the current user address
1195 * space page directory.
1197 * sr3 will contain the space id of the user address space
1198 * of the current running thread while that thread is
1199 * running in the kernel.
1203 * register number allocations. Note that these are all
1204 * in the shadowed registers
1207 t0 = r1 /* temporary register 0 */
1208 va = r8 /* virtual address for which the trap occured */
1209 t1 = r9 /* temporary register 1 */
1210 pte = r16 /* pte/phys page # */
1211 prot = r17 /* prot bits */
1212 spc = r24 /* space for which the trap occured */
1213 ptp = r25 /* page directory/page table pointer */
1218 space_adjust spc,va,t0
1220 space_check spc,t0,dtlb_fault
1222 L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w
1224 update_ptep ptp,pte,t0,t1
1226 make_insert_tlb spc,pte,prot
1233 dtlb_check_alias_20w:
1234 do_alias spc,t0,t1,va,pte,prot,dtlb_fault
1242 space_adjust spc,va,t0
1244 space_check spc,t0,nadtlb_fault
1246 L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w
1248 update_ptep ptp,pte,t0,t1
1250 make_insert_tlb spc,pte,prot
1257 nadtlb_check_flush_20w:
1258 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1260 /* Insert a "flush only" translation */
1265 /* Get rid of prot bits and convert to page addr for idtlbt */
1268 extrd,u pte,56,52,pte
1279 space_check spc,t0,dtlb_fault
1281 L2_ptep ptp,pte,t0,va,dtlb_check_alias_11
1283 update_ptep ptp,pte,t0,t1
1285 make_insert_tlb_11 spc,pte,prot
1287 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
1290 idtlba pte,(%sr1,va)
1291 idtlbp prot,(%sr1,va)
1293 mtsp t0, %sr1 /* Restore sr1 */
1298 dtlb_check_alias_11:
1300 /* Check to see if fault is in the temporary alias region */
1302 cmpib,<>,n 0,spc,dtlb_fault /* forward */
1303 ldil L%(TMPALIAS_MAP_START),t0
1306 cmpb,<>,n t0,t1,dtlb_fault /* forward */
1307 ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
1308 depw,z prot,8,7,prot
1311 * OK, it is in the temp alias region, check whether "from" or "to".
1312 * Check "subtle" note in pacache.S re: r23/r26.
1316 or,tr %r23,%r0,pte /* If "from" use "from" page */
1317 or %r26,%r0,pte /* else "to", use "to" page */
1328 space_check spc,t0,nadtlb_fault
1330 L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11
1332 update_ptep ptp,pte,t0,t1
1334 make_insert_tlb_11 spc,pte,prot
1337 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
1340 idtlba pte,(%sr1,va)
1341 idtlbp prot,(%sr1,va)
1343 mtsp t0, %sr1 /* Restore sr1 */
1348 nadtlb_check_flush_11:
1349 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1351 /* Insert a "flush only" translation */
1356 /* Get rid of prot bits and convert to page addr for idtlba */
1361 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
1364 idtlba pte,(%sr1,va)
1365 idtlbp prot,(%sr1,va)
1367 mtsp t0, %sr1 /* Restore sr1 */
1373 space_adjust spc,va,t0
1375 space_check spc,t0,dtlb_fault
1377 L2_ptep ptp,pte,t0,va,dtlb_check_alias_20
1379 update_ptep ptp,pte,t0,t1
1381 make_insert_tlb spc,pte,prot
1390 dtlb_check_alias_20:
1391 do_alias spc,t0,t1,va,pte,prot,dtlb_fault
1401 space_check spc,t0,nadtlb_fault
1403 L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20
1405 update_ptep ptp,pte,t0,t1
1407 make_insert_tlb spc,pte,prot
1416 nadtlb_check_flush_20:
1417 bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1419 /* Insert a "flush only" translation */
1424 /* Get rid of prot bits and convert to page addr for idtlbt */
1427 extrd,u pte,56,32,pte
1437 * Non access misses can be caused by fdc,fic,pdc,lpa,probe and
1438 * probei instructions. We don't want to fault for these
1439 * instructions (not only does it not make sense, it can cause
1440 * deadlocks, since some flushes are done with the mmap
1441 * semaphore held). If the translation doesn't exist, we can't
1442 * insert a translation, so have to emulate the side effects
1443 * of the instruction. Since we don't insert a translation
1444 * we can get a lot of faults during a flush loop, so it makes
1445 * sense to try to do it here with minimum overhead. We only
1446 * emulate fdc,fic & pdc instructions whose base and index
1447 * registers are not shadowed. We defer everything else to the
1451 mfctl %cr19,%r9 /* Get iir */
1454 cmpb,<>,n %r16,%r17,nadtlb_fault /* Not fdc,fic,pdc */
1455 bb,>=,n %r9,26,nadtlb_nullify /* m bit not set, just nullify */
1456 BL get_register,%r25
1457 extrw,u %r9,15,5,%r8 /* Get index register # */
1458 CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */
1460 BL get_register,%r25
1461 extrw,u %r9,10,5,%r8 /* Get base register # */
1462 CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */
1463 BL set_register,%r25
1464 add,l %r1,%r24,%r1 /* doesn't affect c/b bits */
1467 mfctl %cr22,%r8 /* Get ipsw */
1469 or %r8,%r9,%r8 /* Set PSW_N */
1479 * I miss is a little different, since we allow users to fault
1480 * on the gateway page which is in the kernel address space.
1483 space_adjust spc,va,t0
1485 space_check spc,t0,itlb_fault
1487 L3_ptep ptp,pte,t0,va,itlb_fault
1489 update_ptep ptp,pte,t0,t1
1491 make_insert_tlb spc,pte,prot
1503 space_check spc,t0,itlb_fault
1505 L2_ptep ptp,pte,t0,va,itlb_fault
1507 update_ptep ptp,pte,t0,t1
1509 make_insert_tlb_11 spc,pte,prot
1511 mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
1514 iitlba pte,(%sr1,va)
1515 iitlbp prot,(%sr1,va)
1517 mtsp t0, %sr1 /* Restore sr1 */
1525 space_check spc,t0,itlb_fault
1527 L2_ptep ptp,pte,t0,va,itlb_fault
1529 update_ptep ptp,pte,t0,t1
1531 make_insert_tlb spc,pte,prot
1545 space_adjust spc,va,t0
1547 space_check spc,t0,dbit_fault
1549 L3_ptep ptp,pte,t0,va,dbit_fault
1552 CMPIB=,n 0,spc,dbit_nolock_20w
1553 ldil L%PA(pa_dbit_lock),t0
1554 ldo R%PA(pa_dbit_lock)(t0),t0
1558 cmpib,= 0,t1,dbit_spin_20w
1563 update_dirty ptp,pte,t1
1565 make_insert_tlb spc,pte,prot
1569 CMPIB=,n 0,spc,dbit_nounlock_20w
1584 space_check spc,t0,dbit_fault
1586 L2_ptep ptp,pte,t0,va,dbit_fault
1589 CMPIB=,n 0,spc,dbit_nolock_11
1590 ldil L%PA(pa_dbit_lock),t0
1591 ldo R%PA(pa_dbit_lock)(t0),t0
1595 cmpib,= 0,t1,dbit_spin_11
1600 update_dirty ptp,pte,t1
1602 make_insert_tlb_11 spc,pte,prot
1604 mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */
1607 idtlba pte,(%sr1,va)
1608 idtlbp prot,(%sr1,va)
1610 mtsp t1, %sr1 /* Restore sr1 */
1612 CMPIB=,n 0,spc,dbit_nounlock_11
1625 space_check spc,t0,dbit_fault
1627 L2_ptep ptp,pte,t0,va,dbit_fault
1630 CMPIB=,n 0,spc,dbit_nolock_20
1631 ldil L%PA(pa_dbit_lock),t0
1632 ldo R%PA(pa_dbit_lock)(t0),t0
1636 cmpib,= 0,t1,dbit_spin_20
1641 update_dirty ptp,pte,t1
1643 make_insert_tlb spc,pte,prot
1650 CMPIB=,n 0,spc,dbit_nounlock_20
1661 .import handle_interruption,code
1665 ldi 31,%r8 /* Use an unused code */
1683 /* Register saving semantics for system calls:
1685 %r1 clobbered by system call macro in userspace
1686 %r2 saved in PT_REGS by gateway page
1687 %r3 - %r18 preserved by C code (saved by signal code)
1688 %r19 - %r20 saved in PT_REGS by gateway page
1689 %r21 - %r22 non-standard syscall args
1690 stored in kernel stack by gateway page
1691 %r23 - %r26 arg3-arg0, saved in PT_REGS by gateway page
1692 %r27 - %r30 saved in PT_REGS by gateway page
1693 %r31 syscall return pointer
1696 /* Floating point registers (FIXME: what do we do with these?)
1698 %fr0 - %fr3 status/exception, not preserved
1699 %fr4 - %fr7 arguments
1700 %fr8 - %fr11 not preserved by C code
1701 %fr12 - %fr21 preserved by C code
1702 %fr22 - %fr31 not preserved by C code
1705 .macro reg_save regs
1706 STREG %r3, PT_GR3(\regs)
1707 STREG %r4, PT_GR4(\regs)
1708 STREG %r5, PT_GR5(\regs)
1709 STREG %r6, PT_GR6(\regs)
1710 STREG %r7, PT_GR7(\regs)
1711 STREG %r8, PT_GR8(\regs)
1712 STREG %r9, PT_GR9(\regs)
1713 STREG %r10,PT_GR10(\regs)
1714 STREG %r11,PT_GR11(\regs)
1715 STREG %r12,PT_GR12(\regs)
1716 STREG %r13,PT_GR13(\regs)
1717 STREG %r14,PT_GR14(\regs)
1718 STREG %r15,PT_GR15(\regs)
1719 STREG %r16,PT_GR16(\regs)
1720 STREG %r17,PT_GR17(\regs)
1721 STREG %r18,PT_GR18(\regs)
1724 .macro reg_restore regs
1725 LDREG PT_GR3(\regs), %r3
1726 LDREG PT_GR4(\regs), %r4
1727 LDREG PT_GR5(\regs), %r5
1728 LDREG PT_GR6(\regs), %r6
1729 LDREG PT_GR7(\regs), %r7
1730 LDREG PT_GR8(\regs), %r8
1731 LDREG PT_GR9(\regs), %r9
1732 LDREG PT_GR10(\regs),%r10
1733 LDREG PT_GR11(\regs),%r11
1734 LDREG PT_GR12(\regs),%r12
1735 LDREG PT_GR13(\regs),%r13
1736 LDREG PT_GR14(\regs),%r14
1737 LDREG PT_GR15(\regs),%r15
1738 LDREG PT_GR16(\regs),%r16
1739 LDREG PT_GR17(\regs),%r17
1740 LDREG PT_GR18(\regs),%r18
1743 .export sys_fork_wrapper
1744 .export child_return
1746 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1747 ldo TASK_REGS(%r1),%r1
1750 STREG %r3, PT_CR27(%r1)
1752 STREG %r2,-RP_OFFSET(%r30)
1753 ldo FRAME_SIZE(%r30),%r30
1755 ldo -16(%r30),%r29 /* Reference param save area */
1758 /* These are call-clobbered registers and therefore
1759 also syscall-clobbered (we hope). */
1760 STREG %r2,PT_GR19(%r1) /* save for child */
1761 STREG %r30,PT_GR21(%r1)
1763 LDREG PT_GR30(%r1),%r25
1768 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
1770 ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */
1771 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1772 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1774 LDREG PT_CR27(%r1), %r3
1778 /* strace expects syscall # to be preserved in r20 */
1781 STREG %r20,PT_GR20(%r1)
1783 /* Set the return value for the child */
1785 bl schedule_tail, %r2
1788 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
1789 LDREG TASK_PT_GR19(%r1),%r2
1794 .export sys_clone_wrapper
1796 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1797 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1800 STREG %r3, PT_CR27(%r1)
1802 STREG %r2,-RP_OFFSET(%r30)
1803 ldo FRAME_SIZE(%r30),%r30
1805 ldo -16(%r30),%r29 /* Reference param save area */
1808 STREG %r2,PT_GR19(%r1) /* save for child */
1809 STREG %r30,PT_GR21(%r1)
1814 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
1816 .export sys_vfork_wrapper
1818 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1819 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1822 STREG %r3, PT_CR27(%r1)
1824 STREG %r2,-RP_OFFSET(%r30)
1825 ldo FRAME_SIZE(%r30),%r30
1827 ldo -16(%r30),%r29 /* Reference param save area */
1830 STREG %r2,PT_GR19(%r1) /* save for child */
1831 STREG %r30,PT_GR21(%r1)
1837 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
1840 .macro execve_wrapper execve
1841 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1842 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1845 * Do we need to save/restore r3-r18 here?
1846 * I don't think so. why would new thread need old
1847 * threads registers?
1850 /* %arg0 - %arg3 are already saved for us. */
1852 STREG %r2,-RP_OFFSET(%r30)
1853 ldo FRAME_SIZE(%r30),%r30
1855 ldo -16(%r30),%r29 /* Reference param save area */
1860 ldo -FRAME_SIZE(%r30),%r30
1861 LDREG -RP_OFFSET(%r30),%r2
1863 /* If exec succeeded we need to load the args */
1866 cmpb,>>= %r28,%r1,error_\execve
1874 .export sys_execve_wrapper
1878 execve_wrapper sys_execve
1881 .export sys32_execve_wrapper
1882 .import sys32_execve
1884 sys32_execve_wrapper:
1885 execve_wrapper sys32_execve
1888 .export sys_rt_sigreturn_wrapper
1889 sys_rt_sigreturn_wrapper:
1890 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
1891 ldo TASK_REGS(%r26),%r26 /* get pt regs */
1892 /* Don't save regs, we are going to restore them from sigcontext. */
1893 STREG %r2, -RP_OFFSET(%r30)
1895 ldo FRAME_SIZE(%r30), %r30
1896 bl sys_rt_sigreturn,%r2
1897 ldo -16(%r30),%r29 /* Reference param save area */
1899 bl sys_rt_sigreturn,%r2
1900 ldo FRAME_SIZE(%r30), %r30
1903 ldo -FRAME_SIZE(%r30), %r30
1904 LDREG -RP_OFFSET(%r30), %r2
1906 /* FIXME: I think we need to restore a few more things here. */
1907 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1908 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1911 /* If the signal was received while the process was blocked on a
1912 * syscall, then r2 will take us to syscall_exit; otherwise r2 will
1913 * take us to syscall_exit_rfi and on to intr_return.
1916 LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */
1918 .export sys_sigaltstack_wrapper
1919 sys_sigaltstack_wrapper:
1920 /* Get the user stack pointer */
1921 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1922 ldo TASK_REGS(%r1),%r24 /* get pt regs */
1923 LDREG TASK_PT_GR30(%r24),%r24
1924 STREG %r2, -RP_OFFSET(%r30)
1926 ldo FRAME_SIZE(%r30), %r30
1927 bl do_sigaltstack,%r2
1928 ldo -16(%r30),%r29 /* Reference param save area */
1930 bl do_sigaltstack,%r2
1931 ldo FRAME_SIZE(%r30), %r30
1934 ldo -FRAME_SIZE(%r30), %r30
1935 LDREG -RP_OFFSET(%r30), %r2
1940 .export sys32_sigaltstack_wrapper
1941 sys32_sigaltstack_wrapper:
1942 /* Get the user stack pointer */
1943 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r24
1944 LDREG TASK_PT_GR30(%r24),%r24
1945 STREG %r2, -RP_OFFSET(%r30)
1946 ldo FRAME_SIZE(%r30), %r30
1947 bl do_sigaltstack32,%r2
1948 ldo -16(%r30),%r29 /* Reference param save area */
1950 ldo -FRAME_SIZE(%r30), %r30
1951 LDREG -RP_OFFSET(%r30), %r2
1956 .export sys_rt_sigsuspend_wrapper
1957 sys_rt_sigsuspend_wrapper:
1958 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1959 ldo TASK_REGS(%r1),%r24
1962 STREG %r2, -RP_OFFSET(%r30)
1964 ldo FRAME_SIZE(%r30), %r30
1965 bl sys_rt_sigsuspend,%r2
1966 ldo -16(%r30),%r29 /* Reference param save area */
1968 bl sys_rt_sigsuspend,%r2
1969 ldo FRAME_SIZE(%r30), %r30
1972 ldo -FRAME_SIZE(%r30), %r30
1973 LDREG -RP_OFFSET(%r30), %r2
1975 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1976 ldo TASK_REGS(%r1),%r1
1982 .export syscall_exit
1984 /* NOTE: HP-UX syscalls also come through here
1985 after hpux_syscall_exit fixes up return
1987 /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit
1988 * via syscall_exit_rfi if the signal was received while the process
1992 /* save return value now */
1995 LDREG TI_TASK(%r1),%r1
1996 STREG %r28,TASK_PT_GR28(%r1)
2000 /* <linux/personality.h> cannot be easily included */
2001 #define PER_HPUX 0x10
2002 LDREG TASK_PERSONALITY(%r1),%r19
2004 /* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */
2005 ldo -PER_HPUX(%r19), %r19
2008 /* Save other hpux returns if personality is PER_HPUX */
2009 STREG %r22,TASK_PT_GR22(%r1)
2010 STREG %r29,TASK_PT_GR29(%r1)
2013 #endif /* CONFIG_HPUX */
2015 /* Seems to me that dp could be wrong here, if the syscall involved
2016 * calling a module, and nothing got round to restoring dp on return.
2022 /* Check for software interrupts */
2024 .import irq_stat,data
2026 ldil L%irq_stat,%r19
2027 ldo R%irq_stat(%r19),%r19
2030 /* sched.h: int processor */
2031 /* %r26 is used as scratch register to index into irq_stat[] */
2032 ldw TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
2034 /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
2040 add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */
2041 #endif /* CONFIG_SMP */
2043 LDREG IRQSTAT_SIRQ_PEND(%r19),%r20 /* hardirq.h: unsigned long */
2044 cmpib,<>,n 0,%r20,syscall_do_softirq /* forward */
2046 syscall_check_resched:
2048 /* check for reschedule */
2050 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */
2051 bb,<,n %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
2054 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* get ti flags */
2055 bb,<,n %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
2058 /* Are we being ptraced? */
2059 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2061 LDREG TASK_PTRACE(%r1), %r19
2062 bb,< %r19,31,syscall_restore_rfi
2065 ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */
2068 LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */
2071 LDREG TASK_PT_GR2(%r1),%r2 /* restore user rp */
2072 LDREG TASK_PT_GR19(%r1),%r19
2073 LDREG TASK_PT_GR20(%r1),%r20
2074 LDREG TASK_PT_GR21(%r1),%r21
2075 LDREG TASK_PT_GR22(%r1),%r22
2076 LDREG TASK_PT_GR23(%r1),%r23
2077 LDREG TASK_PT_GR24(%r1),%r24
2078 LDREG TASK_PT_GR25(%r1),%r25
2079 LDREG TASK_PT_GR26(%r1),%r26
2080 LDREG TASK_PT_GR27(%r1),%r27 /* restore user dp */
2081 LDREG TASK_PT_GR28(%r1),%r28 /* syscall return value */
2082 LDREG TASK_PT_GR29(%r1),%r29
2083 LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */
2086 LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */
2087 mfsp %sr3,%r1 /* Get users space id */
2088 mtsp %r1,%sr7 /* Restore sr7 */
2090 mtsp %r1,%sr4 /* Restore sr4 */
2091 mtsp %r1,%sr5 /* Restore sr5 */
2092 mtsp %r1,%sr6 /* Restore sr6 */
2094 depi 3,31,2,%r31 /* ensure return to user mode. */
2097 /* decide whether to reset the wide mode bit
2099 * For a syscall, the W bit is stored in the lowest bit
2100 * of sp. Extract it and reset W if it is zero */
2101 extrd,u,*<> %r30,63,1,%r1
2103 /* now reset the lowest bit of sp if it was set */
2106 be,n 0(%sr3,%r31) /* return to user space */
2108 /* We have to return via an RFI, so that PSW T and R bits can be set
2110 * This sets up pt_regs so we can return via intr_restore, which is not
2111 * the most efficient way of doing things, but it works.
2113 syscall_restore_rfi:
2114 ldo -1(%r0),%r2 /* Set recovery cntr to -1 */
2115 mtctl %r2,%cr0 /* for immediate trap */
2116 LDREG TASK_PT_PSW(%r1),%r2 /* Get old PSW */
2117 ldi 0x0b,%r20 /* Create new PSW */
2118 depi -1,13,1,%r20 /* C, Q, D, and I bits */
2120 /* The values of PA_SINGLESTEP_BIT and PA_BLOCKSTEP_BIT are
2121 * set in include/linux/ptrace.h and converted to PA bitmap
2122 * numbers in asm-offsets.c */
2124 /* if ((%r19.PA_SINGLESTEP_BIT)) { %r20.27=1} */
2125 extru,= %r19,PA_SINGLESTEP_BIT,1,%r0
2126 depi -1,27,1,%r20 /* R bit */
2128 /* if ((%r19.PA_BLOCKSTEP_BIT)) { %r20.7=1} */
2129 extru,= %r19,PA_BLOCKSTEP_BIT,1,%r0
2130 depi -1,7,1,%r20 /* T bit */
2132 STREG %r20,TASK_PT_PSW(%r1)
2134 /* Always store space registers, since sr3 can be changed (e.g. fork) */
2137 STREG %r25,TASK_PT_SR3(%r1)
2138 STREG %r25,TASK_PT_SR4(%r1)
2139 STREG %r25,TASK_PT_SR5(%r1)
2140 STREG %r25,TASK_PT_SR6(%r1)
2141 STREG %r25,TASK_PT_SR7(%r1)
2142 STREG %r25,TASK_PT_IASQ0(%r1)
2143 STREG %r25,TASK_PT_IASQ1(%r1)
2146 /* Now if old D bit is clear, it means we didn't save all registers
2147 * on syscall entry, so do that now. This only happens on TRACEME
2148 * calls, or if someone attached to us while we were on a syscall.
2149 * We could make this more efficient by not saving r3-r18, but
2150 * then we wouldn't be able to use the common intr_restore path.
2151 * It is only for traced processes anyway, so performance is not
2154 bb,< %r2,30,pt_regs_ok /* Branch if D set */
2155 ldo TASK_REGS(%r1),%r25
2156 reg_save %r25 /* Save r3 to r18 */
2158 STREG %r2,TASK_PT_SR0(%r1)
2160 STREG %r2,TASK_PT_SR1(%r1)
2162 STREG %r2,TASK_PT_SR2(%r1)
2164 LDREG TASK_PT_GR31(%r1),%r2
2165 depi 3,31,2,%r2 /* ensure return to user mode. */
2166 STREG %r2,TASK_PT_IAOQ0(%r1)
2168 STREG %r2,TASK_PT_IAOQ1(%r1)
2173 .import do_softirq,code
2177 b syscall_check_resched
2178 ssm PSW_SM_I, %r0 /* do_softirq returns with I bit off */
2180 .import schedule,code
2184 ldo -16(%r30),%r29 /* Reference param save area */
2188 b syscall_check_bh /* if resched, we start over again */
2191 .import do_signal,code
2193 /* Save callee-save registers (for sigcontext).
2194 FIXME: After this point the process structure should be
2195 consistent with all the relevant state of the process
2196 before the syscall. We need to verify this. */
2197 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2198 ldo TASK_REGS(%r1), %r25 /* struct pt_regs *regs */
2201 ldi 1, %r24 /* unsigned long in_syscall */
2204 ldo -16(%r30),%r29 /* Reference param save area */
2207 copy %r0, %r26 /* sigset_t *oldset = NULL */
2209 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2210 ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
2216 * get_register is used by the non access tlb miss handlers to
2217 * copy the value of the general register specified in r8 into
2218 * r1. This routine can't be used for shadowed registers, since
2219 * the rfir will restore the original value. So, for the shadowed
2220 * registers we put a -1 into r1 to indicate that the register
2221 * should not be used (the register being copied could also have
2222 * a -1 in it, but that is OK, it just means that we will have
2223 * to use the slow path instead).
2229 bv %r0(%r25) /* r0 */
2231 bv %r0(%r25) /* r1 - shadowed */
2233 bv %r0(%r25) /* r2 */
2235 bv %r0(%r25) /* r3 */
2237 bv %r0(%r25) /* r4 */
2239 bv %r0(%r25) /* r5 */
2241 bv %r0(%r25) /* r6 */
2243 bv %r0(%r25) /* r7 */
2245 bv %r0(%r25) /* r8 - shadowed */
2247 bv %r0(%r25) /* r9 - shadowed */
2249 bv %r0(%r25) /* r10 */
2251 bv %r0(%r25) /* r11 */
2253 bv %r0(%r25) /* r12 */
2255 bv %r0(%r25) /* r13 */
2257 bv %r0(%r25) /* r14 */
2259 bv %r0(%r25) /* r15 */
2261 bv %r0(%r25) /* r16 - shadowed */
2263 bv %r0(%r25) /* r17 - shadowed */
2265 bv %r0(%r25) /* r18 */
2267 bv %r0(%r25) /* r19 */
2269 bv %r0(%r25) /* r20 */
2271 bv %r0(%r25) /* r21 */
2273 bv %r0(%r25) /* r22 */
2275 bv %r0(%r25) /* r23 */
2277 bv %r0(%r25) /* r24 - shadowed */
2279 bv %r0(%r25) /* r25 - shadowed */
2281 bv %r0(%r25) /* r26 */
2283 bv %r0(%r25) /* r27 */
2285 bv %r0(%r25) /* r28 */
2287 bv %r0(%r25) /* r29 */
2289 bv %r0(%r25) /* r30 */
2291 bv %r0(%r25) /* r31 */
2295 * set_register is used by the non access tlb miss handlers to
2296 * copy the value of r1 into the general register specified in
2303 bv %r0(%r25) /* r0 (silly, but it is a place holder) */
2305 bv %r0(%r25) /* r1 */
2307 bv %r0(%r25) /* r2 */
2309 bv %r0(%r25) /* r3 */
2311 bv %r0(%r25) /* r4 */
2313 bv %r0(%r25) /* r5 */
2315 bv %r0(%r25) /* r6 */
2317 bv %r0(%r25) /* r7 */
2319 bv %r0(%r25) /* r8 */
2321 bv %r0(%r25) /* r9 */
2323 bv %r0(%r25) /* r10 */
2325 bv %r0(%r25) /* r11 */
2327 bv %r0(%r25) /* r12 */
2329 bv %r0(%r25) /* r13 */
2331 bv %r0(%r25) /* r14 */
2333 bv %r0(%r25) /* r15 */
2335 bv %r0(%r25) /* r16 */
2337 bv %r0(%r25) /* r17 */
2339 bv %r0(%r25) /* r18 */
2341 bv %r0(%r25) /* r19 */
2343 bv %r0(%r25) /* r20 */
2345 bv %r0(%r25) /* r21 */
2347 bv %r0(%r25) /* r22 */
2349 bv %r0(%r25) /* r23 */
2351 bv %r0(%r25) /* r24 */
2353 bv %r0(%r25) /* r25 */
2355 bv %r0(%r25) /* r26 */
2357 bv %r0(%r25) /* r27 */
2359 bv %r0(%r25) /* r28 */
2361 bv %r0(%r25) /* r29 */
2363 bv %r0(%r25) /* r30 */
2365 bv %r0(%r25) /* r31 */