diff options
Diffstat (limited to 'arch/mips/kernel/relocate_kernel.S')
-rw-r--r-- | arch/mips/kernel/relocate_kernel.S | 107 |
1 files changed, 106 insertions, 1 deletions
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S index 87481f916a61..e4142c5f7c2b 100644 --- a/arch/mips/kernel/relocate_kernel.S +++ b/arch/mips/kernel/relocate_kernel.S | |||
@@ -15,6 +15,11 @@ | |||
15 | #include <asm/addrspace.h> | 15 | #include <asm/addrspace.h> |
16 | 16 | ||
17 | LEAF(relocate_new_kernel) | 17 | LEAF(relocate_new_kernel) |
18 | PTR_L a0, arg0 | ||
19 | PTR_L a1, arg1 | ||
20 | PTR_L a2, arg2 | ||
21 | PTR_L a3, arg3 | ||
22 | |||
18 | PTR_L s0, kexec_indirection_page | 23 | PTR_L s0, kexec_indirection_page |
19 | PTR_L s1, kexec_start_address | 24 | PTR_L s1, kexec_start_address |
20 | 25 | ||
@@ -26,7 +31,6 @@ process_entry: | |||
26 | and s3, s2, 0x1 | 31 | and s3, s2, 0x1 |
27 | beq s3, zero, 1f | 32 | beq s3, zero, 1f |
28 | and s4, s2, ~0x1 /* store destination addr in s4 */ | 33 | and s4, s2, ~0x1 /* store destination addr in s4 */ |
29 | move a0, s4 | ||
30 | b process_entry | 34 | b process_entry |
31 | 35 | ||
32 | 1: | 36 | 1: |
@@ -60,10 +64,111 @@ copy_word: | |||
60 | b process_entry | 64 | b process_entry |
61 | 65 | ||
62 | done: | 66 | done: |
67 | #ifdef CONFIG_SMP | ||
68 | /* kexec_flag reset is signal to other CPUs what kernel | ||
69 | was moved to it's location. Note - we need relocated address | ||
70 | of kexec_flag. */ | ||
71 | |||
72 | bal 1f | ||
73 | 1: move t1,ra; | ||
74 | PTR_LA t2,1b | ||
75 | PTR_LA t0,kexec_flag | ||
76 | PTR_SUB t0,t0,t2; | ||
77 | PTR_ADD t0,t1,t0; | ||
78 | LONG_S zero,(t0) | ||
79 | #endif | ||
80 | |||
81 | #ifdef CONFIG_CPU_CAVIUM_OCTEON | ||
82 | /* We need to flush I-cache before jumping to new kernel. | ||
83 | * Unfortunatelly, this code is cpu-specific. | ||
84 | */ | ||
85 | .set push | ||
86 | .set noreorder | ||
87 | syncw | ||
88 | syncw | ||
89 | synci 0($0) | ||
90 | .set pop | ||
91 | #else | ||
92 | sync | ||
93 | #endif | ||
63 | /* jump to kexec_start_address */ | 94 | /* jump to kexec_start_address */ |
64 | j s1 | 95 | j s1 |
65 | END(relocate_new_kernel) | 96 | END(relocate_new_kernel) |
66 | 97 | ||
98 | #ifdef CONFIG_SMP | ||
99 | /* | ||
100 | * Other CPUs should wait until code is relocated and | ||
101 | * then start at entry (?) point. | ||
102 | */ | ||
103 | LEAF(kexec_smp_wait) | ||
104 | PTR_L a0, s_arg0 | ||
105 | PTR_L a1, s_arg1 | ||
106 | PTR_L a2, s_arg2 | ||
107 | PTR_L a3, s_arg3 | ||
108 | PTR_L s1, kexec_start_address | ||
109 | |||
110 | /* Non-relocated address works for args and kexec_start_address ( old | ||
111 | * kernel is not overwritten). But we need relocated address of | ||
112 | * kexec_flag. | ||
113 | */ | ||
114 | |||
115 | bal 1f | ||
116 | 1: move t1,ra; | ||
117 | PTR_LA t2,1b | ||
118 | PTR_LA t0,kexec_flag | ||
119 | PTR_SUB t0,t0,t2; | ||
120 | PTR_ADD t0,t1,t0; | ||
121 | |||
122 | 1: LONG_L s0, (t0) | ||
123 | bne s0, zero,1b | ||
124 | |||
125 | #ifdef CONFIG_CPU_CAVIUM_OCTEON | ||
126 | .set push | ||
127 | .set noreorder | ||
128 | synci 0($0) | ||
129 | .set pop | ||
130 | #else | ||
131 | sync | ||
132 | #endif | ||
133 | j s1 | ||
134 | END(kexec_smp_wait) | ||
135 | #endif | ||
136 | |||
137 | #ifdef __mips64 | ||
138 | /* all PTR's must be aligned to 8 byte in 64-bit mode */ | ||
139 | .align 3 | ||
140 | #endif | ||
141 | |||
142 | /* All parameters to new kernel are passed in registers a0-a3. | ||
143 | * kexec_args[0..3] are uses to prepare register values. | ||
144 | */ | ||
145 | |||
146 | kexec_args: | ||
147 | EXPORT(kexec_args) | ||
148 | arg0: PTR 0x0 | ||
149 | arg1: PTR 0x0 | ||
150 | arg2: PTR 0x0 | ||
151 | arg3: PTR 0x0 | ||
152 | .size kexec_args,PTRSIZE*4 | ||
153 | |||
154 | #ifdef CONFIG_SMP | ||
155 | /* | ||
156 | * Secondary CPUs may have different kernel parameters in | ||
157 | * their registers a0-a3. secondary_kexec_args[0..3] are used | ||
158 | * to prepare register values. | ||
159 | */ | ||
160 | secondary_kexec_args: | ||
161 | EXPORT(secondary_kexec_args) | ||
162 | s_arg0: PTR 0x0 | ||
163 | s_arg1: PTR 0x0 | ||
164 | s_arg2: PTR 0x0 | ||
165 | s_arg3: PTR 0x0 | ||
166 | .size secondary_kexec_args,PTRSIZE*4 | ||
167 | kexec_flag: | ||
168 | LONG 0x1 | ||
169 | |||
170 | #endif | ||
171 | |||
67 | kexec_start_address: | 172 | kexec_start_address: |
68 | EXPORT(kexec_start_address) | 173 | EXPORT(kexec_start_address) |
69 | PTR 0x0 | 174 | PTR 0x0 |