Pārlūkot izejas kodu

[SPARC64]: Fix two bugs wrt. kernel 4MB TSB.

1) The TSB lookup was not using the correct hash mask.

2) It was not aligned on a boundary equal to it's size,
   which is required by the sun4v Hypervisor.

wasn't having it's return value checked, and that bug will be fixed up
as well in a subsequent changeset.

Signed-off-by: David S. Miller <davem@davemloft.net>
David S. Miller 18 gadi atpakaļ
vecāks
revīzija
2d9e2763c2
3 mainītis faili ar 31 papildinājumiem un 7 dzēšanām
  1. 25 4
      arch/sparc64/kernel/head.S
  2. 5 2
      arch/sparc64/mm/init.c
  3. 1 1
      include/asm-sparc64/tsb.h

+ 25 - 4
arch/sparc64/kernel/head.S

@@ -653,33 +653,54 @@ setup_tba:
 	 restore
 	 restore
 sparc64_boot_end:
 sparc64_boot_end:
 
 
-#include "ktlb.S"
-#include "tsb.S"
 #include "etrap.S"
 #include "etrap.S"
 #include "rtrap.S"
 #include "rtrap.S"
 #include "winfixup.S"
 #include "winfixup.S"
 #include "entry.S"
 #include "entry.S"
 #include "sun4v_tlb_miss.S"
 #include "sun4v_tlb_miss.S"
 #include "sun4v_ivec.S"
 #include "sun4v_ivec.S"
+#include "ktlb.S"
+#include "tsb.S"
 
 
 /*
 /*
  * The following skip makes sure the trap table in ttable.S is aligned
  * The following skip makes sure the trap table in ttable.S is aligned
  * on a 32K boundary as required by the v9 specs for TBA register.
  * on a 32K boundary as required by the v9 specs for TBA register.
  *
  *
  * We align to a 32K boundary, then we have the 32K kernel TSB,
  * We align to a 32K boundary, then we have the 32K kernel TSB,
- * then the 32K aligned trap table.
+ * the 64K kernel 4MB TSB, and then the 32K aligned trap table.
  */
  */
 1:
 1:
 	.skip	0x4000 + _start - 1b
 	.skip	0x4000 + _start - 1b
 
 
+! 0x0000000000408000
+
 	.globl	swapper_tsb
 	.globl	swapper_tsb
 swapper_tsb:
 swapper_tsb:
 	.skip	(32 * 1024)
 	.skip	(32 * 1024)
 
 
-! 0x0000000000408000
+	.globl	swapper_4m_tsb
+swapper_4m_tsb:
+	.skip	(64 * 1024)
+
+! 0x0000000000420000
 
 
+	/* Some care needs to be exercised if you try to move the
+	 * location of the trap table relative to other things.  For
+	 * one thing there are br* instructions in some of the
+	 * trap table entires which branch back to code in ktlb.S
+	 * Those instructions can only handle a signed 16-bit
+	 * displacement.
+	 *
+	 * There is a binutils bug (bugzilla #4558) which causes
+	 * the relocation overflow checks for such instructions to
+	 * not be done correctly.  So bintuils will not notice the
+	 * error and will instead write junk into the relocation and
+	 * you'll have an unbootable kernel.
+	 */
 #include "ttable.S"
 #include "ttable.S"
 
 
+! 0x0000000000428000
+
 #include "systbls.S"
 #include "systbls.S"
 
 
 	.data
 	.data

+ 5 - 2
arch/sparc64/mm/init.c

@@ -61,8 +61,11 @@ unsigned long kern_linear_pte_xor[2] __read_mostly;
 unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
 unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
 
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
 #ifndef CONFIG_DEBUG_PAGEALLOC
-/* A special kernel TSB for 4MB and 256MB linear mappings.  */
-struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
+/* A special kernel TSB for 4MB and 256MB linear mappings.
+ * Space is allocated for this right after the trap table
+ * in arch/sparc64/kernel/head.S
+ */
+extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
 #endif
 #endif
 
 
 #define MAX_BANKS	32
 #define MAX_BANKS	32

+ 1 - 1
include/asm-sparc64/tsb.h

@@ -271,7 +271,7 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 #define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
 #define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
 	sethi		%hi(swapper_4m_tsb), REG1; \
 	sethi		%hi(swapper_4m_tsb), REG1; \
 	or		REG1, %lo(swapper_4m_tsb), REG1; \
 	or		REG1, %lo(swapper_4m_tsb), REG1; \
-	and		TAG, (KERNEL_TSB_NENTRIES - 1), REG2; \
+	and		TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
 	sllx		REG2, 4, REG2; \
 	sllx		REG2, 4, REG2; \
 	add		REG1, REG2, REG2; \
 	add		REG1, REG2, REG2; \
 	KTSB_LOAD_QUAD(REG2, REG3); \
 	KTSB_LOAD_QUAD(REG2, REG3); \