Skip to contentSkip to conversation

Interface to expose VPHN information

PATCH In review Naveen N. Rao 2 participants 5 messages Dec 10, 2018 – Dec 14, 2018 2 messages not in the archive PowerPC

lore
Share & tools
lore
#0 lore raw

cover Interface to expose VPHN information

This is an alternate way to provide statistics around vcpu dispatches in a SPLPAR environment. By obtaining access to the VPHN information, and in concert with the existing debugfs dtl interface, we can derive different statistics related to how vcpus are dispatched by the hypervisor.

- Naveen

Naveen N. Rao (2):
powerpc/pseries: Generalize hcall_vphn() powerpc/pseries: Add debugfs interface to retrieve VPHN info

 arch/powerpc/mm/numa.c | 132 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 118 insertions(+), 14 deletions(-)
Signature · 1 line
2.19.2
#1 lore raw

PATCH 1/2 powerpc/pseries: Generalize hcall_vphn()

H_HOME_NODE_ASSOCIATIVITY hcall can take two different flags and return different associativity information in each case. Generalize the existing hcall_vphn() function to take flags as an argument and to return the result. Update the only existing user to pass the proper arguments.

---
 arch/powerpc/mm/numa.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)
arch/powerpc/mm/numa.c +13 -14
index 87f0dd004295..6677a578f18d 100644
@@ -1078,6 +1078,17 @@ static void reset_topology_timer(void);
 static int topology_timer_secs = 1;
 static int topology_inited;
 
+static long hcall_vphn(unsigned long cpu, u64 flags, __be32 *associativity)
+{
+	long rc;
+	long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
+
+	rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, cpu);
+	vphn_unpack_associativity(retbuf, associativity);
+
+	return rc;
+}
+
 /*
  * Change polling interval for associativity changes.
  */
@@ -1156,25 +1167,13 @@ static int update_cpu_associativity_changes_mask(void)
  * Retrieve the new associativity information for a virtual processor's
  * home node.
  */
-static long hcall_vphn(unsigned long cpu, __be32 *associativity)
-{
-	long rc;
-	long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
-	u64 flags = 1;
-	int hwcpu = get_hard_smp_processor_id(cpu);
-
-	rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu);
-	vphn_unpack_associativity(retbuf, associativity);
-
-	return rc;
-}
-
 static long vphn_get_associativity(unsigned long cpu,
 					__be32 *associativity)
 {
 	long rc;
+	int hwcpu = get_hard_smp_processor_id(cpu);
 
-	rc = hcall_vphn(cpu, associativity);
+	rc = hcall_vphn(hwcpu, 1, associativity);
 
 	switch (rc) {
 	case H_FUNCTION:
Signature · 1 line
2.19.2
#2 lore raw

PATCH 2/2 powerpc/pseries: Add debugfs interface to retrieve VPHN info

In reply to Naveen N. Rao

Add debugfs interface to retrieve associativity information for lpar vcpus (debugfs/vphn/lpar) and the hypervisor cpus (debugfs/vphn/hyp). This information is useful to derive various metrics, including the vcpu dispatch statistics in a SPLPAR environment.

---
 arch/powerpc/mm/numa.c | 105 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)
arch/powerpc/mm/numa.c +105 -0
index 6677a578f18d..f0b0e87016e6 100644
@@ -40,6 +40,7 @@
 #include <asm/setup.h>
 #include <asm/vdso.h>
 #include <asm/drmem.h>
+#include <asm/debugfs.h>
 
 static int numa_enabled = 1;
 
@@ -1089,6 +1090,107 @@ static long hcall_vphn(unsigned long cpu, u64 flags, __be32 *associativity)
 	return rc;
 }
 
