Primitive interface to check IPI broadcast v.s mask in flat mode.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

This patch applies on top of 5 patches submitted for x86-64 cpu hotplug.

NOTE: Not for -mm.

Cheers,
Ashok Raj

This patch provides a primitive interface to switch mask to 
broadcast version of IPI use. Also provides the following interfaces.

#echo "max_iters=100"  > /proc/ipi -- set number of iterations
#echo "curr_mode=1" > /proc/ipi    -- set 1: broadcast 0: mask version
#echo "start" > /proc/ipi	   -- do the test and print results.

dmesg | tail -1 should give avg numbers for last run.

Signed-off-by: Ashok Raj <[email protected]>
----------------------------------------------------
 arch/x86_64/kernel/genapic_flat.c |  136 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 135 insertions(+), 1 deletion(-)

Index: linux-2.6.12-rc5-mm2/arch/x86_64/kernel/genapic_flat.c
===================================================================
--- linux-2.6.12-rc5-mm2.orig/arch/x86_64/kernel/genapic_flat.c
+++ linux-2.6.12-rc5-mm2/arch/x86_64/kernel/genapic_flat.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <asm/smp.h>
 #include <asm/ipi.h>
+#include <asm/uaccess.h>
 
 /*
  * The following permit choosing broadcast IPI shortcut v.s sending IPI only
@@ -202,10 +203,143 @@ struct genapic apic_flat =  {
 	.phys_pkg_id = phys_pkg_id,
 };
 
-int print_ipi_mode(void)
+#define MAX_IPI_ITERS	10000
+static int ipi_tip; 	/* Test in Progress */
+static int max_iters = 5;
+static int curr_mode = 1;
+
+static struct ipi_stat_tsc {
+	unsigned long long start_tsc;
+	unsigned long long end_tsc;
+} ipi_stat [MAX_IPI_ITERS];
+
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static int ipi_test_read_proc(char *page, char **start, off_t off,
+                  int count, int *eof, void *data)
+{
+	int len;
+
+	len = sprintf (page, "Current test iterations = %d\n", max_iters);
+	len += sprintf (page+len, no_broadcast ? "Mask\n" : "Broadcast\n");
+	len += sprintf (page+len, ipi_tip ? "Test in progress\n" : "Test Idle\n");
+
+	return len;
+}
+
+void
+ipi_dummy(void *ptr)
+{
+}
+
+void
+print_ipi_stats(void)
+{
+	int i;
+	unsigned long long sum, min, max;
+
+	min = ~0;
+	max = 0;
+	sum = 0;
+	for (i=0; i<max_iters; i++) {
+		unsigned long long diff;
+
+		diff = ipi_stat[i].end_tsc - ipi_stat[i].start_tsc;
+
+		min = (min < diff ? min : diff);
+		max = (max > diff ? max : diff);
+		sum += diff;
+
+		printk ("[%d] start: %llx end: %llx diff: %llx\n",
+			i, ipi_stat[i].start_tsc, ipi_stat[i].end_tsc,
+			ipi_stat[i].end_tsc - ipi_stat[i].start_tsc);
+	}
+
+	printk ("Avg = %llx, Min = %llx, Max = %llx\n", sum/max_iters, min, max);
+}
+
+static void
+do_ipi_test(void)
+{
+	int i;
+
+	memset(&ipi_stat[0], 0, sizeof(ipi_stat));
+	ipi_tip = 1;
+	for (i=0; i<max_iters;i++) {
+		rdtscll(ipi_stat[i].start_tsc);
+		smp_call_function(ipi_dummy, NULL, 0, 1);
+		rdtscll(ipi_stat[i].end_tsc);
+	}
+	ipi_tip = 0;
+	print_ipi_stats();
+	memset(&ipi_stat[0], 0, sizeof(ipi_stat));
+}
+
+static int ipi_test_write_proc(struct file *file, const char __user *buffer,
+		unsigned long count, void *data)
+{
+	char cmd[512];
+	size_t size;
+	int retval, num = 0;
+	int mode;
+
+	printk ("In test_write\n");
+	size = sizeof(cmd);
+	if (count < size)
+		size = count;
+
+	if (copy_from_user(cmd, buffer, size))
+		return -EFAULT;
+
+	if (!strncmp(cmd, "start", 5)) {
+		printk ("Got start command\n");
+		do_ipi_test();
+	} else {
+		retval = sscanf(cmd, "max_iters=%d", &num);
+		if (retval == 1) {
+			if (num > MAX_IPI_ITERS) {
+				printk ("Cannot be more than %d entries\n", MAX_IPI_ITERS);
+				printk ("Leaving entries at %d\n", max_iters);
+			} else {
+				printk ("Setting max_iters = %d\n", num);
+				max_iters = num;
+			}
+		} else {
+			retval = sscanf(cmd, "curr_mode=%d", &mode);
+			if (retval == 1) {
+				printk ("Setting mode to %s\n", mode ? "broadcast" : "mask");
+				curr_mode = mode;
+				lock_ipi_call_lock();
+				no_broadcast = mode ? 0 : 1;
+				unlock_ipi_call_lock();
+			}
+		}
+	}
+
+	return count;
+}
+
+void __init ipi_test_proc_init(void)
+{
+	struct proc_dir_entry *entry = NULL;
+
+	entry = create_proc_entry("ipi", 0600, NULL);
+
+	if (entry) {
+		entry->read_proc = ipi_test_read_proc;
+		entry->write_proc = ipi_test_write_proc;
+	}
+
+	printk ("Initialized ipi_proc interface\n");
+}
+
+int __init print_ipi_mode(void)
 {
 	printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
 											"Shortcut");
+	ipi_test_proc_init();
 	return 0;
 }
 
-- 
Cheers,
Ashok Raj
- Open Source Technology Center
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux