]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - arch/mips/cpu/mips64/start.S
MIPS: add support for pre-relocation malloc
[karo-tx-uboot.git] / arch / mips / cpu / mips64 / start.S
index 2b8d531e73b84ef9d2e0280165ed1668dad9d318..471bc1eb663b52a335732732d396e75c6e1ddfc0 100644 (file)
@@ -3,23 +3,7 @@
  *
  *  Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * 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 dlater 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 PARTICUdlaR 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, write to the Free Software
- * Foundation, Inc., 59 Temple Pdlace, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <asm-offsets.h>
 #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
 #endif
 
+#ifndef CONFIG_SYS_INIT_SP_ADDR
+#define CONFIG_SYS_INIT_SP_ADDR        (CONFIG_SYS_SDRAM_BASE + \
+                               CONFIG_SYS_INIT_SP_OFFSET)
+#endif
+
+#ifdef CONFIG_SYS_LITTLE_ENDIAN
+#define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
+       (((r_type) << 24) | ((r_type2) << 16) | ((r_type3) << 8) | (ssym))
+#else
+#define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
+       ((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24)
+#endif
+
        /*
         * For the moment disable interrupts, mark the kernel mode and
         * set ST0_KX so that the CPU does not spit fire when using
        .globl _start
        .text
 _start:
-       .org 0x000
+       /* U-boot entry point */
        b       reset
         nop
-       .org 0x080
-       b       romReserved
-        nop
-       .org 0x100
-       b       romReserved
-        nop
-       .org 0x180
-       b       romReserved
-        nop
+
        .org 0x200
-       b       romReserved
+       /* TLB refill, 32 bit task */
+1:     b       1b
         nop
+
        .org 0x280
-       b       romReserved
+       /* XTLB refill, 64 bit task */
+1:     b       1b
         nop
+
        .org 0x300
-       b       romReserved
+       /* Cache error exception */
+1:     b       1b
         nop
+
        .org 0x380
-       b       romReserved
+       /* General exception */
+1:     b       1b
         nop
+
+       .org 0x400
+       /* Catch interrupt exceptions */
+1:     b       1b
+        nop
+
        .org 0x480
-       b       romReserved
+       /* EJTAG debug exception */
+1:     b       1b
         nop
 
-       /*
-        * We hope there are no more reserved vectors!
-        * 128 * 8 == 1024 == 0x400
-        * so this is address R_VEC+0x400 == 0xbfc00400
-        */
-       .org 0x500
        .align 4
 reset:
 
@@ -137,12 +134,34 @@ reset:
 #endif
 
        /* Set up temporary stack */
-       dli     t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
-       dla     sp, 0(t0)
+       dli     t0, -16
+       dli     t1, CONFIG_SYS_INIT_SP_ADDR
+       and     sp, t1, t0              # force 16 byte alignment
+       dsub    sp, sp, GD_SIZE         # reserve space for gd
+       and     sp, sp, t0              # force 16 byte alignment
+       move    k0, sp                  # save gd pointer
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+       dli     t2, CONFIG_SYS_MALLOC_F_LEN
+       dsub    sp, sp, t2              # reserve space for early malloc
+       and     sp, sp, t0              # force 16 byte alignment
+#endif
+       move    fp, sp
+
+       /* Clear gd */
+       move    t0, k0
+1:
+       sw      zero, 0(t0)
+       blt     t0, t1, 1b
+        daddi  t0, 4
+
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+       daddu   t0, k0, GD_MALLOC_BASE  # gd->malloc_base offset
+       sw      sp, 0(t0)
+#endif
 
        dla     t9, board_init_f
        jr      t9
-        nop
+        move   ra, zero
 
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
@@ -158,59 +177,47 @@ reset:
        .ent    relocate_code
 relocate_code:
        move    sp, a0                  # set new stack pointer
+       move    fp, sp
+
+       move    s0, a1                  # save gd in s0
+       move    s2, a2                  # save destination address in s2
 
        dli     t0, CONFIG_SYS_MONITOR_BASE
+       dsub    s1, s2, t0              # s1 <-- relocation offset
+
        dla     t3, in_ram
-       ld      t2, -24(t3)             # t2 <-- uboot_end_data
+       ld      t2, -24(t3)             # t2 <-- __image_copy_end
        move    t1, a2
-       move    s2, a2                  # s2 <-- destination address
 
-       /*
-        * Fix $gp:
-        *
-        * New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination Address
-        */
-       move    t8, gp
-       dsub    gp, CONFIG_SYS_MONITOR_BASE
-       dadd    gp, a2                  # gp now adjusted
-       dsub    s1, gp, t8              # s1 <-- relocation offset
+       dadd    gp, s1                  # adjust gp
 
        /*
         * t0 = source address
         * t1 = target address
         * t2 = source end address
         */
-
-       /*
-        * Save destination address and size for dlater usage in flush_cache()
-        */
-       move    s0, a1                  # save gd in s0
-       move    a0, t1                  # a0 <-- destination addr
-       dsub    a1, t2, t0              # a1 <-- size
-
 1:
        lw      t3, 0(t0)
        sw      t3, 0(t1)
        daddu   t0, 4
-       ble     t0, t2, 1b
+       blt     t0, t2, 1b
         daddu  t1, 4
 
        /* If caches were enabled, we would have to flush them here. */
-
-       /* a0 & a1 are already set up for flush_cache(start, size) */
+       dsub    a1, t1, s2              # a1 <-- size
        dla     t9, flush_cache
        jalr    t9
-        nop
+        move   a0, s2                  # a0 <-- destination address
 
        /* Jump to where we've relocated ourselves */
        daddi   t0, s2, in_ram - _start
        jr      t0
         nop
 
-       .dword  _gp
+       .dword  __rel_dyn_end
+       .dword  __rel_dyn_start
+       .dword  __image_copy_end
        .dword  _GLOBAL_OFFSET_TABLE_
-       .dword  uboot_end_data
-       .dword  uboot_end
        .dword  num_got_entries
 
 in_ram:
@@ -221,10 +228,8 @@ in_ram:
         * generated by GNU ld. Skip these reserved entries from relocation.
         */
        ld      t3, -8(t0)              # t3 <-- num_got_entries
-       ld      t8, -32(t0)             # t8 <-- _GLOBAL_OFFSET_TABLE_
-       ld      t9, -40(t0)             # t9 <-- _gp
-       dsub    t8, t9                  # compute offset
-       dadd    t8, t8, gp              # t8 now holds relocated _G_O_T_
+       ld      t8, -16(t0)             # t8 <-- _GLOBAL_OFFSET_TABLE_
+       dadd    t8, s1                  # t8 now holds relocated _G_O_T_
        daddi   t8, t8, 16              # skipping first two entries
        dli     t2, 2
 1:
@@ -237,25 +242,50 @@ in_ram:
        blt     t2, t3, 1b
         daddi  t8, 8
 
-       /* Clear BSS */
-       ld      t1, -24(t0)             # t1 <-- uboot_end_data
-       ld      t2, -16(t0)             # t2 <-- uboot_end
-       dadd    t1, s1                  # adjust pointers
-       dadd    t2, s1
+       /* Update dynamic relocations */
+       ld      t1, -32(t0)             # t1 <-- __rel_dyn_start
+       ld      t2, -40(t0)             # t2 <-- __rel_dyn_end
+
+       b       2f                      # skip first reserved entry
+        daddi  t1, 16
 
-       dsub    t1, 8
 1:
-       daddi   t1, 8
-       bltl    t1, t2, 1b
-        sd     zero, 0(t1)
+       lw      t8, -4(t1)              # t8 <-- relocation info
+
+       dli     t3, MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03)
+       bne     t8, t3, 2f              # skip non R_MIPS_REL32 entries
+        nop
+
+       ld      t3, -16(t1)             # t3 <-- location to fix up in FLASH
+
+       ld      t8, 0(t3)               # t8 <-- original pointer
+       dadd    t8, s1                  # t8 <-- adjusted pointer
+
+       dadd    t3, s1                  # t3 <-- location to fix up in RAM
+       sd      t8, 0(t3)
+
+2:
+       blt     t1, t2, 1b
+        daddi  t1, 16                  # each rel.dyn entry is 16 bytes
+
+       /*
+        * Clear BSS
+        *
+        * GOT is now relocated. Thus __bss_start and __bss_end can be
+        * accessed directly via $gp.
+        */
+       dla     t1, __bss_start         # t1 <-- __bss_start
+       dla     t2, __bss_end           # t2 <-- __bss_end
+
+1:
+       sd      zero, 0(t1)
+       blt     t1, t2, 1b
+        daddi  t1, 8
 
        move    a0, s0                  # a0 <-- gd
+       move    a1, s2
        dla     t9, board_init_r
        jr      t9
-        move   a1, s2
+        move   ra, zero
 
        .end    relocate_code
-
-       /* Exception handlers */
-romReserved:
-       b       romReserved