arch/powerpc/kernel/watchdog.c

Source file repositories/reference/linux-study-clean/arch/powerpc/kernel/watchdog.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/kernel/watchdog.c
Extension
.c
Size
16753 bytes
Lines
596
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

for_each_cpu(c, &wd_smp_cpus_ipi) {
			smp_send_nmi_ipi(c, wd_lockup_ipi, 1000000);
			__cpumask_clear_cpu(c, &wd_smp_cpus_ipi);
		}
	}

	sys_info(hardlockup_si_mask & ~SYS_INFO_ALL_BT);
	if (hardlockup_panic)
		nmi_panic(NULL, "Hard LOCKUP");

	wd_end_reporting();

	return;

out:
	wd_smp_unlock(&flags);
}

static void wd_smp_clear_cpu_pending(int cpu)
{
	if (!cpumask_test_cpu(cpu, &wd_smp_cpus_pending)) {
		if (unlikely(cpumask_test_cpu(cpu, &wd_smp_cpus_stuck))) {
			struct pt_regs *regs = get_irq_regs();
			unsigned long flags;

			pr_emerg("CPU %d became unstuck TB:%lld\n",
				 cpu, get_tb());
			print_irqtrace_events(current);
			if (regs)
				show_regs(regs);
			else
				dump_stack();

			wd_smp_lock(&flags);
			cpumask_clear_cpu(cpu, &wd_smp_cpus_stuck);
			wd_smp_unlock(&flags);
		} else {
			/*
			 * The last CPU to clear pending should have reset the
			 * watchdog so we generally should not find it empty
			 * here if our CPU was clear. However it could happen
			 * due to a rare race with another CPU taking the
			 * last CPU out of the mask concurrently.
			 *
			 * We can't add a warning for it. But just in case
			 * there is a problem with the watchdog that is causing
			 * the mask to not be reset, try to kick it along here.
			 */
			if (unlikely(cpumask_empty(&wd_smp_cpus_pending)))
				goto none_pending;
		}
		return;
	}

	/*
	 * All other updates to wd_smp_cpus_pending are performed under
	 * wd_smp_lock. All of them are atomic except the case where the
	 * mask becomes empty and is reset. This will not happen here because
	 * cpu was tested to be in the bitmap (above), and a CPU only clears
	 * its own bit. _Except_ in the case where another CPU has detected a
	 * hard lockup on our CPU and takes us out of the pending mask. So in
	 * normal operation there will be no race here, no problem.
	 *
	 * In the lockup case, this atomic clear-bit vs a store that refills
	 * other bits in the accessed word wll not be a problem. The bit clear
	 * is atomic so it will not cause the store to get lost, and the store
	 * will never set this bit so it will not overwrite the bit clear. The
	 * only way for a stuck CPU to return to the pending bitmap is to
	 * become unstuck itself.
	 */
	cpumask_clear_cpu(cpu, &wd_smp_cpus_pending);

	/*
	 * Order the store to clear pending with the load(s) to check all
	 * words in the pending mask to check they are all empty. This orders
	 * with the same barrier on another CPU. This prevents two CPUs
	 * clearing the last 2 pending bits, but neither seeing the other's
	 * store when checking if the mask is empty, and missing an empty
	 * mask, which ends with a false positive.
	 */
	smp_mb();
	if (cpumask_empty(&wd_smp_cpus_pending)) {
		unsigned long flags;

none_pending:
		/*
		 * Double check under lock because more than one CPU could see
		 * a clear mask with the lockless check after clearing their
		 * pending bits.
		 */

Annotation

Implementation Notes