+#ifdef CONFIG_DEBUG_FS
+static ssize_t vphn_lpar_cpu_file_read(struct file *filp, char __user *buf,
+		size_t len, loff_t *pos)
+{
+	int cpu = (long)filp->private_data;
+	__be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
+	int hwcpu = get_hard_smp_processor_id(cpu);
+	long int rc;
+
+	if (len != sizeof(associativity))
+		return -EINVAL;
+
+	rc = hcall_vphn(hwcpu, 1, associativity);
+	if (rc)
+		return -EFAULT;
+
+	rc = copy_to_user(buf, &associativity, sizeof(associativity));
+	if (rc)
+		return -EFAULT;
+
+	return sizeof(associativity);
+}
+
+static ssize_t vphn_hyp_cpu_file_read(struct file *filp, char __user *buf,
+		size_t len, loff_t *pos)
+{
+	int cpu = (long)filp->private_data;
+	__be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
+	long int rc;
+
+	if (len != sizeof(associativity))
+		return -EINVAL;
+
+	rc = hcall_vphn(cpu, 2, associativity);
+	if (rc)
+		return -EFAULT;
+
+	rc = copy_to_user(buf, &associativity, sizeof(associativity));
+	if (rc)
+		return -EFAULT;
+
+	return sizeof(associativity);
+}
+
+static const struct file_operations vphn_lpar_cpu_fops = {
+	.open		= simple_open,
+	.read		= vphn_lpar_cpu_file_read,
+	.llseek		= no_llseek,
+};
+
+static const struct file_operations vphn_hyp_cpu_fops = {
+	.open		= simple_open,
+	.read		= vphn_hyp_cpu_file_read,
+	.llseek		= no_llseek,
+};
+
+static int debug_init_vphn_entries(void)
+{
+	struct dentry *vphn_dir, *vphn_lpar_dir, *vphn_hyp_dir;
+	struct dentry *vphn_lpar_cpu_file, *vphn_hyp_cpu_file;
+	long cpu;
+	char name[10];
+
+	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+		return 0;
+
+	vphn_dir = debugfs_create_dir("vphn", powerpc_debugfs_root);
+	if (!vphn_dir) {
+		pr_warn("%s: can't create vphn debugfs root dir\n", __func__);
+		return -ENOMEM;
+	}
+
+	vphn_lpar_dir = debugfs_create_dir("lpar", vphn_dir);
+	vphn_hyp_dir = debugfs_create_dir("hyp", vphn_dir);
+	if (!vphn_lpar_dir || !vphn_hyp_dir) {
+		pr_warn("%s: can't create vphn dir\n", __func__);
+		goto err_remove_dir;
+	}
+
+	for_each_possible_cpu(cpu) {
+		sprintf(name, "cpu-%ld", cpu);
+		vphn_lpar_cpu_file = debugfs_create_file(name, 0400,
+				vphn_lpar_dir, (void *)cpu, &vphn_lpar_cpu_fops);
+		vphn_hyp_cpu_file = debugfs_create_file(name, 0400,
+				vphn_hyp_dir, (void *)cpu, &vphn_hyp_cpu_fops);
+		if (!vphn_lpar_cpu_file || !vphn_hyp_cpu_file) {
+			pr_warn("%s: can't create vphn cpu file\n", __func__);
+			goto err_remove_dir;
+		}
+	}
+
+	return 0;
+
+err_remove_dir:
+	debugfs_remove_recursive(vphn_dir);
+	return -ENOMEM;
+}
+#else
+static int debug_init_vphn_entries(void) { return 0; }
+#endif /* CONFIG_DEBUG_FS */
+
 /*
  * Change polling interval for associativity changes.
  */
@@ -1619,6 +1721,9 @@ static int topology_update_init(void)
 	if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
 		return -ENOMEM;
 
+	if (!debug_init_vphn_entries())
+		return -ENOMEM;
+
 	topology_inited = 1;
 	return 0;
 }
Signature · 1 line
2.19.2

A message that is not in the archive (sent off-list or not yet received): e308130fe45a8930743cec9aba83d4885ac8d30d.1544459267.git.naveen.n.rao__35218.1831411601$1544472513$gmane$org@linux.ibm.com

A message that is not in the archive (sent off-list or not yet received): e308130fe45a8930743cec9aba83d4885ac8d30d.1544459267.git.naveen.n.rao__35218. [email protected]

#5 lore raw

Re: [PATCH v1 2/2] powerpc/pseries: Add debugfs interface to retrieve VPHN info

Hi Michael,

Quoted 4 lines · Naveen N. Rao

Add debugfs interface to retrieve associativity information for lpar vcpus (debugfs/vphn/lpar) and the hypervisor cpus (debugfs/vphn/hyp). This information is useful to derive various metrics, including the vcpu dispatch statistics in a SPLPAR environment.

Any thoughts on this approach vs. adding a tracepoint?

Thanks,
Naveen

Quoted 141 lines
---
 arch/powerpc/mm/numa.c | 105 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)
arch/powerpc/mm/numa.c +105 -0
index 6677a578f18d..f0b0e87016e6 100644
@@ -40,6 +40,7 @@
 #include <asm/setup.h>
 #include <asm/vdso.h>
 #include <asm/drmem.h>
+#include <asm/debugfs.h>
 
 static int numa_enabled = 1;
 
@@ -1089,6 +1090,107 @@ static long hcall_vphn(unsigned long cpu, u64 flags, __be32 *associativity)
 	return rc;
 }
 
