diff options
Diffstat (limited to 'arch/sparc/include/asm')
| -rw-r--r-- | arch/sparc/include/asm/hugetlb.h | 7 | ||||
| -rw-r--r-- | arch/sparc/include/asm/page_64.h | 3 | ||||
| -rw-r--r-- | arch/sparc/include/asm/pgtable_64.h | 20 | ||||
| -rw-r--r-- | arch/sparc/include/asm/tsb.h | 36 | 
4 files changed, 63 insertions, 3 deletions
diff --git a/arch/sparc/include/asm/hugetlb.h b/arch/sparc/include/asm/hugetlb.h index d1f837dc77a4..0ca7caab1b06 100644 --- a/arch/sparc/include/asm/hugetlb.h +++ b/arch/sparc/include/asm/hugetlb.h @@ -4,6 +4,13 @@  #include <asm/page.h>  #include <asm-generic/hugetlb.h> +#ifdef CONFIG_HUGETLB_PAGE +struct pud_huge_patch_entry { +	unsigned int addr; +	unsigned int insn; +}; +extern struct pud_huge_patch_entry __pud_huge_patch, __pud_huge_patch_end; +#endif  void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,  		     pte_t *ptep, pte_t pte); diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h index 5961b2d8398a..8ee1f97589a1 100644 --- a/arch/sparc/include/asm/page_64.h +++ b/arch/sparc/include/asm/page_64.h @@ -17,6 +17,7 @@  #define HPAGE_SHIFT		23  #define REAL_HPAGE_SHIFT	22 +#define HPAGE_16GB_SHIFT	34  #define HPAGE_2GB_SHIFT		31  #define HPAGE_256MB_SHIFT	28  #define HPAGE_64K_SHIFT		16 @@ -28,7 +29,7 @@  #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)  #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA  #define REAL_HPAGE_PER_HPAGE	(_AC(1,UL) << (HPAGE_SHIFT - REAL_HPAGE_SHIFT)) -#define HUGE_MAX_HSTATE		4 +#define HUGE_MAX_HSTATE		5  #endif  #ifndef __ASSEMBLY__ diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 6fbd931f0570..4fefe3762083 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -414,6 +414,11 @@ static inline bool is_hugetlb_pmd(pmd_t pmd)  	return !!(pmd_val(pmd) & _PAGE_PMD_HUGE);  } +static inline bool is_hugetlb_pud(pud_t pud) +{ +	return !!(pud_val(pud) & _PAGE_PUD_HUGE); +} +  #ifdef CONFIG_TRANSPARENT_HUGEPAGE  static inline pmd_t pmd_mkhuge(pmd_t pmd)  { @@ -687,6 +692,8 @@ static inline unsigned long pmd_write(pmd_t pmd)  	return pte_write(pte);  } +#define pud_write(pud)	pte_write(__pte(pud_val(pud))) +  #ifdef CONFIG_TRANSPARENT_HUGEPAGE  static inline unsigned long pmd_dirty(pmd_t pmd)  { @@ -823,9 +830,18 @@ static inline unsigned long __pmd_page(pmd_t pmd)  	return ((unsigned long) __va(pfn << PAGE_SHIFT));  } + +static inline unsigned long pud_page_vaddr(pud_t pud) +{ +	pte_t pte = __pte(pud_val(pud)); +	unsigned long pfn; + +	pfn = pte_pfn(pte); + +	return ((unsigned long) __va(pfn << PAGE_SHIFT)); +} +  #define pmd_page(pmd) 			virt_to_page((void *)__pmd_page(pmd)) -#define pud_page_vaddr(pud)		\ -	((unsigned long) __va(pud_val(pud)))  #define pud_page(pud) 			virt_to_page((void *)pud_page_vaddr(pud))  #define pmd_clear(pmdp)			(pmd_val(*(pmdp)) = 0UL)  #define pud_present(pud)		(pud_val(pud) != 0U) diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h index 32258e08da03..acf55063aa3d 100644 --- a/arch/sparc/include/asm/tsb.h +++ b/arch/sparc/include/asm/tsb.h @@ -195,6 +195,41 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;  	 nop; \  699: +	/* PUD has been loaded into REG1, interpret the value, seeing +	 * if it is a HUGE PUD or a normal one.  If it is not valid +	 * then jump to FAIL_LABEL.  If it is a HUGE PUD, and it +	 * translates to a valid PTE, branch to PTE_LABEL. +	 * +	 * We have to propagate bits [32:22] from the virtual address +	 * to resolve at 4M granularity. +	 */ +#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) +#define USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \ +700:	ba 700f;					\ +	 nop;						\ +	.section	.pud_huge_patch, "ax";		\ +	.word		700b;				\ +	nop;						\ +	.previous;					\ +	brz,pn		REG1, FAIL_LABEL;		\ +	 sethi		%uhi(_PAGE_PUD_HUGE), REG2;	\ +	sllx		REG2, 32, REG2;			\ +	andcc		REG1, REG2, %g0;		\ +	be,pt		%xcc, 700f;			\ +	 sethi		%hi(0x1ffc0000), REG2;		\ +	sllx		REG2, 1, REG2;			\ +	brgez,pn	REG1, FAIL_LABEL;		\ +	 andn		REG1, REG2, REG1;		\ +	and		VADDR, REG2, REG2;		\ +	brlz,pt		REG1, PTE_LABEL;		\ +	 or		REG1, REG2, REG1;		\ +700: +#else +#define USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \ +	brz,pn		REG1, FAIL_LABEL; \ +	 nop; +#endif +  	/* PMD has been loaded into REG1, interpret the value, seeing  	 * if it is a HUGE PMD or a normal one.  If it is not valid  	 * then jump to FAIL_LABEL.  If it is a HUGE PMD, and it @@ -242,6 +277,7 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;  	srlx		REG2, 64 - PAGE_SHIFT, REG2; \  	andn		REG2, 0x7, REG2; \  	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ +	USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, 800f) \  	brz,pn		REG1, FAIL_LABEL; \  	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \  	srlx		REG2, 64 - PAGE_SHIFT, REG2; \  | 

