LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] powerpc/pseries: Export raw per-CPU VPA data via debugfs
@ 2018-09-20 10:15 Aravinda Prasad
  2018-09-24 11:42 ` Michael Ellerman
  0 siblings, 1 reply; 3+ messages in thread
From: Aravinda Prasad @ 2018-09-20 10:15 UTC (permalink / raw)
  To: mpe, linuxppc-dev; +Cc: nfont, naveen.n.rao, aravinda

This patch exports the raw per-CPU VPA data via debugfs.
A per-CPU file is created which exports the VPA data of
that CPU to help debug some of the VPA related issues or
to analyze the per-CPU VPA related statistics.

Signed-off-by: Aravinda Prasad <aravinda@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/pseries/lpar.c |   85 +++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index d3992ce..cc12c12 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -48,6 +48,7 @@
 #include <asm/kexec.h>
 #include <asm/fadump.h>
 #include <asm/asm-prototypes.h>
+#include <asm/debugfs.h>
 
 #include "pseries.h"
 
@@ -64,6 +65,16 @@ EXPORT_SYMBOL(plpar_hcall);
 EXPORT_SYMBOL(plpar_hcall9);
 EXPORT_SYMBOL(plpar_hcall_norets);
 
+#ifdef CONFIG_DEBUG_FS
+struct vpa {
+	struct dentry	*file;
+	int		cpu;
+};
+static DEFINE_PER_CPU(struct vpa, cpu_vpa);
+
+static struct dentry *vpa_dir;
+#endif
+
 void vpa_init(int cpu)
 {
 	int hwcpu = get_hard_smp_processor_id(cpu);
@@ -1028,3 +1039,77 @@ static int __init reserve_vrma_context_id(void)
 	return 0;
 }
 machine_device_initcall(pseries, reserve_vrma_context_id);
+
+#ifdef CONFIG_DEBUG_FS
+/* debugfs file interface for vpa data */
+static ssize_t vpa_file_read(struct file *filp, char __user *buf, size_t len,
+		loff_t *pos)
+{
+	long int rc;
+	struct vpa *vpa = filp->private_data;
+	struct lppaca *lppaca = &lppaca_of(vpa->cpu);
+
+	if (len < sizeof(struct lppaca))
+		return -EINVAL;
+
+	rc = copy_to_user(buf, lppaca, sizeof(struct lppaca));
+	if (rc)
+		return -EFAULT;
+
+	return 0;
+}
+
+static int vpa_file_open(struct inode *inode, struct file *filp)
+{
+	struct vpa *vpa = inode->i_private;
+
+	filp->private_data = vpa;
+	return 0;
+}
+
+static int vpa_file_release(struct inode *inode, struct file *filp)
+{
+	return 0;
+}
+
+static const struct file_operations vpa_fops = {
+	.open		= vpa_file_open,
+	.release	= vpa_file_release,
+	.read		= vpa_file_read,
+	.llseek		= no_llseek,
+};
+
+static int __init vpa_debugfs_init(void)
+{
+	char name[10];
+	int i;
+
+	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+		return 0;
+
+	vpa_dir = debugfs_create_dir("vpa", powerpc_debugfs_root);
+	if (!vpa_dir) {
+		pr_warn("%s: can't create vpa root dir\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* set up the per-cpu vpa file*/
+	for_each_possible_cpu(i) {
+		struct vpa *vpa = &per_cpu(cpu_vpa, i);
+
+		vpa->cpu = i;
+		sprintf(name, "cpu-%d", i);
+
+		vpa->file = debugfs_create_file(name, 0400, vpa_dir, vpa,
+					&vpa_fops);
+		if (!vpa->file) {
+			pr_warn("%s: can't create per-cpu vpa file\n",
+					__func__);
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+machine_arch_initcall(pseries, vpa_debugfs_init);
+#endif /* CONFIG_DEBUG_FS */

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] powerpc/pseries: Export raw per-CPU VPA data via debugfs
  2018-09-20 10:15 [PATCH] powerpc/pseries: Export raw per-CPU VPA data via debugfs Aravinda Prasad
@ 2018-09-24 11:42 ` Michael Ellerman
  2018-09-25  6:24   ` Aravinda Prasad
  0 siblings, 1 reply; 3+ messages in thread
From: Michael Ellerman @ 2018-09-24 11:42 UTC (permalink / raw)
  To: Aravinda Prasad, linuxppc-dev; +Cc: nfont, naveen.n.rao, aravinda

Hi Aravinda,

Aravinda Prasad <aravinda@linux.vnet.ibm.com> writes:

> This patch exports the raw per-CPU VPA data via debugfs.
> A per-CPU file is created which exports the VPA data of
> that CPU to help debug some of the VPA related issues or
> to analyze the per-CPU VPA related statistics.

Do we really need this in debugfs? I'm not saying we don't, but I'm also
not really clear why we need it.

If there is a good reason for exporting it, do we really want to export
it in distro kernels, or should it be behind a CONFIG ?

> diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
> index d3992ce..cc12c12 100644
> --- a/arch/powerpc/platforms/pseries/lpar.c
> +++ b/arch/powerpc/platforms/pseries/lpar.c
> @@ -48,6 +48,7 @@
>  #include <asm/kexec.h>
>  #include <asm/fadump.h>
>  #include <asm/asm-prototypes.h>
> +#include <asm/debugfs.h>
>  
>  #include "pseries.h"
>  
> @@ -64,6 +65,16 @@ EXPORT_SYMBOL(plpar_hcall);
>  EXPORT_SYMBOL(plpar_hcall9);
>  EXPORT_SYMBOL(plpar_hcall_norets);
>  
> +#ifdef CONFIG_DEBUG_FS
> +struct vpa {
> +	struct dentry	*file;

You never use this other than temporarily when creating the file.

> +	int		cpu;
> +};
> +static DEFINE_PER_CPU(struct vpa, cpu_vpa);

And you never really use the per_cpu() either.

So you don't need the vpa struct at all AFAICS.

> +
> +static struct dentry *vpa_dir;

That can just be a local in vpa_debugfs_init().

> +#endif
> +
>  void vpa_init(int cpu)
>  {
>  	int hwcpu = get_hard_smp_processor_id(cpu);
> @@ -1028,3 +1039,77 @@ static int __init reserve_vrma_context_id(void)
>  	return 0;
>  }
>  machine_device_initcall(pseries, reserve_vrma_context_id);
> +
> +#ifdef CONFIG_DEBUG_FS
> +/* debugfs file interface for vpa data */
> +static ssize_t vpa_file_read(struct file *filp, char __user *buf, size_t len,
> +		loff_t *pos)

Like this please:

static ssize_t vpa_file_read(struct file *filp, char __user *buf, size_t len,
			     loff_t *pos)

> +{
> +	long int rc;
> +	struct vpa *vpa = filp->private_data;
> +	struct lppaca *lppaca = &lppaca_of(vpa->cpu);

Once you've stashed the CPU number in private_data (see below) you can
get it back with:

	int cpu = (long)filp->private_data;
	struct lppaca *lppaca = &lppaca_of(cpu);

> +
> +	if (len < sizeof(struct lppaca))
> +		return -EINVAL;
> +
> +	rc = copy_to_user(buf, lppaca, sizeof(struct lppaca));
> +	if (rc)
> +		return -EFAULT;

You should use simple_read_from_buffer().

> +
> +	return 0;
> +}
> +
> +static int vpa_file_open(struct inode *inode, struct file *filp)
> +{
> +	struct vpa *vpa = inode->i_private;
> +
> +	filp->private_data = vpa;
> +	return 0;
> +}

You can just use simple_open().

> +static int vpa_file_release(struct inode *inode, struct file *filp)
> +{
> +	return 0;
> +}

I don't think you need release if it's empty.

> +static const struct file_operations vpa_fops = {
> +	.open		= vpa_file_open,
> +	.release	= vpa_file_release,
> +	.read		= vpa_file_read,
> +	.llseek		= no_llseek,
> +};
> +
> +static int __init vpa_debugfs_init(void)
> +{
> +	char name[10];

That's not big enough if you end up with 4 billion CPUs. Make it 16.

> +	int i;
> +
> +	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
> +		return 0;
> +
> +	vpa_dir = debugfs_create_dir("vpa", powerpc_debugfs_root);
> +	if (!vpa_dir) {
> +		pr_warn("%s: can't create vpa root dir\n", __func__);
> +		return -ENOMEM;
> +	}
> +
> +	/* set up the per-cpu vpa file*/
> +	for_each_possible_cpu(i) {

What happens when you read the file for a possible but not present CPU?

> +		struct vpa *vpa = &per_cpu(cpu_vpa, i);
> +
> +		vpa->cpu = i;
> +		sprintf(name, "cpu-%d", i);
> +
> +		vpa->file = debugfs_create_file(name, 0400, vpa_dir, vpa,
> +					&vpa_fops);

Can be:
		struct dentry *d;
		d = debugfs_create_file(name, 0400, dir, (void *)cpu, &vpa_fops);

Where you're stashing the cpu number in the private_data as a void *.

> +		if (!vpa->file) {
> +			pr_warn("%s: can't create per-cpu vpa file\n",
> +					__func__);
> +			return -ENOMEM;
> +		}
> +	}
> +
> +	return 0;
> +}
> +machine_arch_initcall(pseries, vpa_debugfs_init);
> +#endif /* CONFIG_DEBUG_FS */


cheers

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] powerpc/pseries: Export raw per-CPU VPA data via debugfs
  2018-09-24 11:42 ` Michael Ellerman
