sparc64: Move to 64-bit PGDs and PMDs.
To make the page tables compact, we were using 32-bit PGDs and PMDs.
We only had to support <= 43 bits of physical addresses so this was
quite feasible.
In order to support larger physical addresses we have to move to
64-bit PGDs and PMDs.
Most of the changes are straight-forward:
1) {pgd,pmd}_t --> unsigned long
2) Anything that tries to use plain "unsigned int" types with pgd/pmd
   values needs to be adjusted.  In particular things like "0U" become
   "0UL".
3) {PGDIR,PMD}_BITS decrease by one.
4) In the assembler page table walkers, use "ldxa" instead of "lduwa"
   and adjust the low bit masks to clear out the low 3 bits instead of
   just the low 2 bits during pgd/pmd address formation.
Also, use PTRS_PER_PGD and PTRS_PER_PMD in the sizing of the
swapper_{pg_dir,low_pmd_dir} arrays.
This patch does not try to take advantage of having 64-bits in the
PMDs to simplify the hugepage code, that will come in a subsequent
change.
Signed-off-by: David S. Miller <davem@davemloft.net>
	
	
This commit is contained in:
		
					parent
					
						
							
								37b3a8ff3e
							
						
					
				
			
			
				commit
				
					
						2b77933c28
					
				
			
		
					 4 changed files with 34 additions and 31 deletions
				
			
		|  | @ -56,8 +56,8 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct pag | |||
| /* These are used to make use of C type-checking.. */ | ||||
| typedef struct { unsigned long pte; } pte_t; | ||||
| typedef struct { unsigned long iopte; } iopte_t; | ||||
| typedef struct { unsigned int pmd; } pmd_t; | ||||
| typedef struct { unsigned int pgd; } pgd_t; | ||||
| typedef struct { unsigned long pmd; } pmd_t; | ||||
| typedef struct { unsigned long pgd; } pgd_t; | ||||
| typedef struct { unsigned long pgprot; } pgprot_t; | ||||
| 
 | ||||
| #define pte_val(x)	((x).pte) | ||||
|  | @ -76,8 +76,8 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| /* .. while these make it easier on the compiler */ | ||||
| typedef unsigned long pte_t; | ||||
| typedef unsigned long iopte_t; | ||||
| typedef unsigned int pmd_t; | ||||
| typedef unsigned int pgd_t; | ||||
| typedef unsigned long pmd_t; | ||||
| typedef unsigned long pgd_t; | ||||
| typedef unsigned long pgprot_t; | ||||
| 
 | ||||
| #define pte_val(x)	(x) | ||||
|  | @ -97,15 +97,18 @@ typedef unsigned long pgprot_t; | |||
| typedef pte_t *pgtable_t; | ||||
| 
 | ||||
| /* These two values define the virtual address space range in which we
 | ||||
|  * must forbid 64-bit user processes from making mappings.  It | ||||
|  * represents the virtual address space hole present in most early | ||||
|  * sparc64 chips including UltraSPARC-I.  The next two defines specify | ||||
|  * the actual exclusion region we enforce, wherein we use a 4GB red | ||||
|  * zone on each side of the VA hole. | ||||
|  * must forbid 64-bit user processes from making mappings.  It used to | ||||
|  * represent precisely the virtual address space hole present in most | ||||
|  * early sparc64 chips including UltraSPARC-I.  But now it also is | ||||
|  * further constrained by the limits of our page tables, which is | ||||
|  * 43-bits of virtual address. | ||||
|  */ | ||||
| #define SPARC64_VA_HOLE_TOP	_AC(0xfffff80000000000,UL) | ||||
| #define SPARC64_VA_HOLE_BOTTOM	_AC(0x0000080000000000,UL) | ||||
| #define SPARC64_VA_HOLE_TOP	_AC(0xfffffc0000000000,UL) | ||||
| #define SPARC64_VA_HOLE_BOTTOM	_AC(0x0000040000000000,UL) | ||||
| 
 | ||||
| /* The next two defines specify the actual exclusion region we
 | ||||
|  * enforce, wherein we use a 4GB red zone on each side of the VA hole. | ||||
|  */ | ||||
| #define VA_EXCLUDE_START (SPARC64_VA_HOLE_BOTTOM - (1UL << 32UL)) | ||||
| #define VA_EXCLUDE_END   (SPARC64_VA_HOLE_TOP + (1UL << 32UL)) | ||||
| 
 | ||||
|  |  | |||
|  | @ -51,15 +51,15 @@ | |||
| #define PMD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-3)) | ||||
| #define PMD_SIZE	(_AC(1,UL) << PMD_SHIFT) | ||||
| #define PMD_MASK	(~(PMD_SIZE-1)) | ||||
| #define PMD_BITS	(PAGE_SHIFT - 2) | ||||
| #define PMD_BITS	(PAGE_SHIFT - 3) | ||||
| 
 | ||||
| /* PGDIR_SHIFT determines what a third-level page table entry can map */ | ||||
| #define PGDIR_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-3) + PMD_BITS) | ||||
| #define PGDIR_SIZE	(_AC(1,UL) << PGDIR_SHIFT) | ||||
| #define PGDIR_MASK	(~(PGDIR_SIZE-1)) | ||||
| #define PGDIR_BITS	(PAGE_SHIFT - 2) | ||||
| #define PGDIR_BITS	(PAGE_SHIFT - 3) | ||||
| 
 | ||||
| #if (PGDIR_SHIFT + PGDIR_BITS) != 45 | ||||
| #if (PGDIR_SHIFT + PGDIR_BITS) != 43 | ||||
| #error Page table parameters do not cover virtual address space properly. | ||||
| #endif | ||||
| 
 | ||||
