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