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

From: Ashok Raj
Date: Thu Jun 02 2005 - 08:22:54 EST


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 <ashok.raj@xxxxxxxxx>
----------------------------------------------------
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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/