cregit-Linux how code gets into the kernel

Release 4.14 arch/mn10300/kernel/mn10300-watchdog.c

/* MN10300 Watchdog timer
 *
 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 * - Derived from arch/i386/kernel/nmi.c
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public Licence
 * as published by the Free Software Foundation; either version
 * 2 of the Licence, or (at your option) any later version.
 */
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/nmi.h>
#include <asm/processor.h>
#include <linux/atomic.h>
#include <asm/intctl-regs.h>
#include <asm/rtc-regs.h>
#include <asm/div64.h>
#include <asm/smp.h>
#include <asm/gdb-stub.h>
#include <proc/clock.h>

static DEFINE_SPINLOCK(watchdog_print_lock);

static unsigned int watchdog;

static unsigned int watchdog_hz = 1;

unsigned int watchdog_alert_counter[NR_CPUS];


EXPORT_SYMBOL(arch_touch_nmi_watchdog);

/*
 * the best way to detect whether a CPU has a 'hard lockup' problem
 * is to check its timer makes IRQ counts. If they are not
 * changing then that CPU has some problem.
 *
 * since NMIs dont listen to _any_ locks, we have to be extremely
 * careful not to rely on unsafe variables. The printk might lock
 * up though, so we have to break up any console locks first ...
 * [when there will be more tty-related locks, break them up
 *  here too!]
 */

static unsigned int last_irq_sums[NR_CPUS];


int __init check_watchdog(void) { irq_cpustat_t tmp[1]; printk(KERN_INFO "Testing Watchdog... "); memcpy(tmp, irq_stat, sizeof(tmp)); local_irq_enable(); mdelay((10 * 1000) / watchdog_hz); /* wait 10 ticks */ local_irq_disable(); if (nmi_count(0) - tmp[0].__nmi_count <= 5) { printk(KERN_WARNING "CPU#%d: Watchdog appears to be stuck!\n", 0); return -1; } printk(KERN_INFO "OK.\n"); /* now that we know it works we can reduce NMI frequency to something * more reasonable; makes a difference in some configs */ watchdog_hz = 1; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
David Howells9398.94%150.00%
Akira Takeuchi11.06%150.00%
Total94100.00%2100.00%


static int __init setup_watchdog(char *str) { unsigned tmp; int opt; u8 ctr; get_option(&str, &opt); if (opt != 1) return 0; watchdog = opt; if (watchdog) { set_intr_stub(EXCEP_WDT, watchdog_handler); ctr = WDCTR_WDCK_65536th; WDCTR = WDCTR_WDRST | ctr; WDCTR = ctr; tmp = WDCTR; tmp = __muldiv64u(1 << (16 + ctr * 2), 1000000, MN10300_WDCLK); tmp = 1000000000 / tmp; watchdog_hz = (tmp + 500) / 1000; } return 1; }

Contributors

PersonTokensPropCommitsCommitProp
David Howells111100.00%1100.00%
Total111100.00%1100.00%

__setup("watchdog=", setup_watchdog);
void __init watchdog_go(void) { u8 wdt; if (watchdog) { printk(KERN_INFO "Watchdog: running at %uHz\n", watchdog_hz); wdt = WDCTR & ~WDCTR_WDCNE; WDCTR = wdt | WDCTR_WDRST; wdt = WDCTR; WDCTR = wdt | WDCTR_WDCNE; wdt = WDCTR; check_watchdog(); } }

Contributors

PersonTokensPropCommitsCommitProp
David Howells55100.00%1100.00%
Total55100.00%1100.00%

#ifdef CONFIG_SMP
static void watchdog_dump_register(void *dummy) { printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID); show_registers(current_frame()); }

Contributors

PersonTokensPropCommitsCommitProp
Akira Takeuchi2291.67%150.00%
David Howells28.33%150.00%
Total24100.00%2100.00%

#endif
asmlinkage void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) { /* * Since current-> is always on the stack, and we always switch * the stack NMI-atomically, it's safe to use smp_processor_id(). */ int sum, cpu; int irq = NMIIRQ; u8 wdt, tmp; wdt = WDCTR & ~WDCTR_WDCNE; WDCTR = wdt; tmp = WDCTR; NMICR = NMICR_WDIF; nmi_count(smp_processor_id())++; kstat_incr_irq_this_cpu(irq); for_each_online_cpu(cpu) { sum = irq_stat[cpu].__irq_count; if ((last_irq_sums[cpu] == sum) #if defined(CONFIG_GDBSTUB) && defined(CONFIG_SMP) && !(CHK_GDBSTUB_BUSY() || atomic_read(&cpu_doing_single_step)) #endif ) { /* * Ayiee, looks like this CPU is stuck ... * wait a few IRQs (5 seconds) before doing the oops ... */ watchdog_alert_counter[cpu]++; if (watchdog_alert_counter[cpu] == 5 * watchdog_hz) { spin_lock(&watchdog_print_lock); /* * We are in trouble anyway, lets at least try * to get a message out. */ bust_spinlocks(1); printk(KERN_ERR "NMI Watchdog detected LOCKUP on CPU%d," " pc %08lx, registers:\n", cpu, regs->pc); #ifdef CONFIG_SMP printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID); #endif show_registers(regs); #ifdef CONFIG_SMP smp_nmi_call_function(watchdog_dump_register, NULL, 1); #endif printk(KERN_NOTICE "console shuts up ...\n"); console_silent(); spin_unlock(&watchdog_print_lock); bust_spinlocks(0); #ifdef CONFIG_GDBSTUB if (CHK_GDBSTUB_BUSY_AND_ACTIVE()) gdbstub_exception(regs, excep); else gdbstub_intercept(regs, excep); #endif do_exit(SIGSEGV); } } else { last_irq_sums[cpu] = sum; watchdog_alert_counter[cpu] = 0; } } WDCTR = wdt | WDCTR_WDRST; tmp = WDCTR; WDCTR = wdt | WDCTR_WDCNE; tmp = WDCTR; }

Contributors

PersonTokensPropCommitsCommitProp
David Howells19469.53%125.00%
Akira Takeuchi7627.24%125.00%
Mike Travis82.87%125.00%
Thomas Gleixner10.36%125.00%
Total279100.00%4100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
David Howells54482.05%337.50%
Akira Takeuchi10816.29%112.50%
Mike Travis81.21%112.50%
Arun Sharma10.15%112.50%
Thomas Gleixner10.15%112.50%
Nicholas Piggin10.15%112.50%
Total663100.00%8100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.