From 20a58ac0d8e09d0bf1a74c6b68fea22784512b51 Mon Sep 17 00:00:00 2001
From: Igor Guryanov <guryanov@synopsys.com>
Date: Wed, 24 Dec 2014 17:17:11 +0300
Subject: [PATCH] arc: introduce separate section for interrupt vector table

Even though existing implementation works fine in preparation to
submission of ARCv2 architecture we need this change.

In case of ARCv2 interrupt vector table consists of just addresses
of corresponding handlers. And if those addresses will be in .text
section then assembler will encode them as everything in .text section
as middle-endian and then on real execution CPU will read swapped
addresses and will jump into the wild.

Once introduced new section is situated so .text section remains the
first which allows us to use common linker option for linking everything
to a specified CONFIG_SYS_TEXT_BASE.

Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Signed-off-by: Igor Guryanov <guryanov@synopsys.com>
---
 arch/arc/Makefile               |  2 --
 arch/arc/cpu/arc700/Makefile    |  3 +-
 arch/arc/cpu/arc700/start.S     | 49 +++++++++++++++++----------------
 arch/arc/cpu/arc700/u-boot.lds  | 15 +++++++++-
 arch/arc/include/asm/sections.h |  2 ++
 arch/arc/lib/relocate.c         |  4 +--
 arch/arc/lib/sections.c         |  2 ++
 7 files changed, 46 insertions(+), 31 deletions(-)

diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index 03ea6dbae0d..a59231e70eb 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -2,8 +2,6 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-head-y := arch/arc/cpu/$(CPU)/start.o
-
 libs-y += arch/arc/cpu/$(CPU)/
 libs-y += arch/arc/lib/
 
diff --git a/arch/arc/cpu/arc700/Makefile b/arch/arc/cpu/arc700/Makefile
index cdc50022901..021e3a2b5d0 100644
--- a/arch/arc/cpu/arc700/Makefile
+++ b/arch/arc/cpu/arc700/Makefile
@@ -4,10 +4,9 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-extra-y	+= start.o
-
 obj-y	+= cache.o
 obj-y	+= cpu.o
 obj-y	+= interrupts.o
 obj-y	+= reset.o
+obj-y	+= start.o
 obj-y	+= timer.o
diff --git a/arch/arc/cpu/arc700/start.S b/arch/arc/cpu/arc700/start.S
index 2318282bf40..01cfba49339 100644
--- a/arch/arc/cpu/arc700/start.S
+++ b/arch/arc/cpu/arc700/start.S
@@ -88,11 +88,11 @@
 #endif
 .endm
 
+.section .ivt, "ax",@progbits
 .align 4
-.globl _start
-_start:
+_ivt:
 	/* Critical system events */
-	j	reset			/* 0 - 0x000 */
+	j	_start			/* 0 - 0x000 */
 	j	memory_error		/* 1 - 0x008 */
 	j	instruction_error	/* 2 - 0x010 */
 
@@ -110,6 +110,28 @@ _start:
 	j	EV_Trap			/* 0x128, Trap exception       (0x25) */
 	j	EV_Extension		/* 0x130, Extn Intruction Excp (0x26) */
 
+.text
+.globl _start
+_start:
+	/* Setup interrupt vector base that matches "__text_start" */
+	sr	__ivt_start, [ARC_AUX_INTR_VEC_BASE]
+
+	/* Setup stack pointer */
+	mov	%sp, CONFIG_SYS_INIT_SP_ADDR
+	mov	%fp, %sp
+
+	/* Clear bss */
+	mov	%r0, __bss_start
+	mov	%r1, __bss_end
+
+clear_bss:
+	st.ab	0, [%r0, 4]
+	brlt	%r0, %r1, clear_bss
+
+	/* Zero the one and only argument of "board_init_f" */
+	mov_s	%r0, 0
+	j	board_init_f
+
 memory_error:
 	SAVE_ALL_SYS
 	SAVE_EXCEPTION_SOURCE