+#ifdef CONFIG_DEBUG_FS
+static ssize_t vphn_lpar_cpu_file_read(struct file *filp, char __user *buf,
+		size_t len, loff_t *pos)
+{
+	int cpu = (long)filp->private_data;
+	__be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
+	int hwcpu = get_hard_smp_processor_id(cpu);
+	long int rc;
+
+	if (len != sizeof(associativity))
+		return -EINVAL;
+
+	rc = hcall_vphn(hwcpu, 1, associativity);
+	if (rc)
+		return -EFAULT;
+
+	rc = copy_to_user(buf, &associativity, sizeof(associativity));
+	if (rc)
+		return -EFAULT;
+
+	return sizeof(associativity);
+}
+
+static ssize_t vphn_hyp_cpu_file_read(struct file *filp, char __user *buf,
+		size_t len, loff_t *pos)
+{
+	int cpu = (long)filp->private_data;
+	__be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
+	long int rc;
+
+	if (len != sizeof(associativity))
+		return -EINVAL;
+
+	rc = hcall_vphn(cpu, 2, associativity);
+	if (rc)
+		return -EFAULT;
+
+	rc = copy_to_user(buf, &associativity, sizeof(associativity));
+	if (rc)
+		return -EFAULT;
+
+	return sizeof(associativity);
+}
+
+static const struct file_operations vphn_lpar_cpu_fops = {
+	.open		= simple_open,
+	.read		= vphn_lpar_cpu_file_read,
+	.llseek		= no_llseek,
+};
+
+static const struct file_operations vphn_hyp_cpu_fops = {
+	.open		= simple_open,
+	.read		= vphn_hyp_cpu_file_read,
+	.llseek		= no_llseek,
+};
+
+static int debug_init_vphn_entries(void)
+{
+	struct dentry *vphn_dir, *vphn_lpar_dir, *vphn_hyp_dir;
+	struct dentry *vphn_lpar_cpu_file, *vphn_hyp_cpu_file;
+	long cpu;
+	char name[10];
+
+	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+		return 0;
+
+	vphn_dir = debugfs_create_dir("vphn", powerpc_debugfs_root);
+	if (!vphn_dir) {
+		pr_warn("%s: can't create vphn debugfs root dir\n", __func__);
+		return -ENOMEM;
+	}
+
+	vphn_lpar_dir = debugfs_create_dir("lpar", vphn_dir);
+	vphn_hyp_dir = debugfs_create_dir("hyp", vphn_dir);
+	if (!vphn_lpar_dir || !vphn_hyp_dir) {
+		pr_warn("%s: can't create vphn dir\n", __func__);
+		goto err_remove_dir;
+	}
+
+	for_each_possible_cpu(cpu) {
+		sprintf(name, "cpu-%ld", cpu);
+		vphn_lpar_cpu_file = debugfs_create_file(name, 0400,
+				vphn_lpar_dir, (void *)cpu, &vphn_lpar_cpu_fops);
+		vphn_hyp_cpu_file = debugfs_create_file(name, 0400,
+				vphn_hyp_dir, (void *)cpu, &vphn_hyp_cpu_fops);
+		if (!vphn_lpar_cpu_file || !vphn_hyp_cpu_file) {
+			pr_warn("%s: can't create vphn cpu file\n", __func__);
+			goto err_remove_dir;
+		}
+	}
+
+	return 0;
+
+err_remove_dir:
+	debugfs_remove_recursive(vphn_dir);
+	return -ENOMEM;
+}
+#else
+static int debug_init_vphn_entries(void) { return 0; }
+#endif /* CONFIG_DEBUG_FS */
+
 /*
  * Change polling interval for associativity changes.
  */
@@ -1619,6 +1721,9 @@ static int topology_update_init(void)
 	if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
 		return -ENOMEM;
 
+	if (!debug_init_vphn_entries())
+		return -ENOMEM;
+
 	topology_inited = 1;
 	return 0;
 }
Signature · 1 line
2.19.2
#6 lore raw

Re: [PATCH v1 2/2] powerpc/pseries: Add debugfs interface to retrieve VPHN info

Hi Naveen,

Quoted 9 lines · Naveen N. Rao

Hi Michael,

Quoted 4 lines · Naveen N. Rao

Add debugfs interface to retrieve associativity information for lpar vcpus (debugfs/vphn/lpar) and the hypervisor cpus (debugfs/vphn/hyp). This information is useful to derive various metrics, including the vcpu dispatch statistics in a SPLPAR environment.

Any thoughts on this approach vs. adding a tracepoint?

Sorry I've been unresponsive on this stuff, I don't know this area that well.

I guess I'm not opposed to adding some stuff to debugfs, but only if it's for debugging.

We don't want customers running tools or scripts that rely on this stuff in debugfs.

If we need to expose more information to be used by production tools then I think we need to look at sysfs or something like taskstats as a proper API.

cheers