|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] x86/smp: do not use shorthand IPI destinations in CPU hot{,un}plug contexts
commit 171c52fba5d94e050d704770480dcb983490d0ad
Author: Roger Pau Monné <roger.pau@xxxxxxxxxx>
AuthorDate: Wed Jun 12 14:29:31 2024 +0200
Commit: Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Wed Jun 12 14:29:31 2024 +0200
x86/smp: do not use shorthand IPI destinations in CPU hot{,un}plug contexts
Due to the current rwlock logic, if the CPU calling get_cpu_maps() does
so from a cpu_hotplug_{begin,done}() region the function will still
return success, because a CPU taking the rwlock in read mode after
having taken it in write mode is allowed. Such corner case makes using
get_cpu_maps() alone not enough to prevent using the shorthand in CPU
hotplug regions.
Introduce a new helper to detect whether the current caller is between a
cpu_hotplug_{begin,done}() region and use it in send_IPI_mask() to restrict
shorthand usage.
Fixes: 5500d265a2a8 ('x86/smp: use APIC ALLBUT destination shorthand when
possible')
Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
xen/arch/x86/smp.c | 2 +-
xen/common/cpu.c | 5 +++++
xen/include/xen/cpu.h | 10 ++++++++++
xen/include/xen/rwlock.h | 2 ++
4 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c
index 7443ad2033..04c6a05723 100644
--- a/xen/arch/x86/smp.c
+++ b/xen/arch/x86/smp.c
@@ -88,7 +88,7 @@ void send_IPI_mask(const cpumask_t *mask, int vector)
* the system have been accounted for.
*/
if ( system_state > SYS_STATE_smp_boot &&
- !unaccounted_cpus && !disabled_cpus &&
+ !unaccounted_cpus && !disabled_cpus && !cpu_in_hotplug_context() &&
/* NB: get_cpu_maps lock requires enabled interrupts. */
local_irq_is_enabled() && (cpus_locked = get_cpu_maps()) &&
(park_offline_cpus ||
diff --git a/xen/common/cpu.c b/xen/common/cpu.c
index 8709db4d29..6e35b114c0 100644
--- a/xen/common/cpu.c
+++ b/xen/common/cpu.c
@@ -68,6 +68,11 @@ void cpu_hotplug_done(void)
write_unlock(&cpu_add_remove_lock);
}
+bool cpu_in_hotplug_context(void)
+{
+ return rw_is_write_locked_by_me(&cpu_add_remove_lock);
+}
+
static NOTIFIER_HEAD(cpu_chain);
void __init register_cpu_notifier(struct notifier_block *nb)
diff --git a/xen/include/xen/cpu.h b/xen/include/xen/cpu.h
index e1d4eb5967..6bf5786750 100644
--- a/xen/include/xen/cpu.h
+++ b/xen/include/xen/cpu.h
@@ -13,6 +13,16 @@ void put_cpu_maps(void);
void cpu_hotplug_begin(void);
void cpu_hotplug_done(void);
+/*
+ * Returns true when the caller CPU is between a cpu_hotplug_{begin,done}()
+ * region.
+ *
+ * This is required to safely identify hotplug contexts, as get_cpu_maps()
+ * would otherwise succeed because a caller holding the lock in write mode is
+ * allowed to acquire the same lock in read mode.
+ */
+bool cpu_in_hotplug_context(void);
+
/* Receive notification of CPU hotplug events. */
void register_cpu_notifier(struct notifier_block *nb);
diff --git a/xen/include/xen/rwlock.h b/xen/include/xen/rwlock.h
index a2e98cad34..4e78028218 100644
--- a/xen/include/xen/rwlock.h
+++ b/xen/include/xen/rwlock.h
@@ -316,6 +316,8 @@ static always_inline void write_lock_irq(rwlock_t *l)
#define rw_is_locked(l) _rw_is_locked(l)
#define rw_is_write_locked(l) _rw_is_write_locked(l)
+#define rw_is_write_locked_by_me(l) \
+ lock_evaluate_nospec(_is_write_locked_by_me(atomic_read(&(l)->cnts)))
typedef struct percpu_rwlock percpu_rwlock_t;
--
generated by git-patchbot for /home/xen/git/xen.git#master
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |