watchdog: octeon-wdt: Remove old boot vector code.
Signed-off-by: Steven J. Hill <steven.hill@cavium.com> Acked-by: David Daney <david.daney@cavium.com> Acked-by: Guenter Roeck <linux@roeck-us.net> Cc: linux-mips@linux-mips.org Cc: linux-watchdog@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/17209/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
9438a86a07
commit
49d148b4e5
|
@ -73,6 +73,7 @@
|
||||||
#include <asm/uasm.h>
|
#include <asm/uasm.h>
|
||||||
|
|
||||||
#include <asm/octeon/octeon.h>
|
#include <asm/octeon/octeon.h>
|
||||||
|
#include <asm/octeon/cvmx-boot-vector.h>
|
||||||
|
|
||||||
/* The count needed to achieve timeout_sec. */
|
/* The count needed to achieve timeout_sec. */
|
||||||
static unsigned int timeout_cnt;
|
static unsigned int timeout_cnt;
|
||||||
|
@ -104,122 +105,10 @@ MODULE_PARM_DESC(nowayout,
|
||||||
"Watchdog cannot be stopped once started (default="
|
"Watchdog cannot be stopped once started (default="
|
||||||
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||||
|
|
||||||
static u32 nmi_stage1_insns[64] __initdata;
|
static struct cvmx_boot_vector_element *octeon_wdt_bootvector;
|
||||||
/* We need one branch and therefore one relocation per target label. */
|
|
||||||
static struct uasm_label labels[5] __initdata;
|
|
||||||
static struct uasm_reloc relocs[5] __initdata;
|
|
||||||
|
|
||||||
enum lable_id {
|
|
||||||
label_enter_bootloader = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Some CP0 registers */
|
|
||||||
#define K0 26
|
|
||||||
#define C0_CVMMEMCTL 11, 7
|
|
||||||
#define C0_STATUS 12, 0
|
|
||||||
#define C0_EBASE 15, 1
|
|
||||||
#define C0_DESAVE 31, 0
|
|
||||||
|
|
||||||
void octeon_wdt_nmi_stage2(void);
|
void octeon_wdt_nmi_stage2(void);
|
||||||
|
|
||||||
static void __init octeon_wdt_build_stage1(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int len;
|
|
||||||
u32 *p = nmi_stage1_insns;
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
struct uasm_label *l = labels;
|
|
||||||
struct uasm_reloc *r = relocs;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For the next few instructions running the debugger may
|
|
||||||
* cause corruption of k0 in the saved registers. Since we're
|
|
||||||
* about to crash, nobody probably cares.
|
|
||||||
*
|
|
||||||
* Save K0 into the debug scratch register
|
|
||||||
*/
|
|
||||||
uasm_i_dmtc0(&p, K0, C0_DESAVE);
|
|
||||||
|
|
||||||
uasm_i_mfc0(&p, K0, C0_STATUS);
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
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
|
|
||||||
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. */
|
|
||||||
uasm_i_cache(&p, 1, 0, 0);
|
|
||||||
|
|
||||||
/* Use K0 to do a read/modify/write of CVMMEMCTL */
|
|
||||||
uasm_i_dmfc0(&p, K0, C0_CVMMEMCTL);
|
|
||||||
/* Clear out the size of CVMSEG */
|
|
||||||
uasm_i_dins(&p, K0, 0, 0, 6);
|
|
||||||
/* Set CVMSEG to its largest value */
|
|
||||||
uasm_i_ori(&p, K0, K0, 0x1c0 | 54);
|
|
||||||
/* Store the CVMMEMCTL value */
|
|
||||||
uasm_i_dmtc0(&p, K0, C0_CVMMEMCTL);
|
|
||||||
|
|
||||||
/* Load the address of the second stage handler */
|
|
||||||
UASM_i_LA(&p, K0, (long)octeon_wdt_nmi_stage2);
|
|
||||||
uasm_i_jr(&p, K0);
|
|
||||||
uasm_i_dmfc0(&p, K0, C0_DESAVE);
|
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
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);
|
|
||||||
|
|
||||||
len = (int)(p - nmi_stage1_insns);
|
|
||||||
pr_debug("Synthesized NMI stage 1 handler (%d instructions)\n", len);
|
|
||||||
|
|
||||||
pr_debug("\t.set push\n");
|
|
||||||
pr_debug("\t.set noreorder\n");
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
pr_debug("\t.word 0x%08x\n", nmi_stage1_insns[i]);
|
|
||||||
pr_debug("\t.set pop\n");
|
|
||||||
|
|
||||||
if (len > 32)
|
|
||||||
panic("NMI stage 1 handler exceeds 32 instructions, was %d\n",
|
|
||||||
len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cpu2core(int cpu)
|
static int cpu2core(int cpu)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
@ -402,6 +291,8 @@ static int octeon_wdt_cpu_online(unsigned int cpu)
|
||||||
|
|
||||||
core = cpu2core(cpu);
|
core = cpu2core(cpu);
|
||||||
|
|
||||||
|
octeon_wdt_bootvector[core].target_ptr = (u64)octeon_wdt_nmi_stage2;
|
||||||
|
|
||||||
/* Disable it before doing anything with the interrupts. */
|
/* Disable it before doing anything with the interrupts. */
|
||||||
ciu_wdog.u64 = 0;
|
ciu_wdog.u64 = 0;
|
||||||
cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
|
cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
|
||||||
|
@ -544,6 +435,12 @@ static int __init octeon_wdt_init(void)
|
||||||
int ret;
|
int ret;
|
||||||
u64 *ptr;
|
u64 *ptr;
|
||||||
|
|
||||||
|
octeon_wdt_bootvector = cvmx_boot_vector_get();
|
||||||
|
if (!octeon_wdt_bootvector) {
|
||||||
|
pr_err("Error: Cannot allocate boot vector.\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Watchdog time expiration length = The 16 bits of LEN
|
* Watchdog time expiration length = The 16 bits of LEN
|
||||||
* represent the most significant bits of a 24 bit decrementer
|
* represent the most significant bits of a 24 bit decrementer
|
||||||
|
@ -576,17 +473,6 @@ static int __init octeon_wdt_init(void)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build the NMI handler ... */
|
|
||||||
octeon_wdt_build_stage1();
|
|
||||||
|
|
||||||
/* ... and install it. */
|
|
||||||
ptr = (u64 *) nmi_stage1_insns;
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8);
|
|
||||||
cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, ptr[i]);
|
|
||||||
}
|
|
||||||
cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000);
|
|
||||||
|
|
||||||
cpumask_clear(&irq_enabled_cpus);
|
cpumask_clear(&irq_enabled_cpus);
|
||||||
|
|
||||||
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "watchdog/octeon:online",
|
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "watchdog/octeon:online",
|
||||||
|
|
|
@ -3,20 +3,40 @@
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007 Cavium Networks
|
* Copyright (C) 2007-2017 Cavium, Inc.
|
||||||
*/
|
*/
|
||||||
#include <asm/asm.h>
|
#include <asm/asm.h>
|
||||||
#include <asm/regdef.h>
|
#include <asm/regdef.h>
|
||||||
|
|
||||||
#define SAVE_REG(r) sd $r, -32768+6912-(32-r)*8($0)
|
#define CVMSEG_BASE -32768
|
||||||
|
#define CVMSEG_SIZE 6912
|
||||||
|
#define SAVE_REG(r) sd $r, CVMSEG_BASE + CVMSEG_SIZE - ((32 - r) * 8)($0)
|
||||||
|
|
||||||
NESTED(octeon_wdt_nmi_stage2, 0, sp)
|
NESTED(octeon_wdt_nmi_stage2, 0, sp)
|
||||||
.set push
|
.set push
|
||||||
.set noreorder
|
.set noreorder
|
||||||
.set noat
|
.set noat
|
||||||
/* Save all registers to the top CVMSEG. This shouldn't
|
/* Clear Dcache so cvmseg works right. */
|
||||||
|
cache 1,0($0)
|
||||||
|
/* Use K0 to do a read/modify/write of CVMMEMCTL */
|
||||||
|
dmfc0 k0, $11, 7
|
||||||
|
/* Clear out the size of CVMSEG */
|
||||||
|
dins k0, $0, 0, 6
|
||||||
|
/* Set CVMSEG to its largest value */
|
||||||
|
ori k0, k0, 0x1c0 | 54
|
||||||
|
/* Store the CVMMEMCTL value */
|
||||||
|
dmtc0 k0, $11, 7
|
||||||
|
/*
|
||||||
|
* Restore K0 from the debug scratch register, it was saved in
|
||||||
|
* the boot-vector code.
|
||||||
|
*/
|
||||||
|
dmfc0 k0, $31
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save all registers to the top CVMSEG. This shouldn't
|
||||||
* corrupt any state used by the kernel. Also all registers
|
* corrupt any state used by the kernel. Also all registers
|
||||||
* should have the value right before the NMI. */
|
* should have the value right before the NMI.
|
||||||
|
*/
|
||||||
SAVE_REG(0)
|
SAVE_REG(0)
|
||||||
SAVE_REG(1)
|
SAVE_REG(1)
|
||||||
SAVE_REG(2)
|
SAVE_REG(2)
|
||||||
|
@ -49,16 +69,22 @@
|
||||||
SAVE_REG(29)
|
SAVE_REG(29)
|
||||||
SAVE_REG(30)
|
SAVE_REG(30)
|
||||||
SAVE_REG(31)
|
SAVE_REG(31)
|
||||||
|
/* Write zero to all CVMSEG locations per Core-15169 */
|
||||||
|
dli a0, CVMSEG_SIZE - (33 * 8)
|
||||||
|
1: sd zero, CVMSEG_BASE(a0)
|
||||||
|
daddiu a0, a0, -8
|
||||||
|
bgez a0, 1b
|
||||||
|
nop
|
||||||
/* Set the stack to begin right below the registers */
|
/* Set the stack to begin right below the registers */
|
||||||
li sp, -32768+6912-32*8
|
dli sp, CVMSEG_BASE + CVMSEG_SIZE - (32 * 8)
|
||||||
/* Load the address of the third stage handler */
|
/* Load the address of the third stage handler */
|
||||||
dla a0, octeon_wdt_nmi_stage3
|
dla $25, octeon_wdt_nmi_stage3
|
||||||
/* Call the third stage handler */
|
/* Call the third stage handler */
|
||||||
jal a0
|
jal $25
|
||||||
/* a0 is the address of the saved registers */
|
/* a0 is the address of the saved registers */
|
||||||
move a0, sp
|
move a0, sp
|
||||||
/* Loop forvever if we get here. */
|
/* Loop forvever if we get here. */
|
||||||
1: b 1b
|
2: b 2b
|
||||||
nop
|
nop
|
||||||
.set pop
|
.set pop
|
||||||
END(octeon_wdt_nmi_stage2)
|
END(octeon_wdt_nmi_stage2)
|
||||||
|
|
Loading…
Reference in New Issue