Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a fastmsrns test case #242

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 103 additions & 10 deletions BM/fred/fred_test_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include <linux/device.h>
#include <linux/ioctl.h>
#include <linux/err.h>
#include <asm/cpufeatures.h>
#include <asm/msr-index.h>
#include <asm/msr.h>

MODULE_AUTHOR("Shan Kang <[email protected]>");
MODULE_VERSION("1.0");
Expand All @@ -22,8 +25,8 @@ static int __init fred_test_driver_init(void);
static void __exit fred_test_driver_exit(void);
static int fred_test_open(struct inode *inode, struct file *file);
static int fred_test_release(struct inode *inode, struct file *file);
static ssize_t fred_test_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
static ssize_t fred_test_write(struct file *filp, const char *buf, size_t count, loff_t *off);
static ssize_t fred_test_read(struct file *file, char __user *buf, size_t count, loff_t *off);
static ssize_t fred_test_write(struct file *file, const char *buf, size_t count, loff_t *off);
static long fred_test_ioctl(struct file *file, unsigned int cmd, unsigned long arg);

/*
Expand All @@ -38,6 +41,87 @@ static const struct file_operations fops = {
.release = fred_test_release,
};

static inline u64 fred_test_rdmsr(u32 msr)
{
u32 a, d;

__asm__ __volatile__("rdmsr" : "=a"(a), "=d"(d) : "c"(msr) : "memory");

return a | ((u64)d << 32);
}

static inline void fred_test_wrmsr(u32 msr, u64 value)
{
u32 a = value;
u32 d = value >> 32;

__asm__ __volatile__("wrmsr" :: "a"(a), "d"(d), "c"(msr) : "memory");
}

static inline void fred_test_wrmsrns(u32 msr, u64 value)
{
u32 a = value;
u32 d = value >> 32;

__asm__ __volatile__(".byte 0x0f,0x01,0xc6" :: "a"(a), "d"(d), "c"(msr));
}

u64 read_performance_counter(void)
{
u64 value;

rdpmcl(0x40000002, value);

pr_info("REF_TSC Value: %llu\n", value);

return value;
}

static void check_wrmsr_cycles(long loop)
{
u64 start, end, gs_base, elapsed, i;
//if (static_cpu_has(X86_FEATURE_WRMSRNS))
//{
local_irq_disable();
preempt_disable();
gs_base = fred_test_rdmsr(MSR_GS_BASE);
//start = rdtsc();
wrmsrl(0x38f, 0); // clear global_ctrl
wrmsrl(0x30b, 0); // clear fixed counter 2 value (REF_TSC)
wrmsrl(0x38f, BIT_ULL(32 + 2)); // enable fixed counter in global_ctrl
wrmsrl(0x38d, 0x300); // enable fixed counter 2
start = read_performance_counter();
for (i = 0; i < loop; i++)
fred_test_wrmsrns(MSR_GS_BASE, gs_base);
//end = rdtsc();
end = read_performance_counter();
wrmsrl(0x38d, 0); // disable fixed counter 2
wrmsrl(0x38f, 0); // clear global_ctrl
preempt_enable();
local_irq_enable();
elapsed = (end - start) / loop;
pr_info("Elapsed time: wrmsrns used %llu cycles\n", elapsed);
//}

local_irq_disable();
preempt_disable();
gs_base = fred_test_rdmsr(MSR_GS_BASE);
wrmsrl(0x38f, 0); // clear global_ctrl
wrmsrl(0x30b, 0); // clear fixed counter 2 value (REF_TSC)
wrmsrl(0x38f, BIT_ULL(32 + 2)); // enable fixed counter in global_ctrl
wrmsrl(0x38d, 0x300); // enable fixed counter 2
//start = rdtsc();
start = read_performance_counter();
for (i = 0; i < loop; i++)
fred_test_wrmsr(MSR_GS_BASE, gs_base);
//end = rdtsc();
end = read_performance_counter();
preempt_enable();
local_irq_enable();
elapsed = (end - start) / loop;
pr_info("Elapsed time: wrmsr used %llu cycles\n", elapsed);
}

static int fred_enable(void)
{
u64 cr4;
Expand Down Expand Up @@ -89,7 +173,7 @@ static int fred_test_release(struct inode *inode, struct file *file)
return 0;
}

static ssize_t fred_test_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
static ssize_t fred_test_read(struct file *file, char __user *buf, size_t count, loff_t *off)
{
int len;
/* For example - when content of our_buf is "100" - */
Expand All @@ -99,7 +183,7 @@ static ssize_t fred_test_read(struct file *filp, char __user *buf, size_t count,
return len;
}

static ssize_t fred_test_write(struct file *filp, const char *buf, size_t count, loff_t *off)
static ssize_t fred_test_write(struct file *file, const char *buf, size_t count, loff_t *off)
{
long opt;
u64 fred_bit;
Expand All @@ -112,27 +196,35 @@ static ssize_t fred_test_write(struct file *filp, const char *buf, size_t count,
/* Here we read from buf to our_buf */
if (copy_from_user(our_buf, buf, count))
pr_err("Data Write : Err!\n");

else
pr_err("Data Write : %s! count=%ld\n", our_buf, count);
/* we write NULL to end the string */
our_buf[count] = '\0';

if (strncmp(our_buf, "fred_enable ", strlen("fred_enable ")) == 0) {
ret = kstrtol(our_buf + strlen("fred_enable "), 10, &opt);
if (!ret) {
pr_err("kstrtol failed\n");
if (ret) {
pr_err("kstrtol failed ret=%d\n", ret);
return 0;
}
//opt = simple_strtol(our_buf + strlen("fred_enable "), NULL, 10);
pr_info("fred_enable expected %ld\n", opt);
fred_bit = fred_enable();
if (fred_bit == (u64)opt)
pr_info("fred_enable test PASS\n");
else
pr_info("fred_enable test FAIL\n");

} else if (strncmp(our_buf, "double_fault", strlen("double_fault")) == 0) {
pr_info("double_fault test begin\n");
invoke_double_fault();
} else if (strncmp(our_buf, "fast_msr ", strlen("fast_msr ")) == 0) {
pr_info("fast_msr test begin\n");
ret = kstrtol(our_buf + strlen("fast_msr "), 10, &opt);
if (ret) {
pr_err("kstrtol failed ret=%d\n", ret);
return 0;
}
pr_info("fast_msr loop %ld\n", opt);
check_wrmsr_cycles(opt);
} else {
pr_info("Not supported case\n");
}
Expand Down Expand Up @@ -163,7 +255,8 @@ static int __init fred_test_driver_init(void)
goto r_class;
}
/* Creating struct class */
dev_class = class_create(THIS_MODULE, "fred_test_class");
//dev_class = class_create(THIS_MODULE, "fred_test_class");
dev_class = class_create("fred_test_class");
if (IS_ERR(dev_class)) {
pr_err("Cannot create the struct class\n");
goto r_class;
Expand Down
Loading