[PATCH 01/14] Introduce cpu_enabled_map and friends
From: Alex Chiang
Date: Mon Jul 14 2008 - 22:39:07 EST
Currently, the following cpu maps exist:
cpu_possible_map - map of populatable CPUs
cpu_present_map - map of populated CPUs
cpu_online_map - map of schedulable CPUs
These maps do not provide the concept of populated, but disabled CPUs.
That is, a system may contain CPU modules that are physically plugged
in, but disabled by system firmware. The existence of this class of
CPUs breaks the following assumption in smp_init():
for_each_present_cpu(cpu) {
.../...
if (!cpu_online(cpu))
cpu_up(cpu);
}
The assumption is that the kernel should attempt cpu_up() on every
physically populated CPU, which may not be desirable for present but
disabled CPUs.
By providing cpu_enabled_map, we can keep the above [simplifying]
assumption in smp_init(), and push the knowledge of disabled CPUs
and the decision to bring them up, down into arch specific code.
Signed-off-by: Alex Chiang <achiang@xxxxxx>
---
drivers/base/cpu.c | 9 +++++++--
include/linux/cpumask.h | 31 ++++++++++++++++++++++++-------
init/main.c | 1 +
kernel/sched.c | 16 ++++++++++++----
4 files changed, 44 insertions(+), 13 deletions(-)
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index e38dfed..bc300df 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -57,7 +57,10 @@ static SYSDEV_ATTR(online, 0644, show_online, store_online);
static void __cpuinit register_cpu_control(struct cpu *cpu)
{
- sysdev_create_file(&cpu->sysdev, &attr_online);
+ int logical_cpu = cpu->sysdev.id;
+
+ if (cpu_isset(logical_cpu, cpu_enabled_map))
+ sysdev_create_file(&cpu->sysdev, &attr_online);
}
void unregister_cpu(struct cpu *cpu)
{
@@ -125,11 +128,13 @@ struct sysdev_class_attribute attr_##type##_map = \
print_cpus_func(online);
print_cpus_func(possible);
print_cpus_func(present);
+print_cpus_func(enabled);
struct sysdev_class_attribute *cpu_state_attr[] = {
&attr_online_map,
&attr_possible_map,
&attr_present_map,
+ &attr_enabled_map,
};
static int cpu_states_init(void)
@@ -172,7 +177,7 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
register_cpu_under_node(num, cpu_to_node(num));
#ifdef CONFIG_KEXEC
- if (!error)
+ if ((!error) && cpu_isset(num, cpu_enabled_map))
error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes);
#endif
return error;
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index c24875b..bba31aa 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -64,16 +64,19 @@
* int num_online_cpus() Number of online CPUs
* int num_possible_cpus() Number of all possible CPUs
* int num_present_cpus() Number of present CPUs
+ * int num_enabled_cpus() Number of enabled CPUs
*
* int cpu_online(cpu) Is some cpu online?
* int cpu_possible(cpu) Is some cpu possible?
* int cpu_present(cpu) Is some cpu present (can schedule)?
+ * int cpu_enabled(cpu) Is some cpu enabled (by firmware)?
*
* int any_online_cpu(mask) First online cpu in mask
*
* for_each_possible_cpu(cpu) for-loop cpu over cpu_possible_map
* for_each_online_cpu(cpu) for-loop cpu over cpu_online_map
* for_each_present_cpu(cpu) for-loop cpu over cpu_present_map
+ * for_each_enabled_cpu(cpu) for-loop cpu over cpu_enabled_map
*
* Subtlety:
* 1) The 'type-checked' form of cpu_isset() causes gcc (3.3.2, anyway)
@@ -359,16 +362,18 @@ static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp,
/*
* The following particular system cpumasks and operations manage
- * possible, present and online cpus. Each of them is a fixed size
- * bitmap of size NR_CPUS.
+ * possible, present, enabled and online cpus. Each of them is a fixed
+ * size bitmap of size NR_CPUS.
*
* #ifdef CONFIG_HOTPLUG_CPU
* cpu_possible_map - has bit 'cpu' set iff cpu is populatable
* cpu_present_map - has bit 'cpu' set iff cpu is populated
+ * cpu_enabled_map - has bit 'cpu' set iff cpu is enabled by firmware
* cpu_online_map - has bit 'cpu' set iff cpu available to scheduler
* #else
* cpu_possible_map - has bit 'cpu' set iff cpu is populated
* cpu_present_map - copy of cpu_possible_map
+ * cpu_enabled_map - copy of cpu_possible_map
* cpu_online_map - has bit 'cpu' set iff cpu available to scheduler
* #endif
*
@@ -377,9 +382,10 @@ static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp,
* time, as the set of CPU id's that it is possible might ever
* be plugged in at anytime during the life of that system boot.
* The cpu_present_map is dynamic(*), representing which CPUs
- * are currently plugged in. And cpu_online_map is the dynamic
- * subset of cpu_present_map, indicating those CPUs available
- * for scheduling.
+ * are currently plugged in. The cpu_enabled_map is also dynamic(*),
+ * and represents CPUs both plugged in and enabled by firmware.
+ * And cpu_online_map is the dynamic subset of cpu_present_map,
+ * indicating those CPUs available for scheduling.
*
* If HOTPLUG is enabled, then cpu_possible_map is forced to have
* all NR_CPUS bits set, otherwise it is just the set of CPUs that
@@ -389,8 +395,13 @@ static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp,
* depending on what ACPI reports as currently plugged in, otherwise
* cpu_present_map is just a copy of cpu_possible_map.
*
- * (*) Well, cpu_present_map is dynamic in the hotplug case. If not
- * hotplug, it's a copy of cpu_possible_map, hence fixed at boot.
+ * If HOTPLUG is enabled, then cpu_enabled_map varies dynamically,
+ * depending on what ACPI reports as currently enabled by firmware,
+ * otherwise cpu_enabled_map is just a copy of cpu_possible_map.
+ *
+ * (*) Well, cpu_present_map and cpu_enabled_map are dynamic in the
+ * hotplug case. If not hotplug, they're copies of cpu_possible_map,
+ * hence fixed at boot.
*
* Subtleties:
* 1) UP arch's (NR_CPUS == 1, CONFIG_SMP not defined) hardcode
@@ -416,21 +427,26 @@ static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp,
extern cpumask_t cpu_possible_map;
extern cpumask_t cpu_online_map;
extern cpumask_t cpu_present_map;
+extern cpumask_t cpu_enabled_map;
#if NR_CPUS > 1
#define num_online_cpus() cpus_weight(cpu_online_map)
#define num_possible_cpus() cpus_weight(cpu_possible_map)
#define num_present_cpus() cpus_weight(cpu_present_map)
+#define num_enabled_cpus() cpus_weight(cpu_enabled_map)
#define cpu_online(cpu) cpu_isset((cpu), cpu_online_map)
#define cpu_possible(cpu) cpu_isset((cpu), cpu_possible_map)
#define cpu_present(cpu) cpu_isset((cpu), cpu_present_map)
+#define cpu_enabled(cpu) cpu_isset((cpu), cpu_enabled_map)
#else
#define num_online_cpus() 1
#define num_possible_cpus() 1
#define num_present_cpus() 1
+#define num_enabled_cpus() 1
#define cpu_online(cpu) ((cpu) == 0)
#define cpu_possible(cpu) ((cpu) == 0)
#define cpu_present(cpu) ((cpu) == 0)
+#define cpu_enabled(cpu) ((cpu) == 0)
#endif
#define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
@@ -447,5 +463,6 @@ int __any_online_cpu(const cpumask_t *mask);
#define for_each_possible_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map)
#define for_each_online_cpu(cpu) for_each_cpu_mask((cpu), cpu_online_map)
#define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map)
+#define for_each_enabled_cpu(cpu) for_each_cpu_mask((cpu), cpu_enabled_map)
#endif /* __LINUX_CPUMASK_H */
diff --git a/init/main.c b/init/main.c
index f7fb200..1fe50c6 100644
--- a/init/main.c
+++ b/init/main.c
@@ -520,6 +520,7 @@ static void __init boot_cpu_init(void)
/* Mark the boot cpu "present", "online" etc for SMP and UP case */
cpu_set(cpu, cpu_online_map);
cpu_set(cpu, cpu_present_map);
+ cpu_set(cpu, cpu_enabled_map);
cpu_set(cpu, cpu_possible_map);
}
diff --git a/kernel/sched.c b/kernel/sched.c
index 4e2f603..b04eb61 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -5071,15 +5071,23 @@ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
}
/*
- * Represents all cpu's present in the system
+ * Represents all CPUs present in the system
* In systems capable of hotplug, this map could dynamically grow
- * as new cpu's are detected in the system via any platform specific
- * method, such as ACPI for e.g.
+ * as new CPUs are detected in the system via any platform specific
+ * method, such as ACPI.
*/
-
cpumask_t cpu_present_map __read_mostly;
EXPORT_SYMBOL(cpu_present_map);
+/*
+ * Represents all CPUs enabled by firmware in the system
+ * In systems capable of hotplug, this map could dynamically grow
+ * as new CPUs are detected in the system via any platform specific
+ * method, such as ACPI.
+ */
+cpumask_t cpu_enabled_map __read_mostly;
+EXPORT_SYMBOL(cpu_enabled_map);
+
#ifndef CONFIG_SMP
cpumask_t cpu_online_map __read_mostly = CPU_MASK_ALL;
EXPORT_SYMBOL(cpu_online_map);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/