diff mbox series

[v4] MIPS: Expose prid and globalnumber to sysfs

Message ID 20220816091258.9571-1-jiaxun.yang@flygoat.com (mailing list archive)
State Superseded
Headers show
Series [v4] MIPS: Expose prid and globalnumber to sysfs | expand

Commit Message

Jiaxun Yang Aug. 16, 2022, 9:12 a.m. UTC
Some application would like to know precise model and rev of processor
to do errata workaround or optimization.

Expose them in sysfs as:
/sys/devices/system/cpu/cpuX/regs/identification/prid
/sys/devices/system/cpu/cpuX/regs/identification/globalnumber

Reusing AArch64 CPU registers directory.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
v2: Drop static qualifier for kobj (gregkh)
v3: Use kzalloc to allocate struct cpuregs.
    note: When Greg mentioned about static I was thinking about
    static qualifier of percpu variable. After reading documents
    again it turns out kobjs should be allocated at runtime. Arm64's
    cpuinfo kobj is also on a percpu variable... I guess that was a
    intentional use?
v4: Properly handle err of kobj creation. (gregkh)
---
 .../ABI/testing/sysfs-devices-system-cpu      |  11 ++
 arch/mips/kernel/topology.c                   | 103 ++++++++++++++++++
 2 files changed, 114 insertions(+)

Comments

Greg KH Aug. 16, 2022, 9:21 a.m. UTC | #1
On Tue, Aug 16, 2022 at 09:12:58AM +0000, Jiaxun Yang wrote:
> Some application would like to know precise model and rev of processor
> to do errata workaround or optimization.
> 
> Expose them in sysfs as:
> /sys/devices/system/cpu/cpuX/regs/identification/prid
> /sys/devices/system/cpu/cpuX/regs/identification/globalnumber
> 
> Reusing AArch64 CPU registers directory.
> 
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
> v2: Drop static qualifier for kobj (gregkh)
> v3: Use kzalloc to allocate struct cpuregs.
>     note: When Greg mentioned about static I was thinking about
>     static qualifier of percpu variable. After reading documents
>     again it turns out kobjs should be allocated at runtime. Arm64's
>     cpuinfo kobj is also on a percpu variable... I guess that was a
>     intentional use?
> v4: Properly handle err of kobj creation. (gregkh)

