diff options
author | Aaro Koskinen <aaro.koskinen@iki.fi> | 2014-06-27 17:59:50 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-08-01 18:06:42 -0400 |
commit | f64988f13e82dd1797e59b26c8728d26c332aa43 (patch) | |
tree | 603c37b05a1a830847ebb927a126fd43f69e535e /drivers/watchdog | |
parent | 0953609f294bfdffb5144789904f4c11a5dafb38 (diff) |
MIPS: OCTEON: watchdog: don't jump to bootloader without entry address
If CONFIG_HOTPLUG_CPU is set, the driver thinks bootloader entry
address is configured and we should jump there. However, this is
not necessarily true if the kernel is booted on a system
with older/incompatible bootloader.
Add dynamic checks for the bootloader entry address.
Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Cc: linux-watchdog@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: David Daney <ddaney.cavm@gmail.com>
Cc: linux-watchdog@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/7201/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/octeon-wdt-main.c | 62 |
1 files changed, 34 insertions, 28 deletions
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 4baf2d788920..8453531545df 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c | |||
@@ -145,35 +145,39 @@ static void __init octeon_wdt_build_stage1(void) | |||
145 | 145 | ||
146 | uasm_i_mfc0(&p, K0, C0_STATUS); | 146 | uasm_i_mfc0(&p, K0, C0_STATUS); |
147 | #ifdef CONFIG_HOTPLUG_CPU | 147 | #ifdef CONFIG_HOTPLUG_CPU |
148 | uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), label_enter_bootloader); | 148 | if (octeon_bootloader_entry_addr) |
149 | uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), | ||
150 | label_enter_bootloader); | ||
149 | #endif | 151 | #endif |
150 | /* Force 64-bit addressing enabled */ | 152 | /* Force 64-bit addressing enabled */ |
151 | uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX); | 153 | uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX); |
152 | uasm_i_mtc0(&p, K0, C0_STATUS); | 154 | uasm_i_mtc0(&p, K0, C0_STATUS); |
153 | 155 | ||
154 | #ifdef CONFIG_HOTPLUG_CPU | 156 | #ifdef CONFIG_HOTPLUG_CPU |
155 | uasm_i_mfc0(&p, K0, C0_EBASE); | 157 | if (octeon_bootloader_entry_addr) { |
156 | /* Coreid number in K0 */ | 158 | uasm_i_mfc0(&p, K0, C0_EBASE); |
157 | uasm_i_andi(&p, K0, K0, 0xf); | 159 | /* Coreid number in K0 */ |
158 | /* 8 * coreid in bits 16-31 */ | 160 | uasm_i_andi(&p, K0, K0, 0xf); |
159 | uasm_i_dsll_safe(&p, K0, K0, 3 + 16); | 161 | /* 8 * coreid in bits 16-31 */ |
160 | uasm_i_ori(&p, K0, K0, 0x8001); | 162 | uasm_i_dsll_safe(&p, K0, K0, 3 + 16); |
161 | uasm_i_dsll_safe(&p, K0, K0, 16); | 163 | uasm_i_ori(&p, K0, K0, 0x8001); |
162 | uasm_i_ori(&p, K0, K0, 0x0700); | 164 | uasm_i_dsll_safe(&p, K0, K0, 16); |
163 | uasm_i_drotr_safe(&p, K0, K0, 32); | 165 | uasm_i_ori(&p, K0, K0, 0x0700); |
164 | /* | 166 | uasm_i_drotr_safe(&p, K0, K0, 32); |
165 | * Should result in: 0x8001,0700,0000,8*coreid which is | 167 | /* |
166 | * CVMX_CIU_WDOGX(coreid) - 0x0500 | 168 | * Should result in: 0x8001,0700,0000,8*coreid which is |
167 | * | 169 | * CVMX_CIU_WDOGX(coreid) - 0x0500 |
168 | * Now ld K0, CVMX_CIU_WDOGX(coreid) | 170 | * |
169 | */ | 171 | * Now ld K0, CVMX_CIU_WDOGX(coreid) |
170 | uasm_i_ld(&p, K0, 0x500, K0); | 172 | */ |
171 | /* | 173 | uasm_i_ld(&p, K0, 0x500, K0); |
172 | * If bit one set handle the NMI as a watchdog event. | 174 | /* |
173 | * otherwise transfer control to bootloader. | 175 | * If bit one set handle the NMI as a watchdog event. |
174 | */ | 176 | * otherwise transfer control to bootloader. |
175 | uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader); | 177 | */ |
176 | uasm_i_nop(&p); | 178 | uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader); |
179 | uasm_i_nop(&p); | ||
180 | } | ||
177 | #endif | 181 | #endif |
178 | 182 | ||
179 | /* Clear Dcache so cvmseg works right. */ | 183 | /* Clear Dcache so cvmseg works right. */ |
@@ -194,11 +198,13 @@ static void __init octeon_wdt_build_stage1(void) | |||
194 | uasm_i_dmfc0(&p, K0, C0_DESAVE); | 198 | uasm_i_dmfc0(&p, K0, C0_DESAVE); |
195 | 199 | ||
196 | #ifdef CONFIG_HOTPLUG_CPU | 200 | #ifdef CONFIG_HOTPLUG_CPU |
197 | uasm_build_label(&l, p, label_enter_bootloader); | 201 | if (octeon_bootloader_entry_addr) { |
198 | /* Jump to the bootloader and restore K0 */ | 202 | uasm_build_label(&l, p, label_enter_bootloader); |
199 | UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr); | 203 | /* Jump to the bootloader and restore K0 */ |
200 | uasm_i_jr(&p, K0); | 204 | UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr); |
201 | uasm_i_dmfc0(&p, K0, C0_DESAVE); | 205 | uasm_i_jr(&p, K0); |
206 | uasm_i_dmfc0(&p, K0, C0_DESAVE); | ||
207 | } | ||
202 | #endif | 208 | #endif |
203 | uasm_resolve_relocs(relocs, labels); | 209 | uasm_resolve_relocs(relocs, labels); |
204 | 210 | ||