Re: [PATCH v2 03/17] cpumask: Introduce cpu_preferred_mask

From: Shrikanth Hegde

Date: Tue May 05 2026 - 00:11:27 EST


Hi Yury.

On 4/8/26 11:27 PM, Yury Norov wrote:

I suggest adding, for example, config PREFERRED_CPUS that would select
PARAVIRT, and would be disabled by default.

Regardless, whatever you decide, please keep all the cpu_paravirt_mask
ifdefery on the cpumasks level. For example, in patch #5:

+#ifdef CONFIG_PARAVIRT
+static inline bool task_can_run_on_preferred_cpu(struct task_struct *p)
+{
+ return cpumask_intersects(p->cpus_ptr, cpu_preferred_mask);
+}
+#else
+static inline bool task_can_run_on_preferred_cpu(struct task_struct *p)
+{
+ return true;
+}
+#endif

That looks wrong to me. Instead, either declare cpu_preferred_mask
unconditionally, and maintain it well, or

+#ifdef CONFIG_PREFERRED_CPUS
+extern struct cpumask __cpu_preferred_mask;
+#else
+#define __cpu_preferred_mask __cpu_online_mask
+#endif

This way, your higher level code will be clean.

Thanks,
Yury

Thanks Yury for the suggestion. This method is indeed cleaner.

So I have made it as below. It is rough patch, i may have to clean it up still.
But this helps to get much of ifdeffery elsewhere.
Most of the ifdeffery will be in cpumask.h, sched.h.

Hopefully I should be able to send the series by this week.
---

diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
index 88c594c6d7fc..c62001b52fab 100644
--- a/kernel/Kconfig.preempt
+++ b/kernel/Kconfig.preempt
@@ -192,3 +192,17 @@ config SCHED_CLASS_EXT
For more information:
Documentation/scheduler/sched-ext.rst
https://github.com/sched-ext/scx
+
+config PREFERRED_CPU
+ bool "Dynamic vCPU management based on steal time"
+ default y if PARAVIRT
+ help
+ This feature helps to reduce the steal time in paravirtualised
+ environment, there by reducing vCPU preemption. Reducing vCPU
+ preemption provides improved lock holder preemption and reduces
+ cost of vCPU preemption in the host.

diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 80211900f373..577b8d992a45 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -120,12 +120,20 @@ extern struct cpumask __cpu_enabled_mask;
extern struct cpumask __cpu_present_mask;
extern struct cpumask __cpu_active_mask;
extern struct cpumask __cpu_dying_mask;
+
+#ifdef CONFIG_PREFERRED_CPU
+extern struct cpumask __cpu_preferred_mask;
+#else
+#define __cpu_preferred_mask __cpu_online_mask
+#endif
+
#define cpu_possible_mask ((const struct cpumask *)&__cpu_possible_mask)
#define cpu_online_mask ((const struct cpumask *)&__cpu_online_mask)
#define cpu_enabled_mask ((const struct cpumask *)&__cpu_enabled_mask)
#define cpu_present_mask ((const struct cpumask *)&__cpu_present_mask)
#define cpu_active_mask ((const struct cpumask *)&__cpu_active_mask)
#define cpu_dying_mask ((const struct cpumask *)&__cpu_dying_mask)
+#define cpu_preferred_mask ((const struct cpumask *)&__cpu_preferred_mask)
extern atomic_t __num_online_cpus;
extern unsigned int __num_possible_cpus;
@@ -1164,6 +1172,7 @@ void init_cpu_possible(const struct cpumask *src);
void set_cpu_online(unsigned int cpu, bool online);
void set_cpu_possible(unsigned int cpu, bool possible);
+void set_cpu_preferred(unsigned int cpu, bool preferred);
/**
* to_cpumask - convert a NR_CPUS bitmap to a struct cpumask *
@@ -1256,7 +1265,12 @@ static __always_inline bool cpu_dying(unsigned int cpu)
return cpumask_test_cpu(cpu, cpu_dying_mask);
}
-#else
+static __always_inline bool cpu_preferred(unsigned int cpu)
+{
+ return cpumask_test_cpu(cpu, cpu_preferred_mask);
+}
+
+#else /* NR_CPUS <= 1 */
#define num_online_cpus() 1U
#define num_possible_cpus() 1U
@@ -1294,6 +1308,11 @@ static __always_inline bool cpu_dying(unsigned int cpu)
return false;
}
+static __always_inline bool cpu_preferred(unsigned int cpu)
+{
+ return false;
+}
+
#endif /* NR_CPUS > 1 */
#define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
diff --git a/kernel/cpu.c b/kernel/cpu.c
index bc4f7a9ba64e..7787c907f9b8 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -3107,6 +3107,11 @@ EXPORT_SYMBOL(__cpu_dying_mask);
atomic_t __num_online_cpus __read_mostly;
EXPORT_SYMBOL(__num_online_cpus);
+#ifdef CONFIG_PREFERRED_CPU
+struct cpumask __cpu_preferred_mask __read_mostly;
+EXPORT_SYMBOL(__cpu_preferred_mask);
+#endif
+
void init_cpu_present(const struct cpumask *src)
{
cpumask_copy(&__cpu_present_mask, src);
@@ -3154,6 +3159,14 @@ void set_cpu_possible(unsigned int cpu, bool possible)
}
}
+void set_cpu_preferred(unsigned int cpu, bool preferred)
+{
+ if(!IS_ENABLED(CONFIG_PREFERRED_CPU))
+ return;
+
+ assign_cpu((cpu), &__cpu_preferred_mask, (preferred));
+}
+
/*
* Activate the first processor.
*/