VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / parisc / kernel / entry.S
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 <linux/config.h>
26 #include <asm/offsets.h>
27
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 */
31
32
33 #include <asm/assembly.h>       /* for LDREG/STREG defines */
34 #include <asm/pgtable.h>
35 #include <asm/psw.h>
36 #include <asm/signal.h>
37 #include <asm/unistd.h>
38 #include <asm/thread_info.h>
39
40 #ifdef __LP64__
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         rsm     PSW_SM_Q,%r0
71         tovirt_r1 %r29
72         mfsp    %sr7, %r1
73         or,=    %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */
74         mtsp    %r1, %sr3
75         mtsp    %r0, %sr4
76         mtsp    %r0, %sr5
77         mtsp    %r0, %sr6
78         mtsp    %r0, %sr7
79         ldil    L%KERNEL_PSW, %r1
80         ldo     R%KERNEL_PSW(%r1), %r1
81         mtctl   %r1, %cr22
82         mtctl   %r0, %cr17      /* Clear IIASQ tail */
83         mtctl   %r0, %cr17      /* Clear IIASQ head */
84         ldil    L%4f, %r1
85         ldo     R%4f(%r1), %r1
86         mtctl   %r1, %cr18      /* Set IIAOQ tail */
87         ldo     4(%r1), %r1
88         mtctl   %r1, %cr18      /* Set IIAOQ head */
89         rfir
90         nop
91 4:
92         .endm
93
94         /*
95          * The "get_stack" macros are responsible for determining the
96          * kernel stack value.
97          *
98          * For Faults:
99          *      If sr7 == 0
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.
103          *      else
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.
109          *
110          * For Interrupts:
111          *      If sr7 == 0
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.
119          *      else
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.
129          *
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.
140          *
141          * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame.
142          */
143
144         .macro  get_stack_use_cr30
145
146         /* we save the registers in the task struct */
147
148         mfctl   %cr30, %r1
149         tophys  %r1,%r9
150         LDREG   TI_TASK(%r9), %r1       /* thread_info -> task_struct */
151         tophys  %r1,%r9
152         ldo     TASK_REGS(%r9),%r9
153         STREG   %r30, PT_GR30(%r9)
154         STREG   %r29,PT_GR29(%r9)
155         STREG   %r26,PT_GR26(%r9)
156         copy    %r9,%r29
157         mfctl   %cr30, %r1
158         ldo     THREAD_SZ_ALGN(%r1), %r30
159         .endm
160
161         .macro  get_stack_use_r30
162
163         /* we put a struct pt_regs on the stack and save the registers there */
164
165         tophys  %r30,%r9
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)
170         copy    %r9,%r29
171         .endm
172
173         .macro  rest_stack
174         LDREG   PT_GR1(%r29), %r1
175         LDREG   PT_GR30(%r29),%r30
176         LDREG   PT_GR29(%r29),%r29
177         .endm
178
179         /* default interruption handler
180          * (calls traps.c:handle_interruption) */
181         .macro  def code
182         b       intr_save
183         ldi     \code, %r8
184         .align  32
185         .endm
186
187         /* Interrupt interruption handler
188          * (calls irq.c:do_cpu_irq_mask) */
189         .macro  extint code
190         b       intr_extint
191         mfsp    %sr7,%r16
192         .align  32
193         .endm   
194
195         .import os_hpmc, code
196
197         /* HPMC handler */
198         .macro  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
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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 __LP64__
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         /* Only allow faults on different spaces from the
444          * currently active one if we're the kernel */
445         .macro          space_check     spc,tmp,fault
446         mfsp            %sr7,\tmp
447         or,COND(<>)     %r0,\spc,%r0    /* user may execute gateway page
448                                          * as kernel, so defeat the space
449                                          * check if it is */
450         copy            \spc,\tmp
451         or,COND(=)      %r0,\tmp,%r0    /* nullify if executing as kernel */
452         cmpb,COND(<>),n \tmp,\spc,\fault
453         .endm
454
455         /* Look up a PTE in a 2-Level scheme (faulting at each
456          * level if the entry isn't present 
457          *
458          * NOTE: we use ldw even for LP64, since the short pointers
459          * can address up to 1TB
460          */
461         .macro          L2_ptep pmd,pte,index,va,fault
462 #if PT_NLEVELS == 3
463         EXTR            \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index
464 #else
465         EXTR            \va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
466 #endif
467         DEP             %r0,31,PAGE_SHIFT,\pmd  /* clear offset */
468         copy            %r0,\pte
469         ldw,s           \index(\pmd),\pmd
470         bb,>=,n         \pmd,_PxD_PRESENT_BIT,\fault
471         DEP             %r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
472         copy            \pmd,%r9
473 #ifdef __LP64__
474         shld            %r9,PxD_VALUE_SHIFT,\pmd
475 #else
476         shlw            %r9,PxD_VALUE_SHIFT,\pmd
477 #endif
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
483         .endm
484
485         /* Look up PTE in a 3-Level scheme.
486          *
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
497         copy            %r0,\pte
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
505         copy            \index,\pgd
506         extrd,u,*<>     \va,31,32,%r0
507         ldo             ASM_PGD_PMD_OFFSET(\pgd),\pgd
508         L2_ptep         \pgd,\pte,\index,\va,\fault
509         .endm
510
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
515         or              \tmp1,\pte,\tmp
516         and,COND(<>)    \tmp1,\pte,%r0
517         STREG           \tmp,0(\ptep)
518         .endm
519
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
524         or              \tmp,\pte,\pte
525         STREG           \pte,0(\ptep)
526         .endm
527
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
534          * D <-> _PAGE_DIRTY
535          * B <-> _PAGE_DMB (memory break)
536          *
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
540          *
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 */
544         depd            \pte,8,7,\prot
545
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
550         depdi           7,11,3,\prot
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 */
556
557         /* Get rid of prot bits and convert to page addr for iitlbt */
558
559         depd            %r0,63,PAGE_SHIFT,\pte
560         extrd,u         \pte,56,32,\pte
561         .endm
562
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
568         dep             \pte,8,7,\prot
569         extru,=         \pte,_PAGE_NO_CACHE_BIT,1,%r0
570         depi            1,12,1,\prot
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 */
575
576         /* Get rid of prot bits and convert to page addr for iitlba */
577
578         depi            0,31,12,\pte
579         extru           \pte,24,25,\pte
580
581         .endm
582
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
586          * this case */
587         .macro          f_extend        pte,tmp
588         extrd,s         \pte,42,4,\tmp
589         addi,<>         1,\tmp,%r0
590         extrd,s         \pte,63,25,\pte
591         .endm
592
593         /* The alias region is an 8MB aligned 16MB to do clear and
594          * copy user pages at addresses congruent with the user
595          * virtual address.
596          *
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 */
607         depdi           0,31,32,\tmp
608 #endif
609         copy            \va,\tmp1
610         DEPI            0,31,23,\tmp1
611         cmpb,COND(<>),n \tmp,\tmp1,\fault
612         ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot
613         depd,z          \prot,8,7,\prot
614         /*
615          * OK, it is in the temp alias region, check whether "from" or "to".
616          * Check "subtle" note in pacache.S re: r23/r26.
617          */
618 #ifdef __LP64__
619         extrd,u,*=      \va,41,1,%r0
620 #else
621         extrw,u,=       \va,9,1,%r0
622 #endif
623         or,COND(tr)     %r23,%r0,\pte
624         or              %r26,%r0,\pte
625         .endm 
626
627
628         /*
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.
635          */
636
637         .export fault_vector_20
638
639         .text
640
641         .align 4096
642
643 fault_vector_20:
644         /* First vector is invalid (0) */
645         .ascii  "cows can fly"
646         .byte 0
647         .align 32
648
649         hpmc             1
650         def              2
651         def              3
652         extint           4
653         def              5
654         itlb_20          6
655         def              7
656         def              8
657         def              9
658         def             10
659         def             11
660         def             12
661         def             13
662         def             14
663         dtlb_20         15
664 #if 0
665         naitlb_20       16
666 #else
667         def             16
668 #endif
669         nadtlb_20       17
670         def             18
671         def             19
672         dbit_20         20
673         def             21
674         def             22
675         def             23
676         def             24
677         def             25
678         def             26
679         def             27
680         def             28
681         def             29
682         def             30
683         def             31
684
685 #ifndef __LP64__
686
687         .export fault_vector_11
688         
689         .align 2048
690
691 fault_vector_11:
692         /* First vector is invalid (0) */
693         .ascii  "cows can fly"
694         .byte 0
695         .align 32
696
697         hpmc             1
698         def              2
699         def              3
700         extint           4
701         def              5
702         itlb_11          6
703         def              7
704         def              8
705         def              9
706         def             10
707         def             11
708         def             12
709         def             13
710         def             14
711         dtlb_11         15
712 #if 0
713         naitlb_11       16
714 #else
715         def             16
716 #endif
717         nadtlb_11       17
718         def             18
719         def             19
720         dbit_11         20
721         def             21
722         def             22
723         def             23
724         def             24
725         def             25
726         def             26
727         def             27
728         def             28
729         def             29
730         def             30
731         def             31
732
733 #endif
734
735         .import         handle_interruption,code
736         .import         do_cpu_irq_mask,code
737
738         /*
739          * r26 = function to be called
740          * r25 = argument to pass in
741          * r24 = flags for do_fork()
742          *
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.
746          */
747
748 #define CLONE_VM 0x100  /* Must agree with <linux/sched.h> */
749 #define CLONE_UNTRACED 0x00800000
750
751         .export __kernel_thread, code
752         .import do_fork
753 __kernel_thread:
754         STREG   %r2, -RP_OFFSET(%r30)
755
756         copy    %r30, %r1
757         ldo     PT_SZ_ALGN(%r30),%r30
758 #ifdef __LP64__
759         /* Yo, function pointers in wide mode are little structs... -PB */
760         ldd     24(%r26), %r2
761         STREG   %r2, PT_GR27(%r1)       /* Store childs %dp */
762         ldd     16(%r26), %r26
763
764         STREG   %r22, PT_GR22(%r1)      /* save r22 (arg5) */
765         copy    %r0, %r22               /* user_tid */
766 #endif
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 */
774 #ifdef __LP64__
775         ldo     -16(%r30),%r29          /* Reference param save area */
776 #endif
777         bl      do_fork, %r2
778         copy    %r1, %r24               /* pt_regs */
779
780         /* Parent Returns here */
781
782         LDREG   -PT_SZ_ALGN-RP_OFFSET(%r30), %r2
783         ldo     -PT_SZ_ALGN(%r30), %r30
784         bv      %r0(%r2)
785         nop
786
787         /*
788          * Child Returns here
789          *
790          * copy_thread moved args from temp save area set up above
791          * into task save area.
792          */
793
794         .export ret_from_kernel_thread
795 ret_from_kernel_thread:
796
797         /* Call schedule_tail first though */
798         BL      schedule_tail, %r2
799         nop
800
801         LDREG   TI_TASK-THREAD_SZ_ALGN(%r30), %r1
802         LDREG   TASK_PT_GR25(%r1), %r26
803 #ifdef __LP64__
804         LDREG   TASK_PT_GR27(%r1), %r27
805         LDREG   TASK_PT_GR22(%r1), %r22
806 #endif
807         LDREG   TASK_PT_GR26(%r1), %r1
808         ble     0(%sr7, %r1)
809         copy    %r31, %r2
810
811 #ifdef __LP64__
812         ldo     -16(%r30),%r29          /* Reference param save area */
813         loadgp                          /* Thread could have been in a module */
814 #endif
815         b       sys_exit
816         ldi     0, %r26
817
818         .import sys_execve, code
819         .export __execve, code
820 __execve:
821         copy    %r2, %r15
822         copy    %r30, %r16
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)
827 #ifdef __LP64__
828         ldo     -16(%r30),%r29          /* Reference param save area */
829 #endif
830         bl      sys_execve, %r2
831         copy    %r16, %r26
832
833         cmpib,=,n 0,%r28,intr_return    /* forward */
834
835         /* yes, this will trap and die. */
836         copy    %r15, %r2
837         copy    %r16, %r30
838         bv      %r0(%r2)
839         nop
840
841         .align 4
842
843         /*
844          * struct task_struct *_switch_to(struct task_struct *prev,
845          *      struct task_struct *next)
846          *
847          * switch kernel stacks and return prev */
848         .export _switch_to, code
849 _switch_to:
850         STREG    %r2, -RP_OFFSET(%r30)
851
852         callee_save
853
854         ldil    L%_switch_to_ret, %r2
855         ldo     R%_switch_to_ret(%r2), %r2
856
857         STREG   %r2, TASK_PT_KPC(%r26)
858         LDREG   TASK_PT_KPC(%r25), %r2
859
860         STREG   %r30, TASK_PT_KSP(%r26)
861         LDREG   TASK_PT_KSP(%r25), %r30
862         LDREG   TASK_THREAD_INFO(%r25), %r25
863         bv      %r0(%r2)
864         mtctl   %r25,%cr30
865
866 _switch_to_ret:
867         mtctl   %r0, %cr0               /* Needed for single stepping */
868         callee_rest
869
870         LDREG   -RP_OFFSET(%r30), %r2
871         bv      %r0(%r2)
872         copy    %r26, %r28
873
874         /*
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.
881          *
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
884          * adjust IASQ[0..1].
885          *
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
888          * PCXT bug.
889          */
890
891         .align 4096
892
893         .export syscall_exit_rfi
894 syscall_exit_rfi:
895         mfctl   %cr30,%r16
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.
900          */
901         LDREG   PT_IAOQ0(%r16),%r19
902         depi    3,31,2,%r19
903         STREG   %r19,PT_IAOQ0(%r16)
904         LDREG   PT_IAOQ1(%r16),%r19
905         depi    3,31,2,%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
910 #ifdef __LP64__
911         ldil    L%USER_PSW_HI_MASK,%r20
912         ldo     R%USER_PSW_HI_MASK(%r20),%r20
913         depd    %r20,31,32,%r1
914 #endif
915         and     %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */
916         ldil    L%USER_PSW,%r1
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)
920
921         /*
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.
929          */
930
931         STREG   %r0,PT_SR2(%r16)
932         mfsp    %sr3,%r19
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)
940
941 intr_return:
942         ssm     PSW_SM_I, %r0
943
944         /* Check for software interrupts */
945
946         .import irq_stat,data
947
948         ldil    L%irq_stat,%r19
949         ldo     R%irq_stat(%r19),%r19
950 #ifdef CONFIG_SMP
951         mfctl   %cr30,%r1
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.
955         */
956 #ifdef __LP64__
957         shld    %r1, 6, %r20
958 #else
959         shlw    %r1, 5, %r20
960 #endif
961         add     %r19,%r20,%r19  /* now have &irq_stat[smp_processor_id()] */
962 #endif /* CONFIG_SMP */
963
964         LDREG   IRQSTAT_SIRQ_PEND(%r19),%r20    /* hardirq.h: unsigned long */
965         cmpib,<>,n 0,%r20,intr_do_softirq /* forward */
966
967 intr_check_resched:
968
969         /* check for reschedule */
970         mfctl   %cr30,%r1
971         LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_NEED_RESCHED */
972         bb,<,n  %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
973
974 intr_check_sig:
975         /* As above */
976         mfctl   %cr30,%r1
977         LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_SIGPENDING */
978         bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
979
980 intr_restore:
981         copy            %r16,%r29
982         ldo             PT_FR31(%r29),%r1
983         rest_fp         %r1
984         rest_general    %r29
985         ssm             0,%r0
986         nop
987         nop
988         nop
989         nop
990         nop
991         nop
992         nop
993         tophys_r1       %r29
994         rsm             (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0
995         rest_specials   %r29
996         rest_stack
997         rfi
998         nop
999         nop
1000         nop
1001         nop
1002         nop
1003         nop
1004         nop
1005         nop
1006
1007         .import do_softirq,code
1008 intr_do_softirq:
1009         bl      do_softirq,%r2
1010 #ifdef __LP64__
1011         ldo     -16(%r30),%r29          /* Reference param save area */
1012 #else
1013         nop
1014 #endif
1015         b       intr_check_resched
1016         nop
1017
1018         .import schedule,code
1019 intr_do_resched:
1020         /* Only do reschedule if we are returning to user space */
1021         LDREG   PT_IASQ0(%r16), %r20
1022         CMPIB= 0,%r20,intr_restore /* backward */
1023         nop
1024         LDREG   PT_IASQ1(%r16), %r20
1025         CMPIB= 0,%r20,intr_restore /* backward */
1026         nop
1027
1028 #ifdef __LP64__
1029         ldo     -16(%r30),%r29          /* Reference param save area */
1030 #endif
1031
1032         ldil    L%intr_check_sig, %r2
1033         b       schedule
1034         ldo     R%intr_check_sig(%r2), %r2
1035
1036
1037         .import do_signal,code
1038 intr_do_signal:
1039         /* Only do signals if we are returning to user space */
1040         LDREG   PT_IASQ0(%r16), %r20
1041         CMPIB= 0,%r20,intr_restore /* backward */
1042         nop
1043         LDREG   PT_IASQ1(%r16), %r20
1044         CMPIB= 0,%r20,intr_restore /* backward */
1045         nop
1046
1047         copy    %r0, %r24                       /* unsigned long in_syscall */
1048         copy    %r16, %r25                      /* struct pt_regs *regs */
1049 #ifdef __LP64__
1050         ldo     -16(%r30),%r29                  /* Reference param save area */
1051 #endif
1052
1053         bl      do_signal,%r2
1054         copy    %r0, %r26                       /* sigset_t *oldset = NULL */
1055
1056         b       intr_restore
1057         nop
1058
1059         /*
1060          * External interrupts.
1061          */
1062
1063 intr_extint:
1064         CMPIB=,n 0,%r16,1f
1065         get_stack_use_cr30
1066         b,n 3f
1067
1068 1:
1069 #if 0  /* Interrupt Stack support not working yet! */
1070         mfctl   %cr31,%r1
1071         copy    %r30,%r17
1072         /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/
1073 #ifdef __LP64__
1074         depdi   0,63,15,%r17
1075 #else
1076         depi    0,31,15,%r17
1077 #endif
1078         CMPB=,n %r1,%r17,2f
1079         get_stack_use_cr31
1080         b,n 3f
1081 #endif
1082 2:
1083         get_stack_use_r30
1084
1085 3:
1086         save_specials   %r29
1087         virt_map
1088         save_general    %r29
1089
1090         ldo     PT_FR0(%r29), %r24
1091         save_fp %r24
1092         
1093         loadgp
1094
1095         copy    %r29, %r26      /* arg0 is pt_regs */
1096         copy    %r29, %r16      /* save pt_regs */
1097
1098         ldil    L%intr_return, %r2
1099
1100 #ifdef __LP64__
1101         ldo     -16(%r30),%r29  /* Reference param save area */
1102 #endif
1103
1104         b       do_cpu_irq_mask
1105         ldo     R%intr_return(%r2), %r2 /* return to intr_return, not here */
1106
1107
1108         /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
1109
1110         .export         intr_save, code /* for os_hpmc */
1111
1112 intr_save:
1113         mfsp    %sr7,%r16
1114         CMPIB=,n 0,%r16,1f
1115         get_stack_use_cr30
1116         b       2f
1117         copy    %r8,%r26
1118
1119 1:
1120         get_stack_use_r30
1121         copy    %r8,%r26
1122
1123 2:
1124         save_specials   %r29
1125
1126         /* If this trap is a itlb miss, skip saving/adjusting isr/ior */
1127
1128         /*
1129          * FIXME: 1) Use a #define for the hardwired "6" below (and in
1130          *           traps.c.
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.
1134          */
1135
1136         CMPIB=,n        6,%r26,skip_save_ior
1137
1138         /* save_specials left ipsw value in r8 for us to test */
1139
1140         mfctl           %cr20, %r16 /* isr */
1141         mfctl           %cr21, %r17 /* ior */
1142
1143 #ifdef __LP64__
1144         /*
1145          * If the interrupted code was running with W bit off (32 bit),
1146          * clear the b bits (bits 0 & 1) in the ior.
1147          */
1148         extrd,u,*<>     %r8,PSW_W_BIT,1,%r0
1149         depdi           0,1,2,%r17
1150
1151         /*
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.
1155          */
1156
1157         /* adjust isr/ior. */
1158
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 */
1162 #endif
1163         STREG           %r16, PT_ISR(%r29)
1164         STREG           %r17, PT_IOR(%r29)
1165
1166
1167 skip_save_ior:
1168         virt_map
1169         save_general    %r29
1170
1171         ldo             PT_FR0(%r29), %r25
1172         save_fp         %r25
1173         
1174         loadgp
1175
1176         copy            %r29, %r25      /* arg1 is pt_regs */
1177 #ifdef __LP64__
1178         ldo             -16(%r30),%r29  /* Reference param save area */
1179 #endif
1180
1181         ldil            L%intr_check_sig, %r2
1182         copy            %r25, %r16      /* save pt_regs */
1183
1184         b               handle_interruption
1185         ldo             R%intr_check_sig(%r2), %r2
1186
1187
1188         /*
1189          * Note for all tlb miss handlers:
1190          *
1191          * cr24 contains a pointer to the kernel address space
1192          * page directory.
1193          *
1194          * cr25 contains a pointer to the current user address
1195          * space page directory.
1196          *
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.
1200          */
1201
1202         /*
1203          * register number allocations.  Note that these are all
1204          * in the shadowed registers
1205          */
1206
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 */
1214
1215 #ifdef __LP64__
1216
1217 dtlb_miss_20w:
1218         space_adjust    spc,va,t0
1219         get_pgd         spc,ptp
1220         space_check     spc,t0,dtlb_fault
1221
1222         L3_ptep         ptp,pte,t0,va,dtlb_check_alias_20w
1223
1224         update_ptep     ptp,pte,t0,t1
1225
1226         make_insert_tlb spc,pte,prot
1227         
1228         idtlbt          pte,prot
1229
1230         rfir
1231         nop
1232
1233 dtlb_check_alias_20w:
1234         do_alias        spc,t0,t1,va,pte,prot,dtlb_fault
1235
1236         idtlbt          pte,prot
1237
1238         rfir
1239         nop
1240
1241 nadtlb_miss_20w:
1242         space_adjust    spc,va,t0
1243         get_pgd         spc,ptp
1244         space_check     spc,t0,nadtlb_fault
1245
1246         L3_ptep         ptp,pte,t0,va,nadtlb_check_flush_20w
1247
1248         update_ptep     ptp,pte,t0,t1
1249
1250         make_insert_tlb spc,pte,prot
1251
1252         idtlbt          pte,prot
1253
1254         rfir
1255         nop
1256
1257 nadtlb_check_flush_20w:
1258         bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1259
1260         /* Insert a "flush only" translation */
1261
1262         depdi,z         7,7,3,prot
1263         depdi           1,10,1,prot
1264
1265         /* Get rid of prot bits and convert to page addr for idtlbt */
1266
1267         depdi           0,63,12,pte
1268         extrd,u         pte,56,52,pte
1269         idtlbt          pte,prot
1270
1271         rfir
1272         nop
1273
1274 #else
1275
1276 dtlb_miss_11:
1277         get_pgd         spc,ptp
1278
1279         space_check     spc,t0,dtlb_fault
1280
1281         L2_ptep         ptp,pte,t0,va,dtlb_check_alias_11
1282
1283         update_ptep     ptp,pte,t0,t1
1284
1285         make_insert_tlb_11      spc,pte,prot
1286
1287         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1288         mtsp            spc,%sr1
1289
1290         idtlba          pte,(%sr1,va)
1291         idtlbp          prot,(%sr1,va)
1292
1293         mtsp            t0, %sr1        /* Restore sr1 */
1294
1295         rfir
1296         nop
1297
1298 dtlb_check_alias_11:
1299
1300         /* Check to see if fault is in the temporary alias region */
1301
1302         cmpib,<>,n      0,spc,dtlb_fault /* forward */
1303         ldil            L%(TMPALIAS_MAP_START),t0
1304         copy            va,t1
1305         depwi           0,31,23,t1
1306         cmpb,<>,n       t0,t1,dtlb_fault /* forward */
1307         ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
1308         depw,z          prot,8,7,prot
1309
1310         /*
1311          * OK, it is in the temp alias region, check whether "from" or "to".
1312          * Check "subtle" note in pacache.S re: r23/r26.
1313          */
1314
1315         extrw,u,=       va,9,1,r0
1316         or,tr           %r23,%r0,pte    /* If "from" use "from" page */
1317         or              %r26,%r0,pte    /* else "to", use "to" page  */
1318
1319         idtlba          pte,(va)
1320         idtlbp          prot,(va)
1321
1322         rfir
1323         nop
1324
1325 nadtlb_miss_11:
1326         get_pgd         spc,ptp
1327
1328         space_check     spc,t0,nadtlb_fault
1329
1330         L2_ptep         ptp,pte,t0,va,nadtlb_check_flush_11
1331
1332         update_ptep     ptp,pte,t0,t1
1333
1334         make_insert_tlb_11      spc,pte,prot
1335
1336
1337         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1338         mtsp            spc,%sr1
1339
1340         idtlba          pte,(%sr1,va)
1341         idtlbp          prot,(%sr1,va)
1342
1343         mtsp            t0, %sr1        /* Restore sr1 */
1344
1345         rfir
1346         nop
1347
1348 nadtlb_check_flush_11:
1349         bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1350
1351         /* Insert a "flush only" translation */
1352
1353         zdepi           7,7,3,prot
1354         depi            1,10,1,prot
1355
1356         /* Get rid of prot bits and convert to page addr for idtlba */
1357
1358         depi            0,31,12,pte
1359         extru           pte,24,25,pte
1360
1361         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1362         mtsp            spc,%sr1
1363
1364         idtlba          pte,(%sr1,va)
1365         idtlbp          prot,(%sr1,va)
1366
1367         mtsp            t0, %sr1        /* Restore sr1 */
1368
1369         rfir
1370         nop
1371
1372 dtlb_miss_20:
1373         space_adjust    spc,va,t0
1374         get_pgd         spc,ptp
1375         space_check     spc,t0,dtlb_fault
1376
1377         L2_ptep         ptp,pte,t0,va,dtlb_check_alias_20
1378
1379         update_ptep     ptp,pte,t0,t1
1380
1381         make_insert_tlb spc,pte,prot
1382
1383         f_extend        pte,t0
1384
1385         idtlbt          pte,prot
1386
1387         rfir
1388         nop
1389
1390 dtlb_check_alias_20:
1391         do_alias        spc,t0,t1,va,pte,prot,dtlb_fault
1392         
1393         idtlbt          pte,prot
1394
1395         rfir
1396         nop
1397
1398 nadtlb_miss_20:
1399         get_pgd         spc,ptp
1400
1401         space_check     spc,t0,nadtlb_fault
1402
1403         L2_ptep         ptp,pte,t0,va,nadtlb_check_flush_20
1404
1405         update_ptep     ptp,pte,t0,t1
1406
1407         make_insert_tlb spc,pte,prot
1408
1409         f_extend        pte,t0
1410         
1411         idtlbt          pte,prot
1412
1413         rfir
1414         nop
1415
1416 nadtlb_check_flush_20:
1417         bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1418
1419         /* Insert a "flush only" translation */
1420
1421         depdi,z         7,7,3,prot
1422         depdi           1,10,1,prot
1423
1424         /* Get rid of prot bits and convert to page addr for idtlbt */
1425
1426         depdi           0,63,12,pte
1427         extrd,u         pte,56,32,pte
1428         idtlbt          pte,prot
1429
1430         rfir
1431         nop
1432 #endif
1433
1434 nadtlb_emulate:
1435
1436         /*
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
1448          * "slow" path.
1449          */
1450
1451         mfctl           %cr19,%r9 /* Get iir */
1452         ldi             0x280,%r16
1453         and             %r9,%r16,%r17
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 */
1459         copy            %r1,%r24
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 */
1465
1466 nadtlb_nullify:
1467         mfctl           %cr22,%r8              /* Get ipsw */
1468         ldil            L%PSW_N,%r9
1469         or              %r8,%r9,%r8            /* Set PSW_N */
1470         mtctl           %r8,%cr22
1471
1472         rfir
1473         nop
1474
1475 #ifdef __LP64__
1476 itlb_miss_20w:
1477
1478         /*
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.
1481          */
1482
1483         space_adjust    spc,va,t0
1484         get_pgd         spc,ptp
1485         space_check     spc,t0,itlb_fault
1486
1487         L3_ptep         ptp,pte,t0,va,itlb_fault
1488
1489         update_ptep     ptp,pte,t0,t1
1490
1491         make_insert_tlb spc,pte,prot
1492         
1493         iitlbt          pte,prot
1494
1495         rfir
1496         nop
1497
1498 #else
1499
1500 itlb_miss_11:
1501         get_pgd         spc,ptp
1502
1503         space_check     spc,t0,itlb_fault
1504
1505         L2_ptep         ptp,pte,t0,va,itlb_fault
1506
1507         update_ptep     ptp,pte,t0,t1
1508
1509         make_insert_tlb_11      spc,pte,prot
1510
1511         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1512         mtsp            spc,%sr1
1513
1514         iitlba          pte,(%sr1,va)
1515         iitlbp          prot,(%sr1,va)
1516
1517         mtsp            t0, %sr1        /* Restore sr1 */
1518
1519         rfir
1520         nop
1521
1522 itlb_miss_20:
1523         get_pgd         spc,ptp
1524
1525         space_check     spc,t0,itlb_fault
1526
1527         L2_ptep         ptp,pte,t0,va,itlb_fault
1528
1529         update_ptep     ptp,pte,t0,t1
1530
1531         make_insert_tlb spc,pte,prot
1532
1533         f_extend        pte,t0  
1534
1535         iitlbt          pte,prot
1536
1537         rfir
1538         nop
1539
1540 #endif
1541
1542 #ifdef __LP64__
1543
1544 dbit_trap_20w:
1545         space_adjust    spc,va,t0
1546         get_pgd         spc,ptp
1547         space_check     spc,t0,dbit_fault
1548
1549         L3_ptep         ptp,pte,t0,va,dbit_fault
1550
1551 #ifdef CONFIG_SMP
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
1555
1556 dbit_spin_20w:
1557         ldcw            0(t0),t1
1558         cmpib,=         0,t1,dbit_spin_20w
1559         nop
1560
1561 dbit_nolock_20w:
1562 #endif
1563         update_dirty    ptp,pte,t1
1564
1565         make_insert_tlb spc,pte,prot
1566                 
1567         idtlbt          pte,prot
1568 #ifdef CONFIG_SMP
1569         CMPIB=,n        0,spc,dbit_nounlock_20w
1570         ldi             1,t1
1571         stw             t1,0(t0)
1572
1573 dbit_nounlock_20w:
1574 #endif
1575
1576         rfir
1577         nop
1578 #else
1579
1580 dbit_trap_11:
1581
1582         get_pgd         spc,ptp
1583
1584         space_check     spc,t0,dbit_fault
1585
1586         L2_ptep         ptp,pte,t0,va,dbit_fault
1587
1588 #ifdef CONFIG_SMP
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
1592
1593 dbit_spin_11:
1594         ldcw            0(t0),t1
1595         cmpib,=         0,t1,dbit_spin_11
1596         nop
1597
1598 dbit_nolock_11:
1599 #endif
1600         update_dirty    ptp,pte,t1
1601
1602         make_insert_tlb_11      spc,pte,prot
1603
1604         mfsp            %sr1,t1  /* Save sr1 so we can use it in tlb inserts */
1605         mtsp            spc,%sr1
1606
1607         idtlba          pte,(%sr1,va)
1608         idtlbp          prot,(%sr1,va)
1609
1610         mtsp            t1, %sr1     /* Restore sr1 */
1611 #ifdef CONFIG_SMP
1612         CMPIB=,n        0,spc,dbit_nounlock_11
1613         ldi             1,t1
1614         stw             t1,0(t0)
1615
1616 dbit_nounlock_11:
1617 #endif
1618
1619         rfir
1620         nop
1621
1622 dbit_trap_20:
1623         get_pgd         spc,ptp
1624
1625         space_check     spc,t0,dbit_fault
1626
1627         L2_ptep         ptp,pte,t0,va,dbit_fault
1628
1629 #ifdef CONFIG_SMP
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
1633
1634 dbit_spin_20:
1635         ldcw            0(t0),t1
1636         cmpib,=         0,t1,dbit_spin_20
1637         nop
1638
1639 dbit_nolock_20:
1640 #endif
1641         update_dirty    ptp,pte,t1
1642
1643         make_insert_tlb spc,pte,prot
1644
1645         f_extend        pte,t1
1646         
1647         idtlbt          pte,prot
1648
1649 #ifdef CONFIG_SMP
1650         CMPIB=,n        0,spc,dbit_nounlock_20
1651         ldi             1,t1
1652         stw             t1,0(t0)
1653
1654 dbit_nounlock_20:
1655 #endif
1656
1657         rfir
1658         nop
1659 #endif
1660
1661         .import handle_interruption,code
1662
1663 kernel_bad_space:
1664         b               intr_save
1665         ldi             31,%r8  /* Use an unused code */
1666
1667 dbit_fault:
1668         b               intr_save
1669         ldi             20,%r8
1670
1671 itlb_fault:
1672         b               intr_save
1673         ldi             6,%r8
1674
1675 nadtlb_fault:
1676         b               intr_save
1677         ldi             17,%r8
1678
1679 dtlb_fault:
1680         b               intr_save
1681         ldi             15,%r8
1682
1683         /* Register saving semantics for system calls:
1684
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
1694          */
1695
1696         /* Floating point registers (FIXME: what do we do with these?)
1697
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
1703          */
1704
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)
1722         .endm
1723
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
1741         .endm
1742
1743         .export sys_fork_wrapper
1744         .export child_return
1745 sys_fork_wrapper:
1746         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1747         ldo     TASK_REGS(%r1),%r1
1748         reg_save %r1
1749         mfctl   %cr27, %r3
1750         STREG   %r3, PT_CR27(%r1)
1751
1752         STREG   %r2,-RP_OFFSET(%r30)
1753         ldo     FRAME_SIZE(%r30),%r30
1754 #ifdef __LP64__
1755         ldo     -16(%r30),%r29          /* Reference param save area */
1756 #endif
1757
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)
1762
1763         LDREG   PT_GR30(%r1),%r25
1764         copy    %r1,%r24
1765         bl      sys_clone,%r2
1766         ldi     SIGCHLD,%r26
1767
1768         LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
1769 wrapper_exit:
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 */
1773
1774         LDREG   PT_CR27(%r1), %r3
1775         mtctl   %r3, %cr27
1776         reg_restore %r1
1777
1778         /* strace expects syscall # to be preserved in r20 */
1779         ldi     __NR_fork,%r20
1780         bv %r0(%r2)
1781         STREG   %r20,PT_GR20(%r1)
1782
1783         /* Set the return value for the child */
1784 child_return:
1785         bl      schedule_tail, %r2
1786         nop
1787
1788         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
1789         LDREG   TASK_PT_GR19(%r1),%r2
1790         b       wrapper_exit
1791         copy    %r0,%r28
1792
1793         
1794         .export sys_clone_wrapper
1795 sys_clone_wrapper:
1796         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1797         ldo     TASK_REGS(%r1),%r1      /* get pt regs */
1798         reg_save %r1
1799         mfctl   %cr27, %r3
1800         STREG   %r3, PT_CR27(%r1)
1801
1802         STREG   %r2,-RP_OFFSET(%r30)
1803         ldo     FRAME_SIZE(%r30),%r30
1804 #ifdef __LP64__
1805         ldo     -16(%r30),%r29          /* Reference param save area */
1806 #endif
1807
1808         STREG   %r2,PT_GR19(%r1)        /* save for child */
1809         STREG   %r30,PT_GR21(%r1)
1810         bl      sys_clone,%r2
1811         copy    %r1,%r24
1812
1813         b       wrapper_exit
1814         LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
1815
1816         .export sys_vfork_wrapper
1817 sys_vfork_wrapper:
1818         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1819         ldo     TASK_REGS(%r1),%r1      /* get pt regs */
1820         reg_save %r1
1821         mfctl   %cr27, %r3
1822         STREG   %r3, PT_CR27(%r1)
1823
1824         STREG   %r2,-RP_OFFSET(%r30)
1825         ldo     FRAME_SIZE(%r30),%r30
1826 #ifdef __LP64__
1827         ldo     -16(%r30),%r29          /* Reference param save area */
1828 #endif
1829
1830         STREG   %r2,PT_GR19(%r1)        /* save for child */
1831         STREG   %r30,PT_GR21(%r1)
1832
1833         bl      sys_vfork,%r2
1834         copy    %r1,%r26
1835
1836         b       wrapper_exit
1837         LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
1838
1839         
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 */
1843
1844         /*
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?
1848          */
1849
1850         /* %arg0 - %arg3 are already saved for us. */
1851
1852         STREG %r2,-RP_OFFSET(%r30)
1853         ldo FRAME_SIZE(%r30),%r30
1854 #ifdef __LP64__
1855         ldo     -16(%r30),%r29          /* Reference param save area */
1856 #endif
1857         bl \execve,%r2
1858         copy %r1,%arg0
1859
1860         ldo -FRAME_SIZE(%r30),%r30
1861         LDREG -RP_OFFSET(%r30),%r2
1862
1863         /* If exec succeeded we need to load the args */
1864
1865         ldo -1024(%r0),%r1
1866         cmpb,>>= %r28,%r1,error_\execve
1867         copy %r2,%r19
1868
1869 error_\execve:
1870         bv %r0(%r19)
1871         nop
1872         .endm
1873
1874         .export sys_execve_wrapper
1875         .import sys_execve
1876
1877 sys_execve_wrapper:
1878         execve_wrapper sys_execve
1879
1880 #ifdef __LP64__
1881         .export sys32_execve_wrapper
1882         .import sys32_execve
1883
1884 sys32_execve_wrapper:
1885         execve_wrapper sys32_execve
1886 #endif
1887
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)
1894 #ifdef __LP64__
1895         ldo     FRAME_SIZE(%r30), %r30
1896         bl      sys_rt_sigreturn,%r2
1897         ldo     -16(%r30),%r29          /* Reference param save area */
1898 #else
1899         bl      sys_rt_sigreturn,%r2
1900         ldo     FRAME_SIZE(%r30), %r30
1901 #endif
1902
1903         ldo     -FRAME_SIZE(%r30), %r30
1904         LDREG   -RP_OFFSET(%r30), %r2
1905
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 */
1909         reg_restore %r1
1910
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.
1914          */
1915         bv      %r0(%r2)
1916         LDREG   PT_GR28(%r1),%r28  /* reload original r28 for syscall_exit */
1917
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)
1925 #ifdef __LP64__
1926         ldo     FRAME_SIZE(%r30), %r30
1927         bl      do_sigaltstack,%r2
1928         ldo     -16(%r30),%r29          /* Reference param save area */
1929 #else
1930         bl      do_sigaltstack,%r2
1931         ldo     FRAME_SIZE(%r30), %r30
1932 #endif
1933
1934         ldo     -FRAME_SIZE(%r30), %r30
1935         LDREG   -RP_OFFSET(%r30), %r2
1936         bv      %r0(%r2)
1937         nop
1938
1939 #ifdef __LP64__
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 */
1949
1950         ldo     -FRAME_SIZE(%r30), %r30
1951         LDREG   -RP_OFFSET(%r30), %r2
1952         bv      %r0(%r2)
1953         nop
1954 #endif
1955
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
1960         reg_save %r24
1961
1962         STREG   %r2, -RP_OFFSET(%r30)
1963 #ifdef __LP64__
1964         ldo     FRAME_SIZE(%r30), %r30
1965         bl      sys_rt_sigsuspend,%r2
1966         ldo     -16(%r30),%r29          /* Reference param save area */
1967 #else
1968         bl      sys_rt_sigsuspend,%r2
1969         ldo     FRAME_SIZE(%r30), %r30
1970 #endif
1971
1972         ldo     -FRAME_SIZE(%r30), %r30
1973         LDREG   -RP_OFFSET(%r30), %r2
1974
1975         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1976         ldo     TASK_REGS(%r1),%r1
1977         reg_restore %r1
1978
1979         bv      %r0(%r2)
1980         nop
1981
1982         .export syscall_exit
1983 syscall_exit:
1984         /* NOTE: HP-UX syscalls also come through here
1985            after hpux_syscall_exit fixes up return
1986            values. */
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
1989          * was running.
1990          */
1991
1992         /* save return value now */
1993
1994         mfctl     %cr30, %r1
1995         LDREG     TI_TASK(%r1),%r1
1996         STREG     %r28,TASK_PT_GR28(%r1)
1997
1998 #ifdef CONFIG_HPUX
1999
2000 /* <linux/personality.h> cannot be easily included */
2001 #define PER_HPUX 0x10
2002         LDREG     TASK_PERSONALITY(%r1),%r19
2003
2004         /* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */
2005         ldo       -PER_HPUX(%r19), %r19
2006         CMPIB<>,n 0,%r19,1f
2007
2008         /* Save other hpux returns if personality is PER_HPUX */
2009         STREG     %r22,TASK_PT_GR22(%r1)
2010         STREG     %r29,TASK_PT_GR29(%r1)
2011 1:
2012
2013 #endif /* CONFIG_HPUX */
2014
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.
2017          */
2018         loadgp
2019
2020 syscall_check_bh:
2021
2022         /* Check for software interrupts */
2023
2024         .import irq_stat,data
2025
2026         ldil    L%irq_stat,%r19
2027         ldo     R%irq_stat(%r19),%r19
2028
2029 #ifdef CONFIG_SMP
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 # */
2033
2034         /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
2035 #ifdef __LP64__
2036         shld    %r26, 6, %r20
2037 #else
2038         shlw    %r26, 5, %r20
2039 #endif
2040         add     %r19,%r20,%r19  /* now have &irq_stat[smp_processor_id()] */
2041 #endif /* CONFIG_SMP */
2042
2043         LDREG   IRQSTAT_SIRQ_PEND(%r19),%r20    /* hardirq.h: unsigned long */
2044         cmpib,<>,n 0,%r20,syscall_do_softirq /* forward */
2045
2046 syscall_check_resched:
2047
2048         /* check for reschedule */
2049
2050         LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19   /* long */
2051         bb,<,n  %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
2052
2053 syscall_check_sig:
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 */
2056
2057 syscall_restore:
2058         /* Are we being ptraced? */
2059         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2060
2061         LDREG   TASK_PTRACE(%r1), %r19
2062         bb,<    %r19,31,syscall_restore_rfi
2063         nop
2064
2065         ldo     TASK_PT_FR31(%r1),%r19             /* reload fpregs */
2066         rest_fp %r19
2067
2068         LDREG   TASK_PT_SAR(%r1),%r19              /* restore SAR */
2069         mtsar   %r19
2070
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 */
2084
2085         rsm     PSW_SM_I, %r0
2086         LDREG   TASK_PT_GR30(%r1),%r30             /* restore user sp */
2087         mfsp    %sr3,%r1                           /* Get users space id */
2088         mtsp    %r1,%sr7                           /* Restore sr7 */
2089         ssm     PSW_SM_I, %r0
2090         mtsp    %r1,%sr4                           /* Restore sr4 */
2091         mtsp    %r1,%sr5                           /* Restore sr5 */
2092         mtsp    %r1,%sr6                           /* Restore sr6 */
2093
2094         depi    3,31,2,%r31                        /* ensure return to user mode. */
2095
2096 #ifdef __LP64__
2097         /* decide whether to reset the wide mode bit
2098          *
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
2102         rsm     PSW_SM_W, %r0
2103         /* now reset the lowest bit of sp if it was set */
2104         xor     %r30,%r1,%r30
2105 #endif
2106         be,n    0(%sr3,%r31)                       /* return to user space */
2107
2108         /* We have to return via an RFI, so that PSW T and R bits can be set
2109          * appropriately.
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.
2112          */
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 */
2119
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 */
2123
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 */
2127
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 */
2131
2132         STREG   %r20,TASK_PT_PSW(%r1)
2133
2134         /* Always store space registers, since sr3 can be changed (e.g. fork) */
2135
2136         mfsp    %sr3,%r25
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)
2144
2145         /* XXX W bit??? */
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
2152          * an issue.
2153          */
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 */
2157         mfsp    %sr0,%r2
2158         STREG   %r2,TASK_PT_SR0(%r1)
2159         mfsp    %sr1,%r2
2160         STREG   %r2,TASK_PT_SR1(%r1)
2161         mfsp    %sr2,%r2
2162         STREG   %r2,TASK_PT_SR2(%r1)
2163 pt_regs_ok:
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)
2167         ldo     4(%r2),%r2
2168         STREG   %r2,TASK_PT_IAOQ1(%r1)
2169         copy    %r25,%r16
2170         b       intr_restore
2171         nop
2172
2173         .import do_softirq,code
2174 syscall_do_softirq:
2175         bl      do_softirq,%r2
2176         nop
2177         b       syscall_check_resched
2178         ssm     PSW_SM_I, %r0  /* do_softirq returns with I bit off */
2179
2180         .import schedule,code
2181 syscall_do_resched:
2182         bl      schedule,%r2
2183 #ifdef __LP64__
2184         ldo     -16(%r30),%r29          /* Reference param save area */
2185 #else
2186         nop
2187 #endif
2188         b       syscall_check_bh  /* if resched, we start over again */
2189         nop
2190
2191         .import do_signal,code
2192 syscall_do_signal:
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 */
2199         reg_save %r25
2200
2201         ldi     1, %r24                         /* unsigned long in_syscall */
2202
2203 #ifdef __LP64__
2204         ldo     -16(%r30),%r29                  /* Reference param save area */
2205 #endif
2206         bl      do_signal,%r2
2207         copy    %r0, %r26                       /* sigset_t *oldset = NULL */
2208
2209         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2210         ldo     TASK_REGS(%r1), %r20            /* reload pt_regs */
2211         reg_restore %r20
2212
2213         b,n     syscall_restore
2214
2215         /*
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).
2224          */
2225
2226 get_register:
2227         blr     %r8,%r0
2228         nop
2229         bv      %r0(%r25)    /* r0 */
2230         copy    %r0,%r1
2231         bv      %r0(%r25)    /* r1 - shadowed */
2232         ldi     -1,%r1
2233         bv      %r0(%r25)    /* r2 */
2234         copy    %r2,%r1
2235         bv      %r0(%r25)    /* r3 */
2236         copy    %r3,%r1
2237         bv      %r0(%r25)    /* r4 */
2238         copy    %r4,%r1
2239         bv      %r0(%r25)    /* r5 */
2240         copy    %r5,%r1
2241         bv      %r0(%r25)    /* r6 */
2242         copy    %r6,%r1
2243         bv      %r0(%r25)    /* r7 */
2244         copy    %r7,%r1
2245         bv      %r0(%r25)    /* r8 - shadowed */
2246         ldi     -1,%r1
2247         bv      %r0(%r25)    /* r9 - shadowed */
2248         ldi     -1,%r1
2249         bv      %r0(%r25)    /* r10 */
2250         copy    %r10,%r1
2251         bv      %r0(%r25)    /* r11 */
2252         copy    %r11,%r1
2253         bv      %r0(%r25)    /* r12 */
2254         copy    %r12,%r1
2255         bv      %r0(%r25)    /* r13 */
2256         copy    %r13,%r1
2257         bv      %r0(%r25)    /* r14 */
2258         copy    %r14,%r1
2259         bv      %r0(%r25)    /* r15 */
2260         copy    %r15,%r1
2261         bv      %r0(%r25)    /* r16 - shadowed */
2262         ldi     -1,%r1
2263         bv      %r0(%r25)    /* r17 - shadowed */
2264         ldi     -1,%r1
2265         bv      %r0(%r25)    /* r18 */
2266         copy    %r18,%r1
2267         bv      %r0(%r25)    /* r19 */
2268         copy    %r19,%r1
2269         bv      %r0(%r25)    /* r20 */
2270         copy    %r20,%r1
2271         bv      %r0(%r25)    /* r21 */
2272         copy    %r21,%r1
2273         bv      %r0(%r25)    /* r22 */
2274         copy    %r22,%r1
2275         bv      %r0(%r25)    /* r23 */
2276         copy    %r23,%r1
2277         bv      %r0(%r25)    /* r24 - shadowed */
2278         ldi     -1,%r1
2279         bv      %r0(%r25)    /* r25 - shadowed */
2280         ldi     -1,%r1
2281         bv      %r0(%r25)    /* r26 */
2282         copy    %r26,%r1
2283         bv      %r0(%r25)    /* r27 */
2284         copy    %r27,%r1
2285         bv      %r0(%r25)    /* r28 */
2286         copy    %r28,%r1
2287         bv      %r0(%r25)    /* r29 */
2288         copy    %r29,%r1
2289         bv      %r0(%r25)    /* r30 */
2290         copy    %r30,%r1
2291         bv      %r0(%r25)    /* r31 */
2292         copy    %r31,%r1
2293
2294         /*
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
2297          * r8.
2298          */
2299
2300 set_register:
2301         blr     %r8,%r0
2302         nop
2303         bv      %r0(%r25)    /* r0 (silly, but it is a place holder) */
2304         copy    %r1,%r0
2305         bv      %r0(%r25)    /* r1 */
2306         copy    %r1,%r1
2307         bv      %r0(%r25)    /* r2 */
2308         copy    %r1,%r2
2309         bv      %r0(%r25)    /* r3 */
2310         copy    %r1,%r3
2311         bv      %r0(%r25)    /* r4 */
2312         copy    %r1,%r4
2313         bv      %r0(%r25)    /* r5 */
2314         copy    %r1,%r5
2315         bv      %r0(%r25)    /* r6 */
2316         copy    %r1,%r6
2317         bv      %r0(%r25)    /* r7 */
2318         copy    %r1,%r7
2319         bv      %r0(%r25)    /* r8 */
2320         copy    %r1,%r8
2321         bv      %r0(%r25)    /* r9 */
2322         copy    %r1,%r9
2323         bv      %r0(%r25)    /* r10 */
2324         copy    %r1,%r10
2325         bv      %r0(%r25)    /* r11 */
2326         copy    %r1,%r11
2327         bv      %r0(%r25)    /* r12 */
2328         copy    %r1,%r12
2329         bv      %r0(%r25)    /* r13 */
2330         copy    %r1,%r13
2331         bv      %r0(%r25)    /* r14 */
2332         copy    %r1,%r14
2333         bv      %r0(%r25)    /* r15 */
2334         copy    %r1,%r15
2335         bv      %r0(%r25)    /* r16 */
2336         copy    %r1,%r16
2337         bv      %r0(%r25)    /* r17 */
2338         copy    %r1,%r17
2339         bv      %r0(%r25)    /* r18 */
2340         copy    %r1,%r18
2341         bv      %r0(%r25)    /* r19 */
2342         copy    %r1,%r19
2343         bv      %r0(%r25)    /* r20 */
2344         copy    %r1,%r20
2345         bv      %r0(%r25)    /* r21 */
2346         copy    %r1,%r21
2347         bv      %r0(%r25)    /* r22 */
2348         copy    %r1,%r22
2349         bv      %r0(%r25)    /* r23 */
2350         copy    %r1,%r23
2351         bv      %r0(%r25)    /* r24 */
2352         copy    %r1,%r24
2353         bv      %r0(%r25)    /* r25 */
2354         copy    %r1,%r25
2355         bv      %r0(%r25)    /* r26 */
2356         copy    %r1,%r26
2357         bv      %r0(%r25)    /* r27 */
2358         copy    %r1,%r27
2359         bv      %r0(%r25)    /* r28 */
2360         copy    %r1,%r28
2361         bv      %r0(%r25)    /* r29 */
2362         copy    %r1,%r29
2363         bv      %r0(%r25)    /* r30 */
2364         copy    %r1,%r30
2365         bv      %r0(%r25)    /* r31 */
2366         copy    %r1,%r31