我正在编写一个内核模块,它是关于读写MSR的。我写了一个简单的程序来测试,但它仍然失败。它所做的一切就是写入MSR,然后读回它。代码如下:
static int __init test3_init(void)
{
uint32_t hi,lo;
hi=0; lo=0xb;
asm volatile("mov %0,%%eax"::"r"(lo));
asm volatile("mov %0,%%edx"::"r"(hi));
asm volatile("mov $0x38d,%ecx");
asm volatile("wrmsr");
printk("exit_write: hi=%08x lo=%08x\n",hi,lo);
asm volatile("mov $0x38d,%ecx");
asm volatile("rdmsr":"=a"(lo),"=d"(hi));
printk("exit_write2: hi=%08x lo=%08x\n",hi,lo);
return 0;
}输出如下所示:
exit_write: hi=00000000 lo=0000000b
exit_write2: hi=00000000 lo=00000000
谁能告诉我为什么在第二个输出中返回值是0,而不是原始输出?我的代码有什么问题吗?非常感谢。
发布于 2012-06-25 16:19:01
这个问题与这样一个事实有关,即你没有完全告诉gcc你在内联汇编中使用了哪些寄存器以及如何使用,而且你也希望gcc不会对你的内联汇编代码片段之间的寄存器做任何奇怪的事情。相关的mov和xxmsr指令应该在同一个asm块中。
看看gcc对你的代码做了什么(我对它做了一点改动,使它可以像普通程序一样编译)……
来源:
// file: msr.c
#include <stdio.h>
typedef unsigned uint32_t;
#define printk printf
#define __init
static int __init test3_init(void)
{
uint32_t hi,lo;
hi=0; lo=0xb;
asm volatile("mov %0,%%eax"::"r"(lo));
asm volatile("mov %0,%%edx"::"r"(hi));
asm volatile("mov $0x38d,%ecx");
asm volatile("wrmsr");
printk("exit_write: hi=%08x lo=%08x\n",hi,lo);
asm volatile("mov $0x38d,%ecx");
asm volatile("rdmsr":"=a"(lo),"=d"(hi));
printk("exit_write2: hi=%08x lo=%08x\n",hi,lo);
return 0;
}
int main(void)
{
return test3_init();
}编译(使用MinGW gcc 4.6.2):
gcc msr.c -c -S -o msr.s从msr.s中反汇编test3_init():
_test3_init:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %ebx
subl $32, %esp
movl $0, -12(%ebp)
movl $11, -16(%ebp)
movl -16(%ebp), %eax
mov %eax,%eax
movl -12(%ebp), %eax
mov %eax,%edx
mov $0x38d,%ecx
wrmsr
movl -16(%ebp), %eax
movl %eax, 8(%esp)
movl -12(%ebp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
mov $0x38d,%ecx
rdmsr
movl %edx, %ebx
movl %eax, %esi
movl %esi, -16(%ebp)
movl %ebx, -12(%ebp)
movl -16(%ebp), %eax
movl %eax, 8(%esp)
movl -12(%ebp), %eax
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
movl $0, %eax
addl $32, %esp
popl %ebx
popl %esi
popl %ebp
ret注意,当CPU开始执行wrmsr时,它的ecx=0x38d (OK),edx=0 (OK),eax=0 (不是0xb,糟糕!)。请按照说明进行查看。
你可以写的和应该写的内容类似于以下内容,甚至比以前更短:
static int __init test3_init2(void)
{
uint32_t hi,lo;
hi=0; lo=0xb;
asm volatile("wrmsr"::"c"(0x38d),"a"(lo),"d"(hi));
printk("exit_write: hi=%08x lo=%08x\n",hi,lo);
asm volatile("rdmsr":"=a"(lo),"=d"(hi):"c"(0x38d));
printk("exit_write2: hi=%08x lo=%08x\n",hi,lo);
return 0;
}现在,test3_init2()的反汇编
_test3_init2:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %ebx
subl $48, %esp
movl $0, -12(%ebp)
movl $11, -16(%ebp)
movl $909, %ecx
movl -16(%ebp), %eax
movl -12(%ebp), %edx
wrmsr
movl -16(%ebp), %eax
movl %eax, 8(%esp)
movl -12(%ebp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
movl $909, -28(%ebp)
movl -28(%ebp), %ecx
rdmsr
movl %edx, %ebx
movl %eax, %esi
movl %esi, -16(%ebp)
movl %ebx, -12(%ebp)
movl -16(%ebp), %eax
movl %eax, 8(%esp)
movl -12(%ebp), %eax
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
movl $0, %eax
addl $48, %esp
popl %ebx
popl %esi
popl %ebp
ret此外,请记住,每个CPU都有自己的MSR,您可能希望在所有CPU上都设置此MSR。另一个重要的注意事项是,在处理完MSR之前,不应该在不同的CPU之间移动正在操作MSR的线程。
https://stackoverflow.com/questions/11183654
复制相似问题