[parisc-linux] Re: [parisc-linux-cvs] linux-2.6 jejb
James Bottomley
James.Bottomley at steeleye.com
Tue Apr 27 11:15:48 MDT 2004
On Tue, 2004-04-27 at 12:11, James Bottomley wrote:
> CVSROOT: /var/cvs
> Module name: linux-2.6
> Changes by: jejb 04/04/27 11:11:39
>
> Modified files:
> . : Makefile
> arch/parisc/kernel: entry.S
> include/asm-parisc: page.h
>
> Log message:
> More assembler magic entry removal.
>
> Also macro'ise the tlb miss handlers, making it much easier to
> alter them since all the information is collated in one place
===== arch/parisc/kernel/entry.S 1.15 vs edited =====
--- 1.15/arch/parisc/kernel/entry.S Sun Apr 25 04:00:10 2004
+++ edited/arch/parisc/kernel/entry.S Tue Apr 27 11:05:46 2004
@@ -40,11 +40,13 @@
#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
@@ -389,6 +391,208 @@
.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
+
+ /* 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 */
+ .macro L2_ptep pmd,pte,index,va,fault
+ EXTR \va,31-PMD_SHIFT,PAGE_SHIFT-BITS_PER_PMD,\index
+ copy %r0,\pte
+ DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */
+ LDREG,s \index(\pmd),\pmd
+ EXTR \va,31-PAGE_SHIFT,PAGE_SHIFT-BITS_PER_PTE,\index
+ bb,>=,n \pmd,_PAGE_PRESENT_BIT,\fault
+ DEP %r0,31,PAGE_SHIFT,\pmd /* clear offset */
+ shladd \index,BITS_PER_PTE,\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 */
+ .macro L3_ptep pgd,pte,index,va,fault
+ extrd,u \va,63-PGDIR_SHIFT,PAGE_SHIFT-BITS_PER_PGD,\index
+ copy %r0,\pte
+ ldd,s \index(\pgd),\pgd
+ bb,>=,n \pgd,_PAGE_PRESENT_BIT,\fault
+ 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,tmp1
+ 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,44,4,\tmp
+ addi,<> 1,\tmp,%r0
+ extrd,s \pte,63,32,\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
@@ -979,85 +1183,23 @@
#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
-
- /* Check whether the "accessed" bit was set, otherwise do so */
-
- 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 */
-
- 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 */
+ space_adjust spc,va,t0
+ get_pgd spc,ptp
+ space_check spc,t0,dtlb_fault
- /* Get rid of prot bits and convert to page addr for idtlbt */
+ L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w
- depdi 0,63,12,pte
- extrd,u pte,56,52,pte
+ update_ptep ptp,pte,t0,t1
+
+ 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
-#if (TMPALIAS_MAP_START >= 0x80000000)
- depdi 0,31,32,t0 /* clear any sign extension */
-#endif
- 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
@@ -1065,51 +1207,16 @@
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 */
-
- shladd t0,3,ptp,ptp
- ldi _PAGE_ACCESSED,t1
- ldd 0(ptp),pte
- bb,>=,n pte,_PAGE_PRESENT_BIT,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 */
-
- 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 */
+ space_adjust spc,va,t0
+ get_pgd spc,ptp
+ space_check spc,t0,nadtlb_fault
- /* Get rid of prot bits and convert to page addr for idtlbt */
+ L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb spc,pte,prot
- depdi 0,63,12,pte
- extrd,u pte,56,52,pte
idtlbt pte,prot
rfir
@@ -1135,49 +1242,15 @@
#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 */
-
- sh2addl t0,ptp,ptp
- ldi _PAGE_ACCESSED,t1
- ldw 0(ptp),pte
- bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_check_alias_11
-
- /* Check whether the "accessed" bit was set, otherwise do so */
-
- 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_pgd spc,ptp
- /* Get rid of prot bits and convert to page addr for idtlba */
+ space_check spc,t0,dtlb_fault
- depi 0,31,12,pte
- extru pte,24,25,pte
+ L2_ptep ptp,pte,t0,va,dtlb_check_alias_11
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb_11 spc,pte,prot
mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
mtsp spc,%sr1
@@ -1218,43 +1291,16 @@
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 */
-
- 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 */
-
- /* Second level page table lookup */
-
- sh2addl t0,ptp,ptp
- ldi _PAGE_ACCESSED,t1
- ldw 0(ptp),pte
- bb,>=,n pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_11
-
- 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_pgd spc,ptp
- /* Get rid of prot bits and convert to page addr for idtlba */
+ space_check spc,t0,nadtlb_fault
+
+ L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb_11 spc,pte,prot
- 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
@@ -1292,120 +1338,44 @@
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 */
-
- /* Second level page table lookup */
-
- sh2addl t0,ptp,ptp
- ldi _PAGE_ACCESSED,t1
- ldw 0(ptp),pte
- bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20
-
- /* Check whether the "accessed" bit was set, otherwise do so */
-
- 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 */
-
- 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 */
+ space_adjust spc,va,t0
+ get_pgd spc,ptp
+ space_check spc,t0,dtlb_fault
- /* Get rid of prot bits and convert to page addr for idtlbt */
+ L2_ptep ptp,pte,t0,va,dtlb_check_alias_20
+
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb spc,pte,prot
+
+ f_extend pte,t0
- 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 */
-
- /* 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,nadtlb_emulate
- depi 0,31,12,ptp /* clear prot bits */
-
- /* Second level page table lookup */
-
- sh2addl t0,ptp,ptp
- ldi _PAGE_ACCESSED,t1
- ldw 0(ptp),pte
- bb,>=,n pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20
-
- 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_pgd spc,ptp
- /* Get rid of prot bits and convert to page addr for idtlbt */
+ space_check spc,t0,nadtlb_fault
+
+ L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20
- 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 */
+ update_ptep ptp,pte,t0,t1
+
+ make_insert_tlb spc,pte,prot
+
+ f_extend pte,t0
+
idtlbt pte,prot
rfir
@@ -1478,119 +1448,33 @@
* 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 */
+ space_adjust spc,va,t0
+ get_pgd spc,ptp
+ space_check spc,t0,itlb_fault
- 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 */
+ L3_ptep ptp,pte,t0,va,itlb_fault
- /* Third level page table lookup */
+ update_ptep ptp,pte,t0,t1
- 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 */
-
- 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 */
-
- 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 */
-
- 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 */
+ space_check spc,t0,itlb_fault
- /* First level page table lookup */
+ L2_ptep ptp,pte,t0,va,itlb_fault
-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 */
+ update_ptep ptp,pte,t0,t1
- /* Second level page table lookup */
-
- sh2addl t0,ptp,ptp
- ldi _PAGE_ACCESSED,t1
- ldw 0(ptp),pte
- bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault
-
- /* Check whether the "accessed" bit was set, otherwise do so */
-
- 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
@@ -1603,106 +1487,35 @@
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 */
+ space_check spc,t0,itlb_fault
- mfsp %sr7,t0 /* Get current space */
- or,= %r0,t0,%r0 /* If kernel, nullify following test */
- cmpb,<>,n t0,spc,itlb_fault /* forward */
+ L2_ptep ptp,pte,t0,va,itlb_fault
- /* First level page table lookup */
+ update_ptep ptp,pte,t0,t1
-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 */
+ make_insert_tlb spc,pte,prot
- /* Second level page table lookup */
+ f_extend pte,t0
- sh2addl t0,ptp,ptp
- ldi _PAGE_ACCESSED,t1
- ldw 0(ptp),pte
- bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault
-
- /* Check whether the "accessed" bit was set, otherwise do so */
-
- 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 */
-
- 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 */
-
- /* 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,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
- /* Third level page table lookup */
+ L3_ptep ptp,pte,t0,va,dbit_fault
- shladd t0,3,ptp,ptp
#ifdef CONFIG_SMP
CMPIB=,n 0,spc,dbit_nolock_20w
ldil L%PA(pa_dbit_lock),t0
@@ -1715,27 +1528,10 @@
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 */
+ update_dirty ptp,pte,t0,t1
- /* 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
#ifdef CONFIG_SMP
CMPIB=,n 0,spc,dbit_nounlock_20w
@@ -1750,25 +1546,13 @@
#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
@@ -1781,29 +1565,9 @@
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 */
-
- 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 */
+ update_dirty ptp,pte,t0,t1
- 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
@@ -1824,25 +1588,12 @@
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 */
+ get_pgd spc,ptp
- mfsp %sr7,t0 /* Get current space */
- or,= %r0,t0,%r0 /* If kernel, nullify following test */
- cmpb,<>,n t0,spc,dbit_fault /* forward */
+ space_check spc,t0,dbit_fault
- /* First level page table lookup */
+ L2_ptep ptp,pte,t0,va,dbit_fault
- 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 */
-
- /* Second level page table lookup */
-
- sh2addl t0,ptp,ptp
#ifdef CONFIG_SMP
CMPIB=,n 0,spc,dbit_nolock_20
ldil L%PA(pa_dbit_lock),t0
@@ -1855,28 +1606,12 @@
dbit_nolock_20:
#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 */
-
- 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 */
+ update_dirty ptp,pte,t0,t1
+
+ make_insert_tlb spc,pte,prot
+
+ f_extend pte,t0
+
idtlbt pte,prot
#ifdef CONFIG_SMP
===== include/asm-parisc/page.h 1.6 vs edited =====
--- 1.6/include/asm-parisc/page.h Sun Apr 25 04:00:21 2004
+++ edited/include/asm-parisc/page.h Tue Apr 27 11:02:42 2004
@@ -84,6 +84,15 @@
#endif /* !__ASSEMBLY__ */
+#ifdef __LP64__
+#define BITS_PER_PTE 3
+#define BITS_PER_PMD 3
+#define BITS_PER_PGD 3
+#else
+#define BITS_PER_PTE 2
+#define BITS_PER_PMD 2
+#endif
+
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
More information about the parisc-linux
mailing list