1468e15fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * kernel/ksysfs.c - sysfs attributes in /sys/kernel, which
41da177e4SLinus Torvalds * are not related to any other subsystem
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
71da177e4SLinus Torvalds */
81da177e4SLinus Torvalds
9d3d76fbdSThomas Weißschuh #include <asm/byteorder.h>
101da177e4SLinus Torvalds #include <linux/kobject.h>
111da177e4SLinus Torvalds #include <linux/string.h>
121da177e4SLinus Torvalds #include <linux/sysfs.h>
139984de1aSPaul Gortmaker #include <linux/export.h>
141da177e4SLinus Torvalds #include <linux/init.h>
15c330dda9SJeff Moyer #include <linux/kexec.h>
1622b8ce94SDave Hansen #include <linux/profile.h>
171596425fSPaul Gortmaker #include <linux/stat.h>
185cb350baSDhaval Giani #include <linux/sched.h>
19088ab0b4SLudwig Nussel #include <linux/capability.h>
2052f5684cSGideon Israel Dsouza #include <linux/compiler.h>
211da177e4SLinus Torvalds
225a9be7c6SPaul E. McKenney #include <linux/rcupdate.h> /* rcu_expedited and rcu_normal */
237a754743SPaul Gortmaker
24d3d76fbdSThomas Weißschuh #if defined(__LITTLE_ENDIAN)
25d3d76fbdSThomas Weißschuh #define CPU_BYTEORDER_STRING "little"
26d3d76fbdSThomas Weißschuh #elif defined(__BIG_ENDIAN)
27d3d76fbdSThomas Weißschuh #define CPU_BYTEORDER_STRING "big"
28d3d76fbdSThomas Weißschuh #else
29d3d76fbdSThomas Weißschuh #error Unknown byteorder
30d3d76fbdSThomas Weißschuh #endif
31d3d76fbdSThomas Weißschuh
321da177e4SLinus Torvalds #define KERNEL_ATTR_RO(_name) \
33386f275fSKay Sievers static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
341da177e4SLinus Torvalds
351da177e4SLinus Torvalds #define KERNEL_ATTR_RW(_name) \
36a7cd9a53SMiaohe Lin static struct kobj_attribute _name##_attr = __ATTR_RW(_name)
371da177e4SLinus Torvalds
380f76e5acSKay Sievers /* current uevent sequence number */
uevent_seqnum_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)39386f275fSKay Sievers static ssize_t uevent_seqnum_show(struct kobject *kobj,
40386f275fSKay Sievers struct kobj_attribute *attr, char *buf)
411da177e4SLinus Torvalds {
429f33a88cSThomas Weißschuh return sysfs_emit(buf, "%llu\n", (unsigned long long)uevent_seqnum);
431da177e4SLinus Torvalds }
440f76e5acSKay Sievers KERNEL_ATTR_RO(uevent_seqnum);
450f76e5acSKay Sievers
46d3d76fbdSThomas Weißschuh /* cpu byteorder */
cpu_byteorder_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)47d3d76fbdSThomas Weißschuh static ssize_t cpu_byteorder_show(struct kobject *kobj,
48d3d76fbdSThomas Weißschuh struct kobj_attribute *attr, char *buf)
49d3d76fbdSThomas Weißschuh {
50d3d76fbdSThomas Weißschuh return sysfs_emit(buf, "%s\n", CPU_BYTEORDER_STRING);
51d3d76fbdSThomas Weißschuh }
52d3d76fbdSThomas Weißschuh KERNEL_ATTR_RO(cpu_byteorder);
53d3d76fbdSThomas Weißschuh
5400142bfdSThomas Weißschuh /* address bits */
address_bits_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)5500142bfdSThomas Weißschuh static ssize_t address_bits_show(struct kobject *kobj,
5600142bfdSThomas Weißschuh struct kobj_attribute *attr, char *buf)
5700142bfdSThomas Weißschuh {
5800142bfdSThomas Weißschuh return sysfs_emit(buf, "%zu\n", sizeof(void *) * 8 /* CHAR_BIT */);
5900142bfdSThomas Weißschuh }
6000142bfdSThomas Weißschuh KERNEL_ATTR_RO(address_bits);
6100142bfdSThomas Weißschuh
6286d56134SMichael Marineau #ifdef CONFIG_UEVENT_HELPER
63af665852SThadeu Lima de Souza Cascardo /* uevent helper program, used during early boot */
uevent_helper_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)64386f275fSKay Sievers static ssize_t uevent_helper_show(struct kobject *kobj,
65386f275fSKay Sievers struct kobj_attribute *attr, char *buf)
660f76e5acSKay Sievers {
679f33a88cSThomas Weißschuh return sysfs_emit(buf, "%s\n", uevent_helper);
680f76e5acSKay Sievers }
uevent_helper_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)69386f275fSKay Sievers static ssize_t uevent_helper_store(struct kobject *kobj,
70386f275fSKay Sievers struct kobj_attribute *attr,
71386f275fSKay Sievers const char *buf, size_t count)
720f76e5acSKay Sievers {
73312c004dSKay Sievers if (count+1 > UEVENT_HELPER_PATH_LEN)
740f76e5acSKay Sievers return -ENOENT;
75386f275fSKay Sievers memcpy(uevent_helper, buf, count);
76312c004dSKay Sievers uevent_helper[count] = '\0';
77312c004dSKay Sievers if (count && uevent_helper[count-1] == '\n')
78312c004dSKay Sievers uevent_helper[count-1] = '\0';
790f76e5acSKay Sievers return count;
800f76e5acSKay Sievers }
810f76e5acSKay Sievers KERNEL_ATTR_RW(uevent_helper);
8286d56134SMichael Marineau #endif
831da177e4SLinus Torvalds
8422b8ce94SDave Hansen #ifdef CONFIG_PROFILING
profiling_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)8522b8ce94SDave Hansen static ssize_t profiling_show(struct kobject *kobj,
8622b8ce94SDave Hansen struct kobj_attribute *attr, char *buf)
8722b8ce94SDave Hansen {
889f33a88cSThomas Weißschuh return sysfs_emit(buf, "%d\n", prof_on);
8922b8ce94SDave Hansen }
profiling_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)9022b8ce94SDave Hansen static ssize_t profiling_store(struct kobject *kobj,
9122b8ce94SDave Hansen struct kobj_attribute *attr,
9222b8ce94SDave Hansen const char *buf, size_t count)
9322b8ce94SDave Hansen {
9422b8ce94SDave Hansen int ret;
9522b8ce94SDave Hansen
9622b8ce94SDave Hansen if (prof_on)
9722b8ce94SDave Hansen return -EEXIST;
9822b8ce94SDave Hansen /*
9922b8ce94SDave Hansen * This eventually calls into get_option() which
10022b8ce94SDave Hansen * has a ton of callers and is not const. It is
10122b8ce94SDave Hansen * easiest to cast it away here.
10222b8ce94SDave Hansen */
10322b8ce94SDave Hansen profile_setup((char *)buf);
10422b8ce94SDave Hansen ret = profile_init();
10522b8ce94SDave Hansen if (ret)
10622b8ce94SDave Hansen return ret;
10722b8ce94SDave Hansen ret = create_proc_profile();
10822b8ce94SDave Hansen if (ret)
10922b8ce94SDave Hansen return ret;
11022b8ce94SDave Hansen return count;
11122b8ce94SDave Hansen }
11222b8ce94SDave Hansen KERNEL_ATTR_RW(profiling);
11322b8ce94SDave Hansen #endif
11422b8ce94SDave Hansen
1152965faa5SDave Young #ifdef CONFIG_KEXEC_CORE
kexec_loaded_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)116386f275fSKay Sievers static ssize_t kexec_loaded_show(struct kobject *kobj,
117386f275fSKay Sievers struct kobj_attribute *attr, char *buf)
118c330dda9SJeff Moyer {
1199f33a88cSThomas Weißschuh return sysfs_emit(buf, "%d\n", !!kexec_image);
120c330dda9SJeff Moyer }
121c330dda9SJeff Moyer KERNEL_ATTR_RO(kexec_loaded);
122c330dda9SJeff Moyer
kexec_crash_loaded_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)123386f275fSKay Sievers static ssize_t kexec_crash_loaded_show(struct kobject *kobj,
124386f275fSKay Sievers struct kobj_attribute *attr, char *buf)
125c330dda9SJeff Moyer {
1269f33a88cSThomas Weißschuh return sysfs_emit(buf, "%d\n", kexec_crash_loaded());
127c330dda9SJeff Moyer }
128c330dda9SJeff Moyer KERNEL_ATTR_RO(kexec_crash_loaded);
129fd59d231SKen'ichi Ohmichi
kexec_crash_size_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)13006a7f711SAmerigo Wang static ssize_t kexec_crash_size_show(struct kobject *kobj,
13106a7f711SAmerigo Wang struct kobj_attribute *attr, char *buf)
13206a7f711SAmerigo Wang {
1337bb5da0dSValentin Schneider ssize_t size = crash_get_memory_size();
1347bb5da0dSValentin Schneider
1357bb5da0dSValentin Schneider if (size < 0)
1367bb5da0dSValentin Schneider return size;
1377bb5da0dSValentin Schneider
1389f33a88cSThomas Weißschuh return sysfs_emit(buf, "%zd\n", size);
13906a7f711SAmerigo Wang }
kexec_crash_size_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)14006a7f711SAmerigo Wang static ssize_t kexec_crash_size_store(struct kobject *kobj,
14106a7f711SAmerigo Wang struct kobj_attribute *attr,
14206a7f711SAmerigo Wang const char *buf, size_t count)
14306a7f711SAmerigo Wang {
14406a7f711SAmerigo Wang unsigned long cnt;
14506a7f711SAmerigo Wang int ret;
14606a7f711SAmerigo Wang
1476072ddc8SJingoo Han if (kstrtoul(buf, 0, &cnt))
14806a7f711SAmerigo Wang return -EINVAL;
14906a7f711SAmerigo Wang
15006a7f711SAmerigo Wang ret = crash_shrink_memory(cnt);
15106a7f711SAmerigo Wang return ret < 0 ? ret : count;
15206a7f711SAmerigo Wang }
15306a7f711SAmerigo Wang KERNEL_ATTR_RW(kexec_crash_size);
15406a7f711SAmerigo Wang
155692f66f2SHari Bathini #endif /* CONFIG_KEXEC_CORE */
156692f66f2SHari Bathini
157692f66f2SHari Bathini #ifdef CONFIG_CRASH_CORE
158692f66f2SHari Bathini
vmcoreinfo_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)159386f275fSKay Sievers static ssize_t vmcoreinfo_show(struct kobject *kobj,
160386f275fSKay Sievers struct kobj_attribute *attr, char *buf)
161fd59d231SKen'ichi Ohmichi {
162dae28018SRussell King phys_addr_t vmcore_base = paddr_vmcoreinfo_note();
1639f33a88cSThomas Weißschuh return sysfs_emit(buf, "%pa %x\n", &vmcore_base,
164203e9e41SXunlei Pang (unsigned int)VMCOREINFO_NOTE_SIZE);
165fd59d231SKen'ichi Ohmichi }
166fd59d231SKen'ichi Ohmichi KERNEL_ATTR_RO(vmcoreinfo);
167fd59d231SKen'ichi Ohmichi
168*a72bbec7SEric DeVolder #ifdef CONFIG_CRASH_HOTPLUG
crash_elfcorehdr_size_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)169*a72bbec7SEric DeVolder static ssize_t crash_elfcorehdr_size_show(struct kobject *kobj,
170*a72bbec7SEric DeVolder struct kobj_attribute *attr, char *buf)
171*a72bbec7SEric DeVolder {
172*a72bbec7SEric DeVolder unsigned int sz = crash_get_elfcorehdr_size();
173*a72bbec7SEric DeVolder
174*a72bbec7SEric DeVolder return sysfs_emit(buf, "%u\n", sz);
175*a72bbec7SEric DeVolder }
176*a72bbec7SEric DeVolder KERNEL_ATTR_RO(crash_elfcorehdr_size);
177*a72bbec7SEric DeVolder
178*a72bbec7SEric DeVolder #endif
179*a72bbec7SEric DeVolder
180692f66f2SHari Bathini #endif /* CONFIG_CRASH_CORE */
181c330dda9SJeff Moyer
182088ab0b4SLudwig Nussel /* whether file capabilities are enabled */
fscaps_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)183088ab0b4SLudwig Nussel static ssize_t fscaps_show(struct kobject *kobj,
184088ab0b4SLudwig Nussel struct kobj_attribute *attr, char *buf)
185088ab0b4SLudwig Nussel {
1869f33a88cSThomas Weißschuh return sysfs_emit(buf, "%d\n", file_caps_enabled);
187088ab0b4SLudwig Nussel }
188088ab0b4SLudwig Nussel KERNEL_ATTR_RO(fscaps);
189088ab0b4SLudwig Nussel
19079cfea02SPaul E. McKenney #ifndef CONFIG_TINY_RCU
1913705b88dSAntti P Miettinen int rcu_expedited;
rcu_expedited_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)1923705b88dSAntti P Miettinen static ssize_t rcu_expedited_show(struct kobject *kobj,
1933705b88dSAntti P Miettinen struct kobj_attribute *attr, char *buf)
1943705b88dSAntti P Miettinen {
1959f33a88cSThomas Weißschuh return sysfs_emit(buf, "%d\n", READ_ONCE(rcu_expedited));
1963705b88dSAntti P Miettinen }
rcu_expedited_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)1973705b88dSAntti P Miettinen static ssize_t rcu_expedited_store(struct kobject *kobj,
1983705b88dSAntti P Miettinen struct kobj_attribute *attr,
1993705b88dSAntti P Miettinen const char *buf, size_t count)
2003705b88dSAntti P Miettinen {
2013705b88dSAntti P Miettinen if (kstrtoint(buf, 0, &rcu_expedited))
2023705b88dSAntti P Miettinen return -EINVAL;
2033705b88dSAntti P Miettinen
2043705b88dSAntti P Miettinen return count;
2053705b88dSAntti P Miettinen }
2063705b88dSAntti P Miettinen KERNEL_ATTR_RW(rcu_expedited);
2073705b88dSAntti P Miettinen
2085a9be7c6SPaul E. McKenney int rcu_normal;
rcu_normal_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)2095a9be7c6SPaul E. McKenney static ssize_t rcu_normal_show(struct kobject *kobj,
2105a9be7c6SPaul E. McKenney struct kobj_attribute *attr, char *buf)
2115a9be7c6SPaul E. McKenney {
2129f33a88cSThomas Weißschuh return sysfs_emit(buf, "%d\n", READ_ONCE(rcu_normal));
2135a9be7c6SPaul E. McKenney }
rcu_normal_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)2145a9be7c6SPaul E. McKenney static ssize_t rcu_normal_store(struct kobject *kobj,
2155a9be7c6SPaul E. McKenney struct kobj_attribute *attr,
2165a9be7c6SPaul E. McKenney const char *buf, size_t count)
2175a9be7c6SPaul E. McKenney {
2185a9be7c6SPaul E. McKenney if (kstrtoint(buf, 0, &rcu_normal))
2195a9be7c6SPaul E. McKenney return -EINVAL;
2205a9be7c6SPaul E. McKenney
2215a9be7c6SPaul E. McKenney return count;
2225a9be7c6SPaul E. McKenney }
2235a9be7c6SPaul E. McKenney KERNEL_ATTR_RW(rcu_normal);
22479cfea02SPaul E. McKenney #endif /* #ifndef CONFIG_TINY_RCU */
2255a9be7c6SPaul E. McKenney
226da1a679cSRoland McGrath /*
227da1a679cSRoland McGrath * Make /sys/kernel/notes give the raw contents of our kernel .notes section.
228da1a679cSRoland McGrath */
22952f5684cSGideon Israel Dsouza extern const void __start_notes __weak;
23052f5684cSGideon Israel Dsouza extern const void __stop_notes __weak;
231da1a679cSRoland McGrath #define notes_size (&__stop_notes - &__start_notes)
232da1a679cSRoland McGrath
notes_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)2332c3c8beaSChris Wright static ssize_t notes_read(struct file *filp, struct kobject *kobj,
2342c3c8beaSChris Wright struct bin_attribute *bin_attr,
235da1a679cSRoland McGrath char *buf, loff_t off, size_t count)
236da1a679cSRoland McGrath {
237da1a679cSRoland McGrath memcpy(buf, &__start_notes + off, count);
238da1a679cSRoland McGrath return count;
239da1a679cSRoland McGrath }
240da1a679cSRoland McGrath
241738bc38dSBhumika Goyal static struct bin_attribute notes_attr __ro_after_init = {
242da1a679cSRoland McGrath .attr = {
243da1a679cSRoland McGrath .name = "notes",
244da1a679cSRoland McGrath .mode = S_IRUGO,
245da1a679cSRoland McGrath },
246da1a679cSRoland McGrath .read = ¬es_read,
247da1a679cSRoland McGrath };
248da1a679cSRoland McGrath
2490ff21e46SGreg Kroah-Hartman struct kobject *kernel_kobj;
2500ff21e46SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(kernel_kobj);
2511da177e4SLinus Torvalds
2521da177e4SLinus Torvalds static struct attribute * kernel_attrs[] = {
253088ab0b4SLudwig Nussel &fscaps_attr.attr,
2540f76e5acSKay Sievers &uevent_seqnum_attr.attr,
255d3d76fbdSThomas Weißschuh &cpu_byteorder_attr.attr,
25600142bfdSThomas Weißschuh &address_bits_attr.attr,
25786d56134SMichael Marineau #ifdef CONFIG_UEVENT_HELPER
2580f76e5acSKay Sievers &uevent_helper_attr.attr,
25986d56134SMichael Marineau #endif
26022b8ce94SDave Hansen #ifdef CONFIG_PROFILING
26122b8ce94SDave Hansen &profiling_attr.attr,
26222b8ce94SDave Hansen #endif
2632965faa5SDave Young #ifdef CONFIG_KEXEC_CORE
264c330dda9SJeff Moyer &kexec_loaded_attr.attr,
265c330dda9SJeff Moyer &kexec_crash_loaded_attr.attr,
26606a7f711SAmerigo Wang &kexec_crash_size_attr.attr,
267692f66f2SHari Bathini #endif
268692f66f2SHari Bathini #ifdef CONFIG_CRASH_CORE
269fd59d231SKen'ichi Ohmichi &vmcoreinfo_attr.attr,
270*a72bbec7SEric DeVolder #ifdef CONFIG_CRASH_HOTPLUG
271*a72bbec7SEric DeVolder &crash_elfcorehdr_size_attr.attr,
272*a72bbec7SEric DeVolder #endif
273c330dda9SJeff Moyer #endif
27479cfea02SPaul E. McKenney #ifndef CONFIG_TINY_RCU
2753705b88dSAntti P Miettinen &rcu_expedited_attr.attr,
2765a9be7c6SPaul E. McKenney &rcu_normal_attr.attr,
27779cfea02SPaul E. McKenney #endif
2781da177e4SLinus Torvalds NULL
2791da177e4SLinus Torvalds };
2801da177e4SLinus Torvalds
2819dcdcea1SArvind Yadav static const struct attribute_group kernel_attr_group = {
2821da177e4SLinus Torvalds .attrs = kernel_attrs,
2831da177e4SLinus Torvalds };
2841da177e4SLinus Torvalds
ksysfs_init(void)2851da177e4SLinus Torvalds static int __init ksysfs_init(void)
2861da177e4SLinus Torvalds {
287bd35b93dSGreg Kroah-Hartman int error;
2881da177e4SLinus Torvalds
2890ff21e46SGreg Kroah-Hartman kernel_kobj = kobject_create_and_add("kernel", NULL);
2900ff21e46SGreg Kroah-Hartman if (!kernel_kobj) {
291bd35b93dSGreg Kroah-Hartman error = -ENOMEM;
292bd35b93dSGreg Kroah-Hartman goto exit;
293bd35b93dSGreg Kroah-Hartman }
2940ff21e46SGreg Kroah-Hartman error = sysfs_create_group(kernel_kobj, &kernel_attr_group);
295bd35b93dSGreg Kroah-Hartman if (error)
296bd35b93dSGreg Kroah-Hartman goto kset_exit;
297bd35b93dSGreg Kroah-Hartman
298bd35b93dSGreg Kroah-Hartman if (notes_size > 0) {
299da1a679cSRoland McGrath notes_attr.size = notes_size;
3000ff21e46SGreg Kroah-Hartman error = sysfs_create_bin_file(kernel_kobj, ¬es_attr);
301bd35b93dSGreg Kroah-Hartman if (error)
302bd35b93dSGreg Kroah-Hartman goto group_exit;
303da1a679cSRoland McGrath }
304da1a679cSRoland McGrath
305bd35b93dSGreg Kroah-Hartman return 0;
306bd35b93dSGreg Kroah-Hartman
307bd35b93dSGreg Kroah-Hartman group_exit:
3080ff21e46SGreg Kroah-Hartman sysfs_remove_group(kernel_kobj, &kernel_attr_group);
309bd35b93dSGreg Kroah-Hartman kset_exit:
31078a2d906SGreg Kroah-Hartman kobject_put(kernel_kobj);
311bd35b93dSGreg Kroah-Hartman exit:
3121da177e4SLinus Torvalds return error;
3131da177e4SLinus Torvalds }
3141da177e4SLinus Torvalds
3151da177e4SLinus Torvalds core_initcall(ksysfs_init);
316