Skip to content

Commit

Permalink
sparc64: Fix huge PMD to PTE translation for sun4u in TLB miss handler.
Browse files Browse the repository at this point in the history
When we set the sun4u version of the PTE execute bit, it's:

	or	REG, _PAGE_EXEC_4U, REG

_PAGE_EXEC_4U is 0x1000, unfortunately the immedate field of the
'or' instruction is a signed 13-bit value.  So the above actually
assembles into:

	or	REG, -4096, REG

completely corrupting the final PTE value.

Set it with a:

	sethi	%hi(_PAGE_EXEC_4U), TMP
	or	REG, TMP, REG

sequence instead.

This fixes "git gc" crashes on sun4u machines.

Reported-by: Meelis Roos <mroos@linux.ee>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 20, 2013
1 parent 0fbebed commit 76968ad
Showing 1 changed file with 19 additions and 9 deletions.
28 changes: 19 additions & 9 deletions arch/sparc/include/asm/tsb.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,17 +157,26 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
andn REG2, 0x7, REG2; \
add REG1, REG2, REG1;

/* This macro exists only to make the PMD translator below easier
* to read. It hides the ELF section switch for the sun4v code
* patching.
/* 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(REG, NAME) \
#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; \
Expand Down Expand Up @@ -214,12 +223,13 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
andn REG1, PMD_HUGE_PROTBITS, REG2; \
sllx REG2, PMD_PADDR_SHIFT, REG2; \
/* REG2 now holds PFN << PAGE_SHIFT */ \
andcc REG1, PMD_HUGE_EXEC, %g0; \
bne,a,pt %xcc, 1f; \
OR_PTE_BIT(REG2, EXEC); \
1: andcc REG1, PMD_HUGE_WRITE, %g0; \
andcc REG1, PMD_HUGE_WRITE, %g0; \
bne,a,pt %xcc, 1f; \
OR_PTE_BIT(REG2, W); \
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; \
Expand Down

0 comments on commit 76968ad

Please sign in to comment.