vserver 1.9.5.x5
[linux-2.6.git] / arch / parisc / kernel / entry.S
index 040956b..b1dd08b 100644 (file)
 #ifdef __LP64__
 #define CMPIB           cmpib,*
 #define CMPB            cmpb,*
+#define COND(x)                *x
 
        .level 2.0w
 #else
 #define CMPIB           cmpib,
 #define CMPB            cmpb,
+#define COND(x)                x
 
        .level 2.0
 #endif
        .align          32
        .endm
 
+       /* The following are simple 32 vs 64 bit instruction
+        * abstractions for the macros */
+       .macro          EXTR    reg1,start,length,reg2
+#ifdef __LP64__
+       extrd,u         \reg1,32+\start,\length,\reg2
+#else
+       extrw,u         \reg1,\start,\length,\reg2
+#endif
+       .endm
+
+       .macro          DEP     reg1,start,length,reg2
+#ifdef __LP64__
+       depd            \reg1,32+\start,\length,\reg2
+#else
+       depw            \reg1,\start,\length,\reg2
+#endif
+       .endm
+
+       .macro          DEPI    val,start,length,reg
+#ifdef __LP64__
+       depdi           \val,32+\start,\length,\reg
+#else
+       depwi           \val,\start,\length,\reg
+#endif
+       .endm
+
+       /* In LP64, the space contains part of the upper 32 bits of the
+        * fault.  We have to extract this and place it in the va,
+        * zeroing the corresponding bits in the space register */
+       .macro          space_adjust    spc,va,tmp
+#ifdef __LP64__
+       extrd,u         \spc,63,SPACEID_SHIFT,\tmp
+       depd            %r0,63,SPACEID_SHIFT,\spc
+       depd            \tmp,31,SPACEID_SHIFT,\va
+#endif
+       .endm
+
+       .import         swapper_pg_dir,code
+
+       /* Get the pgd.  For faults on space zero (kernel space), this
+        * is simply swapper_pg_dir.  For user space faults, the
+        * pgd is stored in %cr25 */
+       .macro          get_pgd         spc,reg
+       ldil            L%PA(swapper_pg_dir),\reg
+       ldo             R%PA(swapper_pg_dir)(\reg),\reg
+       or,COND(=)      %r0,\spc,%r0
+       mfctl           %cr25,\reg
+       .endm
+
+       /* 
+               space_check(spc,tmp,fault)
+
+               spc - The space we saw the fault with.
+               tmp - The place to store the current space.
+               fault - Function to call on failure.
+
+               Only allow faults on different spaces from the
+               currently active one if we're the kernel 
+
+       */
+       .macro          space_check     spc,tmp,fault
+       mfsp            %sr7,\tmp
+       or,COND(<>)     %r0,\spc,%r0    /* user may execute gateway page
+                                        * as kernel, so defeat the space
+                                        * check if it is */
+       copy            \spc,\tmp
+       or,COND(=)      %r0,\tmp,%r0    /* nullify if executing as kernel */
+       cmpb,COND(<>),n \tmp,\spc,\fault
+       .endm
+
+       /* Look up a PTE in a 2-Level scheme (faulting at each
+        * level if the entry isn't present 
+        *
+        * NOTE: we use ldw even for LP64, since the short pointers
+        * can address up to 1TB
+        */
+       .macro          L2_ptep pmd,pte,index,va,fault
+#if PT_NLEVELS == 3
+       EXTR            \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index
+#else
+       EXTR            \va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
+#endif
+       DEP             %r0,31,PAGE_SHIFT,\pmd  /* clear offset */
+       copy            %r0,\pte
+       ldw,s           \index(\pmd),\pmd
+       bb,>=,n         \pmd,_PxD_PRESENT_BIT,\fault
+       DEP             %r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
+       copy            \pmd,%r9
+#ifdef __LP64__
+       shld            %r9,PxD_VALUE_SHIFT,\pmd
+#else
+       shlw            %r9,PxD_VALUE_SHIFT,\pmd
+#endif
+       EXTR            \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
+       DEP             %r0,31,PAGE_SHIFT,\pmd  /* clear offset */
+       shladd          \index,BITS_PER_PTE_ENTRY,\pmd,\pmd
+       LDREG           %r0(\pmd),\pte          /* pmd is now pte */
+       bb,>=,n         \pte,_PAGE_PRESENT_BIT,\fault
+       .endm
+
+       /* Look up PTE in a 3-Level scheme.
+        *
+        * Here we implement a Hybrid L2/L3 scheme: we allocate the
+        * first pmd adjacent to the pgd.  This means that we can
+        * subtract a constant offset to get to it.  The pmd and pgd
+        * sizes are arranged so that a single pmd covers 4GB (giving
+        * a full LP64 process access to 8TB) so our lookups are
+        * effectively L2 for the first 4GB of the kernel (i.e. for
+        * all ILP32 processes and all the kernel for machines with
+        * under 4GB of memory) */
+       .macro          L3_ptep pgd,pte,index,va,fault
+       extrd,u         \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
+       copy            %r0,\pte
+       extrd,u,*=      \va,31,32,%r0
+       ldw,s           \index(\pgd),\pgd
+       extrd,u,*=      \va,31,32,%r0
+       bb,>=,n         \pgd,_PxD_PRESENT_BIT,\fault
+       extrd,u,*=      \va,31,32,%r0
+       shld            \pgd,PxD_VALUE_SHIFT,\index
+       extrd,u,*=      \va,31,32,%r0
+       copy            \index,\pgd
+       extrd,u,*<>     \va,31,32,%r0
+       ldo             ASM_PGD_PMD_OFFSET(\pgd),\pgd
+       L2_ptep         \pgd,\pte,\index,\va,\fault
+       .endm
+
+       /* Set the _PAGE_ACCESSED bit of the PTE.  Be clever and
+        * don't needlessly dirty the cache line if it was already set */
+       .macro          update_ptep     ptep,pte,tmp,tmp1
+       ldi             _PAGE_ACCESSED,\tmp1
+       or              \tmp1,\pte,\tmp
+       and,COND(<>)    \tmp1,\pte,%r0
+       STREG           \tmp,0(\ptep)
+       .endm
+
+       /* Set the dirty bit (and accessed bit).  No need to be
+        * clever, this is only used from the dirty fault */
+       .macro          update_dirty    ptep,pte,tmp
+       ldi             _PAGE_ACCESSED|_PAGE_DIRTY,\tmp
+       or              \tmp,\pte,\pte
+       STREG           \pte,0(\ptep)
+       .endm
+
+       /* Convert the pte and prot to tlb insertion values.  How
+        * this happens is quite subtle, read below */
+       .macro          make_insert_tlb spc,pte,prot
+       space_to_prot   \spc \prot        /* create prot id from space */
+       /* The following is the real subtlety.  This is depositing
+        * T <-> _PAGE_REFTRAP
+        * D <-> _PAGE_DIRTY
+        * B <-> _PAGE_DMB (memory break)
+        *
+        * Then incredible subtlety: The access rights are
+        * _PAGE_GATEWAY _PAGE_EXEC _PAGE_READ
+        * See 3-14 of the parisc 2.0 manual
+        *
+        * Finally, _PAGE_READ goes in the top bit of PL1 (so we
+        * trigger an access rights trap in user space if the user
+        * tries to read an unreadable page */
+       depd            \pte,8,7,\prot
+
+       /* PAGE_USER indicates the page can be read with user privileges,
+        * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1
+        * contains _PAGE_READ */
+       extrd,u,*=      \pte,_PAGE_USER_BIT+32,1,%r0
+       depdi           7,11,3,\prot
+       /* If we're a gateway page, drop PL2 back to zero for promotion
+        * to kernel privilege (so we can execute the page as kernel).
+        * Any privilege promotion page always denys read and write */
+       extrd,u,*=      \pte,_PAGE_GATEWAY_BIT+32,1,%r0
+       depd            %r0,11,2,\prot  /* If Gateway, Set PL2 to 0 */
+
+       /* Get rid of prot bits and convert to page addr for iitlbt */
+
+       depd            %r0,63,PAGE_SHIFT,\pte
+       extrd,u         \pte,56,32,\pte
+       .endm
+
+       /* Identical macro to make_insert_tlb above, except it
+        * makes the tlb entry for the differently formatted pa11
+        * insertion instructions */
+       .macro          make_insert_tlb_11      spc,pte,prot
+       zdep            \spc,30,15,\prot
+       dep             \pte,8,7,\prot
+       extru,=         \pte,_PAGE_NO_CACHE_BIT,1,%r0
+       depi            1,12,1,\prot
+       extru,=         \pte,_PAGE_USER_BIT,1,%r0
+       depi            7,11,3,\prot   /* Set for user space (1 rsvd for read) */
+       extru,=         \pte,_PAGE_GATEWAY_BIT,1,%r0
+       depi            0,11,2,\prot    /* If Gateway, Set PL2 to 0 */
+
+       /* Get rid of prot bits and convert to page addr for iitlba */
+
+       depi            0,31,12,\pte
+       extru           \pte,24,25,\pte
+
+       .endm
+
+       /* This is for ILP32 PA2.0 only.  The TLB insertion needs
+        * to extend into I/O space if the address is 0xfXXXXXXX
+        * so we extend the f's into the top word of the pte in
+        * this case */
+       .macro          f_extend        pte,tmp
+       extrd,s         \pte,42,4,\tmp
+       addi,<>         1,\tmp,%r0
+       extrd,s         \pte,63,25,\pte
+       .endm
+
+       /* The alias region is an 8MB aligned 16MB to do clear and
+        * copy user pages at addresses congruent with the user
+        * virtual address.
+        *
+        * To use the alias page, you set %r26 up with the to TLB
+        * entry (identifying the physical page) and %r23 up with
+        * the from tlb entry (or nothing if only a to entry---for
+        * clear_user_page_asm) */
+       .macro          do_alias        spc,tmp,tmp1,va,pte,prot,fault
+       cmpib,COND(<>),n 0,\spc,\fault
+       ldil            L%(TMPALIAS_MAP_START),\tmp
+#if defined(__LP64__) && (TMPALIAS_MAP_START >= 0x80000000)
+       /* on LP64, ldi will sign extend into the upper 32 bits,
+        * which is behaviour we don't want */
+       depdi           0,31,32,\tmp
+#endif
+       copy            \va,\tmp1
+       DEPI            0,31,23,\tmp1
+       cmpb,COND(<>),n \tmp,\tmp1,\fault
+       ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot
+       depd,z          \prot,8,7,\prot
+       /*
+        * OK, it is in the temp alias region, check whether "from" or "to".
+        * Check "subtle" note in pacache.S re: r23/r26.
+        */
+#ifdef __LP64__
+       extrd,u,*=      \va,41,1,%r0
+#else
+       extrw,u,=       \va,9,1,%r0
+#endif
+       or,COND(tr)     %r23,%r0,\pte
+       or              %r26,%r0,\pte
+       .endm 
+
+
        /*
         * Align fault_vector_20 on 4K boundary so that both
         * fault_vector_11 and fault_vector_20 are on the
@@ -538,7 +783,7 @@ __kernel_thread:
 #ifdef __LP64__
        ldo     -16(%r30),%r29          /* Reference param save area */
 #endif
