Skip to contentSkip to conversation

powerpc: Instrument Hypervisor Calls

PATCH In review Mike Kravetz 2 participants 6 messages Jul 21, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover powerpc: Instrument Hypervisor Calls

Here is a version of the instrumentation patches built on top of Anton's hcall cleanup patch. In addition, I have gathered the timebase and PURR snapshots in assembly code. However, it still performs a call out to C code that updates the data structures.

I'd appreciate some comments on the assembly code as it has been a looooong time since I've written any.

Signature · 1 line
Mike
#1 lore raw

PATCH 1/3 powerpc: Instrument Hypervisor Calls: merge headers

Move all the Hypervisor call definitions to to a single header file. --

drivers/net/ibmveth.h +0 -10
diff -Naupr powerpc/drivers/net/ibmveth.h powerpc.work/drivers/net/ibmveth.h
@@ -41,16 +41,6 @@
 #define IbmVethMcastRemoveFilter     0x2UL
 #define IbmVethMcastClearFilterTable 0x3UL
 
-/* hcall numbers */
-#define H_VIO_SIGNAL             0x104
-#define H_REGISTER_LOGICAL_LAN   0x114
-#define H_FREE_LOGICAL_LAN       0x118
-#define H_ADD_LOGICAL_LAN_BUFFER 0x11C
-#define H_SEND_LOGICAL_LAN       0x120
-#define H_MULTICAST_CTRL         0x130
-#define H_CHANGE_LOGICAL_LAN_MAC 0x14C
-#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
-
 /* hcall macros */
 #define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \
   plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, ua, buflst, rxq, fltlst, mac)
include/asm-powerpc/hvcall.h +8 -0
diff -Naupr powerpc/include/asm-powerpc/hvcall.h powerpc.work/include/asm-powerpc/hvcall.h
@@ -164,9 +164,15 @@
 #define H_VIO_SIGNAL		0x104
 #define H_SEND_CRQ		0x108
 #define H_COPY_RDMA		0x110
+#define H_REGISTER_LOGICAL_LAN	0x114
+#define H_FREE_LOGICAL_LAN	0x118
+#define H_ADD_LOGICAL_LAN_BUFFER 0x11C
+#define H_SEND_LOGICAL_LAN	0x120
+#define H_MULTICAST_CTRL	0x130
 #define H_SET_XDABR		0x134
 #define H_STUFF_TCE		0x138
 #define H_PUT_TCE_INDIRECT	0x13C
+#define H_CHANGE_LOGICAL_LAN_MAC 0x14C
 #define H_VTERM_PARTNER_INFO	0x150
 #define H_REGISTER_VTERM	0x154
 #define H_FREE_VTERM		0x158
@@ -196,11 +202,13 @@
 #define H_GET_HCA_INFO          0x1B8
 #define H_GET_PERF_COUNT        0x1BC
 #define H_MANAGE_TRACE          0x1C0
+#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
 #define H_QUERY_INT_STATE       0x1E4
 #define H_POLL_PENDING		0x1D8
 #define H_JOIN			0x298
 #define H_VASI_STATE            0x2A4
 #define H_ENABLE_CRQ		0x2B0
+#define MAX_HCALL_OPCODES	(H_ENABLE_CRQ >> 2)
 
 #ifndef __ASSEMBLY__
 
#2 lore raw

Re: [PATCH 1/3] powerpc: Instrument Hypervisor Calls: merge headers

Hi Paulus,

Quoted 4 lines · On Thu, 20 Jul 2006 23:39:51 -0700 Mike Kravetz <[email protected]> wrote:

Move all the Hypervisor call definitions to to a single header file. --

Can you put this one in immediately just to save Mike having to repost it :-)

Signature · 3 lines
Cheers,
Stephen Rothwell                    [email protected]
http://www.canb.auug.org.au/~sfr/
#3 lore raw

PATCH 2/3 powerpc: Instrument Hypervisor Calls: add instrumentation

In reply to Mike Kravetz

Gather snapshots in the hcall routines and make callout to update data. --

arch/powerpc/Kconfig.debug +10 -0
diff -Naupr linux-2.6.17-rc6/arch/powerpc/Kconfig.debug linux-2.6.17-rc6.work/arch/powerpc/Kconfig.debug
@@ -18,6 +18,16 @@ config DEBUG_STACK_USAGE
 
 	  This option will slow down process creation somewhat.
 
+config HCALL_STATS
+	bool "Hypervisor call instrumentation"
+	depends on PPC_PSERIES
+	help
+	  Adds code to keep track of number of hypervisor calls made and
+	  the amount of time spent in hypervisor calls.
+
+	  This option will add a small amount of overhead to all hypervisor
+	  calls.
+
 config DEBUGGER
 	bool "Enable debugger hooks"
 	depends on DEBUG_KERNEL
