xtensa: allow merging vectors into .text section
authorMax Filippov <jcmvbkbc@gmail.com>
Wed, 4 Jan 2017 18:40:49 +0000 (10:40 -0800)
committerMax Filippov <jcmvbkbc@gmail.com>
Wed, 1 Mar 2017 20:32:50 +0000 (12:32 -0800)
Currently code for exception/IRQ vectors is stored in kernel image as
initialization data and is copied to its working addresses during
startup. It doesn't always make sense. In many cases vectors location
can be automatically decided at kernel link time and code can be placed
right there. This is especially useful for XIP kernel.

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

index 77d41cc7a688ac0b2a4c8239231a7edd75c3ff34..65d3da9db19bebaff6120ca3544ad7c198e1af80 100644 (file)
@@ -67,7 +67,11 @@ static inline unsigned long xtensa_get_kio_paddr(void)
 #endif /* CONFIG_MMU */
 
 #define RESET_VECTOR1_VADDR            (XCHAL_RESET_VECTOR1_VADDR)
+#ifdef CONFIG_VECTORS_OFFSET
 #define VECBASE_VADDR                  (KERNELOFFSET - CONFIG_VECTORS_OFFSET)
+#else
+#define VECBASE_VADDR                  _vecbase
+#endif
 
 #if defined(XCHAL_HAVE_VECBASE) && XCHAL_HAVE_VECBASE
 
index 23f2e034ba46cb03cff51e734d96def6b5548fb5..7fc7bb9f3b8482c7a5af78d6b26df73ebbd4cba0 100644 (file)
@@ -455,6 +455,7 @@ void __init setup_arch(char **cmdline_p)
 
        mem_reserve(__pa(&_stext), __pa(&_end));
 
+#ifdef CONFIG_VECTORS_OFFSET
        mem_reserve(__pa(&_WindowVectors_text_start),
                    __pa(&_WindowVectors_text_end));
 
@@ -491,6 +492,8 @@ void __init setup_arch(char **cmdline_p)
                    __pa(&_Level6InterruptVector_text_end));
 #endif
 
+#endif /* CONFIG_VECTORS_OFFSET */
+
 #ifdef CONFIG_SMP
        mem_reserve(__pa(&_SecondaryResetVector_text_start),
                    __pa(&_SecondaryResetVector_text_end));
index 31411fc82662c82ec127188ccdb5fc3ac818e4e9..30d9fc21e0763c4115f7f5c74b78aba46ead1109 100644 (file)
@@ -59,6 +59,7 @@ jiffies = jiffies_64;
  * garbage.)
  */
 
+#ifdef CONFIG_VECTORS_OFFSET
 #define SECTION_VECTOR(sym, section, addr, max_prevsec_size, prevsec)       \
   section addr : AT((MIN(LOADADDR(prevsec) + max_prevsec_size,             \
                         LOADADDR(prevsec) + SIZEOF(prevsec)) + 3) & ~ 3)   \
@@ -68,6 +69,11 @@ jiffies = jiffies_64;
     *(section)                                                             \
     sym ## _end = ABSOLUTE(.);                                             \
   }
+#else
+#define SECTION_VECTOR(section, addr)                                      \
+  . = addr;                                                                \
+  *(section)
+#endif
 
 /*
  *  Mapping of input sections to output sections when linking.
@@ -85,6 +91,37 @@ SECTIONS
   {
     /* The HEAD_TEXT section must be the first section! */
     HEAD_TEXT
+
+#ifndef CONFIG_VECTORS_OFFSET
+  . = ALIGN(PAGE_SIZE);
+  _vecbase = .;
+
+  SECTION_VECTOR (.WindowVectors.text, WINDOW_VECTORS_VADDR)
+#if XCHAL_EXCM_LEVEL >= 2
+  SECTION_VECTOR (.Level2InterruptVector.text, INTLEVEL2_VECTOR_VADDR)
+#endif
+#if XCHAL_EXCM_LEVEL >= 3
+  SECTION_VECTOR (.Level3InterruptVector.text, INTLEVEL3_VECTOR_VADDR)
+#endif
+#if XCHAL_EXCM_LEVEL >= 4
+  SECTION_VECTOR (.Level4InterruptVector.text, INTLEVEL4_VECTOR_VADDR)
+#endif
+#if XCHAL_EXCM_LEVEL >= 5
+  SECTION_VECTOR (.Level5InterruptVector.text, INTLEVEL5_VECTOR_VADDR)
+#endif
+#if XCHAL_EXCM_LEVEL >= 6
+  SECTION_VECTOR (.Level6InterruptVector.text, INTLEVEL6_VECTOR_VADDR)
+#endif
+  SECTION_VECTOR (.DebugInterruptVector.literal, DEBUG_VECTOR_VADDR - 4)
+  SECTION_VECTOR (.DebugInterruptVector.text, DEBUG_VECTOR_VADDR)
+  SECTION_VECTOR (.KernelExceptionVector.literal, KERNEL_VECTOR_VADDR - 4)
+  SECTION_VECTOR (.KernelExceptionVector.text, KERNEL_VECTOR_VADDR)
+  SECTION_VECTOR (.UserExceptionVector.literal, USER_VECTOR_VADDR - 4)
+  SECTION_VECTOR (.UserExceptionVector.text, USER_VECTOR_VADDR)
+  SECTION_VECTOR (.DoubleExceptionVector.literal, DOUBLEEXC_VECTOR_VADDR - 48)
+  SECTION_VECTOR (.DoubleExceptionVector.text, DOUBLEEXC_VECTOR_VADDR)
+#endif
+
     TEXT_TEXT
     VMLINUX_SYMBOL(__sched_text_start) = .;
     *(.sched.literal .sched.text)
@@ -132,6 +169,7 @@ SECTIONS
     . = ALIGN(16);
     __boot_reloc_table_start = ABSOLUTE(.);
 
+#ifdef CONFIG_VECTORS_OFFSET
     RELOCATE_ENTRY(_WindowVectors_text,
                   .WindowVectors.text);
 #if XCHAL_EXCM_LEVEL >= 2
@@ -164,6 +202,7 @@ SECTIONS
                   .DoubleExceptionVector.text);
     RELOCATE_ENTRY(_DebugInterruptVector_text,
                   .DebugInterruptVector.text);
+#endif
 #if defined(CONFIG_SMP)
     RELOCATE_ENTRY(_SecondaryResetVector_text,
                   .SecondaryResetVector.text);
@@ -186,6 +225,7 @@ SECTIONS
   . = ALIGN(4);
   .dummy : { LONG(0) }
 
+#ifdef CONFIG_VECTORS_OFFSET
   /* The vectors are relocated to the real position at startup time */
 
   SECTION_VECTOR (_WindowVectors_text,
@@ -277,6 +317,7 @@ SECTIONS
 
   . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
 
+#endif
 #if defined(CONFIG_SMP)
 
   SECTION_VECTOR (_SecondaryResetVector_text,