[PATCH 01/14] Introduce cpu_enabled_map and friends

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux