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:
Родитель
0953609f29
Коммит
f64988f13e
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче