cpu.c revision e37d05dad7ff9744efd8ea95a70d389e9a65a6fc
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * drivers/base/cpu.c - basic CPU class support 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sysdev.h> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 8f6a570333e554b48ad589e7137c77c57809eee81Al Viro#include <linux/sched.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/cpu.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/topology.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h> 1276b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki#include <linux/node.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14a1bdc7aad8b557176ccecff1da137ebe3090871eBen Dooks#include "base.h" 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sysdev_class cpu_sysdev_class = { 17af5ca3f4ec5cc4432a42a73b050dd8898ce8fd00Kay Sievers .name = "cpu", 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(cpu_sysdev_class); 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21e37d05dad7ff9744efd8ea95a70d389e9a65a6fcMike Travisstatic DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices); 22ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_HOTPLUG_CPU 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t show_online(struct sys_device *dev, char *buf) 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cpu *cpu = container_of(dev, struct cpu, sysdev); 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 316c847402e1c69c1cfe2bddeadc8391bacbb3d0a5Sam Ravnborgstatic ssize_t __ref store_online(struct sys_device *dev, const char *buf, 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t count) 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cpu *cpu = container_of(dev, struct cpu, sysdev); 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ssize_t ret; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (buf[0]) { 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case '0': 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = cpu_down(cpu->sysdev.id); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret) 41312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers kobject_uevent(&dev->kobj, KOBJ_OFFLINE); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case '1': 4434f361ade2fb4a869f6a7714d01c04ce4cfa75d9Ashok Raj ret = cpu_up(cpu->sysdev.id); 45fb69c3907ead36b9e9f41ea6f0d0e0ae10a38a47Nathan Lynch if (!ret) 46312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers kobject_uevent(&dev->kobj, KOBJ_ONLINE); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret >= 0) 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = count; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 569eb3ff40376e505eafb927b4a4cbccc928df68ecUlrich Drepperstatic SYSDEV_ATTR(online, 0644, show_online, store_online); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 586c847402e1c69c1cfe2bddeadc8391bacbb3d0a5Sam Ravnborgstatic void __cpuinit register_cpu_control(struct cpu *cpu) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysdev_create_file(&cpu->sysdev, &attr_online); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6276b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyukivoid unregister_cpu(struct cpu *cpu) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 64ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj int logical_cpu = cpu->sysdev.id; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6676b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu)); 6776b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysdev_remove_file(&cpu->sysdev, &attr_online); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysdev_unregister(&cpu->sysdev); 71e37d05dad7ff9744efd8ea95a70d389e9a65a6fcMike Travis per_cpu(cpu_sys_devices, logical_cpu) = NULL; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* ... !CONFIG_HOTPLUG_CPU */ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void register_cpu_control(struct cpu *cpu) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_HOTPLUG_CPU */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8051be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#ifdef CONFIG_KEXEC 8151be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#include <linux/kexec.h> 8251be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 8351be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyalstatic ssize_t show_crash_notes(struct sys_device *dev, char *buf) 8451be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal{ 8551be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal struct cpu *cpu = container_of(dev, struct cpu, sysdev); 8651be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal ssize_t rc; 8751be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal unsigned long long addr; 8851be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal int cpunum; 8951be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 9051be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal cpunum = cpu->sysdev.id; 9151be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 9251be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal /* 9351be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * Might be reading other cpu's data based on which cpu read thread 9451be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * has been scheduled. But cpu data (memory) is allocated once during 9551be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * boot up and this data does not change there after. Hence this 9651be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal * operation should be safe. No locking required. 9751be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal */ 9851be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal addr = __pa(per_cpu_ptr(crash_notes, cpunum)); 9951be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal rc = sprintf(buf, "%Lx\n", addr); 10051be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal return rc; 10151be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal} 10251be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyalstatic SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); 10351be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#endif 10451be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1069d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis * Print cpu online, possible, present, and system maps 1079d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis */ 1089d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travisstatic ssize_t print_cpus_map(char *buf, cpumask_t *map) 1099d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis{ 1109d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *map); 1119d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1129d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis buf[n++] = '\n'; 1139d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis buf[n] = '\0'; 1149d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis return n; 1159d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis} 1169d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1179d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis#define print_cpus_func(type) \ 1189d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travisstatic ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \ 1199d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis{ \ 1209d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis return print_cpus_map(buf, &cpu_##type##_map); \ 1219d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis} \ 1229d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travisstruct sysdev_class_attribute attr_##type##_map = \ 1239d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL) 1249d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1259d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travisprint_cpus_func(online); 1269d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travisprint_cpus_func(possible); 1279d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travisprint_cpus_func(present); 1289d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1299d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travisstruct sysdev_class_attribute *cpu_state_attr[] = { 1309d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis &attr_online_map, 1319d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis &attr_possible_map, 1329d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis &attr_present_map, 1339d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis}; 1349d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1359d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travisstatic int cpu_states_init(void) 1369d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis{ 1379d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis int i; 1389d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis int err = 0; 1399d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1409d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis for (i = 0; i < ARRAY_SIZE(cpu_state_attr); i++) { 1419d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis int ret; 1429d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis ret = sysdev_class_create_file(&cpu_sysdev_class, 1439d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis cpu_state_attr[i]); 1449d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis if (!err) 1459d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis err = ret; 1469d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis } 1479d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis return err; 1489d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis} 1499d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1509d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis/* 151405ae7d381302468ecc803f2148a2ae40a04c999Robert P. J. Day * register_cpu - Setup a sysfs device for a CPU. 15272486f1f8f0a2bc828b9d30cf4690cf2dd6807fcSiddha, Suresh B * @cpu - cpu->hotpluggable field set to 1 will generate a control file in 15372486f1f8f0a2bc828b9d30cf4690cf2dd6807fcSiddha, Suresh B * sysfs for this CPU. 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @num - CPU number to use when creating the device. 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize and register the CPU device. 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15833b5f31bbc4d047d048d8635fccdab38ffe6c287Randy Dunlapint __cpuinit register_cpu(struct cpu *cpu, int num) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu->node_id = cpu_to_node(num); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu->sysdev.id = num; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu->sysdev.cls = &cpu_sysdev_class; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = sysdev_register(&cpu->sysdev); 16676b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki 16772486f1f8f0a2bc828b9d30cf4690cf2dd6807fcSiddha, Suresh B if (!error && cpu->hotpluggable) 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_cpu_control(cpu); 169ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj if (!error) 170e37d05dad7ff9744efd8ea95a70d389e9a65a6fcMike Travis per_cpu(cpu_sys_devices, num) = &cpu->sysdev; 17176b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki if (!error) 17276b67ed9dce69a6a329cdd66f94af1787f417b62KAMEZAWA Hiroyuki register_cpu_under_node(num, cpu_to_node(num)); 17351be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal 17451be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#ifdef CONFIG_KEXEC 17551be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal if (!error) 17651be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes); 17751be5606d9ff9eb27ed6514f6172fbd7578a25d6Vivek Goyal#endif 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181a29d642a4aa99c5234314ab2523281139226c231Andrew Mortonstruct sys_device *get_cpu_sysdev(unsigned cpu) 182ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj{ 183e37d05dad7ff9744efd8ea95a70d389e9a65a6fcMike Travis if (cpu < nr_cpu_ids && cpu_possible(cpu)) 184e37d05dad7ff9744efd8ea95a70d389e9a65a6fcMike Travis return per_cpu(cpu_sys_devices, cpu); 185ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj else 186ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj return NULL; 187ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok Raj} 188ad74557a49d1dea428fb0ad60e75a5aa37610e1dAshok RajEXPORT_SYMBOL_GPL(get_cpu_sysdev); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init cpu_dev_init(void) 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1925c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B int err; 1935c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B 1945c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B err = sysdev_class_register(&cpu_sysdev_class); 1959d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis if (!err) 1969d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis err = cpu_states_init(); 1979d1fe3236a1d64ab687e16b4cbbaa1383352a2c1Mike Travis 1985c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) 1995c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B if (!err) 2005c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class); 2015c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B#endif 2025c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B 2035c45bf279d378d436ce45825c0f136696c7b6109Siddha, Suresh B return err; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 205