0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kobject.h>
0010 #include <linux/string.h>
0011 #include <linux/sysfs.h>
0012 #include <linux/export.h>
0013 #include <linux/init.h>
0014 #include <linux/kexec.h>
0015 #include <linux/profile.h>
0016 #include <linux/stat.h>
0017 #include <linux/sched.h>
0018 #include <linux/capability.h>
0019 #include <linux/compiler.h>
0020
0021 #include <linux/rcupdate.h> /* rcu_expedited and rcu_normal */
0022
0023 #define KERNEL_ATTR_RO(_name) \
0024 static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
0025
0026 #define KERNEL_ATTR_RW(_name) \
0027 static struct kobj_attribute _name##_attr = __ATTR_RW(_name)
0028
0029
0030 static ssize_t uevent_seqnum_show(struct kobject *kobj,
0031 struct kobj_attribute *attr, char *buf)
0032 {
0033 return sprintf(buf, "%llu\n", (unsigned long long)uevent_seqnum);
0034 }
0035 KERNEL_ATTR_RO(uevent_seqnum);
0036
0037 #ifdef CONFIG_UEVENT_HELPER
0038
0039 static ssize_t uevent_helper_show(struct kobject *kobj,
0040 struct kobj_attribute *attr, char *buf)
0041 {
0042 return sprintf(buf, "%s\n", uevent_helper);
0043 }
0044 static ssize_t uevent_helper_store(struct kobject *kobj,
0045 struct kobj_attribute *attr,
0046 const char *buf, size_t count)
0047 {
0048 if (count+1 > UEVENT_HELPER_PATH_LEN)
0049 return -ENOENT;
0050 memcpy(uevent_helper, buf, count);
0051 uevent_helper[count] = '\0';
0052 if (count && uevent_helper[count-1] == '\n')
0053 uevent_helper[count-1] = '\0';
0054 return count;
0055 }
0056 KERNEL_ATTR_RW(uevent_helper);
0057 #endif
0058
0059 #ifdef CONFIG_PROFILING
0060 static ssize_t profiling_show(struct kobject *kobj,
0061 struct kobj_attribute *attr, char *buf)
0062 {
0063 return sprintf(buf, "%d\n", prof_on);
0064 }
0065 static ssize_t profiling_store(struct kobject *kobj,
0066 struct kobj_attribute *attr,
0067 const char *buf, size_t count)
0068 {
0069 int ret;
0070
0071 if (prof_on)
0072 return -EEXIST;
0073
0074
0075
0076
0077
0078 profile_setup((char *)buf);
0079 ret = profile_init();
0080 if (ret)
0081 return ret;
0082 ret = create_proc_profile();
0083 if (ret)
0084 return ret;
0085 return count;
0086 }
0087 KERNEL_ATTR_RW(profiling);
0088 #endif
0089
0090 #ifdef CONFIG_KEXEC_CORE
0091 static ssize_t kexec_loaded_show(struct kobject *kobj,
0092 struct kobj_attribute *attr, char *buf)
0093 {
0094 return sprintf(buf, "%d\n", !!kexec_image);
0095 }
0096 KERNEL_ATTR_RO(kexec_loaded);
0097
0098 static ssize_t kexec_crash_loaded_show(struct kobject *kobj,
0099 struct kobj_attribute *attr, char *buf)
0100 {
0101 return sprintf(buf, "%d\n", kexec_crash_loaded());
0102 }
0103 KERNEL_ATTR_RO(kexec_crash_loaded);
0104
0105 static ssize_t kexec_crash_size_show(struct kobject *kobj,
0106 struct kobj_attribute *attr, char *buf)
0107 {
0108 return sprintf(buf, "%zu\n", crash_get_memory_size());
0109 }
0110 static ssize_t kexec_crash_size_store(struct kobject *kobj,
0111 struct kobj_attribute *attr,
0112 const char *buf, size_t count)
0113 {
0114 unsigned long cnt;
0115 int ret;
0116
0117 if (kstrtoul(buf, 0, &cnt))
0118 return -EINVAL;
0119
0120 ret = crash_shrink_memory(cnt);
0121 return ret < 0 ? ret : count;
0122 }
0123 KERNEL_ATTR_RW(kexec_crash_size);
0124
0125 #endif
0126
0127 #ifdef CONFIG_CRASH_CORE
0128
0129 static ssize_t vmcoreinfo_show(struct kobject *kobj,
0130 struct kobj_attribute *attr, char *buf)
0131 {
0132 phys_addr_t vmcore_base = paddr_vmcoreinfo_note();
0133 return sprintf(buf, "%pa %x\n", &vmcore_base,
0134 (unsigned int)VMCOREINFO_NOTE_SIZE);
0135 }
0136 KERNEL_ATTR_RO(vmcoreinfo);
0137
0138 #endif
0139
0140
0141 static ssize_t fscaps_show(struct kobject *kobj,
0142 struct kobj_attribute *attr, char *buf)
0143 {
0144 return sprintf(buf, "%d\n", file_caps_enabled);
0145 }
0146 KERNEL_ATTR_RO(fscaps);
0147
0148 #ifndef CONFIG_TINY_RCU
0149 int rcu_expedited;
0150 static ssize_t rcu_expedited_show(struct kobject *kobj,
0151 struct kobj_attribute *attr, char *buf)
0152 {
0153 return sprintf(buf, "%d\n", READ_ONCE(rcu_expedited));
0154 }
0155 static ssize_t rcu_expedited_store(struct kobject *kobj,
0156 struct kobj_attribute *attr,
0157 const char *buf, size_t count)
0158 {
0159 if (kstrtoint(buf, 0, &rcu_expedited))
0160 return -EINVAL;
0161
0162 return count;
0163 }
0164 KERNEL_ATTR_RW(rcu_expedited);
0165
0166 int rcu_normal;
0167 static ssize_t rcu_normal_show(struct kobject *kobj,
0168 struct kobj_attribute *attr, char *buf)
0169 {
0170 return sprintf(buf, "%d\n", READ_ONCE(rcu_normal));
0171 }
0172 static ssize_t rcu_normal_store(struct kobject *kobj,
0173 struct kobj_attribute *attr,
0174 const char *buf, size_t count)
0175 {
0176 if (kstrtoint(buf, 0, &rcu_normal))
0177 return -EINVAL;
0178
0179 return count;
0180 }
0181 KERNEL_ATTR_RW(rcu_normal);
0182 #endif
0183
0184
0185
0186
0187 extern const void __start_notes __weak;
0188 extern const void __stop_notes __weak;
0189 #define notes_size (&__stop_notes - &__start_notes)
0190
0191 static ssize_t notes_read(struct file *filp, struct kobject *kobj,
0192 struct bin_attribute *bin_attr,
0193 char *buf, loff_t off, size_t count)
0194 {
0195 memcpy(buf, &__start_notes + off, count);
0196 return count;
0197 }
0198
0199 static struct bin_attribute notes_attr __ro_after_init = {
0200 .attr = {
0201 .name = "notes",
0202 .mode = S_IRUGO,
0203 },
0204 .read = ¬es_read,
0205 };
0206
0207 struct kobject *kernel_kobj;
0208 EXPORT_SYMBOL_GPL(kernel_kobj);
0209
0210 static struct attribute * kernel_attrs[] = {
0211 &fscaps_attr.attr,
0212 &uevent_seqnum_attr.attr,
0213 #ifdef CONFIG_UEVENT_HELPER
0214 &uevent_helper_attr.attr,
0215 #endif
0216 #ifdef CONFIG_PROFILING
0217 &profiling_attr.attr,
0218 #endif
0219 #ifdef CONFIG_KEXEC_CORE
0220 &kexec_loaded_attr.attr,
0221 &kexec_crash_loaded_attr.attr,
0222 &kexec_crash_size_attr.attr,
0223 #endif
0224 #ifdef CONFIG_CRASH_CORE
0225 &vmcoreinfo_attr.attr,
0226 #endif
0227 #ifndef CONFIG_TINY_RCU
0228 &rcu_expedited_attr.attr,
0229 &rcu_normal_attr.attr,
0230 #endif
0231 NULL
0232 };
0233
0234 static const struct attribute_group kernel_attr_group = {
0235 .attrs = kernel_attrs,
0236 };
0237
0238 static int __init ksysfs_init(void)
0239 {
0240 int error;
0241
0242 kernel_kobj = kobject_create_and_add("kernel", NULL);
0243 if (!kernel_kobj) {
0244 error = -ENOMEM;
0245 goto exit;
0246 }
0247 error = sysfs_create_group(kernel_kobj, &kernel_attr_group);
0248 if (error)
0249 goto kset_exit;
0250
0251 if (notes_size > 0) {
0252 notes_attr.size = notes_size;
0253 error = sysfs_create_bin_file(kernel_kobj, ¬es_attr);
0254 if (error)
0255 goto group_exit;
0256 }
0257
0258 return 0;
0259
0260 group_exit:
0261 sysfs_remove_group(kernel_kobj, &kernel_attr_group);
0262 kset_exit:
0263 kobject_put(kernel_kobj);
0264 exit:
0265 return error;
0266 }
0267
0268 core_initcall(ksysfs_init);