首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法从MSR回读

无法从MSR回读
EN

Stack Overflow用户
提问于 2012-06-25 12:50:53
回答 1查看 3.1K关注 0票数 1

我正在编写一个内核模块,它是关于读写MSR的。我写了一个简单的程序来测试,但它仍然失败。它所做的一切就是写入MSR,然后读回它。代码如下:

代码语言:javascript
复制
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,而不是原始输出?我的代码有什么问题吗?非常感谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-06-25 16:19:01

这个问题与这样一个事实有关,即你没有完全告诉gcc你在内联汇编中使用了哪些寄存器以及如何使用,而且你也希望gcc不会对你的内联汇编代码片段之间的寄存器做任何奇怪的事情。相关的movxxmsr指令应该在同一个asm块中。

看看gcc对你的代码做了什么(我对它做了一点改动,使它可以像普通程序一样编译)……

来源:

代码语言:javascript
复制
// 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):

代码语言:javascript
复制
gcc msr.c -c -S -o msr.s

从msr.s中反汇编test3_init()

代码语言:javascript
复制
_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,糟糕!)。请按照说明进行查看。

你可以写的和应该写的内容类似于以下内容,甚至比以前更短:

代码语言:javascript
复制
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()的反汇编

代码语言:javascript
复制
_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的线程。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11183654

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档