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>
This commit is contained in:
Aaro Koskinen 2014-06-28 00:59:50 +03:00 committed by Ralf Baechle
parent 0953609f29
commit f64988f13e
1 changed files with 34 additions and 28 deletions

View File

@ -145,35 +145,39 @@ static void __init octeon_wdt_build_stage1(void)
uasm_i_mfc0(&p, K0, C0_STATUS);
#ifdef CONFIG_HOTPLUG_CPU
uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), label_enter_bootloader);
if (octeon_bootloader_entry_addr)
uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI),
label_enter_bootloader);
#endif
/* Force 64-bit addressing enabled */
uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX);
uasm_i_mtc0(&p, K0, C0_STATUS);
#ifdef CONFIG_HOTPLUG_CPU
uasm_i_mfc0(&p, K0, C0_EBASE);
/* Coreid number in K0 */
uasm_i_andi(&p, K0, K0, 0xf);
/* 8 * coreid in bits 16-31 */
uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
uasm_i_ori(&p, K0, K0, 0x8001);
uasm_i_dsll_safe(&p, K0, K0, 16);
uasm_i_ori(&p, K0, K0, 0x0700);
uasm_i_drotr_safe(&p, K0, K0, 32);
/*
* Should result in: 0x8001,0700,0000,8*coreid which is
* CVMX_CIU_WDOGX(coreid) - 0x0500
*
* Now ld K0, CVMX_CIU_WDOGX(coreid)
*/
uasm_i_ld(&p, K0, 0x500, K0);
/*
* If bit one set handle the NMI as a watchdog event.
* otherwise transfer control to bootloader.
*/
uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
uasm_i_nop(&p);
if (octeon_bootloader_entry_addr) {
uasm_i_mfc0(&p, K0, C0_EBASE);
/* Coreid number in K0 */
uasm_i_andi(&p, K0, K0, 0xf);
/* 8 * coreid in bits 16-31 */
uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
uasm_i_ori(&p, K0, K0, 0x8001);
uasm_i_dsll_safe(&p, K0, K0, 16);
uasm_i_ori(&p, K0, K0, 0x0700);
uasm_i_drotr_safe(&p, K0, K0, 32);
/*
* Should result in: 0x8001,0700,0000,8*coreid which is
* CVMX_CIU_WDOGX(coreid) - 0x0500
*
* Now ld K0, CVMX_CIU_WDOGX(coreid)
*/
uasm_i_ld(&p, K0, 0x500, K0);
/*
* If bit one set handle the NMI as a watchdog event.
* otherwise transfer control to bootloader.
*/
uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
uasm_i_nop(&p);
}
#endif
/* Clear Dcache so cvmseg works right. */
@ -194,11 +198,13 @@ static void __init octeon_wdt_build_stage1(void)
uasm_i_dmfc0(&p, K0, C0_DESAVE);
#ifdef CONFIG_HOTPLUG_CPU
uasm_build_label(&l, p, label_enter_bootloader);
/* Jump to the bootloader and restore K0 */
UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
uasm_i_jr(&p, K0);
uasm_i_dmfc0(&p, K0, C0_DESAVE);
if (octeon_bootloader_entry_addr) {
uasm_build_label(&l, p, label_enter_bootloader);
/* Jump to the bootloader and restore K0 */
UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
uasm_i_jr(&p, K0);
uasm_i_dmfc0(&p, K0, C0_DESAVE);
}
#endif
uasm_resolve_relocs(relocs, labels);