|  | @ -714,7 +714,7 @@ extern pgprot_t pmd_pgprot(pmd_t entry); | |||
| 
 | ||||
| static inline int pmd_present(pmd_t pmd) | ||||
| { | ||||
| 	return pmd_val(pmd) != 0U; | ||||
| 	return pmd_val(pmd) != 0UL; | ||||
| } | ||||
| 
 | ||||
| #define pmd_none(pmd)			(!pmd_val(pmd)) | ||||
|  | @ -741,7 +741,7 @@ static inline void pmd_set(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) | |||
| 	(pud_val(*(pudp)) = (__pa((unsigned long) (pmdp)) >> PGD_PADDR_SHIFT)) | ||||
| static inline unsigned long __pmd_page(pmd_t pmd) | ||||
| { | ||||
| 	unsigned long paddr = (unsigned long) pmd_val(pmd); | ||||
| 	unsigned long paddr = pmd_val(pmd); | ||||
| #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||||
| 	if (pmd_val(pmd) & PMD_ISHUGE) | ||||
| 		paddr &= PMD_HUGE_PADDR; | ||||
|  | @ -751,14 +751,14 @@ static inline unsigned long __pmd_page(pmd_t pmd) | |||
| } | ||||
| #define pmd_page(pmd) 			virt_to_page((void *)__pmd_page(pmd)) | ||||
| #define pud_page_vaddr(pud)		\ | ||||
| 	((unsigned long) __va((((unsigned long)pud_val(pud))<<PGD_PADDR_SHIFT))) | ||||
| 	((unsigned long) __va((pud_val(pud)<<PGD_PADDR_SHIFT))) | ||||
| #define pud_page(pud) 			virt_to_page((void *)pud_page_vaddr(pud)) | ||||
| #define pmd_bad(pmd)			(0) | ||||
| #define pmd_clear(pmdp)			(pmd_val(*(pmdp)) = 0U) | ||||
| #define pmd_clear(pmdp)			(pmd_val(*(pmdp)) = 0UL) | ||||
| #define pud_none(pud)			(!pud_val(pud)) | ||||
| #define pud_bad(pud)			(0) | ||||
| #define pud_present(pud)		(pud_val(pud) != 0U) | ||||
| #define pud_clear(pudp)			(pud_val(*(pudp)) = 0U) | ||||
| #define pud_clear(pudp)			(pud_val(*(pudp)) = 0UL) | ||||
| 
 | ||||
| /* Same in both SUN4V and SUN4U.  */ | ||||
| #define pte_none(pte) 			(!pte_val(pte)) | ||||
|  | @ -793,7 +793,7 @@ static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, | |||
| 				       pmd_t *pmdp) | ||||
| { | ||||
| 	pmd_t pmd = *pmdp; | ||||
| 	set_pmd_at(mm, addr, pmdp, __pmd(0U)); | ||||
| 	set_pmd_at(mm, addr, pmdp, __pmd(0UL)); | ||||
| 	return pmd; | ||||
| } | ||||
| 
 | ||||
|  | @ -841,8 +841,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
| }) | ||||
| #endif | ||||
| 
 | ||||
| extern pgd_t swapper_pg_dir[2048]; | ||||
| extern pmd_t swapper_low_pmd_dir[2048]; | ||||
| extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | ||||
| extern pmd_t swapper_low_pmd_dir[PTRS_PER_PMD]; | ||||
| 
 | ||||
| extern void paging_init(void); | ||||
| extern unsigned long find_ecache_flush_span(unsigned long size); | ||||
|  |  | |||
|  | @ -142,14 +142,14 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; | |||
| 	or		REG1, %lo(swapper_pg_dir), REG1; \ | ||||
| 	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \ | ||||
| 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \ | ||||
| 	andn		REG2, 0x3, REG2; \ | ||||
| 	lduw		[REG1 + REG2], REG1; \ | ||||
| 	andn		REG2, 0x7, REG2; \ | ||||
| 	ldx		[REG1 + REG2], REG1; \ | ||||
| 	brz,pn		REG1, FAIL_LABEL; \ | ||||
| 	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ | ||||
| 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \ | ||||
| 	sllx		REG1, PGD_PADDR_SHIFT, REG1; \ | ||||
| 	andn		REG2, 0x3, REG2; \ | ||||
| 	lduwa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ | ||||
| 	andn		REG2, 0x7, REG2; \ | ||||
| 	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ | ||||
| 	brz,pn		REG1, FAIL_LABEL; \ | ||||
| 	 sllx		VADDR, 64 - PMD_SHIFT, REG2; \ | ||||
| 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \ | ||||
|  | @ -260,14 +260,14 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; | |||
| #define USER_PGTABLE_WALK_TL1(VADDR, PHYS_PGD, REG1, REG2, FAIL_LABEL)	\ | ||||
| 	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \ | ||||
| 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \ | ||||
| 	andn		REG2, 0x3, REG2; \ | ||||
| 	lduwa		[PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \ | ||||
| 	andn		REG2, 0x7, REG2; \ | ||||
| 	ldxa		[PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \ | ||||
| 	brz,pn		REG1, FAIL_LABEL; \ | ||||
| 	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ | ||||
| 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \ | ||||
| 	sllx		REG1, PGD_PADDR_SHIFT, REG1; \ | ||||
| 	andn		REG2, 0x3, REG2; \ | ||||
| 	lduwa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ | ||||
| 	andn		REG2, 0x7, REG2; \ | ||||
| 	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ | ||||
| 	USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, 800f) \ | ||||
| 	sllx		VADDR, 64 - PMD_SHIFT, REG2; \ | ||||
| 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 David S. Miller
				David S. Miller