treewide: fix replace nbd@openwrt.org with nbd@nbd.name
[openwrt.git] / target / linux / generic / image / relocate / head.S
1 /*
2  * Kernel relocation stub for MIPS devices
3  *
4  * Copyright (C) 2015 Felix Fietkau <nbd@nbd.name>
5  *
6  * Based on:
7  *
8  * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
9  *
10  * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
11  *
12  * Some parts of this code was based on the OpenWrt specific lzma-loader
13  * for the BCM47xx and ADM5120 based boards:
14  *      Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
15  *      Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
16  *
17  * This program is free software; you can redistribute it and/or modify it
18  * under the terms of the GNU General Public License version 2 as published
19  * by the Free Software Foundation.
20  */
21
22 #include <asm/asm.h>
23 #include <asm/regdef.h>
24 #include "cp0regdef.h"
25 #include "cacheops.h"
26
27 #define KSEG0           0x80000000
28
29         .macro  ehb
30         sll     zero, 3
31         .endm
32
33         .macro reset
34         li t0, 0xbe000034
35         lw t1, 0(t0)
36         ori t1, 1
37         sw t1, 0(t0)
38         .endm
39
40         .text
41
42 LEAF(startup)
43         .set noreorder
44         .set mips32
45
46         .fill 0x10000
47
48         mtc0    zero, CP0_WATCHLO       # clear watch registers
49         mtc0    zero, CP0_WATCHHI
50         mtc0    zero, CP0_CAUSE         # clear before writing status register
51
52         mfc0    t0, CP0_STATUS
53         li      t1, 0x1000001f
54         or      t0, t1
55         xori    t0, 0x1f
56         mtc0    t0, CP0_STATUS
57         ehb
58
59         mtc0    zero, CP0_COUNT
60         mtc0    zero, CP0_COMPARE
61         ehb
62
63         la      t0, __reloc_label       # get linked address of label
64         bal     __reloc_label           # branch and link to label to
65         nop                             # get actual address
66 __reloc_label:
67         subu    t0, ra, t0              # get reloc_delta
68
69         /* Copy our code to the right place */
70         la      t1, _code_start         # get linked address of _code_start
71         la      t2, _code_end           # get linked address of _code_end
72
73         addu    t4, t2, t0              # calculate actual address of _code_end
74         lw      t5, 0(t4)               # get extra data size
75
76         add     t2, t5
77         add     t2, 4
78
79         add     t0, t1                  # calculate actual address of _code_start
80
81 __reloc_copy:
82         lw      t3, 0(t0)
83         sw      t3, 0(t1)
84         add     t1, 4
85         blt     t1, t2, __reloc_copy
86         add     t0, 4
87
88         /* flush cache */
89         la      t0, _code_start
90         la      t1, _code_end
91
92         li      t2, ~(CONFIG_CACHELINE_SIZE - 1)
93         and     t0, t2
94         and     t1, t2
95         li      t2, CONFIG_CACHELINE_SIZE
96
97         b       __flush_check
98         nop
99
100 __flush_line:
101         cache   Hit_Writeback_Inv_D, 0(t0)
102         cache   Hit_Invalidate_I, 0(t0)
103         add     t0, t2
104
105 __flush_check:
106         bne     t0, t1, __flush_line
107         nop
108
109         sync
110
111         la      t0, __reloc_back
112         j       t0
113         nop
114
115 __reloc_back:
116         la      t0, _code_end
117         add     t0, 4
118
119         addu    t1, t0, t5
120
121         li      t2, KERNEL_ADDR
122
123 __kernel_copy:
124         lw      t3, 0(t0)
125         sw      t3, 0(t2)
126         add     t0, 4
127         blt     t0, t1, __kernel_copy
128         add     t2, 4
129
130         /* flush cache */
131         li      t0, KERNEL_ADDR
132         addu    t1, t0, t5
133
134         add t1, CONFIG_CACHELINE_SIZE - 1
135         li      t2, ~(CONFIG_CACHELINE_SIZE - 1)
136         and     t0, t2
137         and     t1, t2
138         li      t2, CONFIG_CACHELINE_SIZE
139
140         b       __kernel_flush_check
141         nop
142
143 __kernel_flush_line:
144         cache   Hit_Writeback_Inv_D, 0(t0)
145         cache   Hit_Invalidate_I, 0(t0)
146         add     t0, t2
147
148 __kernel_flush_check:
149         bne     t0, t1, __kernel_flush_line
150         nop
151
152         sync
153
154         li      t0, KERNEL_ADDR
155         jr      t0
156         nop
157
158         .set reorder
159 END(startup)