]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - arch/arm/kernel/vmlinux.lds.S
Merge commit 'main-jb-2012.08.03-B4' into t114-0806
[linux-2.6.git] / arch / arm / kernel / vmlinux.lds.S
index faf32de5c5ad4dffb63d8d43cda1f66a74f70805..432e112ddf6aa57074b305f708bdc042c5b4f8af 100644 (file)
@@ -1,12 +1,61 @@
+/*
+ * arch/arm/kernel/vmlinux.lds.S
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
 /* ld script to make ARM Linux kernel
  * taken from the i386 version by Russell King
  * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
 #include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
+#include <asm/page.h>
        
+#define PROC_INFO                                                      \
+       . = ALIGN(4);                                                   \
+       VMLINUX_SYMBOL(__proc_info_begin) = .;                          \
+       *(.proc.info.init)                                              \
+       VMLINUX_SYMBOL(__proc_info_end) = .;
+
+#define IDMAP_TEXT                                                     \
+       ALIGN_FUNCTION();                                               \
+       VMLINUX_SYMBOL(__idmap_text_start) = .;                         \
+       *(.idmap.text)                                                  \
+       VMLINUX_SYMBOL(__idmap_text_end) = .;
+
+#ifdef CONFIG_HOTPLUG_CPU
+#define ARM_CPU_DISCARD(x)
+#define ARM_CPU_KEEP(x)                x
+#else
+#define ARM_CPU_DISCARD(x)     x
+#define ARM_CPU_KEEP(x)
+#endif
+
+#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \
+       defined(CONFIG_GENERIC_BUG)
+#define ARM_EXIT_KEEP(x)       x
+#define ARM_EXIT_DISCARD(x)
+#else
+#define ARM_EXIT_KEEP(x)
+#define ARM_EXIT_DISCARD(x)    x
+#endif
+
 OUTPUT_ARCH(arm)
 ENTRY(stext)
 
@@ -18,133 +67,178 @@ jiffies = jiffies_64 + 4;
 
 SECTIONS
 {
-#ifdef CONFIG_XIP_KERNEL
-       . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
-#else
-       . = PAGE_OFFSET + TEXT_OFFSET;
-#endif
-       .init : {                       /* Init code and data           */
-               _stext = .;
-                       _sinittext = .;
-                       *(.init.text)
-                       _einittext = .;
-               __proc_info_begin = .;
-                       *(.proc.info.init)
-               __proc_info_end = .;
-               __arch_info_begin = .;
-                       *(.arch.info.init)
-               __arch_info_end = .;
-               __tagtable_begin = .;
-                       *(.taglist.init)
-               __tagtable_end = .;
-               . = ALIGN(16);
-               __setup_start = .;
-                       *(.init.setup)
-               __setup_end = .;
-               __early_begin = .;
-                       *(.early_param.init)
-               __early_end = .;
-               __initcall_start = .;
-                       INITCALLS
-               __initcall_end = .;
-               __con_initcall_start = .;
-                       *(.con_initcall.init)
-               __con_initcall_end = .;
-               __security_initcall_start = .;
-                       *(.security_initcall.init)
-               __security_initcall_end = .;
-#ifdef CONFIG_BLK_DEV_INITRD
-               . = ALIGN(32);
-               __initramfs_start = .;
-                       usr/built-in.o(.init.ramfs)
-               __initramfs_end = .;
-#endif
-               . = ALIGN(4096);
-               __per_cpu_start = .;
-                       *(.data.percpu)
-               __per_cpu_end = .;
-#ifndef CONFIG_XIP_KERNEL
-               __init_begin = _stext;
-               *(.init.data)
-               . = ALIGN(4096);
-               __init_end = .;
+       /*
+        * XXX: The linker does not define how output sections are
+        * assigned to input sections when there are multiple statements
+        * matching the same input section name.  There is no documented
+        * order of matching.
+        *
+        * unwind exit sections must be discarded before the rest of the
+        * unwind sections get included.
+        */
+       /DISCARD/ : {
+               *(.ARM.exidx.exit.text)
+               *(.ARM.extab.exit.text)
+               ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
+               ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
+               ARM_EXIT_DISCARD(EXIT_TEXT)
+               ARM_EXIT_DISCARD(EXIT_DATA)
+               EXIT_CALL
+#ifndef CONFIG_HOTPLUG
+               *(.ARM.exidx.devexit.text)
+               *(.ARM.extab.devexit.text)
 #endif
-       }
-
-       /DISCARD/ : {                   /* Exit code and data           */
-               *(.exit.text)
-               *(.exit.data)
-               *(.exitcall.exit)
 #ifndef CONFIG_MMU
                *(.fixup)
                *(__ex_table)
 #endif
+#ifndef CONFIG_SMP_ON_UP
+               *(.alt.smp.init)
+#endif
+               *(.discard)
+               *(.discard.*)
        }
 