@ 2018-09-25  6:24   ` Aravinda Prasad
  0 siblings, 0 replies; 3+ messages in thread
From: Aravinda Prasad @ 2018-09-25  6:24 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev; +Cc: nfont, naveen.n.rao

Hi Michael,

On Monday 24 September 2018 05:12 PM, Michael Ellerman wrote:
> Hi Aravinda,
> 
> Aravinda Prasad <aravinda@linux.vnet.ibm.com> writes:
> 
>> This patch exports the raw per-CPU VPA data via debugfs.
>> A per-CPU file is created which exports the VPA data of
>> that CPU to help debug some of the VPA related issues or
>> to analyze the per-CPU VPA related statistics.
> 
> Do we really need this in debugfs? I'm not saying we don't, but I'm also
> not really clear why we need it.

Two reasons. First, if a new stat from VPA needs to be exported to user,
then we end up with a kernel patch. By exporting the VPA data, only the
user space tool needs to be updated.

Second is that we need this if we want to debug any per-CPU statistics
like stolen time etc.

> 
> If there is a good reason for exporting it, do we really want to export
> it in distro kernels, or should it be behind a CONFIG ?

I am fine to put this behind a CONFIG.

> 
>> diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
>> index d3992ce..cc12c12 100644
>> --- a/arch/powerpc/platforms/pseries/lpar.c
>> +++ b/arch/powerpc/platforms/pseries/lpar.c
>> @@ -48,6 +48,7 @@
>>  #include <asm/kexec.h>
>>  #include <asm/fadump.h>
>>  #include <asm/asm-prototypes.h>
>> +#include <asm/debugfs.h>
>>  
>>  #include "pseries.h"
>>  
>> @@ -64,6 +65,16 @@ EXPORT_SYMBOL(plpar_hcall);
>>  EXPORT_SYMBOL(plpar_hcall9);
>>  EXPORT_SYMBOL(plpar_hcall_norets);
>>  
>> +#ifdef CONFIG_DEBUG_FS
>> +struct vpa {
>> +	struct dentry	*file;
> 
> You never use this other than temporarily when creating the file.
> 
>> +	int		cpu;
>> +};
>> +static DEFINE_PER_CPU(struct vpa, cpu_vpa);
> 
> And you never really use the per_cpu() either.
> 
> So you don't need the vpa struct at all AFAICS.

I now think so. Will rework on the patch.

> 
>> +
>> +static struct dentry *vpa_dir;
> 
> That can just be a local in vpa_debugfs_init().

ok.

> 
>> +#endif
>> +
>>  void vpa_init(int cpu)
>>  {
>>  	int hwcpu = get_hard_smp_processor_id(cpu);
>> @@ -1028,3 +1039,77 @@ static int __init reserve_vrma_context_id(void)
>>  	return 0;
>>  }
>>  machine_device_initcall(pseries, reserve_vrma_context_id);
>> +
>> +#ifdef CONFIG_DEBUG_FS
>> +/* debugfs file interface for vpa data */
>> +static ssize_t vpa_file_read(struct file *filp, char __user *buf, size_t len,
>> +		loff_t *pos)
> 
> Like this please:
> 
> static ssize_t vpa_file_read(struct file *filp, char __user *buf, size_t len,
> 			     loff_t *pos)
> 

noted

>> +{
>> +	long int rc;
>> +	struct vpa *vpa = filp->private_data;
>> +	struct lppaca *lppaca = &lppaca_of(vpa->cpu);
> 
> Once you've stashed the CPU number in private_data (see below) you can
> get it back with:
> 
> 	int cpu = (long)filp->private_data;
> 	struct lppaca *lppaca = &lppaca_of(cpu);

sure

> 
>> +
>> +	if (len < sizeof(struct lppaca))
>> +		return -EINVAL;
>> +
>> +	rc = copy_to_user(buf, lppaca, sizeof(struct lppaca));
>> +	if (rc)
>> +		return -EFAULT;
> 
> You should use simple_read_from_buffer().

ok

> 
>> +
>> +	return 0;
>> +}
>> +
>> +static int vpa_file_open(struct inode *inode, struct file *filp)
>> +{
>> +	struct vpa *vpa = inode->i_private;
>> +
>> +	filp->private_data = vpa;
>> +	return 0;
>> +}
> 
> You can just use simple_open().

ok

> 
>> +static int vpa_file_release(struct inode *inode, struct file *filp)
>> +{
>> +	return 0;
>> +}
> 
> I don't think you need release if it's empty.

noted

> 
>> +static const struct file_operations vpa_fops = {
>> +	.open		= vpa_file_open,
>> +	.release	= vpa_file_release,
>> +	.read		= vpa_file_read,
>> +	.llseek		= no_llseek,
>> +};
>> +
>> +static int __init vpa_debugfs_init(void)
>> +{
>> +	char name[10];
> 
> That's not big enough if you end up with 4 billion CPUs. Make it 16.

Will make it 16.

> 
>> +	int i;
>> +
>> +	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
>> +		return 0;
>> +
>> +	vpa_dir = debugfs_create_dir("vpa", powerpc_debugfs_root);
>> +	if (!vpa_dir) {
>> +		pr_warn("%s: can't create vpa root dir\n", __func__);
>> +		return -ENOMEM;
>> +	}
>> +
>> +	/* set up the per-cpu vpa file*/
>> +	for_each_possible_cpu(i) {
> 
> What happens when you read the file for a possible but not present CPU?

Right now the VPA data is still fetched. We can have an additional check
in open or read to check if the CPU is online and return error if the
CPU is offline.

> 
>> +		struct vpa *vpa = &per_cpu(cpu_vpa, i);
>> +
>> +		vpa->cpu = i;
>> +		sprintf(name, "cpu-%d", i);
>> +
>> +		vpa->file = debugfs_create_file(name, 0400, vpa_dir, vpa,
>> +					&vpa_fops);
> 
> Can be:
> 		struct dentry *d;
> 		d = debugfs_create_file(name, 0400, dir, (void *)cpu, &vpa_fops);
> 
> Where you're stashing the cpu number in the private_data as a void *.

ok.

Regards,
Aravinda

> 
>> +		if (!vpa->file) {
>> +			pr_warn("%s: can't create per-cpu vpa file\n",
>> +					__func__);
>> +			return -ENOMEM;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +machine_arch_initcall(pseries, vpa_debugfs_init);
>> +#endif /* CONFIG_DEBUG_FS */
> 
> 
> cheers
> 

-- 
Regards,
Aravinda

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-09-25  6:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-20 10:15 [PATCH] powerpc/pseries: Export raw per-CPU VPA data via debugfs Aravinda Prasad
2018-09-24 11:42 ` Michael Ellerman
2018-09-25  6:24   ` Aravinda Prasad

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox