msr寄存器的读写有两个指令rdmsr和wrmsr。他们可以用来读写一些系统相关的寄存器。格式是:
首先向ecx写入msr寄存器的地址,这要查一下手册。对于rdmsr,会将读到的信息,一个64bit数据,高32bit放到edx,低32存访到eax。对于wrmsr,除了向ecx写入msr寄存器的地址,还要向edx和eax写入要写入的值。
读写msr需要在kernel态进行,因此,我们用一个kernel module来实现。下面是一个例子:
#include<linux/module.h> #include<linux/kernel.h> #include<linux/init.h> #include<linux/slab.h> MODULE_LICENSE("GPL"); static inline void mywrmsr(void) { unsigned int flag = 0x1d9; unsigned int high = 0x0, low = 0; unsigned int loop = 100000; __asm__ __volatile__ ( "mov %2, %%ecx\n\t" "mov %3, %%ebx\n\t" "rdmsr\n\t" "1:\n\t" "wrmsr\n\t" "dec %%ebx\n\t" "jnz 1b\n\t" : "=r"(high), "=r"(low) : "r"(flag), "r"(loop) : "%edx", "%eax","%ecx", "%ebx", "memory" ); } static inline void myrdmsr(void) { unsigned int flag = 0x1d9; unsigned int high = 0, low = 0, loop = 100000; __asm__ __volatile__( "movl %2, %%ecx\n\t" "mov %3, %%ebx\n\t" "1:\n\t" "rdmsr\n\t" "dec %%ebx\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t" "jnz 1b\n\t" : "=r"(high), "=r"(low) : "r"(flag), "r"(loop) : "%eax", "%edx", "%ecx", "%ebx", "memory" ); } static inline uint64_t myrdtsc(void) { uint32_t low, high; __asm__ __volatile__ ("rdtsc" : "=a" (low), "=d" (high)); return ((uint64_t)high << 32) | low; } static int mymsr_init(void) { uint64_t start, end, diff, start_ns, end_ns, diff_ns; start_ns = ktime_get_raw_ns(); start = myrdtsc(); mywrmsr(); end = myrdtsc(); end_ns = ktime_get_raw_ns(); diff = end - start; diff_ns = end_ns - start_ns; pr_info("%llu cycles, %llu ns elpased\n", diff, diff_ns); return 0; } static void mymsr_exit(void) { pr_info("Goodbye mymsr\n"); } module_init(mymsr_init); module_exit(mymsr_exit);
这个例子在inline 汇编中执行读写msr的循环,从而测量出耗时。
标签:__,%%,读写,msr,high,low,寄存器,ebx From: https://www.cnblogs.com/banshanjushi/p/18414508