+#ifdef CONFIG_XIP_KERNEL
+       . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
+#else
+       . = PAGE_OFFSET + TEXT_OFFSET;
+#endif
+       .head.text : {
+               _text = .;
+               HEAD_TEXT
+       }
        .text : {                       /* Real text segment            */
-               _text = .;              /* Text and read-only data      */
+               _stext = .;             /* Text and read-only data      */
                        __exception_text_start = .;
                        *(.exception.text)
                        __exception_text_end = .;
-                       *(.text)
+                       IRQENTRY_TEXT
+                       TEXT_TEXT
                        SCHED_TEXT
                        LOCK_TEXT
+                       KPROBES_TEXT
+                       IDMAP_TEXT
 #ifdef CONFIG_MMU
                        *(.fixup)
 #endif
                        *(.gnu.warning)
-                       *(.rodata)
-                       *(.rodata.*)
                        *(.glue_7)
                        *(.glue_7t)
+               . = ALIGN(4);
                *(.got)                 /* Global offset table          */
+                       ARM_CPU_KEEP(PROC_INFO)
        }
 
-       RODATA
+       RO_DATA(PAGE_SIZE)
+
+#ifdef CONFIG_ARM_UNWIND
+       /*
+        * Stack unwinding tables
+        */
+       . = ALIGN(8);
+       .ARM.unwind_idx : {
+               __start_unwind_idx = .;
+               *(.ARM.exidx*)
+               __stop_unwind_idx = .;
+       }
+       .ARM.unwind_tab : {
+               __start_unwind_tab = .;
+               *(.ARM.extab*)
+               __stop_unwind_tab = .;
+       }
+#endif
 
        _etext = .;                     /* End of text and rodata section */
 
+#ifndef CONFIG_XIP_KERNEL
+       . = ALIGN(PAGE_SIZE);
+       __init_begin = .;
+#endif
+
+       INIT_TEXT_SECTION(8)
+       .exit.text : {
+               ARM_EXIT_KEEP(EXIT_TEXT)
+       }
+       .init.proc.info : {
+               ARM_CPU_DISCARD(PROC_INFO)
+       }
+       .init.arch.info : {
+               __arch_info_begin = .;
+               *(.arch.info.init)
+               __arch_info_end = .;
+       }
+       .init.tagtable : {
+               __tagtable_begin = .;
+               *(.taglist.init)
+               __tagtable_end = .;
+       }
+#ifdef CONFIG_SMP_ON_UP
+       .init.smpalt : {
+               __smpalt_begin = .;
+               *(.alt.smp.init)
+               __smpalt_end = .;
+       }
+#endif
+       .init.pv_table : {
+               __pv_table_begin = .;
+               *(.pv_table)
+               __pv_table_end = .;
+       }
+       .init.data : {
+#ifndef CONFIG_XIP_KERNEL
+               INIT_DATA
+#endif
+               INIT_SETUP(16)
+               INIT_CALLS
+               CON_INITCALL
+               SECURITY_INITCALL
+               INIT_RAM_FS
+       }
+#ifndef CONFIG_XIP_KERNEL
+       .exit.data : {
+               ARM_EXIT_KEEP(EXIT_DATA)
+       }
+#endif
+
+       PERCPU_SECTION(L1_CACHE_BYTES)
+
 #ifdef CONFIG_XIP_KERNEL
        __data_loc = ALIGN(4);          /* location in binary */
        . = PAGE_OFFSET + TEXT_OFFSET;
 #else