arch/powerpc/platforms/pseries/Makefile +1 -0
diff -Naupr linux-2.6.17-rc6/arch/powerpc/platforms/pseries/Makefile linux-2.6.17-rc6.work/arch/powerpc/platforms/pseries/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o e
 
 obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
+obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
arch/powerpc/platforms/pseries/hvCall.S +28 -0
diff -Naupr linux-2.6.17-rc6/arch/powerpc/platforms/pseries/hvCall.S linux-2.6.17-rc6.work/arch/powerpc/platforms/pseries/hvCall.S
@@ -25,7 +25,11 @@
 			unsigned long *out2,		R9
 			unsigned long *out3);		R10
  */
+#ifdef CONFIG_HCALL_STATS
+_GLOBAL(plpar_hcall_base)
+#else
 _GLOBAL(plpar_hcall)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -52,7 +56,15 @@ _GLOBAL(plpar_hcall)
 
 
 /* Simple interface with no output values (other than status) */
+#ifdef CONFIG_HCALL_STATS
 _GLOBAL(plpar_hcall_norets)
+	b	plpar_hcall_norets_C
+
+
+_GLOBAL(plpar_hcall_norets_base)
+#else
+_GLOBAL(plpar_hcall_norets)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -76,7 +88,11 @@ _GLOBAL(plpar_hcall_norets)
 			unsigned long arg8,		112(R1)
 			unsigned long *out1);		120(R1)
  */
+#ifdef CONFIG_HCALL_STATS
+_GLOBAL(plpar_hcall_8arg_2ret_base)
+#else
 _GLOBAL(plpar_hcall_8arg_2ret)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -102,7 +118,11 @@ _GLOBAL(plpar_hcall_8arg_2ret)
 		 	unsigned long *out3,		R10
 		 	unsigned long *out4);		112(R1)
  */
+#ifdef CONFIG_HCALL_STATS
+_GLOBAL(plpar_hcall_4out_base)
+#else
 _GLOBAL(plpar_hcall_4out)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -144,7 +164,11 @@ _GLOBAL(plpar_hcall_4out)
 			 unsigned long *out6,		102(R1)
 			 unsigned long *out7);		100(R1)
 */
+#ifdef CONFIG_HCALL_STATS
+_GLOBAL(plpar_hcall_7arg_7ret_base)
+#else
 _GLOBAL(plpar_hcall_7arg_7ret)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -193,7 +217,11 @@ _GLOBAL(plpar_hcall_7arg_7ret)
 			 unsigned long *out8,		 94(R1)
 		         unsigned long *out9,            92(R1)
 */
+#ifdef CONFIG_HCALL_STATS
+_GLOBAL(plpar_hcall_9arg_9ret_base)
+#else
 _GLOBAL(plpar_hcall_9arg_9ret)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
arch/powerpc/platforms/pseries/hvCall_inst.c +239 -0

239 lines not on this page · raw message

include/asm-powerpc/hvcall.h +7 -0
diff -Naupr linux-2.6.17-rc6/include/asm-powerpc/hvcall.h linux-2.6.17-rc6.work/include/asm-powerpc/hvcall.h
@@ -292,6 +292,13 @@ long plpar_hcall_9arg_9ret(unsigned long
 			   unsigned long *out8,
 			   unsigned long *out9);
 
+#ifdef CONFIG_HCALL_STATS
+struct hcall_stats {
+	unsigned long	num_calls;
+	unsigned long	total_time;
+};
+#endif /* CONFIG_HCALL_STATS */
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */
#4 lore raw

Re: [PATCH 2/3] powerpc: Instrument Hypervisor Calls: add instrumentation

Quoted 1 line · Mike Kravetz

Gather snapshots in the hcall routines and make callout to update data.

Wrong patch!!!! Sorry! Here is the correct one.

Gather snapshots in the hcall routines and make callout to update data. --

arch/powerpc/Kconfig.debug +14 -0
diff -Naupr powerpc/arch/powerpc/Kconfig.debug powerpc.work/arch/powerpc/Kconfig.debug
@@ -18,6 +18,20 @@ config DEBUG_STACK_USAGE
 
 	  This option will slow down process creation somewhat.
 
+config HCALL_STATS
+	bool "Hypervisor call instrumentation"
+	depends on PPC_PSERIES && DEBUG_FS
+	help
+	  Adds code to keep track of the number of hypervisor calls made and
+	  the amount of time spent in hypervisor calls: both wall time (based
+	  on time base) and cpu time (based on PURR).  A directory named
+	  hcall_inst is added at the root of the debugfs filesystem.  Within
+	  the hcall_inst directory are files that contain CPU specific call
+	  statistics.
+
+	  This option will add a small amount of overhead to all hypervisor
+	  calls.
+
 config DEBUGGER
 	bool "Enable debugger hooks"
 	depends on DEBUG_KERNEL
