Branch data Line data Source code
1 : : /*
2 : : * CPU subsystem support
3 : : */
4 : :
5 : : #include <linux/kernel.h>
6 : : #include <linux/module.h>
7 : : #include <linux/init.h>
8 : : #include <linux/sched.h>
9 : : #include <linux/cpu.h>
10 : : #include <linux/topology.h>
11 : : #include <linux/device.h>
12 : : #include <linux/node.h>
13 : : #include <linux/gfp.h>
14 : : #include <linux/slab.h>
15 : : #include <linux/percpu.h>
16 : : #include <linux/acpi.h>
17 : : #include <linux/of.h>
18 : :
19 : : #include "base.h"
20 : :
21 : : static DEFINE_PER_CPU(struct device *, cpu_sys_devices);
22 : :
23 : 0 : static int cpu_subsys_match(struct device *dev, struct device_driver *drv)
24 : : {
25 : : /* ACPI style match is the only one that may succeed. */
26 : : if (acpi_driver_match_device(dev, drv))
27 : : return 1;
28 : :
29 : : return 0;
30 : : }
31 : :
32 : : #ifdef CONFIG_HOTPLUG_CPU
33 : : static void change_cpu_under_node(struct cpu *cpu,
34 : : unsigned int from_nid, unsigned int to_nid)
35 : : {
36 : : int cpuid = cpu->dev.id;
37 : : unregister_cpu_under_node(cpuid, from_nid);
38 : : register_cpu_under_node(cpuid, to_nid);
39 : : cpu->node_id = to_nid;
40 : : }
41 : :
42 : 0 : static int __ref cpu_subsys_online(struct device *dev)
43 : : {
44 : : struct cpu *cpu = container_of(dev, struct cpu, dev);
45 : 0 : int cpuid = dev->id;
46 : : int from_nid, to_nid;
47 : : int ret;
48 : :
49 : : from_nid = cpu_to_node(cpuid);
50 : : if (from_nid == NUMA_NO_NODE)
51 : : return -ENODEV;
52 : :
53 : 0 : ret = cpu_up(cpuid);
54 : : /*
55 : : * When hot adding memory to memoryless node and enabling a cpu
56 : : * on the node, node number of the cpu may internally change.
57 : : */
58 : : to_nid = cpu_to_node(cpuid);
59 : : if (from_nid != to_nid)
60 : : change_cpu_under_node(cpu, from_nid, to_nid);
61 : :
62 : : return ret;
63 : : }
64 : :
65 : 0 : static int cpu_subsys_offline(struct device *dev)
66 : : {
67 : 0 : return cpu_down(dev->id);
68 : : }
69 : :
70 : 0 : void unregister_cpu(struct cpu *cpu)
71 : : {
72 : 0 : int logical_cpu = cpu->dev.id;
73 : :
74 : : unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu));
75 : :
76 : 0 : device_unregister(&cpu->dev);
77 : 0 : per_cpu(cpu_sys_devices, logical_cpu) = NULL;
78 : 0 : return;
79 : : }
80 : :
81 : : #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
82 : : static ssize_t cpu_probe_store(struct device *dev,
83 : : struct device_attribute *attr,
84 : : const char *buf,
85 : : size_t count)
86 : : {
87 : : ssize_t cnt;
88 : : int ret;
89 : :
90 : : ret = lock_device_hotplug_sysfs();
91 : : if (ret)
92 : : return ret;
93 : :
94 : : cnt = arch_cpu_probe(buf, count);
95 : :
96 : : unlock_device_hotplug();
97 : : return cnt;
98 : : }
99 : :
100 : : static ssize_t cpu_release_store(struct device *dev,
101 : : struct device_attribute *attr,
102 : : const char *buf,
103 : : size_t count)
104 : : {
105 : : ssize_t cnt;
106 : : int ret;
107 : :
108 : : ret = lock_device_hotplug_sysfs();
109 : : if (ret)
110 : : return ret;
111 : :
112 : : cnt = arch_cpu_release(buf, count);
113 : :
114 : : unlock_device_hotplug();
115 : : return cnt;
116 : : }
117 : :
118 : : static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
119 : : static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store);
120 : : #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
121 : : #endif /* CONFIG_HOTPLUG_CPU */
122 : :
123 : : struct bus_type cpu_subsys = {
124 : : .name = "cpu",
125 : : .dev_name = "cpu",
126 : : .match = cpu_subsys_match,
127 : : #ifdef CONFIG_HOTPLUG_CPU
128 : : .online = cpu_subsys_online,
129 : : .offline = cpu_subsys_offline,
130 : : #endif
131 : : };
132 : : EXPORT_SYMBOL_GPL(cpu_subsys);
133 : :
134 : : #ifdef CONFIG_KEXEC
135 : : #include <linux/kexec.h>
136 : :
137 : : static ssize_t show_crash_notes(struct device *dev, struct device_attribute *attr,
138 : : char *buf)
139 : : {
140 : : struct cpu *cpu = container_of(dev, struct cpu, dev);
141 : : ssize_t rc;
142 : : unsigned long long addr;
143 : : int cpunum;
144 : :
145 : : cpunum = cpu->dev.id;
146 : :
147 : : /*
148 : : * Might be reading other cpu's data based on which cpu read thread
149 : : * has been scheduled. But cpu data (memory) is allocated once during
150 : : * boot up and this data does not change there after. Hence this
151 : : * operation should be safe. No locking required.
152 : : */
153 : : addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpunum));
154 : : rc = sprintf(buf, "%Lx\n", addr);
155 : : return rc;
156 : : }
157 : : static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
158 : :
159 : : static ssize_t show_crash_notes_size(struct device *dev,
160 : : struct device_attribute *attr,
161 : : char *buf)
162 : : {
163 : : ssize_t rc;
164 : :
165 : : rc = sprintf(buf, "%zu\n", sizeof(note_buf_t));
166 : : return rc;
167 : : }
168 : : static DEVICE_ATTR(crash_notes_size, 0400, show_crash_notes_size, NULL);
169 : :
170 : : static struct attribute *crash_note_cpu_attrs[] = {
171 : : &dev_attr_crash_notes.attr,
172 : : &dev_attr_crash_notes_size.attr,
173 : : NULL
174 : : };
175 : :
176 : : static struct attribute_group crash_note_cpu_attr_group = {
177 : : .attrs = crash_note_cpu_attrs,
178 : : };
179 : : #endif
180 : :
181 : : static const struct attribute_group *common_cpu_attr_groups[] = {
182 : : #ifdef CONFIG_KEXEC
183 : : &crash_note_cpu_attr_group,
184 : : #endif
185 : : NULL
186 : : };
187 : :
188 : : static const struct attribute_group *hotplugable_cpu_attr_groups[] = {
189 : : #ifdef CONFIG_KEXEC
190 : : &crash_note_cpu_attr_group,
191 : : #endif
192 : : NULL
193 : : };
194 : :
195 : : /*
196 : : * Print cpu online, possible, present, and system maps
197 : : */
198 : :
199 : : struct cpu_attr {
200 : : struct device_attribute attr;
201 : : const struct cpumask *const * const map;
202 : : };
203 : :
204 : 0 : static ssize_t show_cpus_attr(struct device *dev,
205 : : struct device_attribute *attr,
206 : : char *buf)
207 : : {
208 : : struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr);
209 : 267 : int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *(ca->map));
210 : :
211 : 267 : buf[n++] = '\n';
212 : 267 : buf[n] = '\0';
213 : 267 : return n;
214 : : }
215 : :
216 : : #define _CPU_ATTR(name, map) \
217 : : { __ATTR(name, 0444, show_cpus_attr, NULL), map }
218 : :
219 : : /* Keep in sync with cpu_subsys_attrs */
220 : : static struct cpu_attr cpu_attrs[] = {
221 : : _CPU_ATTR(online, &cpu_online_mask),
222 : : _CPU_ATTR(possible, &cpu_possible_mask),
223 : : _CPU_ATTR(present, &cpu_present_mask),
224 : : };
225 : :
226 : : /*
227 : : * Print values for NR_CPUS and offlined cpus
228 : : */
229 : 0 : static ssize_t print_cpus_kernel_max(struct device *dev,
230 : : struct device_attribute *attr, char *buf)
231 : : {
232 : 0 : int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
233 : 0 : return n;
234 : : }
235 : : static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
236 : :
237 : : /* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
238 : : unsigned int total_cpus;
239 : :
240 : 0 : static ssize_t print_cpus_offline(struct device *dev,
241 : : struct device_attribute *attr, char *buf)
242 : : {
243 : : int n = 0, len = PAGE_SIZE-2;
244 : : cpumask_var_t offline;
245 : :
246 : : /* display offline cpus < nr_cpu_ids */
247 : : if (!alloc_cpumask_var(&offline, GFP_KERNEL))
248 : : return -ENOMEM;
249 : 0 : cpumask_andnot(offline, cpu_possible_mask, cpu_online_mask);
250 : : n = cpulist_scnprintf(buf, len, offline);
251 : : free_cpumask_var(offline);
252 : :
253 : : /* display offline cpus >= nr_cpu_ids */
254 [ # # ][ # # ]: 0 : if (total_cpus && nr_cpu_ids < total_cpus) {
255 [ # # ]: 0 : if (n && n < len)
256 : 0 : buf[n++] = ',';
257 : :
258 [ # # ]: 0 : if (nr_cpu_ids == total_cpus-1)
259 : 0 : n += snprintf(&buf[n], len - n, "%d", nr_cpu_ids);
260 : : else
261 : 0 : n += snprintf(&buf[n], len - n, "%d-%d",
262 : : nr_cpu_ids, total_cpus-1);
263 : : }
264 : :
265 : 0 : n += snprintf(&buf[n], len - n, "\n");
266 : : return n;
267 : : }
268 : : static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
269 : :
270 : 0 : static void cpu_device_release(struct device *dev)
271 : : {
272 : : /*
273 : : * This is an empty function to prevent the driver core from spitting a
274 : : * warning at us. Yes, I know this is directly opposite of what the
275 : : * documentation for the driver core and kobjects say, and the author
276 : : * of this code has already been publically ridiculed for doing
277 : : * something as foolish as this. However, at this point in time, it is
278 : : * the only way to handle the issue of statically allocated cpu
279 : : * devices. The different architectures will have their cpu device
280 : : * code reworked to properly handle this in the near future, so this
281 : : * function will then be changed to correctly free up the memory held
282 : : * by the cpu device.
283 : : *
284 : : * Never copy this way of doing things, or you too will be made fun of
285 : : * on the linux-kernel list, you have been warned.
286 : : */
287 : 0 : }
288 : :
289 : : /*
290 : : * register_cpu - Setup a sysfs device for a CPU.
291 : : * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
292 : : * sysfs for this CPU.
293 : : * @num - CPU number to use when creating the device.
294 : : *
295 : : * Initialize and register the CPU device.
296 : : */
297 : 0 : int register_cpu(struct cpu *cpu, int num)
298 : : {
299 : : int error;
300 : :
301 : 0 : cpu->node_id = cpu_to_node(num);
302 : 0 : memset(&cpu->dev, 0x00, sizeof(struct device));
303 : 0 : cpu->dev.id = num;
304 : 0 : cpu->dev.bus = &cpu_subsys;
305 : 0 : cpu->dev.release = cpu_device_release;
306 : 0 : cpu->dev.offline_disabled = !cpu->hotpluggable;
307 : 0 : cpu->dev.offline = !cpu_online(num);
308 : 0 : cpu->dev.of_node = of_get_cpu_node(num, NULL);
309 : : #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
310 : : cpu->dev.bus->uevent = arch_cpu_uevent;
311 : : #endif
312 : 0 : cpu->dev.groups = common_cpu_attr_groups;
313 [ # # ]: 0 : if (cpu->hotpluggable)
314 : 0 : cpu->dev.groups = hotplugable_cpu_attr_groups;
315 : 0 : error = device_register(&cpu->dev);
316 [ # # ]: 0 : if (!error)
317 : 0 : per_cpu(cpu_sys_devices, num) = &cpu->dev;
318 : : if (!error)
319 : : register_cpu_under_node(num, cpu_to_node(num));
320 : :
321 : 0 : return error;
322 : : }
323 : :
324 : 0 : struct device *get_cpu_device(unsigned cpu)
325 : : {
326 [ # # ][ # # ]: 0 : if (cpu < nr_cpu_ids && cpu_possible(cpu))
327 : 0 : return per_cpu(cpu_sys_devices, cpu);
328 : : else
329 : : return NULL;
330 : : }
331 : : EXPORT_SYMBOL_GPL(get_cpu_device);
332 : :
333 : : #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
334 : : static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
335 : : #endif
336 : :
337 : : static struct attribute *cpu_root_attrs[] = {
338 : : #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
339 : : &dev_attr_probe.attr,
340 : : &dev_attr_release.attr,
341 : : #endif
342 : : &cpu_attrs[0].attr.attr,
343 : : &cpu_attrs[1].attr.attr,
344 : : &cpu_attrs[2].attr.attr,
345 : : &dev_attr_kernel_max.attr,
346 : : &dev_attr_offline.attr,
347 : : #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
348 : : &dev_attr_modalias.attr,
349 : : #endif
350 : : NULL
351 : : };
352 : :
353 : : static struct attribute_group cpu_root_attr_group = {
354 : : .attrs = cpu_root_attrs,
355 : : };
356 : :
357 : : static const struct attribute_group *cpu_root_attr_groups[] = {
358 : : &cpu_root_attr_group,
359 : : NULL,
360 : : };
361 : :
362 : 0 : bool cpu_is_hotpluggable(unsigned cpu)
363 : : {
364 : 0 : struct device *dev = get_cpu_device(cpu);
365 [ # # ][ # # ]: 0 : return dev && container_of(dev, struct cpu, dev)->hotpluggable;
366 : : }
367 : : EXPORT_SYMBOL_GPL(cpu_is_hotpluggable);
368 : :
369 : : #ifdef CONFIG_GENERIC_CPU_DEVICES
370 : : static DEFINE_PER_CPU(struct cpu, cpu_devices);
371 : : #endif
372 : :
373 : : static void __init cpu_dev_register_generic(void)
374 : : {
375 : : #ifdef CONFIG_GENERIC_CPU_DEVICES
376 : : int i;
377 : :
378 : : for_each_possible_cpu(i) {
379 : : if (register_cpu(&per_cpu(cpu_devices, i), i))
380 : : panic("Failed to register CPU device");
381 : : }
382 : : #endif
383 : : }
384 : :
385 : 0 : void __init cpu_dev_init(void)
386 : : {
387 [ # # ]: 0 : if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))
388 : 0 : panic("Failed to register CPU subsystem");
389 : :
390 : : cpu_dev_register_generic();
391 : 0 : }
|