arch/x86/kernel/smp.c

Source file repositories/reference/linux-study-clean/arch/x86/kernel/smp.c

File Facts

System
Linux kernel
Corpus path
arch/x86/kernel/smp.c
Extension
.c
Size
9728 bytes
Lines
327
Domain
Architecture Layer
Bucket
arch/x86
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

if (!smp_no_nmi_ipi && !register_stop_handler()) {
			unsigned int cpu;

			pr_emerg("Shutting down cpus with NMI\n");

			for_each_cpu(cpu, &cpus_stop_mask)
				__apic_send_IPI(cpu, NMI_VECTOR);
		}
		/*
		 * Don't wait longer than 10 ms if the caller didn't
		 * request it. If wait is true, the machine hangs here if
		 * one or more CPUs do not reach shutdown state.
		 */
		timeout = USEC_PER_MSEC * 10;
		while (!cpumask_empty(&cpus_stop_mask) && (wait || timeout--))
			udelay(1);
	}

	local_irq_save(flags);
	disable_local_APIC();
	mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
	local_irq_restore(flags);

	/*
	 * Ensure that the cpus_stop_mask cache lines are invalidated on
	 * the other CPUs. See comment vs. SME in stop_this_cpu().
	 */
	cpumask_clear(&cpus_stop_mask);
}

/*
 * Reschedule call back. KVM uses this interrupt to force a cpu out of
 * guest mode.
 */
DEFINE_IDTENTRY_SYSVEC_SIMPLE(sysvec_reschedule_ipi)
{
	apic_eoi();
	trace_reschedule_entry(RESCHEDULE_VECTOR);
	inc_irq_stat(RESCHEDULE);
	scheduler_ipi();
	trace_reschedule_exit(RESCHEDULE_VECTOR);
}

DEFINE_IDTENTRY_SYSVEC(sysvec_call_function)
{
	apic_eoi();
	trace_call_function_entry(CALL_FUNCTION_VECTOR);
	inc_irq_stat(CALL_FUNCTION);
	generic_smp_call_function_interrupt();
	trace_call_function_exit(CALL_FUNCTION_VECTOR);
}

DEFINE_IDTENTRY_SYSVEC(sysvec_call_function_single)
{
	apic_eoi();
	trace_call_function_single_entry(CALL_FUNCTION_SINGLE_VECTOR);
	inc_irq_stat(CALL_FUNCTION);
	generic_smp_call_function_single_interrupt();
	trace_call_function_single_exit(CALL_FUNCTION_SINGLE_VECTOR);
}

static int __init nonmi_ipi_setup(char *str)
{
	smp_no_nmi_ipi = true;
	return 1;
}

__setup("nonmi_ipi", nonmi_ipi_setup);

struct smp_ops smp_ops = {
	.smp_prepare_boot_cpu	= native_smp_prepare_boot_cpu,
	.smp_prepare_cpus	= native_smp_prepare_cpus,
	.smp_cpus_done		= native_smp_cpus_done,

	.stop_other_cpus	= native_stop_other_cpus,
#if defined(CONFIG_CRASH_DUMP)
	.crash_stop_other_cpus	= kdump_nmi_shootdown_cpus,
#endif
	.smp_send_reschedule	= native_smp_send_reschedule,

	.kick_ap_alive		= native_kick_ap,
	.cpu_disable		= native_cpu_disable,
	.play_dead		= native_play_dead,

	.send_call_func_ipi	= native_send_call_func_ipi,
	.send_call_func_single_ipi = native_send_call_func_single_ipi,
};
EXPORT_SYMBOL_GPL(smp_ops);

int arch_cpu_rescan_dead_smt_siblings(void)

Annotation

Implementation Notes