summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2017-01-04 10:40:49 -0800
committerMax Filippov <jcmvbkbc@gmail.com>2017-03-01 12:32:50 -0800
commitb46dcfa378b0cdea1ee832802c9e36750e0fffa9 (patch)
tree38f96eb95db4e95c8240c80c352a29ba49c7e846
parent9a736fcb096b43b68af8329eb12abc8256dceaba (diff)
xtensa: allow merging vectors into .text section
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>
-rw-r--r--arch/xtensa/include/asm/vectors.h4
-rw-r--r--arch/xtensa/kernel/setup.c3
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S41
3 files changed, 48 insertions, 0 deletions
diff --git a/arch/xtensa/include/asm/vectors.h b/arch/xtensa/include/asm/vectors.h
index 77d41cc7a688..65d3da9db19b 100644
--- a/arch/xtensa/include/asm/vectors.h
+++ b/arch/xtensa/include/asm/vectors.h
@@ -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
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 23f2e034ba46..7fc7bb9f3b84 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -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));
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index 31411fc82662..30d9fc21e076 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -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,