-       bl      do_fork, %r2
+       BL      do_fork, %r2
        copy    %r1, %r24               /* pt_regs */
 
        /* Parent Returns here */
@@ -559,7 +804,7 @@ __kernel_thread:
 ret_from_kernel_thread:
 
        /* Call schedule_tail first though */
-       bl      schedule_tail, %r2
+       BL      schedule_tail, %r2
        nop
 
        LDREG   TI_TASK-THREAD_SZ_ALGN(%r30), %r1
@@ -591,7 +836,7 @@ __execve:
 #ifdef __LP64__
        ldo     -16(%r30),%r29          /* Reference param save area */
 #endif
-       bl      sys_execve, %r2
+       BL      sys_execve, %r2
        copy    %r16, %r26
 
        cmpib,=,n 0,%r28,intr_return    /* forward */
@@ -703,6 +948,7 @@ syscall_exit_rfi:
        STREG   %r19,PT_SR7(%r16)
 
 intr_return:
+       /* NOTE: Need to enable interrupts incase we schedule. */
        ssm     PSW_SM_I, %r0
 
        /* Check for software interrupts */
@@ -746,6 +992,8 @@ intr_restore:
        ldo             PT_FR31(%r29),%r1
        rest_fp         %r1
        rest_general    %r29
+
+       /* Create a "relied upon translation" PA 2.0 Arch. F-5 */
        ssm             0,%r0
        nop
        nop