+       __init_end = .;
        . = ALIGN(THREAD_SIZE);
        __data_loc = .;
 #endif
 
        .data : AT(__data_loc) {
-               __data_start = .;       /* address in memory */
+               _data = .;              /* address in memory */
+               _sdata = .;
 
                /*
                 * first, the init task union, aligned
                 * to an 8192 byte boundary.
                 */
-               *(.data.init_task)
+               INIT_TASK_DATA(THREAD_SIZE)
 
 #ifdef CONFIG_XIP_KERNEL
-               . = ALIGN(4096);
+               . = ALIGN(PAGE_SIZE);
                __init_begin = .;
-               *(.init.data)
-               . = ALIGN(4096);
+               INIT_DATA
+               ARM_EXIT_KEEP(EXIT_DATA)
+               . = ALIGN(PAGE_SIZE);
                __init_end = .;
 #endif
 
-               . = ALIGN(4096);
-               __nosave_begin = .;
-               *(.data.nosave)
-               . = ALIGN(4096);
-               __nosave_end = .;
-
-               /*
-                * then the cacheline aligned data
-                */
-               . = ALIGN(32);
-               *(.data.cacheline_aligned)
+               NOSAVE_DATA
+               CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
+               READ_MOSTLY_DATA(L1_CACHE_BYTES)
 
                /*
                 * The exception fixup table (might need resorting at runtime)
                 */
-               . = ALIGN(32);
+               . = ALIGN(4);
                __start___ex_table = .;
 #ifdef CONFIG_MMU
                *(__ex_table)
@@ -154,26 +248,76 @@ SECTIONS
                /*
                 * and the usual data section
                 */
-               *(.data)
+               DATA_DATA
                CONSTRUCTORS
 
                _edata = .;
        }
        _edata_loc = __data_loc + SIZEOF(.data);
 
-       .bss : {
-               __bss_start = .;        /* BSS                          */
-               *(.bss)
-               *(COMMON)
-               _end = .;
-       }
-                                       /* Stabs debugging sections.    */
-       .stab 0 : { *(.stab) }
-       .stabstr 0 : { *(.stabstr) }
-       .stab.excl 0 : { *(.stab.excl) }
-       .stab.exclstr 0 : { *(.stab.exclstr) }
-       .stab.index 0 : { *(.stab.index) }
-       .stab.indexstr 0 : { *(.stab.indexstr) }
+#ifdef CONFIG_HAVE_TCM
+        /*
+        * We align everything to a page boundary so we can
+        * free it after init has commenced and TCM contents have
+        * been copied to its destination.
+        */
+       .tcm_start : {
+               . = ALIGN(PAGE_SIZE);
+               __tcm_start = .;
+               __itcm_start = .;
+       }
+
+       /*
+        * Link these to the ITCM RAM
+        * Put VMA to the TCM address and LMA to the common RAM
+        * and we'll upload the contents from RAM to TCM and free
+        * the used RAM after that.
+        */
+       .text_itcm ITCM_OFFSET : AT(__itcm_start)
+       {
+               __sitcm_text = .;
+               *(.tcm.text)
+               *(.tcm.rodata)
+               . = ALIGN(4);
+               __eitcm_text = .;
+       }
+
+       /*
+        * Reset the dot pointer, this is needed to create the
+        * relative __dtcm_start below (to be used as extern in code).
+        */
+       . = ADDR(.tcm_start) + SIZEOF(.tcm_start) + SIZEOF(.text_itcm);
+
+       .dtcm_start : {
+               __dtcm_start = .;
+       }
+
+       /* TODO: add remainder of ITCM as well, that can be used for data! */
+       .data_dtcm DTCM_OFFSET : AT(__dtcm_start)
+       {
+               . = ALIGN(4);
+               __sdtcm_data = .;
+               *(.tcm.data)
+               . = ALIGN(4);
+               __edtcm_data = .;
+       }
+
+       /* Reset the dot pointer or the linker gets confused */
+       . = ADDR(.dtcm_start) + SIZEOF(.data_dtcm);
+
+       /* End marker for freeing TCM copy in linked object */
+       .tcm_end : AT(ADDR(.dtcm_start) + SIZEOF(.data_dtcm)){
+               . = ALIGN(PAGE_SIZE);
+               __tcm_end = .;
+       }
+#endif
+
+       NOTES
+
+       BSS_SECTION(0, 0, 0)
+       _end = .;
+
+       STABS_DEBUG
        .comment 0 : { *(.comment) }
 }