arch/powerpc/platforms/pseries/Makefile +1 -0
diff -Naupr powerpc/arch/powerpc/platforms/pseries/Makefile powerpc.work/arch/powerpc/platforms/pseries/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o e
 
 obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
+obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
arch/powerpc/platforms/pseries/hvCall.S +63 -1

102 lines not on this page · raw message

arch/powerpc/platforms/pseries/hvCall_inst.c +44 -0

44 lines not on this page · raw message

include/asm-powerpc/hvcall.h +9 -0
diff -Naupr powerpc/include/asm-powerpc/hvcall.h powerpc.work/include/asm-powerpc/hvcall.h
@@ -246,6 +246,15 @@ long plpar_hcall(unsigned long opcode, u
 #define PLPAR_HCALL9_BUFSIZE 9
 long plpar_hcall9(unsigned long opcode, unsigned long *retbuf, ...);
 
+/* For hcall instrumentation.  One structure per-hcall, per-CPU */
+struct hcall_stats {
+	unsigned long	num_calls;	/* number of calls (on this CPU) */
+	unsigned long	tb_total;	/* total wall time (mftb) of calls. */
+	unsigned long	purr_total;	/* total cpu time (PURR) of calls. */
+};
+void update_hcall_stats(unsigned long opcode, unsigned long tb_delta,
+			unsigned long purr_delta);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */
#5 lore raw

PATCH 3/3 powerpc: Instrument Hypervisor Calls: add debugfs file

In reply to Mike Kravetz

Make statistics available via files in debugfs.
--

arch/powerpc/platforms/pseries/hvCall_inst.c +93 -0
diff -Naupr powerpc/arch/powerpc/platforms/pseries/hvCall_inst.c powerpc.work/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -42,3 +42,96 @@ void update_hcall_stats(unsigned long op
 	hs->purr_total += purr_delta;
 	hs->num_calls++;
 }
+
+/*
+ * Routines for displaying the statistics in debugfs
+ */
+static void *hc_start(struct seq_file *m, loff_t *pos)
+{
+	if ((int)*pos < MAX_HCALL_OPCODES)
+		return (void *)(unsigned long)(*pos + 1);
+
+	return NULL;
+}
+
+static void *hc_next(struct seq_file *m, void *p, loff_t * pos)
+{
+	++*pos;
+
+	return hc_start(m, pos);
+}
+
+static void hc_stop(struct seq_file *m, void *p)
+{
+}
+
+static int hc_show(struct seq_file *m, void *p)
+{
+	unsigned long h_num = (unsigned long)p;
+	struct hcall_stats *hs = (struct hcall_stats *)m->private;
+
+	if (hs[h_num].num_calls)
+		seq_printf(m, "%lu %lu %lu %lu\n", h_num<<2,
+			   hs[h_num].num_calls,
+			   hs[h_num].tb_total,
+			   hs[h_num].purr_total);
+
+	return 0;
+}
+
+static struct seq_operations hcall_inst_seq_ops = {
+        .start = hc_start,
+        .next  = hc_next,
+        .stop  = hc_stop,
+        .show  = hc_show
+};
+
+static int hcall_inst_seq_open(struct inode *inode, struct file *file)
+{
+	int rc;
+	struct seq_file *seq;
+
+	rc = seq_open(file, &hcall_inst_seq_ops);
+	seq = file->private_data;
+	seq->private = file->f_dentry->d_inode->u.generic_ip;
+
+	return rc;
+}
+
+static struct file_operations hcall_inst_seq_fops = {
+	.open = hcall_inst_seq_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+#define	HCALL_ROOT_DIR		"hcall_inst"
+#define CPU_NAME_BUF_SIZE	32
+
+static int __init hcall_inst_init(void)
+{
+	struct dentry *hcall_root;
+	struct dentry *hcall_file;
+	char cpu_name_buf[CPU_NAME_BUF_SIZE];
+	int cpu;
+
+	if (!firmware_has_feature(FW_FEATURE_LPAR))
+		return 0;
+
+	hcall_root = debugfs_create_dir(HCALL_ROOT_DIR, NULL);
+	if (!hcall_root)
+		return -ENOMEM;
+
+	for_each_possible_cpu(cpu) {
+		snprintf(cpu_name_buf, CPU_NAME_BUF_SIZE, "cpu%d", cpu);
+		hcall_file = debugfs_create_file(cpu_name_buf, S_IRUGO,
+						 hcall_root,
+						 per_cpu(hcall_stats, cpu),
+						 &hcall_inst_seq_fops);
+		if (!hcall_file)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+__initcall(hcall_inst_init);