@@ -756,8 +1004,15 @@ intr_restore:
        nop
        tophys_r1       %r29
        rsm             (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0
+
+       /* Restore space id's and special cr's from PT_REGS
+        * structure pointed to by r29 */
        rest_specials   %r29
+
+       /* Important: Note that rest_stack restores r29
+        * last (we are using it)! It also restores r1 and r30. */
        rest_stack
+
        rfi
        nop
        nop
@@ -800,7 +1055,14 @@ intr_do_resched:
 
        .import do_signal,code
 intr_do_signal:
-       /* Only do signals if we are returning to user space */
+       /* 
+               This check is critical to having LWS
+               working. The IASQ is zero on the gateway
+               page and we cannot deliver any signals until
+               we get off the gateway page.
+
+               Only do signals if we are returning to user space 
+       */
        LDREG   PT_IASQ0(%r16), %r20
        CMPIB= 0,%r20,intr_restore /* backward */
        nop
@@ -814,7 +1076,7 @@ intr_do_signal:
        ldo     -16(%r30),%r29                  /* Reference param save area */
 #endif
 
-       bl      do_signal,%r2
+       BL      do_signal,%r2
        copy    %r0, %r26                       /* sigset_t *oldset = NULL */
 
        b       intr_restore
@@ -979,82 +1241,23 @@ skip_save_ior:
 #ifdef __LP64__
 
 dtlb_miss_20w:
-       extrd,u         spc,63,7,t1     /* adjust va */
-       depd            t1,31,7,va      /* adjust va */
-       depdi           0,63,7,spc      /* adjust space */
-       mfctl           %cr25,ptp       /* Assume user space miss */
-       or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
-       mfctl           %cr24,ptp       /* Load kernel pgd instead */
-       extrd,u         va,33,9,t1      /* Get pgd index */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,*<>,n       t0,spc,dtlb_fault /* forward */
-
-       /* First level page table lookup */
-
-       ldd,s           t1(ptp),ptp
-       extrd,u         va,42,9,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
-       depdi           0,63,12,ptp     /* clear prot bits */
-
-       /* Second level page table lookup */
-
-       ldd,s           t0(ptp),ptp
-       extrd,u         va,51,9,t0     /* get third-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
-       depdi           0,63,12,ptp     /* clear prot bits */
-
-       /* Third level page table lookup */
-
-       shladd           t0,3,ptp,ptp
-       ldi             _PAGE_ACCESSED,t1
-       ldd              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
+       space_adjust    spc,va,t0
+       get_pgd         spc,ptp
+       space_check     spc,t0,dtlb_fault
 
-       /* Check whether the "accessed" bit was set, otherwise do so */
+       L3_ptep         ptp,pte,t0,va,dtlb_check_alias_20w
 
-       or              t1,pte,t0       /* t0 has R bit set */
-       and,*<>         t1,pte,%r0      /* test and nullify if already set */
-       std             t0,0(ptp)       /* write back pte */
+       update_ptep     ptp,pte,t0,t1
 
-       space_to_prot   spc prot        /* create prot id from space */
-       depd            pte,8,7,prot    /* add in prot bits from pte */
-
-       extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
-       depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
-       depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-       /* Get rid of prot bits and convert to page addr for idtlbt */
-
-       depdi           0,63,12,pte
-       extrd,u         pte,56,52,pte
+       make_insert_tlb spc,pte,prot
+       
        idtlbt          pte,prot
 
        rfir
        nop
 
 dtlb_check_alias_20w:
-
-       /* Check to see if fault is in the temporary alias region */
-
-       cmpib,*<>,n     0,spc,dtlb_fault /* forward */
-       ldil            L%(TMPALIAS_MAP_START),t0
-       copy            va,t1
-       depdi           0,63,23,t1
-       cmpb,*<>,n      t0,t1,dtlb_fault /* forward */
-       ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
-       depd,z          prot,8,7,prot
-
-       /*
-        * OK, it is in the temp alias region, check whether "from" or "to".
-        * Check "subtle" note in pacache.S re: r23/r26.
-        */
-
-       extrd,u,*=      va,41,1,r0
-       or,*tr          %r23,%r0,pte    /* If "from" use "from" page */
-       or,*            %r26,%r0,pte    /* else "to", use "to" page  */
+       do_alias        spc,t0,t1,va,pte,prot,dtlb_fault
 
        idtlbt          pte,prot
 
@@ -1062,51 +1265,16 @@ dtlb_check_alias_20w:
        nop
 
 nadtlb_miss_20w:
-       extrd,u         spc,63,7,t1     /* adjust va */
-       depd            t1,31,7,va      /* adjust va */
-       depdi           0,63,7,spc      /* adjust space */
-       mfctl           %cr25,ptp       /* Assume user space miss */
-       or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
-       mfctl           %cr24,ptp       /* Load kernel pgd instead */
-       extrd,u         va,33,9,t1      /* Get pgd index */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,*<>,n       t0,spc,nadtlb_fault /* forward */
-
-       /* First level page table lookup */
-
-       ldd,s           t1(ptp),ptp
-       extrd,u         va,42,9,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
-       depdi           0,63,12,ptp     /* clear prot bits */
-
-       /* Second level page table lookup */
-
-       ldd,s           t0(ptp),ptp
-       extrd,u         va,51,9,t0     /* get third-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
-       depdi           0,63,12,ptp     /* clear prot bits */
-
-       /* Third level page table lookup */
+       space_adjust    spc,va,t0
+       get_pgd         spc,ptp
+       space_check     spc,t0,nadtlb_fault
 
-       shladd           t0,3,ptp,ptp
-       ldi             _PAGE_ACCESSED,t1
-       ldd              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20w
+       L3_ptep         ptp,pte,t0,va,nadtlb_check_flush_20w
 
-       space_to_prot   spc prot        /* create prot id from space */
-       depd            pte,8,7,prot    /* add in prot bits from pte */
+       update_ptep     ptp,pte,t0,t1
 
-       extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
-       depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
-       depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
+       make_insert_tlb spc,pte,prot
 
-       /* Get rid of prot bits and convert to page addr for idtlbt */
-
-       depdi           0,63,12,pte
-       extrd,u         pte,56,52,pte
        idtlbt          pte,prot
 
        rfir
@@ -1132,49 +1300,15 @@ nadtlb_check_flush_20w:
 #else
 
 dtlb_miss_11:
-       mfctl           %cr25,ptp       /* Assume user space miss */
-       or,<>           %r0,spc,%r0     /* If it is user space, nullify */
-       mfctl           %cr24,ptp       /* Load kernel pgd instead */
-       extru           va,9,10,t1      /* Get pgd index */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,=            %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,<>,n       t0,spc,dtlb_fault /* forward */
-
-       /* First level page table lookup */
-
-       ldwx,s          t1(ptp),ptp
-       extru           va,19,10,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_11
-       depi            0,31,12,ptp     /* clear prot bits */
-
-       /* Second level page table lookup */
+       get_pgd         spc,ptp
 
-       sh2addl          t0,ptp,ptp
-       ldi             _PAGE_ACCESSED,t1
-       ldw              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_11
+       space_check     spc,t0,dtlb_fault
 
-       /* Check whether the "accessed" bit was set, otherwise do so */
+       L2_ptep         ptp,pte,t0,va,dtlb_check_alias_11
 
-       or              t1,pte,t0       /* t0 has R bit set */
-       and,<>          t1,pte,%r0      /* test and nullify if already set */
-       stw             t0,0(ptp)       /* write back pte */
+       update_ptep     ptp,pte,t0,t1
 
-       zdep            spc,30,15,prot  /* create prot id from space */
-       dep             pte,8,7,prot    /* add in prot bits from pte */
-
-       extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
-       depi            1,12,1,prot
-       extru,=         pte,_PAGE_USER_BIT,1,r0
-       depi            7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
-       depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-       /* Get rid of prot bits and convert to page addr for idtlba */
-
-       depi            0,31,12,pte
-       extru           pte,24,25,pte
+       make_insert_tlb_11      spc,pte,prot
 
        mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
        mtsp            spc,%sr1
@@ -1215,43 +1349,16 @@ dtlb_check_alias_11:
        nop
 
 nadtlb_miss_11:
-       mfctl           %cr25,ptp       /* Assume user space miss */
-       or,<>           %r0,spc,%r0     /* If it is user space, nullify */
-       mfctl           %cr24,ptp       /* Load kernel pgd instead */
-       extru           va,9,10,t1      /* Get pgd index */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,=            %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,<>,n       t0,spc,nadtlb_fault /* forward */
-
-       /* First level page table lookup */
+       get_pgd         spc,ptp
 
-       ldwx,s          t1(ptp),ptp
-       extru           va,19,10,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
-       depi            0,31,12,ptp     /* clear prot bits */
+       space_check     spc,t0,nadtlb_fault
 
-       /* Second level page table lookup */
+       L2_ptep         ptp,pte,t0,va,nadtlb_check_flush_11
 
-       sh2addl          t0,ptp,ptp
-       ldi             _PAGE_ACCESSED,t1
-       ldw              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_11
+       update_ptep     ptp,pte,t0,t1
 
-       zdep            spc,30,15,prot  /* create prot id from space */
-       dep             pte,8,7,prot    /* add in prot bits from pte */
+       make_insert_tlb_11      spc,pte,prot
 
-       extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
-       depi            1,12,1,prot
-       extru,=         pte,_PAGE_USER_BIT,1,r0
-       depi            7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
-       depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-       /* Get rid of prot bits and convert to page addr for idtlba */
-
-       depi            0,31,12,pte
-       extru           pte,24,25,pte
 
        mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
        mtsp            spc,%sr1
@@ -1289,120 +1396,44 @@ nadtlb_check_flush_11:
        nop
 
 dtlb_miss_20:
-       mfctl           %cr25,ptp       /* Assume user space miss */
-       or,<>           %r0,spc,%r0     /* If it is user space, nullify */
-       mfctl           %cr24,ptp       /* Load kernel pgd instead */
-       extru           va,9,10,t1      /* Get pgd index */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,=            %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,<>,n       t0,spc,dtlb_fault /* forward */
-
-       /* First level page table lookup */
-
-       ldwx,s          t1(ptp),ptp
-       extru           va,19,10,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20
-       depi            0,31,12,ptp     /* clear prot bits */
+       space_adjust    spc,va,t0
+       get_pgd         spc,ptp
+       space_check     spc,t0,dtlb_fault
 
-       /* Second level page table lookup */
+       L2_ptep         ptp,pte,t0,va,dtlb_check_alias_20
 
-       sh2addl          t0,ptp,ptp
-       ldi             _PAGE_ACCESSED,t1
-       ldw              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20
+       update_ptep     ptp,pte,t0,t1
 
-       /* Check whether the "accessed" bit was set, otherwise do so */
+       make_insert_tlb spc,pte,prot
 
-       or              t1,pte,t0       /* t0 has R bit set */
-       and,<>          t1,pte,%r0      /* test and nullify if already set */
-       stw             t0,0(ptp)       /* write back pte */
+       f_extend        pte,t0
 
-       space_to_prot   spc prot        /* create prot id from space */
-       depd            pte,8,7,prot    /* add in prot bits from pte */
-
-       extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
-       depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
-       depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-       /* Get rid of prot bits and convert to page addr for idtlbt */
-
-       extrd,s         pte,35,4,t0
-       depdi           0,63,12,pte     /* clear lower 12 bits */
-        addi,=          1,t0,0 
-        extrd,u,*tr     pte,56,25,pte 
-       extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */ 
        idtlbt          pte,prot
 
        rfir
        nop
 
 dtlb_check_alias_20:
-
-       /* Check to see if fault is in the temporary alias region */
-
-       cmpib,<>,n      0,spc,dtlb_fault /* forward */
-       ldil            L%(TMPALIAS_MAP_START),t0
-       copy            va,t1
-       depwi           0,31,23,t1
-       cmpb,<>,n       t0,t1,dtlb_fault /* forward */
-       ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
-       depd,z          prot,8,7,prot
-
-       /*
-        * OK, it is in the temp alias region, check whether "from" or "to".
-        * Check "subtle" note in pacache.S re: r23/r26.
-        */
-
-       extrw,u,=       va,9,1,r0
-       or,tr           %r23,%r0,pte    /* If "from" use "from" page */
-       or              %r26,%r0,pte    /* else "to", use "to" page  */
-
+       do_alias        spc,t0,t1,va,pte,prot,dtlb_fault
+       
        idtlbt          pte,prot
 
        rfir
        nop
 
 nadtlb_miss_20:
-       mfctl           %cr25,ptp       /* Assume user space miss */
-       or,<>           %r0,spc,%r0     /* If it is user space, nullify */
-       mfctl           %cr24,ptp       /* Load kernel pgd instead */
-       extru           va,9,10,t1      /* Get pgd index */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,=            %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,<>,n       t0,spc,nadtlb_fault /* forward */
+       get_pgd         spc,ptp
 
-       /* First level page table lookup */
+       space_check     spc,t0,nadtlb_fault
 
-       ldwx,s          t1(ptp),ptp
-       extru           va,19,10,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
-       depi            0,31,12,ptp     /* clear prot bits */
+       L2_ptep         ptp,pte,t0,va,nadtlb_check_flush_20
 
-       /* Second level page table lookup */
+       update_ptep     ptp,pte,t0,t1
 
-       sh2addl          t0,ptp,ptp
-       ldi             _PAGE_ACCESSED,t1
-       ldw              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20
+       make_insert_tlb spc,pte,prot
 
-       space_to_prot   spc prot        /* create prot id from space */
-       depd            pte,8,7,prot    /* add in prot bits from pte */
-
-       extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
-       depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
-       depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-       /* Get rid of prot bits and convert to page addr for idtlbt */
-
-        extrd,s         pte,35,4,t0
-        depdi           0,63,12,pte     /* clear lower 12 bits */
-        addi,=          1,t0,0
-        extrd,u,*tr     pte,56,25,pte
-        extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
+       f_extend        pte,t0
+       
         idtlbt          pte,prot
 
        rfir
@@ -1438,24 +1469,29 @@ nadtlb_emulate:
         * of the instruction. Since we don't insert a translation
         * we can get a lot of faults during a flush loop, so it makes
         * sense to try to do it here with minimum overhead. We only
-        * emulate fdc,fic & pdc instructions whose base and index
-        * registers are not shadowed. We defer everything else to the
-        * "slow" path.
+        * emulate fdc,fic,pdc,probew,prober instructions whose base 
+        * and index registers are not shadowed. We defer everything 
+        * else to the "slow" path.
         */
 
        mfctl           %cr19,%r9 /* Get iir */
+
+       /* PA 2.0 Arch Ref. Book pg 382 has a good description of the insn bits.
+          Checks for fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw */
+
+       /* Checks for fdc,fdce,pdc,"fic,4f" only */
        ldi             0x280,%r16
        and             %r9,%r16,%r17
-       cmpb,<>,n       %r16,%r17,nadtlb_fault /* Not fdc,fic,pdc */
+       cmpb,<>,n       %r16,%r17,nadtlb_probe_check
        bb,>=,n         %r9,26,nadtlb_nullify  /* m bit not set, just nullify */
-       b,l             get_register,%r25
+       BL              get_register,%r25
        extrw,u         %r9,15,5,%r8           /* Get index register # */
        CMPIB=,n        -1,%r1,nadtlb_fault    /* have to use slow path */
        copy            %r1,%r24
-       b,l             get_register,%r25
+       BL              get_register,%r25
        extrw,u         %r9,10,5,%r8           /* Get base register # */
        CMPIB=,n        -1,%r1,nadtlb_fault    /* have to use slow path */
-       b,l             set_register,%r25
+       BL              set_register,%r25
        add,l           %r1,%r24,%r1           /* doesn't affect c/b bits */
 
 nadtlb_nullify:
@@ -1467,6 +1503,32 @@ nadtlb_nullify:
        rfir
        nop
 
+       /* 
+               When there is no translation for the probe address then we
+               must nullify the insn and return zero in the target regsiter.
+               This will indicate to the calling code that it does not have 
+               write/read privileges to this address.
+
+               This should technically work for prober and probew in PA 1.1,
+               and also probe,r and probe,w in PA 2.0
+
+               WARNING: USE ONLY NON-SHADOW REGISTERS WITH PROBE INSN!
+               THE SLOW-PATH EMULATION HAS NOT BEEN WRITTEN YET.
+
+       */
+nadtlb_probe_check:
+       ldi             0x80,%r16
+       and             %r9,%r16,%r17
+       cmpb,<>,n       %r16,%r17,nadtlb_fault /* Must be probe,[rw]*/
+       BL              get_register,%r25      /* Find the target register */
+       extrw,u         %r9,31,5,%r8           /* Get target register */
+       CMPIB=,n        -1,%r1,nadtlb_fault    /* have to use slow path */
+       BL              set_register,%r25
+       copy            %r0,%r1                /* Write zero to target register */
+       b nadtlb_nullify                       /* Nullify return insn */
+       nop
+
+
 #ifdef __LP64__
 itlb_miss_20w:
 
@@ -1475,119 +1537,33 @@ itlb_miss_20w:
         * on the gateway page which is in the kernel address space.
         */
 
-       extrd,u         spc,63,7,t1     /* adjust va */
-       depd            t1,31,7,va      /* adjust va */
-       depdi           0,63,7,spc      /* adjust space */
-       cmpib,*=        0,spc,itlb_miss_kernel_20w
-       extrd,u         va,33,9,t1      /* Get pgd index */
-
-       mfctl           %cr25,ptp       /* load user pgd */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,*<>,n      t0,spc,itlb_fault /* forward */
-
-       /* First level page table lookup */
-
-itlb_miss_common_20w:
-       ldd,s           t1(ptp),ptp
-       extrd,u         va,42,9,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
-       depdi           0,63,12,ptp     /* clear prot bits */
-
-       /* Second level page table lookup */
-
-       ldd,s           t0(ptp),ptp
-       extrd,u         va,51,9,t0     /* get third-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
-       depdi           0,63,12,ptp     /* clear prot bits */
-
-       /* Third level page table lookup */
-
-       shladd           t0,3,ptp,ptp
-       ldi             _PAGE_ACCESSED,t1
-       ldd              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,itlb_fault
-
-       /* Check whether the "accessed" bit was set, otherwise do so */
+       space_adjust    spc,va,t0
+       get_pgd         spc,ptp
+       space_check     spc,t0,itlb_fault
 
-       or              t1,pte,t0       /* t0 has R bit set */
-       and,*<>         t1,pte,%r0      /* test and nullify if already set */
-       std             t0,0(ptp)       /* write back pte */
+       L3_ptep         ptp,pte,t0,va,itlb_fault
 
-       space_to_prot   spc prot        /* create prot id from space */
-       depd            pte,8,7,prot    /* add in prot bits from pte */
+       update_ptep     ptp,pte,t0,t1
 
-       extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
-       depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
-       depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-       /* Get rid of prot bits and convert to page addr for iitlbt */
-
-       depdi           0,63,12,pte
-       extrd,u         pte,56,32,pte
+       make_insert_tlb spc,pte,prot
+       
        iitlbt          pte,prot
 
        rfir
        nop
 
-itlb_miss_kernel_20w:
-       b               itlb_miss_common_20w
-       mfctl           %cr24,ptp       /* Load kernel pgd */
 #else
 
 itlb_miss_11:
+       get_pgd         spc,ptp
 
-       /*
-        * I miss is a little different, since we allow users to fault
-        * on the gateway page which is in the kernel address space.
-        */
-
-       cmpib,=         0,spc,itlb_miss_kernel_11
-       extru           va,9,10,t1      /* Get pgd index */
-
-       mfctl           %cr25,ptp       /* load user pgd */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,=            %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,<>,n       t0,spc,itlb_fault /* forward */
-
-       /* First level page table lookup */
-
-itlb_miss_common_11:
-       ldwx,s          t1(ptp),ptp
-       extru           va,19,10,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
-       depi            0,31,12,ptp     /* clear prot bits */
-
-       /* Second level page table lookup */
+       space_check     spc,t0,itlb_fault
 
-       sh2addl          t0,ptp,ptp
-       ldi             _PAGE_ACCESSED,t1
-       ldw              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,itlb_fault
+       L2_ptep         ptp,pte,t0,va,itlb_fault
 
-       /* Check whether the "accessed" bit was set, otherwise do so */
+       update_ptep     ptp,pte,t0,t1
 
-       or              t1,pte,t0       /* t0 has R bit set */
-       and,<>          t1,pte,%r0      /* test and nullify if already set */
-       stw             t0,0(ptp)       /* write back pte */
-
-       zdep            spc,30,15,prot  /* create prot id from space */
-       dep             pte,8,7,prot    /* add in prot bits from pte */
-
-       extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
-       depi            1,12,1,prot
-       extru,=         pte,_PAGE_USER_BIT,1,r0
-       depi            7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
-       depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-       /* Get rid of prot bits and convert to page addr for iitlba */
-
-       depi            0,31,12,pte
-       extru           pte,24,25,pte
+       make_insert_tlb_11      spc,pte,prot
 
        mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
        mtsp            spc,%sr1
@@ -1600,106 +1576,35 @@ itlb_miss_common_11:
        rfir
        nop
 
-itlb_miss_kernel_11:
-       b               itlb_miss_common_11
-       mfctl           %cr24,ptp       /* Load kernel pgd */
-
 itlb_miss_20:
+       get_pgd         spc,ptp
 
-       /*
-        * I miss is a little different, since we allow users to fault
-        * on the gateway page which is in the kernel address space.
-        */
-
-       cmpib,=         0,spc,itlb_miss_kernel_20
-       extru           va,9,10,t1      /* Get pgd index */
-
-       mfctl           %cr25,ptp       /* load user pgd */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,=            %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,<>,n       t0,spc,itlb_fault /* forward */
-
-       /* First level page table lookup */
-
-itlb_miss_common_20:
-       ldwx,s          t1(ptp),ptp
-       extru           va,19,10,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
-       depi            0,31,12,ptp     /* clear prot bits */
+       space_check     spc,t0,itlb_fault
 
-       /* Second level page table lookup */
+       L2_ptep         ptp,pte,t0,va,itlb_fault
 
-       sh2addl          t0,ptp,ptp
-       ldi             _PAGE_ACCESSED,t1
-       ldw              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,itlb_fault
+       update_ptep     ptp,pte,t0,t1
 
-       /* Check whether the "accessed" bit was set, otherwise do so */
+       make_insert_tlb spc,pte,prot
 
-       or              t1,pte,t0       /* t0 has R bit set */
-       and,<>          t1,pte,%r0      /* test and nullify if already set */
-       stw             t0,0(ptp)       /* write back pte */
+       f_extend        pte,t0  
 
-       space_to_prot   spc prot        /* create prot id from space */
-       depd            pte,8,7,prot    /* add in prot bits from pte */
-
-       extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
-       depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
-       depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-       /* Get rid of prot bits and convert to page addr for iitlbt */
-
-        extrd,s         pte,35,4,t0 
-        depdi           0,63,12,pte     /* clear lower 12 bits */
-        addi,=          1,t0,0
-        extrd,u,*tr     pte,56,25,pte 
-        extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
        iitlbt          pte,prot
 
        rfir
        nop
 
-
-itlb_miss_kernel_20:
-       b               itlb_miss_common_20
-       mfctl           %cr24,ptp       /* Load kernel pgd */
 #endif
 
 #ifdef __LP64__
 
 dbit_trap_20w:
-       extrd,u         spc,63,7,t1     /* adjust va */
-       depd            t1,31,7,va      /* adjust va */
-       depdi           0,1,2,va        /* adjust va */
-       depdi           0,63,7,spc      /* adjust space */
-       mfctl           %cr25,ptp       /* Assume user space miss */
-       or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
-       mfctl           %cr24,ptp       /* Load kernel pgd instead */
-       extrd,u         va,33,9,t1      /* Get pgd index */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,*<>,n       t0,spc,dbit_fault /* forward */
-
-       /* First level page table lookup */
-
-       ldd,s           t1(ptp),ptp
-       extrd,u         va,42,9,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
-       depdi           0,63,12,ptp     /* clear prot bits */
+       space_adjust    spc,va,t0
+       get_pgd         spc,ptp
+       space_check     spc,t0,dbit_fault
 
-       /* Second level page table lookup */
+       L3_ptep         ptp,pte,t0,va,dbit_fault
 
-       ldd,s           t0(ptp),ptp
-       extrd,u         va,51,9,t0     /* get third-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
-       depdi           0,63,12,ptp     /* clear prot bits */
-
-       /* Third level page table lookup */
-
-       shladd           t0,3,ptp,ptp
 #ifdef CONFIG_SMP
        CMPIB=,n        0,spc,dbit_nolock_20w
        ldil            L%PA(pa_dbit_lock),t0
@@ -1712,27 +1617,10 @@ dbit_spin_20w:
 
 dbit_nolock_20w:
 #endif
-       ldi             (_PAGE_ACCESSED|_PAGE_DIRTY),t1
-       ldd              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,dbit_fault
-
-       /* Set Accessed and Dirty bits in the pte */
-
-       or              t1,pte,pte
-       std             pte,0(ptp)      /* write back pte */
-
-       space_to_prot   spc prot        /* create prot id from space */
-       depd            pte,8,7,prot    /* add in prot bits from pte */
-
-       extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
-       depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
-       depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-       /* Get rid of prot bits and convert to page addr for idtlbt */
+       update_dirty    ptp,pte,t1
 
-       depdi           0,63,12,pte
-       extrd,u         pte,56,52,pte
+       make_insert_tlb spc,pte,prot
+               
        idtlbt          pte,prot
 #ifdef CONFIG_SMP
        CMPIB=,n        0,spc,dbit_nounlock_20w
@@ -1747,25 +1635,13 @@ dbit_nounlock_20w:
 #else
 
 dbit_trap_11:
-       mfctl           %cr25,ptp       /* Assume user space trap */
-       or,<>           %r0,spc,%r0     /* If it is user space, nullify */
-       mfctl           %cr24,ptp       /* Load kernel pgd instead */
-       extru           va,9,10,t1      /* Get pgd index */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,=            %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,<>,n       t0,spc,dbit_fault /* forward */
 
-       /* First level page table lookup */
+       get_pgd         spc,ptp
 
-       ldwx,s          t1(ptp),ptp
-       extru           va,19,10,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
-       depi            0,31,12,ptp     /* clear prot bits */
+       space_check     spc,t0,dbit_fault
 
-       /* Second level page table lookup */
+       L2_ptep         ptp,pte,t0,va,dbit_fault
 
-       sh2addl          t0,ptp,ptp
 #ifdef CONFIG_SMP
        CMPIB=,n        0,spc,dbit_nolock_11
        ldil            L%PA(pa_dbit_lock),t0
@@ -1778,29 +1654,9 @@ dbit_spin_11:
 
 dbit_nolock_11:
 #endif
-       ldi             (_PAGE_ACCESSED|_PAGE_DIRTY),t1
-       ldw              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,dbit_fault
-
-       /* Set Accessed and Dirty bits in the pte */
-
-       or              t1,pte,pte
-       stw             pte,0(ptp)      /* write back pte */
+       update_dirty    ptp,pte,t1
 
-       zdep            spc,30,15,prot  /* create prot id from space */
-       dep             pte,8,7,prot    /* add in prot bits from pte */
-
-       extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
-       depi            1,12,1,prot
-       extru,=         pte,_PAGE_USER_BIT,1,r0
-       depi            7,11,3,prot /* Set for user space (1 rsvd for read) */
-       extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
-       depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-       /* Get rid of prot bits and convert to page addr for idtlba */
-
-       depi            0,31,12,pte
-       extru           pte,24,25,pte
+       make_insert_tlb_11      spc,pte,prot
 
        mfsp            %sr1,t1  /* Save sr1 so we can use it in tlb inserts */
        mtsp            spc,%sr1
@@ -1821,25 +1677,12 @@ dbit_nounlock_11:
        nop
 
 dbit_trap_20:
-       mfctl           %cr25,ptp       /* Assume user space trap */
-       or,<>           %r0,spc,%r0     /* If it is user space, nullify */
-       mfctl           %cr24,ptp       /* Load kernel pgd instead */
-       extru           va,9,10,t1      /* Get pgd index */
-
-       mfsp            %sr7,t0         /* Get current space */
-       or,=            %r0,t0,%r0      /* If kernel, nullify following test */
-       cmpb,<>,n       t0,spc,dbit_fault /* forward */
-
-       /* First level page table lookup */
+       get_pgd         spc,ptp
 
-       ldwx,s          t1(ptp),ptp
-       extru           va,19,10,t0     /* get second-level index */
-       bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
-       depi            0,31,12,ptp     /* clear prot bits */
+       space_check     spc,t0,dbit_fault
 
-       /* Second level page table lookup */
+       L2_ptep         ptp,pte,t0,va,dbit_fault
 
-       sh2addl          t0,ptp,ptp
 #ifdef CONFIG_SMP
        CMPIB=,n        0,spc,dbit_nolock_20
        ldil            L%PA(pa_dbit_lock),t0
@@ -1852,28 +1695,12 @@ dbit_spin_20:
 
 dbit_nolock_20:
 #endif
-       ldi             (_PAGE_ACCESSED|_PAGE_DIRTY),t1
-       ldw              0(ptp),pte
-       bb,>=,n          pte,_PAGE_PRESENT_BIT,dbit_fault
+       update_dirty    ptp,pte,t1
 
-       /* Set Accessed and Dirty bits in the pte */
+       make_insert_tlb spc,pte,prot
 
-       or              t1,pte,pte
-       stw             pte,0(ptp)      /* write back pte */
-
-       space_to_prot   spc prot        /* create prot id from space */
-       depd            pte,8,7,prot    /* add in prot bits from pte */
-
-       extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
-       depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
-       extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
-       depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
-
-        extrd,s         pte,35,4,t0 
-        depdi           0,63,12,pte     /* clear lower 12 bits */
-        addi,=          1,t0,0
-        extrd,u,*tr     pte,56,25,pte 
-        extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
+       f_extend        pte,t1
+       
         idtlbt          pte,prot
 
 #ifdef CONFIG_SMP
@@ -1992,7 +1819,7 @@ sys_fork_wrapper:
 
        LDREG   PT_GR30(%r1),%r25
        copy    %r1,%r24
-       bl      sys_clone,%r2
+       BL      sys_clone,%r2
        ldi     SIGCHLD,%r26
 
        LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
@@ -2012,7 +1839,7 @@ wrapper_exit:
 
        /* Set the return value for the child */
 child_return:
-       bl      schedule_tail, %r2
+       BL      schedule_tail, %r2
        nop
 
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
@@ -2037,7 +1864,7 @@ sys_clone_wrapper:
 
        STREG   %r2,PT_GR19(%r1)        /* save for child */
        STREG   %r30,PT_GR21(%r1)
-       bl      sys_clone,%r2
+       BL      sys_clone,%r2
        copy    %r1,%r24
 
        b       wrapper_exit
@@ -2060,7 +1887,7 @@ sys_vfork_wrapper:
        STREG   %r2,PT_GR19(%r1)        /* save for child */
        STREG   %r30,PT_GR21(%r1)
 
-       bl      sys_vfork,%r2
+       BL      sys_vfork,%r2
        copy    %r1,%r26
 
        b       wrapper_exit
@@ -2123,10 +1950,10 @@ sys_rt_sigreturn_wrapper:
        STREG   %r2, -RP_OFFSET(%r30)
 #ifdef __LP64__
        ldo     FRAME_SIZE(%r30), %r30
-       bl      sys_rt_sigreturn,%r2
+       BL      sys_rt_sigreturn,%r2
        ldo     -16(%r30),%r29          /* Reference param save area */
 #else
-       bl      sys_rt_sigreturn,%r2
+       BL      sys_rt_sigreturn,%r2
        ldo     FRAME_SIZE(%r30), %r30
 #endif
 
@@ -2154,7 +1981,7 @@ sys_sigaltstack_wrapper:
        STREG   %r2, -RP_OFFSET(%r30)
 #ifdef __LP64__
        ldo     FRAME_SIZE(%r30), %r30
-       b     do_sigaltstack,%r2
+       b,l     do_sigaltstack,%r2
        ldo     -16(%r30),%r29          /* Reference param save area */
 #else
        bl      do_sigaltstack,%r2
@@ -2174,7 +2001,7 @@ sys32_sigaltstack_wrapper:
        LDREG   TASK_PT_GR30(%r24),%r24
        STREG   %r2, -RP_OFFSET(%r30)
        ldo     FRAME_SIZE(%r30), %r30
-       b     do_sigaltstack32,%r2
+       b,l     do_sigaltstack32,%r2
        ldo     -16(%r30),%r29          /* Reference param save area */
 
        ldo     -FRAME_SIZE(%r30), %r30
@@ -2192,7 +2019,7 @@ sys_rt_sigsuspend_wrapper:
        STREG   %r2, -RP_OFFSET(%r30)
 #ifdef __LP64__
        ldo     FRAME_SIZE(%r30), %r30
-       b     sys_rt_sigsuspend,%r2
+       b,l     sys_rt_sigsuspend,%r2
        ldo     -16(%r30),%r29          /* Reference param save area */
 #else
        bl      sys_rt_sigsuspend,%r2
@@ -2211,9 +2038,11 @@ sys_rt_sigsuspend_wrapper:
 
        .export syscall_exit
 syscall_exit:
+
        /* NOTE: HP-UX syscalls also come through here
-          after hpux_syscall_exit fixes up return
-          values. */
+        * after hpux_syscall_exit fixes up return
+        * values. */
+
        /* NOTE: Not all syscalls exit this way.  rt_sigreturn will exit
         * via syscall_exit_rfi if the signal was received while the process
         * was running.
@@ -2285,9 +2114,13 @@ syscall_check_sig:
        bb,<,n  %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
 
 syscall_restore:
-       LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19    /* get ti flags */
-       bb,<    %r19, 31-TIF_SYSCALL_TRACE,syscall_restore_rfi
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1     /* delay slot! */
+       /* Are we being ptraced? */
+       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+
+       LDREG   TASK_PTRACE(%r1), %r19
+       bb,<    %r19,31,syscall_restore_rfi
+       nop
+
        ldo     TASK_PT_FR31(%r1),%r19             /* reload fpregs */
        rest_fp %r19
 
@@ -2308,11 +2141,15 @@ syscall_restore:
        LDREG   TASK_PT_GR29(%r1),%r29
        LDREG   TASK_PT_GR31(%r1),%r31     /* restore syscall rp */
 
+       /* NOTE: We use rsm/ssm pair to make this operation atomic */
        rsm     PSW_SM_I, %r0
        LDREG   TASK_PT_GR30(%r1),%r30             /* restore user sp */
        mfsp    %sr3,%r1                           /* Get users space id */
        mtsp    %r1,%sr7                           /* Restore sr7 */
        ssm     PSW_SM_I, %r0
+
+       /* Set sr2 to zero for userspace syscalls to work. */
+       mtsp    %r0,%sr2 
        mtsp    %r1,%sr4                           /* Restore sr4 */
        mtsp    %r1,%sr5                           /* Restore sr5 */
        mtsp    %r1,%sr6                           /* Restore sr6 */
@@ -2337,7 +2174,6 @@ syscall_restore:
         * the most efficient way of doing things, but it works.
         */
 syscall_restore_rfi:
-       LDREG   TASK_PTRACE(%r1), %r19
        ldo     -1(%r0),%r2                        /* Set recovery cntr to -1 */
        mtctl   %r2,%cr0                           /*   for immediate trap */
        LDREG   TASK_PT_PSW(%r1),%r2               /* Get old PSW */
@@ -2381,12 +2217,18 @@ syscall_restore_rfi:
        bb,<    %r2,30,pt_regs_ok                  /* Branch if D set */
        ldo     TASK_REGS(%r1),%r25
        reg_save %r25                              /* Save r3 to r18 */
+
+       /* Save the current sr */
        mfsp    %sr0,%r2
        STREG   %r2,TASK_PT_SR0(%r1)
+
+       /* Save the scratch sr */
        mfsp    %sr1,%r2
        STREG   %r2,TASK_PT_SR1(%r1)
-       mfsp    %sr2,%r2
-       STREG   %r2,TASK_PT_SR2(%r1)
+
+       /* sr2 should be set to zero for userspace syscalls */
+       STREG   %r0,TASK_PT_SR2(%r1)
+
 pt_regs_ok:
        LDREG   TASK_PT_GR31(%r1),%r2
        depi    3,31,2,%r2                         /* ensure return to user mode. */
@@ -2401,12 +2243,15 @@ pt_regs_ok:
 syscall_do_softirq:
        bl      do_softirq,%r2
        nop
+       /* NOTE: We enable I-bit incase we schedule later,
+        * and we might be going back to userspace if we were
+        * traced. */
        b       syscall_check_resched
        ssm     PSW_SM_I, %r0  /* do_softirq returns with I bit off */
 
        .import schedule,code
 syscall_do_resched:
-       bl      schedule,%r2
+       BL      schedule,%r2
 #ifdef __LP64__
        ldo     -16(%r30),%r29          /* Reference param save area */
 #else
@@ -2430,7 +2275,7 @@ syscall_do_signal:
 #ifdef __LP64__
        ldo     -16(%r30),%r29                  /* Reference param save area */
 #endif
-       bl      do_signal,%r2
+       BL      do_signal,%r2
        copy    %r0, %r26                       /* sigset_t *oldset = NULL */
 
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1