@@ -164,27 +186,6 @@ EV_Extension:
 	mov	%r0, %sp
 	j	do_extension
 
-
-reset:
-	/* Setup interrupt vector base that matches "__text_start" */
-	sr	__text_start, [ARC_AUX_INTR_VEC_BASE]
-
-	/* Setup stack pointer */
-	mov	%sp, CONFIG_SYS_INIT_SP_ADDR
-	mov	%fp, %sp
-
-	/* Clear bss */
-	mov	%r0, __bss_start
-	mov	%r1, __bss_end
-
-clear_bss:
-	st.ab	0, [%r0, 4]
-	brlt	%r0, %r1, clear_bss
-
-	/* Zero the one and only argument of "board_init_f" */
-	mov_s	%r0, 0
-	j	board_init_f
-
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
  *
diff --git a/arch/arc/cpu/arc700/u-boot.lds b/arch/arc/cpu/arc700/u-boot.lds
index 2d01b21b367..ccddbf7dc9b 100644
--- a/arch/arc/cpu/arc700/u-boot.lds
+++ b/arch/arc/cpu/arc700/u-boot.lds
@@ -13,7 +13,6 @@ SECTIONS
 	.text :	{
 		*(.__text_start)
 		*(.__image_copy_start)
-		CPUDIR/start.o (.text*)
 		*(.text*)
 	}
 
@@ -23,6 +22,20 @@ SECTIONS
 		*(.__text_end)
 	}
 
+	. = ALIGN(1024);
+	.ivt_start : {
+		*(.__ivt_start)
+	}
+
+	.ivt :
+	{
+		*(.ivt)
+	}
+
+	.ivt_end : {
+		*(.__ivt_end)
+	}
+
 	. = ALIGN(4);
 	.rodata : {
 		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
diff --git a/arch/arc/include/asm/sections.h b/arch/arc/include/asm/sections.h
index 18484a17f21..2a7a98713da 100644
--- a/arch/arc/include/asm/sections.h
+++ b/arch/arc/include/asm/sections.h
@@ -10,5 +10,7 @@
 #include <asm-generic/sections.h>
 
 extern ulong __text_end;
+extern ulong __ivt_start;
+extern ulong __ivt_end;
 
 #endif /* __ASM_ARC_SECTIONS_H */
diff --git a/arch/arc/lib/relocate.c b/arch/arc/lib/relocate.c
index 2482bcdffcc..5618b6ae938 100644
--- a/arch/arc/lib/relocate.c
+++ b/arch/arc/lib/relocate.c
@@ -44,7 +44,7 @@ int do_elf_reloc_fixups(void)
 #ifdef __LITTLE_ENDIAN__
 			/* If location in ".text" section swap value */
 			if ((unsigned int)offset_ptr_rom <
-			    (unsigned int)&__text_end)
+			    (unsigned int)&__ivt_end)
 				val = (val << 16) | (val >> 16);
 #endif
 
@@ -55,7 +55,7 @@ int do_elf_reloc_fixups(void)
 #ifdef __LITTLE_ENDIAN__
 				/* If location in ".text" section swap value */
 				if ((unsigned int)offset_ptr_rom <
-				    (unsigned int)&__text_end)
+				    (unsigned int)&__ivt_end)
 					val = (val << 16) | (val >> 16);
 #endif
 				memcpy(offset_ptr_ram, &val, sizeof(int));
diff --git a/arch/arc/lib/sections.c b/arch/arc/lib/sections.c
index b0b46a4e9ae..a72c6946d53 100644
--- a/arch/arc/lib/sections.c
+++ b/arch/arc/lib/sections.c
@@ -19,3 +19,5 @@ char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
 char __text_start[0] __attribute__((section(".__text_start")));
 char __text_end[0] __attribute__((section(".__text_end")));
 char __init_end[0] __attribute__((section(".__init_end")));
+char __ivt_start[0] __attribute__((section(".__ivt_start")));
+char __ivt_end[0] __attribute__((section(".__ivt_end")));
-- 
GitLab