Nothing was fixed :(

Again, please read the documentation for the kobject calls you are
making as it explains how to properly handle errors being returned from
them, and what you need to call if that happens.

thanks,

greg k-h
Greg KH Aug. 16, 2022, 11:55 a.m. UTC | #2
On Tue, Aug 16, 2022 at 12:43:52PM +0100, Jiaxun Yang wrote:

<snip>

Sorry, html email will be rejected by the mailing list, please resend
after fixing up your email client.

thanks,

greg k-h
Jiaxun Yang Aug. 16, 2022, 12:38 p.m. UTC | #3
在2022年8月16日八月 上午10:21,Greg KH写道:
> On Tue, Aug 16, 2022 at 09:12:58AM +0000, Jiaxun Yang wrote:
>> Some application would like to know precise model and rev of processor
>> to do errata workaround or optimization.
>> 
>> Expose them in sysfs as:
>> /sys/devices/system/cpu/cpuX/regs/identification/prid
>> /sys/devices/system/cpu/cpuX/regs/identification/globalnumber
>> 
>> Reusing AArch64 CPU registers directory.
>> 
>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>> ---
>> v2: Drop static qualifier for kobj (gregkh)
>> v3: Use kzalloc to allocate struct cpuregs.
>>     note: When Greg mentioned about static I was thinking about
>>     static qualifier of percpu variable. After reading documents
>>     again it turns out kobjs should be allocated at runtime. Arm64's
>>     cpuinfo kobj is also on a percpu variable... I guess that was a
>>     intentional use?
>> v4: Properly handle err of kobj creation. (gregkh)
>
> Nothing was fixed :(

[Resending due to previous mail contains HTML. I just got a Macbook
and was trying to use it's built-in mail client. Turns out that it's
sending HTML even with "Plain Text" selected...
Now turning back to mutt. Apologise for inconvinence.]

Hi Greg,

Sorry for misinterpret your comments again :(

Hmm I just use kobject_put to replace kobject_del.
I thought that was what you were trying to say?

>
> Again, please read the documentation for the kobject calls you are
> making as it explains how to properly handle errors being returned from
> them, and what you need to call if that happens.

Quoting the document the only sentence mentioning error handling is:

It is good practice to always use kobject_put() after kobject_init() to avoid
errors creeping in.

In our case is it safe to call kobject_put if() the error happens at kobject_init()
stage of kobject_init_and_add()? Do you mean that I should use kobject_put to
clean up kobject_init_and_add() error?

Thanks
- Jiaxun

>
> thanks,
>
> greg k-h
Greg KH Aug. 16, 2022, 12:42 p.m. UTC | #4
On Tue, Aug 16, 2022 at 01:38:27PM +0100, Jiaxun Yang wrote:
> 
> 
> 在2022年8月16日八月 上午10:21,Greg KH写道:
> > On Tue, Aug 16, 2022 at 09:12:58AM +0000, Jiaxun Yang wrote:
> >> Some application would like to know precise model and rev of processor
> >> to do errata workaround or optimization.
> >> 
> >> Expose them in sysfs as:
> >> /sys/devices/system/cpu/cpuX/regs/identification/prid
> >> /sys/devices/system/cpu/cpuX/regs/identification/globalnumber
> >> 
> >> Reusing AArch64 CPU registers directory.
> >> 
> >> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >> ---
> >> v2: Drop static qualifier for kobj (gregkh)
> >> v3: Use kzalloc to allocate struct cpuregs.
> >>     note: When Greg mentioned about static I was thinking about
> >>     static qualifier of percpu variable. After reading documents
> >>     again it turns out kobjs should be allocated at runtime. Arm64's
> >>     cpuinfo kobj is also on a percpu variable... I guess that was a
> >>     intentional use?
> >> v4: Properly handle err of kobj creation. (gregkh)
> >
> > Nothing was fixed :(
> 
> [Resending due to previous mail contains HTML. I just got a Macbook
> and was trying to use it's built-in mail client. Turns out that it's
> sending HTML even with "Plain Text" selected...
> Now turning back to mutt. Apologise for inconvinence.]
> 
> Hi Greg,
> 
> Sorry for misinterpret your comments again :(
> 
> Hmm I just use kobject_put to replace kobject_del.
> I thought that was what you were trying to say?

Yes, I think that is correct (I have no context here), but you can't
then call kfree() as the memory is now gone from the last put, right?

Try it and see :)

thanks,

greg k-h
diff mbox series

Patch

diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 5bf61881f012..adf855e7bb9b 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -512,6 +512,17 @@  Description:	information about CPUs heterogeneity.
 
 		cpu_capacity: capacity of cpuX.
 
+What:		/sys/devices/system/cpu/cpuX/regs/
+		/sys/devices/system/cpu/cpuX/regs/identification/
+		/sys/devices/system/cpu/cpuX/regs/identification/prid
+		/sys/devices/system/cpu/cpuX/regs/identification/globalnumber
+Date:		Augest 2022
+Contact:	Linux MIPS Kernel Mailing list <linux-mips@vger.kernel.org>
+Description:	MIPS CPU registers
+
+		'identification' directory exposes the Processor ID and Global Number
+		registers for identifying model and revision of the CPU.
+
 What:		/sys/devices/system/cpu/vulnerabilities
 		/sys/devices/system/cpu/vulnerabilities/meltdown
 		/sys/devices/system/cpu/vulnerabilities/spectre_v1
diff --git a/arch/mips/kernel/topology.c b/arch/mips/kernel/topology.c
index 9429d85a4703..45a15eda651a 100644
--- a/arch/mips/kernel/topology.c
+++ b/arch/mips/kernel/topology.c
@@ -5,6 +5,8 @@ 
 #include <linux/node.h>
 #include <linux/nodemask.h>
 #include <linux/percpu.h>
+#include <linux/seq_file.h>
+#include <linux/smp.h>
 
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
@@ -26,3 +28,104 @@  static int __init topology_init(void)
 }
 
 subsys_initcall(topology_init);
+
+static struct kobj_type cpuregs_kobj_type = {
+	.sysfs_ops = &kobj_sysfs_ops,
+};
+
+struct cpureg {
+	struct kobject kobj;
+	struct cpuinfo_mips *info;
+};
+static DEFINE_PER_CPU(struct cpureg *, cpuregs);
+
+#define kobj_to_cpureg(kobj)	container_of(kobj, struct cpureg, kobj)
+#define CPUREGS_ATTR_RO(_name, _field)						\
+	static ssize_t _name##_show(struct kobject *kobj,			\
+			struct kobj_attribute *attr, char *buf)			\
+	{									\
+		struct cpuinfo_mips *info = kobj_to_cpureg(kobj)->info;		\
+										\
+		return sprintf(buf, "0x%08x\n", info->_field);	\
+	}									\
+	static struct kobj_attribute cpuregs_attr_##_name = __ATTR_RO(_name)
+
+CPUREGS_ATTR_RO(prid, processor_id);
+CPUREGS_ATTR_RO(globalnumber, globalnumber);
+
+static struct attribute *cpuregs_id_attrs[] = {
+	&cpuregs_attr_prid.attr,
+	&cpuregs_attr_globalnumber.attr,
+	NULL
+};
+
+static const struct attribute_group cpuregs_attr_group = {
+	.attrs = cpuregs_id_attrs,
+	.name = "identification"
+};
+
+static int cpuregs_cpu_online(unsigned int cpu)
+{
+	int rc;
+	struct device *dev;
+	struct cpureg *reg;
+
+	dev = get_cpu_device(cpu);
+	if (!dev) {
+		rc = -ENODEV;
+		goto out;
+	}
+	reg = kzalloc(sizeof(struct cpureg), GFP_KERNEL);
+	if (!reg) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	rc = kobject_init_and_add(&reg->kobj, &cpuregs_kobj_type,
+					&dev->kobj, "regs");
+	if (rc)
+		goto out_kfree;
+	rc = sysfs_create_group(&reg->kobj, &cpuregs_attr_group);
+	if (rc)
+		goto out_kobj;
+
+	return 0;
+out_kobj:
+	kobject_put(&reg->kobj);
+out_kfree:
+	kfree(reg);
+out:
+	return rc;
+}
+
+static int cpuregs_cpu_offline(unsigned int cpu)
+{
+	struct device *dev;
+	struct cpureg *reg = per_cpu(cpuregs, cpu);
+
+	dev = get_cpu_device(cpu);
+	if (!dev || !reg)
+		return -ENODEV;
+	if (reg->kobj.parent) {
+		sysfs_remove_group(&reg->kobj, &cpuregs_attr_group);
+		kobject_put(&reg->kobj);
+	}
+	kfree(reg);
+
+	return 0;
+}
+
+static int __init cpuinfo_regs_init(void)
+{
+	int ret;
+
+
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mips/topology:online",
+				cpuregs_cpu_online, cpuregs_cpu_offline);
+	if (ret < 0) {
+		pr_err("cpuinfo: failed to register hotplug callbacks.\n");
+		return ret;
+	}
+	return 0;
+}
+
+device_initcall(cpuinfo_regs_init);