hv: use SELF IPI Register for self IPI in X2APIC mode

According to SDM 10.12.11, we can know this register is dedicated to the
purpose of sending self-IPIs with the intent of enabling a highly
optimized path for sending self-IPIs. Also sending the IPI via the Self
Interrupt Register ensures that interrupt is delivered to the processor
core. Specifically completion of the WRMSR instruction to the SELF IPI
register implies that the interrupt has been logged into the IRR.

Tracked-On: #4937
Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Shuo A Liu 2020-06-19 17:10:54 +08:00 committed by wenlingz
parent 0397cb7174
commit 025df6d44c

View File

@ -213,22 +213,13 @@ send_startup_ipi(uint16_t dest_pcpu_id, uint64_t cpu_startup_start_address)
void send_dest_ipi_mask(uint32_t dest_mask, uint32_t vector)
{
union apic_icr icr;
uint16_t pcpu_id;
uint32_t mask = dest_mask;
icr.value_32.lo_32 = vector | (INTR_LAPIC_ICR_PHYSICAL << 11U);
pcpu_id = ffs64(mask);
while (pcpu_id < MAX_PCPU_NUM) {
bitmap32_clear_nolock(pcpu_id, &mask);
if (is_pcpu_active(pcpu_id)) {
icr.value_32.hi_32 = per_cpu(lapic_id, pcpu_id);
msr_write(MSR_IA32_EXT_APIC_ICR, icr.value);
} else {
pr_err("pcpu_id %d not in active!", pcpu_id);
}
send_single_ipi(pcpu_id, vector);
pcpu_id = ffs64(mask);
}
}
@ -238,13 +229,17 @@ void send_single_ipi(uint16_t pcpu_id, uint32_t vector)
union apic_icr icr;
if (is_pcpu_active(pcpu_id)) {
/* Set the destination field to the target processor. */
icr.value_32.hi_32 = per_cpu(lapic_id, pcpu_id);
if (get_pcpu_id() == pcpu_id) {
msr_write(MSR_IA32_EXT_APIC_SELF_IPI, vector);
} else {
/* Set the destination field to the target processor. */
icr.value_32.hi_32 = per_cpu(lapic_id, pcpu_id);
/* Write the vector ID to ICR. */
icr.value_32.lo_32 = vector | (INTR_LAPIC_ICR_PHYSICAL << 11U);
/* Write the vector ID to ICR. */
icr.value_32.lo_32 = vector | (INTR_LAPIC_ICR_PHYSICAL << 11U);
msr_write(MSR_IA32_EXT_APIC_ICR, icr.value);
msr_write(MSR_IA32_EXT_APIC_ICR, icr.value);
}
} else {
pr_err("pcpu_id %d not in active!", pcpu_id);
}