Skip to content

Commit f5c20e4

Browse files
vittyvkliuw
authored andcommitted
x86/hyperv: Avoid erroneously sending IPI to 'self'
__send_ipi_mask_ex() uses an optimization: when the target CPU mask is equal to 'cpu_present_mask' it uses 'HV_GENERIC_SET_ALL' format to avoid converting the specified cpumask to VP_SET. This case was overlooked when 'exclude_self' parameter was added. As the result, a spurious IPI to 'self' can be send. Reported-by: Thomas Gleixner <[email protected]> Fixes: dfb5c1e ("x86/hyperv: remove on-stack cpumask from hv_send_ipi_mask_allbutself") Signed-off-by: Vitaly Kuznetsov <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]>
1 parent 95a13ee commit f5c20e4

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

arch/x86/hyperv/hv_apic.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,27 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
122122
ipi_arg->reserved = 0;
123123
ipi_arg->vp_set.valid_bank_mask = 0;
124124

125-
if (!cpumask_equal(mask, cpu_present_mask)) {
125+
/*
126+
* Use HV_GENERIC_SET_ALL and avoid converting cpumask to VP_SET
127+
* when the IPI is sent to all currently present CPUs.
128+
*/
129+
if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) {
126130
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
127131
if (exclude_self)
128132
nr_bank = cpumask_to_vpset_noself(&(ipi_arg->vp_set), mask);
129133
else
130134
nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask);
131-
}
132-
if (nr_bank < 0)
133-
goto ipi_mask_ex_done;
134-
if (!nr_bank)
135+
136+
/*
137+
* 'nr_bank <= 0' means some CPUs in cpumask can't be
138+
* represented in VP_SET. Return an error and fall back to
139+
* native (architectural) method of sending IPIs.
140+
*/
141+
if (nr_bank <= 0)
142+
goto ipi_mask_ex_done;
143+
} else {
135144
ipi_arg->vp_set.format = HV_GENERIC_SET_ALL;
145+
}
136146

137147
status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
138148
ipi_arg, NULL);

0 commit comments

Comments
 (0)