[PATCH update 1/3] HW-latency: hardware latency test 0.10
This patch is the first step to test some basic hardware functions like TSC to help people understand if there is any hardware latency as well as throughput problem exposed on bare metal or left behind by BIOS or interfered by SMI. Currently the patch tests TSC, CPU Frequency and RDRAND which is a new CPU instruction to get random number introduced in new CPU like Intel Ivy Bridge in stop_machine context,which is choosen to make sure testers fully control their system under test to rule out some level of unwanted noise. Signed-off-by: Jon Masters Signed-off-by: Luming Yu --- drivers/misc/Kconfig | 6 + drivers/misc/Makefile | 1 + drivers/misc/hw_latency_test.c | 939 + 3 files changed, 946 insertions(+) create mode 100644 drivers/misc/hw_latency_test.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b151b7c..a00b039 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -114,6 +114,12 @@ config IBM_ASM for information on the specific driver level and support statement for your IBM server. +config HW_LATENCY_TEST + tristate "Testing module to detect hardware lattency and throughput" + depends on DEBUG_FS + depends on RING_BUFFER + default m + config PHANTOM tristate "Sensable PHANToM (PCI)" depends on PCI diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 2129377..c195cce 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -49,3 +49,4 @@ obj-y += carma/ obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ obj-$(CONFIG_INTEL_MEI)+= mei/ +obj-$(CONFIG_HW_LATENCY_TEST) += hw_latency_test.o diff --git a/drivers/misc/hw_latency_test.c b/drivers/misc/hw_latency_test.c new file mode 100644 index 000..0a4d23b --- /dev/null +++ b/drivers/misc/hw_latency_test.c @@ -0,0 +1,939 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUF_SIZE_DEFAULT 262144UL +#define BUF_FLAGS (RB_FL_OVERWRITE) +#defineU64STR_SIZE 22 +#define DEBUGFS_BUF_SIZE 1024 +#define DEBUGFS_NAME_SIZE 32 + +#defineVERSION "0.1.0" +#define BANNER "hardware latency test" +#define DRVNAME"hw_latency_test" + +#define DEFAULT_SAMPLE_WINDOW 100 +#defineDEFAULT_SAMPLE_WIDTH50 +#defineDEFAULT_LAT_THRESHOLD 10 + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Luming Yu "); +MODULE_DESCRIPTION("A simple hardware latency test"); +MODULE_VERSION(VERSION); + +static int debug; +static int enabled; +static int threshold; + +module_param(debug, int, 0); +module_param(enabled, int, 0); +module_param(threshold, int, 0); + +static struct ring_buffer *ring_buffer; +static DEFINE_MUTEX(ring_buffer_mutex); +static unsigned long buf_size = 262144UL; +static struct task_struct *kthread; + +#ifdef CONFIG_X86_64 +static u8 *__start = (u8 *)0x8800; +static u8 *__end = (u8 *)0xc7ff; +#else +static u8 *__start = (u8 *)0xc000; +static u8 *__end = (u8 *)0x; +#endif + +struct sample { + unsigned int cpu; + u64 seqnum; + u64 duration; + struct timespec timestamp; + u64 addr; + u8 unit; /*0: ns 1:us*/ + unsigned long lost; +}; + +static struct data { + struct mutex lock; + u64 count; + u64 max_sample; + u64 threshold; + + u64 sample_window; + u64 sample_width; + + atomic_t sample_open; + + wait_queue_head_t wq; +} data; + +static ktime_t now; +struct sample_function { + const char *name; + u8 type; /* 0=all parallel, 1=anyone, 2=all sequential*/ + struct list_head list; + int (*get_sample)(void *unused); +}; +static struct sample_function *current_sample_func = NULL; +static LIST_HEAD(sample_function_list); +static DEFINE_MUTEX(sample_function_mutex); +static int sample_function_register(struct sample_function *sf); +static struct dentry *debug_dir; + +static int sample_function_register(struct sample_function *sf) +{ + struct list_head *entry = _function_list; + mutex_lock(_function_mutex); + list_add(>list, entry); + current_sample_func = sf; + mutex_unlock(_function_mutex); + return 0; +} + +static int __buffer_add_sample(struct sample *sample) +{ + return ring_buffer_write(ring_buffer, + sizeof(struct sample), sample); +} + +static struct sample *buffer_get_sample(struct sample *sample) +{ + struct ring_buffer_event *e = NULL; + struct sample *s = NULL; + unsigned int cpu = 0; + + if (!sample) + return NULL; + + mutex_lock(_buffer_mutex); + for_each_online_cpu(cpu) { +
[PATCH update 1/3] HW-latency: hardware latency test 0.10
This patch is the first step to test some basic hardware functions like TSC to help people understand if there is any hardware latency as well as throughput problem exposed on bare metal or left behind by BIOS or interfered by SMI. Currently the patch tests TSC, CPU Frequency and RDRAND which is a new CPU instruction to get random number introduced in new CPU like Intel Ivy Bridge in stop_machine context,which is choosen to make sure testers fully control their system under test to rule out some level of unwanted noise. Signed-off-by: Jon Masters j...@redhat.com Signed-off-by: Luming Yu luming...@intel.com --- drivers/misc/Kconfig | 6 + drivers/misc/Makefile | 1 + drivers/misc/hw_latency_test.c | 939 + 3 files changed, 946 insertions(+) create mode 100644 drivers/misc/hw_latency_test.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b151b7c..a00b039 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -114,6 +114,12 @@ config IBM_ASM for information on the specific driver level and support statement for your IBM server. +config HW_LATENCY_TEST + tristate Testing module to detect hardware lattency and throughput + depends on DEBUG_FS + depends on RING_BUFFER + default m + config PHANTOM tristate Sensable PHANToM (PCI) depends on PCI diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 2129377..c195cce 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -49,3 +49,4 @@ obj-y += carma/ obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ obj-$(CONFIG_INTEL_MEI)+= mei/ +obj-$(CONFIG_HW_LATENCY_TEST) += hw_latency_test.o diff --git a/drivers/misc/hw_latency_test.c b/drivers/misc/hw_latency_test.c new file mode 100644 index 000..0a4d23b --- /dev/null +++ b/drivers/misc/hw_latency_test.c @@ -0,0 +1,939 @@ +#include linux/module.h +#include linux/init.h +#include linux/ring_buffer.h +#include linux/stop_machine.h +#include linux/time.h +#include linux/hrtimer.h +#include linux/kthread.h +#include linux/debugfs.h +#include linux/seq_file.h +#include linux/uaccess.h +#include linux/version.h +#include linux/delay.h +#include linux/slab.h +#include linux/random.h +#include asm/tlbflush.h + +#define BUF_SIZE_DEFAULT 262144UL +#define BUF_FLAGS (RB_FL_OVERWRITE) +#defineU64STR_SIZE 22 +#define DEBUGFS_BUF_SIZE 1024 +#define DEBUGFS_NAME_SIZE 32 + +#defineVERSION 0.1.0 +#define BANNER hardware latency test +#define DRVNAMEhw_latency_test + +#define DEFAULT_SAMPLE_WINDOW 100 +#defineDEFAULT_SAMPLE_WIDTH50 +#defineDEFAULT_LAT_THRESHOLD 10 + +MODULE_LICENSE(GPL); +MODULE_AUTHOR(Luming Yu luming...@gmail.com); +MODULE_DESCRIPTION(A simple hardware latency test); +MODULE_VERSION(VERSION); + +static int debug; +static int enabled; +static int threshold; + +module_param(debug, int, 0); +module_param(enabled, int, 0); +module_param(threshold, int, 0); + +static struct ring_buffer *ring_buffer; +static DEFINE_MUTEX(ring_buffer_mutex); +static unsigned long buf_size = 262144UL; +static struct task_struct *kthread; + +#ifdef CONFIG_X86_64 +static u8 *__start = (u8 *)0x8800; +static u8 *__end = (u8 *)0xc7ff; +#else +static u8 *__start = (u8 *)0xc000; +static u8 *__end = (u8 *)0x; +#endif + +struct sample { + unsigned int cpu; + u64 seqnum; + u64 duration; + struct timespec timestamp; + u64 addr; + u8 unit; /*0: ns 1:us*/ + unsigned long lost; +}; + +static struct data { + struct mutex lock; + u64 count; + u64 max_sample; + u64 threshold; + + u64 sample_window; + u64 sample_width; + + atomic_t sample_open; + + wait_queue_head_t wq; +} data; + +static ktime_t now; +struct sample_function { + const char *name; + u8 type; /* 0=all parallel, 1=anyone, 2=all sequential*/ + struct list_head list; + int (*get_sample)(void *unused); +}; +static struct sample_function *current_sample_func = NULL; +static LIST_HEAD(sample_function_list); +static DEFINE_MUTEX(sample_function_mutex); +static int sample_function_register(struct sample_function *sf); +static struct dentry *debug_dir; + +static int sample_function_register(struct sample_function *sf) +{ + struct list_head *entry = sample_function_list; + mutex_lock(sample_function_mutex); + list_add(sf-list, entry); + current_sample_func = sf; + mutex_unlock(sample_function_mutex); + return 0; +} + +static int __buffer_add_sample(struct sample *sample) +{ + return ring_buffer_write(ring_buffer, + sizeof(struct sample), sample); +} + +static struct sample