]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
xtensa: fix secondary core boot in SMP
authorMax Filippov <jcmvbkbc@gmail.com>
Fri, 16 Oct 2015 14:01:04 +0000 (17:01 +0300)
committerLuis Henriques <luis.henriques@canonical.com>
Sun, 13 Dec 2015 17:49:05 +0000 (17:49 +0000)
commit ab45fb145096799dabd18afc58bb5f97171017cd upstream.

There are multiple factors adding to the issue in different
configurations:

- commit 17290231df16eeee ("xtensa: add fixup for double exception raised
  in window overflow") added function window_overflow_restore_a0_fixup to
  double exception vector overlapping reset vector location of secondary
  processor cores.
- on MMUv2 cores RESET_VECTOR1_VADDR may point to uncached kernel memory
  making code overlapping depend on cache type and size, so that without
  cache or with WT cache reset vector code overwrites double exception
  code, making issue even harder to detect.
- on MMUv3 cores RESET_VECTOR1_VADDR may point to unmapped area, as
  MMUv3 cores change virtual address map to match MMUv2 layout, but
  reset vector virtual address is given for the original MMUv3 mapping.
- physical memory region of the secondary reset vector is not reserved
  in the physical memory map, and thus may be allocated and overwritten
  at arbitrary moment.

Fix it as follows:

- move window_overflow_restore_a0_fixup code to .text section.
- define RESET_VECTOR1_VADDR so that it points to reset vector in the
  cacheable MMUv2 map for cores with MMU.
- reserve reset vector region in the physical memory map. Drop separate
  literal section and build mxhead.S with text section literals.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
arch/xtensa/include/asm/vectors.h
arch/xtensa/kernel/Makefile
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/vectors.S
arch/xtensa/kernel/vmlinux.lds.S

index f74ddfbb92ef56587b618db2a7e80a2c96593499..29804fa6a7a3eee3ef848627bf9ffe3d2cff1a32 100644 (file)
@@ -47,6 +47,9 @@
   #define LOAD_MEMORY_ADDRESS          0xD0003000
 #endif
 
+#define RESET_VECTOR1_VADDR            (VIRTUAL_MEMORY_ADDRESS + \
+                                        XCHAL_RESET_VECTOR1_PADDR)
+
 #else /* !defined(CONFIG_MMU) */
   /* MMU Not being used - Virtual == Physical */
 
@@ -59,6 +62,8 @@
   /* Loaded just above possibly live vectors */
   #define LOAD_MEMORY_ADDRESS          0x00003000
 
+#define RESET_VECTOR1_VADDR            (XCHAL_RESET_VECTOR1_VADDR)
+
 #endif /* CONFIG_MMU */
 
 #define XC_VADDR(offset)               (VIRTUAL_MEMORY_ADDRESS  + offset)
                                                VECBASE_RESET_VADDR)
 #define RESET_VECTOR_VADDR             XC_VADDR(RESET_VECTOR_VECOFS)
 
-#define RESET_VECTOR1_VECOFS           (XCHAL_RESET_VECTOR1_VADDR - \
-                                               VECBASE_RESET_VADDR)
-#define RESET_VECTOR1_VADDR            XC_VADDR(RESET_VECTOR1_VECOFS)
-
 #if defined(XCHAL_HAVE_VECBASE) && XCHAL_HAVE_VECBASE
 
 #define USER_VECTOR_VADDR              XC_VADDR(XCHAL_USER_VECOFS)
index 18d962a8c0c2d1fccc5411fadbdc087bb5b05573..093be9122ee7e0b26787eb46ce05ad960b438b03 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_FUNCTION_TRACER) += mcount.o
 obj-$(CONFIG_SMP) += smp.o mxhead.o
 
 AFLAGS_head.o += -mtext-section-literals
+AFLAGS_mxhead.o += -mtext-section-literals
 
 # In the Xtensa architecture, assembly generates literals which must always
 # precede the L32R instruction with a relative offset less than 256 kB.
index 06370ccea9e90d8d9fff96555e2c4eaafd38afd6..ed5b8b9b8d96dac6f0c0fc36e74db6f9f4d52e20 100644 (file)
@@ -334,7 +334,10 @@ extern char _Level5InterruptVector_text_end;
 extern char _Level6InterruptVector_text_start;
 extern char _Level6InterruptVector_text_end;
 #endif
-
+#ifdef CONFIG_SMP
+extern char _SecondaryResetVector_text_start;
+extern char _SecondaryResetVector_text_end;
+#endif
 
 
 #ifdef CONFIG_S32C1I_SELFTEST
@@ -506,6 +509,10 @@ void __init setup_arch(char **cmdline_p)
                    __pa(&_Level6InterruptVector_text_end), 0);
 #endif
 
+#ifdef CONFIG_SMP
+       mem_reserve(__pa(&_SecondaryResetVector_text_start),
+                   __pa(&_SecondaryResetVector_text_end), 0);
+#endif
        parse_early_param();
        bootmem_init();
 
index 8453e6e398951b0d1864b6e570c8d7d63e45d356..7a1ff5e553b7539e1ca056d6449f1748b315bf77 100644 (file)
@@ -472,6 +472,9 @@ _DoubleExceptionVector_handle_exception:
 
 ENDPROC(_DoubleExceptionVector)
 
+       .end literal_prefix
+
+       .text
 /*
  * Fixup handler for TLB miss in double exception handler for window owerflow.
  * We get here with windowbase set to the window that was being spilled and
@@ -581,7 +584,6 @@ ENTRY(window_overflow_restore_a0_fixup)
 
 ENDPROC(window_overflow_restore_a0_fixup)
 
-       .end literal_prefix
 /*
  * Debug interrupt vector
  *
index d16db6df86f8e3d823ac2f189816d9889249323e..126de5b30b9f64ddb5f8c64c7deeab71390d8e8f 100644 (file)
@@ -166,8 +166,6 @@ SECTIONS
     RELOCATE_ENTRY(_DebugInterruptVector_text,
                   .DebugInterruptVector.text);
 #if defined(CONFIG_SMP)
-    RELOCATE_ENTRY(_SecondaryResetVector_literal,
-                  .SecondaryResetVector.literal);
     RELOCATE_ENTRY(_SecondaryResetVector_text,
                   .SecondaryResetVector.text);
 #endif
@@ -282,17 +280,11 @@ SECTIONS
 
 #if defined(CONFIG_SMP)
 
-  SECTION_VECTOR (_SecondaryResetVector_literal,
-                 .SecondaryResetVector.literal,
-                 RESET_VECTOR1_VADDR - 4,
-                 SIZEOF(.DoubleExceptionVector.text),
-                 .DoubleExceptionVector.text)
-
   SECTION_VECTOR (_SecondaryResetVector_text,
                  .SecondaryResetVector.text,
                  RESET_VECTOR1_VADDR,
-                 4,
-                 .SecondaryResetVector.literal)
+                 SIZEOF(.DoubleExceptionVector.text),
+                 .DoubleExceptionVector.text)
 
   . = LOADADDR(.SecondaryResetVector.text)+SIZEOF(.SecondaryResetVector.text);