void apic_smt_update(void)
{ /* * Do not switch to broadcast mode if: * - Disabled on the command line * - Only a single CPU is online * - Not all present CPUs have been at least booted once * * The latter is important as the local APIC might be in some * random state and a broadcast might cause havoc. That's * especially true for NMI broadcasting.
*/ if (apic_ipi_shorthand_off || num_online_cpus() == 1 ||
!cpumask_equal(cpu_present_mask, &cpus_booted_once_mask)) {
static_branch_disable(&apic_use_ipi_shorthand);
} else {
static_branch_enable(&apic_use_ipi_shorthand);
}
}
void apic_send_IPI_allbutself(unsignedint vector)
{ if (num_online_cpus() < 2) return;
if (static_branch_likely(&apic_use_ipi_shorthand))
__apic_send_IPI_allbutself(vector); else
__apic_send_IPI_mask_allbutself(cpu_online_mask, vector);
}
/* * Send a 'reschedule' IPI to another CPU. It goes straight through and * wastes no time serializing anything. Worst case is that we lose a * reschedule ...
*/ void native_smp_send_reschedule(int cpu)
{ if (unlikely(cpu_is_offline(cpu))) {
WARN(1, "sched: Unexpected reschedule of offline CPU#%d!\n", cpu); return;
}
__apic_send_IPI(cpu, RESCHEDULE_VECTOR);
}
void apic_mem_wait_icr_idle(void)
{ while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY)
cpu_relax();
}
/* * This is safe against interruption because it only writes the lower 32 * bits of the APIC_ICR register. The destination field is ignored for * short hand IPIs. * * wait_icr_idle() * write(ICR2, dest) * NMI * wait_icr_idle() * write(ICR) * wait_icr_idle() * write(ICR) * * This function does not need to disable interrupts as there is no ICR2 * interaction. The memory write is direct except when the machine is * affected by the 11AP Pentium erratum, which turns the plain write into * an XCHG operation.
*/ staticvoid __default_send_IPI_shortcut(unsignedint shortcut, int vector)
{ /* * Wait for the previous ICR command to complete. Use * safe_apic_wait_icr_idle() for the NMI vector as there have been * issues where otherwise the system hangs when the panic CPU tries * to stop the others before launching the kdump kernel.
*/ if (unlikely(vector == NMI_VECTOR))
apic_mem_wait_icr_idle_timeout(); else
apic_mem_wait_icr_idle();
/* Destination field (ICR2) and the destination mode are ignored */
native_apic_mem_write(APIC_ICR, __prepare_ICR(shortcut, vector, 0));
}
/* * This is used to send an IPI with no shorthand notation (the destination is * specified in bits 56 to 63 of the ICR).
*/ void __default_send_IPI_dest_field(unsignedint dest_mask, int vector, unsignedint dest_mode)
{ /* See comment in __default_send_IPI_shortcut() */ if (unlikely(vector == NMI_VECTOR))
apic_mem_wait_icr_idle_timeout(); else
apic_mem_wait_icr_idle();
/* Set the IPI destination field in the ICR */
native_apic_mem_write(APIC_ICR2, __prepare_ICR2(dest_mask)); /* Send it with the proper destination mode */
native_apic_mem_write(APIC_ICR, __prepare_ICR(0, vector, dest_mode));
}
void default_send_IPI_single_phys(int cpu, int vector)
{ unsignedlong flags;
/* * Helper function for APICs which insist on cpumasks
*/ void default_send_IPI_single(int cpu, int vector)
{
__apic_send_IPI_mask(cpumask_of(cpu), vector);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.