无法从 MSR 读回

2023-12-03

我正在编写一个内核模块,它是关于读写 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,而不是原来的吗?我的代码有问题吗?多谢。


问题与以下事实有关:您没有完全告诉 gcc 您在内联汇编中使用哪些寄存器以及如何使用,并且您还期望 gcc 不会对内联汇编代码片段之间的寄存器执行任何奇怪的操作。有关的mov and xxmsr指令应该位于同一个 asm 块中。

看看 gcc 对你的代码做了什么(我对它做了一点修改,使其可以作为常规程序进行编译)...

Source:

// 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

拆解test3_init()来自 s 女士:

_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 it has ecx=0x38d(确定),edx=0(确定),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 的线程。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法从 MSR 读回 的相关文章

  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • C++ 求二维数组每一行的最大值

    我已经设法用这个找到我的二维数组的每一行的最小值 void findLowest int A Cm int n int m int min A 0 0 for int i 0 i lt n i for int j 0 j lt m j if
  • 如何在C++中实现模板类协变?

    是否可以以这样一种方式实现类模板 如果模板参数相关 一个对象可以转换为另一个对象 这是一个展示这个想法的例子 当然它不会编译 struct Base struct Derived Base template
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • 基于范围的 for 循环中的未命名循环变量?

    有没有什么方法可以不在基于范围的 for 循环中 使用 循环变量 同时也避免编译器发出有关未使用它的警告 对于上下文 我正在尝试执行以下操作 我启用了 将警告视为错误 并且我不想进行像通过在某处毫无意义地提及变量来强制 使用 变量这样的黑客
  • 按字典顺序对整数数组进行排序 C++

    我想按字典顺序对一个大整数数组 例如 100 万个元素 进行排序 Example input 100 21 22 99 1 927 sorted 1 100 21 22 927 99 我用最简单的方法做到了 将所有数字转换为字符串 非常昂贵
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反

随机推荐

  • 在 Mac 10.8 上从另一个本地设备访问 Meteor 本地 Web 服务器

    我正在开发一个 Meteor 网站 方便地 它将使用简单的命令在本地主机上运行 meteor 但是 我希望能够从本地网络上的其他计算机访问该网站 我想这样做的主要原因是为了在移动设备上查看和测试应用程序 我运行的是 Mac Mountain
  • 如何防止 Firebase 匿名用户令牌过期

    我使用的是 Firebase 应用程序的匿名身份验证 我刚刚注意到我现在有超过 100 个匿名用户注册 尽管我所做的只是测试该应用程序 看起来用户令牌的过期时间很短 一旦过期 下次登录就会创建一个新用户 避免这种情况的最佳方法是什么 我大概
  • 如何禁止不在服务器中的人

    我想知道是否可以通过以下方式禁止某人User ID 通常 要禁止某人 您可以使用GuildMember和 ban method GuildMember ban However 如果用户不在您想要禁止他们加入的公会中 则不可能获得他们的Gui
  • OpenGL:将 VBO 与 std::vector 结合使用

    我正在尝试加载一个对象并使用 VBO 和 glDrawArrays 来渲染它 问题是像这样的简单浮点指针float f 在我的情况下不起作用 因为我超过了该指针可以存储的值的限制 所以我的解决方案是使用向量 而且它不起作用 这是我的代码 u
  • 在 .NET Winforms 应用程序中保存设置[重复]

    这个问题在这里已经有答案了 可能的重复 存储 NET 应用程序的用户设置的最佳方式是什么 我发现了很多关于如何从 Winforms 应用程序保存应用程序设置 每个用户 的非常不同的示例 我想在 C 中执行此操作的正确方法非常简单 希望有人能
  • 在单个 DataGridView 单元格中设置两种颜色的文本

    我的 C Windows 应用程序中有一个数据网格视图 我需要更改单元格中最后 5 个字符的颜色 但我不知道该怎么做 我在 CellPainting 事件中有此代码 但不起作用 private void dgvSorteados CellP
  • 如何使用ajax调用将对象传递给控制器

    我想将一个对象传递给控制器 并检索控制器中的值 我的定义如下 网页代码 var positionarray JavaScript button live click function positionarray push id sessio
  • 在 C 中从字符串调用函数

    在 C 中 如何通过名称作为字符串来调用函数 我有这个 int main int argc const char argv char events test test2 int i 0 for i lt 2 i char event eve
  • 如何在 Android 内部存储上创建文件?

    我想将内部存储上的文件保存到特定文件夹中 我的代码是 File mediaDir new File media if mediaDir exists mediaDir createNewFile mediaDir mkdir File f
  • 从 DOM 中删除 HTMLCollection 元素

    我有一个段落元素的集合 有些是空的 有些只包含空格 而另一些则有内容 p Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpi
  • 如何构建新的 ASP MVC 应用程序?

    我需要启动一个新的 mvc 项目 并且一如既往地我有关于 ASP 身份的问题 永远不知道把它放在哪里 我计划像这样组织解决方案 ProjectWebUI 具有 asp 身份框架的 mvc 应用程序 由具有身份验证的互联网模板制成 Proje
  • Racket 流会记住它们的元素吗?

    当从无限流中计算大量数字时 Racket 是否使用记忆 因此 举例来说 如果我打印 也称为计算并显示 无限整数流上的前 400 个数字 1 2 3 399 400 就在我要求打印这个无限流上的前 500 个数字之后 第二组计算会使用记忆吗
  • Laravel 迁移更改使列可以为空

    我创建了一个未签名的迁移user id 我怎样才能编辑user id在新的迁移中也能做到这一点nullable Schema create throttle function Blueprint table table gt increme
  • 在iOS应用程序中使用本地视频文件(xcode)

    我正在寻找在 iOS 应用程序中播放视频文件的最佳方式 我的应用程序目前正在开发中 将有大约 50 个视频 每个视频长 30 秒 和简短教程 如果可能的话 我希望它们全部在本地 这样用户就可以在没有互联网连接时观看视频 我在堆栈溢出上找不到
  • 如何使用AspectJ修改返回对象的属性?

    我有一个如下所示的类 来自 Spring Roo DataOnDemand 它返回一个新的瞬态 非持久化 对象以用于单元测试 这就是我们从 Spring Roo 的 ITD 进行推送后的代码 public class MyObjectOnD
  • 错误:java.lang.ClassNotFoundException:更新 android studio 3.0.0 时未找到类 org.openjdk.jdi.ReferenceType

    我已将我的项目从 2 2 3 迁移到稳定的 android studio 3 0 0 并设置 jdk 1 8 现在我们运行该应用程序 我正进入 状态 以下例外 Error java lang ClassNotFoundException C
  • jquery .each() .load() 等待完成

    我正在使用 jquery 将行加载到表中 我想知道如何使它们一一加载 即 只有在第一个块完成加载后 第二个块才应开始加载 我的桌子看起来有点像这样 table thead tr th Heading th tr thead tbody tb
  • 无法在 Xcode 6.1 中存档正在运行的 6.0.1 Swift 项目/分段错误:11

    由于信号导致命令失败 分段错误 11 在 Users thedude Documents Repositories MyProject Data swift 258 36 line 258 56 RangeText UILocalNotif
  • 调试 winform 崩溃 - C# [ADPlus + Windbg]

    System AccessViolationException was unhandled Message Attempted to read or write protected memory This is often an indic
  • 无法从 MSR 读回

    我正在编写一个内核模块 它是关于读写 MSR 的 我写了一个简单的程序进行测试 但仍然失败 它所做的就是写入 MSR 然后读回 这是代码 static int init test3 init void uint32 t hi lo hi 0