@@ -13,6 +13,7 @@
* Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
*/
+
#include <linux/init.h>
#include <linux/threads.h>
@@ -26,6 +27,152 @@
#include <kernel-entry-init.h>
+ .macro do_relocate_kernel
+ .set push
+#ifdef CONFIG_RELOCATABLE
+#define R_MIPS_32 2
+#define R_MIPS_26 4
+#define R_MIPS_HI16 5
+#define R_MIPS_64 18
+ /* Save args */
+ move s0, a0
+ move s1, a1
+ move s2, a2
+ move s3, a3
+
+ /* Whether the PC meets expectation */
+ bal 1f
+1: move a0, ra
+ PTR_LA a1, 1b
+ PTR_SUB a0, a0, a1
+ beqz a0, 999f
+
+ /* Whether offset 64KB aligned */
+ and t0, a0, 0xffff
+ bnez t0, 999f
+
+ /* Whether current _text and _end are in the PC region */
+ PTR_LA t0, _end
+ PTR_ADDU t1, t0, a0
+ PTR_SRL t1, 28
+ PTR_SRL t0, 28
+ bne t0, t1, 999f
+
+ PTR_LA t0, _text
+ PTR_ADDU t1, t0, a0
+ move a3, t1
+ PTR_SRL t1, 28
+ PTR_SRL t0, 28
+ bne t0, t1, 999f
+
+ /* get current __start/stop___ex_table address */
+ PTR_LA a1, __start___ex_table
+ PTR_ADDU a1, a0
+ PTR_LA a2, __stop___ex_table
+ PTR_ADDU a2, a0
+
+ /*
+ * a0: offset
+ * a1: current __start___ex_table
+ * a2: current __stop___ex_table
+ */
+1: beq a1, a2, 998f
+ PTR_L t0, 0(a1)
+ PTR_ADDU t0, a0
+ PTR_S t0, 0(a1)
+ LONG_ADDIU a1, PTRSIZE
+ b 1b
+
+998:
+ /* get current _relocation_start address */
+ PTR_LA a1, _relocation_start
+ PTR_ADDU a1, a0
+
+ /*
+ * a0: offset
+ * a1: _relocation_start[]
+ * a2: offset >> 16, to relocate R_MIPS_HI16
+ * a3: current _text
+ * t0: to load _relocation_start[]
+ * t1: relocation type
+ * t2: current relocate position
+ * t3: temporarily
+ * t8: 0x00ffffff, mask, to get relocate position
+ * t9: offset >> 2, to relocate R_MIPS_26
+ */
+ li t8, 0x00ffffff
+ LONG_SRL t9, a0, 2
+ LONG_SRL a2, a0, 16
+1: lw t0, 0(a1)
+ beqz t0, 900f
+ LONG_SRL t1, t0, 24
+ and t1, 0xff
+ and t2, t0, t8
+ LONG_SLL t2, 2
+ PTR_ADDU t2, a3
+
+ li t3, R_MIPS_64
+ beq t1, t3, 964f
+ li t3, R_MIPS_32
+ beq t1, t3, 932f
+ li t3, R_MIPS_26
+ beq t1, t3, 926f
+ li t3, R_MIPS_HI16
+ beq t1, t3, 916f
+ b 999f
+
+964:
+#ifdef CONFIG_64BIT
+ ld t3, 0(t2)
+ LONG_ADDU t3, a0
+ sd t3, 0(t2)
+#endif
+ LONG_ADDIU a1, 4
+ b 1b
+
+932:
+ lw t3, 0(t2)
+ LONG_ADDU t3, a0
+ sw t3, 0(t2)
+ LONG_ADDIU a1, 4
+ b 1b
+
+926:
+ lw t3, 0(t2)
+ LONG_ADDU t3, t9
+ sw t3, 0(t2)
+ LONG_ADDIU a1, 4
+ b 1b
+
+916:
+ lw t3, 0(t2)
+ LONG_ADDU t3, a2
+ sw t3, 0(t2)
+ LONG_ADDIU a1, 4
+ b 1b
+
+900:
+ /* Complete! And flush i-cache */
+ PTR_LA a0, _text
+ PTR_LA a1, _end
+ synci 0(a0)
+ rdhwr t0, $1
+ beqz t0, 999f
+ PTR_ADDU a0, t0
+ PTR_SUBU t0, a1, a0
+ bgtz t0, 900b
+ sync
+
+999:
+ /* Restore args */
+ move a0, s0
+ move a1, s1
+ move a2, s2
+ move a3, s3
+#endif /* CONFIG_RELOCATABLE */
+ .set pop
+ .endm
+
/*
* For the moment disable interrupts, mark the kernel mode and
* set ST0_KX so that the CPU does not spit fire when using
@@ -83,6 +230,8 @@ FEXPORT(__kernel_entry)
NESTED(kernel_entry, 16, sp) # kernel entry point
+ do_relocate_kernel
+
kernel_entry_setup # cpu specific setup
setup_c0_status_pri
These asm code is based on relocate.c. And in this stage, only do relocate for _text and ex_table. Signed-off-by: Jinyang He <hejinyang@loongson.cn> --- arch/mips/kernel/head.S | 149 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+)