diff options
Diffstat (limited to 'arch/sparc/include/asm/tsb.h')
| -rw-r--r-- | arch/sparc/include/asm/tsb.h | 106 | 
1 files changed, 23 insertions, 83 deletions
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h index e696432b950..90916f955ca 100644 --- a/arch/sparc/include/asm/tsb.h +++ b/arch/sparc/include/asm/tsb.h @@ -142,98 +142,40 @@ 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 - 1), REG2; \ -	sllx		REG1, PMD_PADDR_SHIFT, REG1; \ +	srlx		REG2, 64 - PAGE_SHIFT, REG2; \  	andn		REG2, 0x7, REG2; \  	add		REG1, REG2, REG1; -	/* These macros exists only to make the PMD translator below -	 * easier to read.  It hides the ELF section switch for the -	 * sun4v code patching. -	 */ -#define OR_PTE_BIT_1INSN(REG, NAME)			\ -661:	or		REG, _PAGE_##NAME##_4U, REG;	\ -	.section	.sun4v_1insn_patch, "ax";	\ -	.word		661b;				\ -	or		REG, _PAGE_##NAME##_4V, REG;	\ -	.previous; - -#define OR_PTE_BIT_2INSN(REG, TMP, NAME)		\ -661:	sethi		%hi(_PAGE_##NAME##_4U), TMP;	\ -	or		REG, TMP, REG;			\ -	.section	.sun4v_2insn_patch, "ax";	\ -	.word		661b;				\ -	mov		-1, TMP;			\ -	or		REG, _PAGE_##NAME##_4V, REG;	\ -	.previous; - -	/* Load into REG the PTE value for VALID, CACHE, and SZHUGE.  */ -#define BUILD_PTE_VALID_SZHUGE_CACHE(REG)				   \ -661:	sethi		%uhi(_PAGE_VALID|_PAGE_SZHUGE_4U), REG;		   \ -	.section	.sun4v_1insn_patch, "ax";			   \ -	.word		661b;						   \ -	sethi		%uhi(_PAGE_VALID), REG;				   \ -	.previous;							   \ -	sllx		REG, 32, REG;					   \ -661:	or		REG, _PAGE_CP_4U|_PAGE_CV_4U, REG;		   \ -	.section	.sun4v_1insn_patch, "ax";			   \ -	.word		661b;						   \ -	or		REG, _PAGE_CP_4V|_PAGE_CV_4V|_PAGE_SZHUGE_4V, REG; \ -	.previous; -  	/* 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  	 * translates to a valid PTE, branch to PTE_LABEL.  	 * -	 * We translate the PMD by hand, one bit at a time, -	 * constructing the huge PTE. -	 * -	 * So we construct the PTE in REG2 as follows: -	 * -	 * 1) Extract the PMD PFN from REG1 and place it into REG2. -	 * -	 * 2) Translate PMD protection bits in REG1 into REG2, one bit -	 *    at a time using andcc tests on REG1 and OR's into REG2. -	 * -	 *    Only two bits to be concerned with here, EXEC and WRITE. -	 *    Now REG1 is freed up and we can use it as a temporary. -	 * -	 * 3) Construct the VALID, CACHE, and page size PTE bits in -	 *    REG1, OR with REG2 to form final PTE. +	 * We have to propagate the 4MB bit of the virtual address +	 * because we are fabricating 8MB pages using 4MB hw pages.  	 */  #ifdef CONFIG_TRANSPARENT_HUGEPAGE  #define USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \ -	brz,pn		REG1, FAIL_LABEL;				      \ -	 andcc		REG1, PMD_ISHUGE, %g0;				      \ -	be,pt		%xcc, 700f;					      \ -	 and		REG1, PMD_HUGE_PRESENT|PMD_HUGE_ACCESSED, REG2;	      \ -	cmp		REG2, PMD_HUGE_PRESENT|PMD_HUGE_ACCESSED;	      \ -	bne,pn		%xcc, FAIL_LABEL;				      \ -	 andn		REG1, PMD_HUGE_PROTBITS, REG2;			      \ -	sllx		REG2, PMD_PADDR_SHIFT, REG2;			      \ -	/* REG2 now holds PFN << PAGE_SHIFT */				      \ -	andcc		REG1, PMD_HUGE_WRITE, %g0;			      \ -	bne,a,pt	%xcc, 1f;					      \ -	 OR_PTE_BIT_1INSN(REG2, W);					      \ -1:	andcc		REG1, PMD_HUGE_EXEC, %g0;			      \ -	be,pt		%xcc, 1f;					      \ -	 nop;								      \ -	OR_PTE_BIT_2INSN(REG2, REG1, EXEC);				      \ -	/* REG1 can now be clobbered, build final PTE */		      \ -1:	BUILD_PTE_VALID_SZHUGE_CACHE(REG1);				      \ -	ba,pt		%xcc, PTE_LABEL;				      \ -	 or		REG1, REG2, REG1;				      \ +	brz,pn		REG1, FAIL_LABEL;		\ +	 sethi		%uhi(_PAGE_PMD_HUGE), REG2;	\ +	sllx		REG2, 32, REG2;			\ +	andcc		REG1, REG2, %g0;		\ +	be,pt		%xcc, 700f;			\ +	 sethi		%hi(4 * 1024 * 1024), 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_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \ @@ -253,18 +195,16 @@ 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 - 1), REG2; \ -	sllx		REG1, PMD_PADDR_SHIFT, REG1; \ +	srlx		REG2, 64 - PAGE_SHIFT, REG2; \  	andn		REG2, 0x7, REG2; \  	add		REG1, REG2, REG1; \  	ldxa		[REG1] ASI_PHYS_USE_EC, REG1; \  | 
