Blackfin: fix relocation errors with large initramfs images
[safe/jmp/linux-2.6] / arch / blackfin / kernel / vmlinux.lds.S
index 1ef1e36..be4b1bb 100644 (file)
@@ -1,36 +1,13 @@
 /*
- * File:         arch/blackfin/kernel/vmlinux.lds.S
- * Based on:     none - original work
- * Author:
+ * Copyright 2004-2009 Analog Devices Inc.
  *
- * Created:      Tue Sep 21 2004
- * Description:  Master linker script for blackfin architecture
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that 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 the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later
  */
 
-#define VMLINUX_SYMBOL(_sym_) _##_sym_
-
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/mem_map.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
 
 OUTPUT_FORMAT("elf32-bfin")
 ENTRY(__start)
@@ -39,105 +16,150 @@ _jiffies = _jiffies_64;
 SECTIONS
 {
        . = CONFIG_BOOT_LOAD;
+       /* Neither the text, ro_data or bss section need to be aligned
+        * So pack them back to back
+        */
        .text :
        {
                __text = .;
                _text = .;
                __stext = .;
                TEXT_TEXT
+#ifndef CONFIG_SCHEDULE_L1
                SCHED_TEXT
+#endif
                LOCK_TEXT
-               *(.text.lock)
+               IRQENTRY_TEXT
+               KPROBES_TEXT
+               *(.text.*)
                *(.fixup)
 
+#if !L1_CODE_LENGTH
+               *(.l1.text)
+#endif
+
                . = ALIGN(16);
                ___start___ex_table = .;
                *(__ex_table)
                ___stop___ex_table = .;
 
-               . = ALIGN(4);
                __etext = .;
        }
 
-       RODATA
+       NOTES
+
+       /* Just in case the first read only is a 32-bit access */
+       RO_DATA(4)
+
+       .bss :
+       {
+               . = ALIGN(4);
+               ___bss_start = .;
+               *(.bss .bss.*)
+               *(COMMON)
+#if !L1_DATA_A_LENGTH
+               *(.l1.bss)
+#endif
+#if !L1_DATA_B_LENGTH
+               *(.l1.bss.B)
+#endif
+               . = ALIGN(4);
+               ___bss_stop = .;
+       }
 
        .data :
        {
                __sdata = .;
-               . = ALIGN(0x2000);
-               *(.data.init_task)
+               /* This gets done first, so the glob doesn't suck it in */
+               CACHELINE_ALIGNED_DATA(32)
+
+#if !L1_DATA_A_LENGTH
+               . = ALIGN(32);
+               *(.data_l1.cacheline_aligned)
+               *(.l1.data)
+#endif
+#if !L1_DATA_B_LENGTH
+               *(.l1.data.B)
+#endif
+#if !L2_LENGTH
+               . = ALIGN(32);
+               *(.data_l2.cacheline_aligned)
+               *(.l2.data)
+#endif
+
                DATA_DATA
                CONSTRUCTORS
 
-               . = ALIGN(32);
-               *(.data.cacheline_aligned)
+               INIT_TASK_DATA(THREAD_SIZE)
 
-               . = ALIGN(0x2000);
                __edata = .;
        }
 
+       /* The init section should be last, so when we free it, it goes into
+        * the general memory pool, and (hopefully) will decrease fragmentation
+        * a tiny bit. The init section has a _requirement_ that it be
+        * PAGE_SIZE aligned
+        */
+       . = ALIGN(PAGE_SIZE);
        ___init_begin = .;
-       .init :
+
+       INIT_TEXT_SECTION(PAGE_SIZE)
+
+       /* We have to discard exit text and such at runtime, not link time, to
+        * handle embedded cross-section references (alt instructions, bug
+        * table, eh_frame, etc...).  We need all of our .text up front and
+        * .data after it for PCREL call issues.
+        */
+       .exit.text :
        {
-               . = ALIGN(4096);
-               __sinittext = .;
-               *(.init.text)
-               __einittext = .;
-               *(.init.data)
-               . = ALIGN(16);
-               ___setup_start = .;
-               *(.init.setup)
-               ___setup_end = .;
-               ___start___param = .;
-               *(__param)
-               ___stop___param = .;
-               ___initcall_start = .;
-               INITCALLS
-               ___initcall_end = .;
-               ___con_initcall_start = .;
-               *(.con_initcall.init)
-               ___con_initcall_end = .;
-               ___security_initcall_start = .;
-               *(.security_initcall.init)
-               ___security_initcall_end = .;
-               . = ALIGN(4);
-               ___initramfs_start = .;
-               *(.init.ramfs)
-               ___initramfs_end = .;
-               . = ALIGN(4);
+               EXIT_TEXT
        }
 
-       __l1_lma_start = .;
+       . = ALIGN(16);
+       INIT_DATA_SECTION(16)
+       PERCPU(4)
+
+       .exit.data :
+       {
+               EXIT_DATA
+       }
 
-       .text_l1 L1_CODE_START : AT(LOADADDR(.init) + SIZEOF(.init))
+       .text_l1 L1_CODE_START : AT(LOADADDR(.exit.data) + SIZEOF(.exit.data))
        {
                . = ALIGN(4);
                __stext_l1 = .;
                *(.l1.text)
-
+#ifdef CONFIG_SCHEDULE_L1
+               SCHED_TEXT
+#endif
                . = ALIGN(4);
                __etext_l1 = .;
        }
+       __text_l1_lma = LOADADDR(.text_l1);
+       __text_l1_len = SIZEOF(.text_l1);
+       ASSERT (__text_l1_len <= L1_CODE_LENGTH, "L1 text overflow!")
 
-       .data_l1 L1_DATA_A_START : AT(LOADADDR(.text_l1) + SIZEOF(.text_l1))
+       .data_l1 L1_DATA_A_START : AT(__text_l1_lma + __text_l1_len)
        {
                . = ALIGN(4);
                __sdata_l1 = .;
                *(.l1.data)
                __edata_l1 = .;
 
-               . = ALIGN(4);
-               __sbss_l1 = .;
-               *(.l1.bss)
-
                . = ALIGN(32);
                *(.data_l1.cacheline_aligned)
 
                . = ALIGN(4);
+               __sbss_l1 = .;
+               *(.l1.bss)
+               . = ALIGN(4);
                __ebss_l1 = .;
        }
+       __data_l1_lma = LOADADDR(.data_l1);
+       __data_l1_len = SIZEOF(.data_l1);
+       ASSERT (__data_l1_len <= L1_DATA_A_LENGTH, "L1 data A overflow!")
 
-       .data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
+       .data_b_l1 L1_DATA_B_START : AT(__data_l1_lma + __data_l1_len)
        {
                . = ALIGN(4);
                __sdata_b_l1 = .;
@@ -147,28 +169,51 @@ SECTIONS
                . = ALIGN(4);
                __sbss_b_l1 = .;
                *(.l1.bss.B)
-
                . = ALIGN(4);
                __ebss_b_l1 = .;
        }
+       __data_b_l1_lma = LOADADDR(.data_b_l1);
+       __data_b_l1_len = SIZEOF(.data_b_l1);
+       ASSERT (__data_b_l1_len <= L1_DATA_B_LENGTH, "L1 data B overflow!")
 
-       ___init_end = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
-
-       .bss LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1) :
+       .text_data_l2 L2_START : AT(__data_b_l1_lma + __data_b_l1_len)
        {
                . = ALIGN(4);
-               ___bss_start = .;
-               *(.bss)
-               *(COMMON)
+               __stext_l2 = .;
+               *(.l2.text)
                . = ALIGN(4);
-               ___bss_stop = .;
-               __end = .;
-       }
+               __etext_l2 = .;
 
-       /DISCARD/ :
-       {
-               *(.exit.text)
-               *(.exit.data)
-               *(.exitcall.exit)
+               . = ALIGN(4);
+               __sdata_l2 = .;
+               *(.l2.data)
+               __edata_l2 = .;
+
+               . = ALIGN(32);
+               *(.data_l2.cacheline_aligned)
+
+               . = ALIGN(4);
+               __sbss_l2 = .;
+               *(.l2.bss)
+               . = ALIGN(4);
+               __ebss_l2 = .;
        }
+       __l2_lma = LOADADDR(.text_data_l2);
+       __l2_len = SIZEOF(.text_data_l2);
+       ASSERT (__l2_len <= L2_LENGTH, "L2 overflow!")
+
+       /* Force trailing alignment of our init section so that when we
+        * free our init memory, we don't leave behind a partial page.
+        */
+       . = __l2_lma + __l2_len;
+       . = ALIGN(PAGE_SIZE);
+       ___init_end = .;
+
+       __end =.;
+
+       STABS_DEBUG
+
+       DWARF_DEBUG
+
+       DISCARDS
 }