驱动程序如何使用 MONITOR 指令(_mm_monitor 内在函数)?

2024-03-18

我正在探索使用MONITOR指令(或等效的内在指令,_mm_monitor)。尽管我找到了描述它们的文献,但我找不到任何关于如何使用它的具体示例/样本。

任何人都可以分享如何在驱动程序中使用该指令/内在的示例吗?本质上,我想用它来观察内存范围。


The monitor http://x86.renejeschke.de/html/file_module_x86_id_175.html instruction arms the address monitoring hardware using the address specified in RAX/EAX/AX.Quote from Intel
The state of the monitor is used by the instruction mwait.

使用的有效地址大小(16、32 或 64 位)取决于编码指令的有效地址大小(即可以用67h前缀,默认情况下它与代码大小相同)。

中给出的地址rax/eax/ax是逻辑地址的偏移部分,用于计算用于装备监视器的线性地址。
段部分是ds默认情况下,可以应用段覆盖前缀来更改段。
作为监视器使用的线性地址,分页不会影响监视。

The availability of the monitor (and mwait) instruction is indicated by the bit CPUID.01H:ECX.MONITOR[bit 3]1.
It is a privileged instruction but Intel claims:

这些指令在大于 0 的级别上有条件地可用。

检测这种情况的建议方法是try执行monitor并处理最终的#UD异常(以操作系统将其报告给用户层程序的自定义方式)。

监控的地址范围must可回写缓存。
由于涉及缓存和缓存一致性子系统size地址范围以最小和最大大小给出。
CPUID.01H:EAX[位 15:0]给出最小范围大小。这是硬件监视器监视的区域的长度。
然而,缓存一致性流量可能适用于较大尺寸的“块”(行),并且如果后者包含在前者中,则与受监控区域相邻的写入仍然会触发它。
这产生了最大范围大小,可以在CPUID.01H:EBX[位 15:0].
要正确使用monitor确保监视的数据结构适合最小范围大小,但也确保没有代理在其旁边的地址中写入最大范围大小。

例如,如果最小范围大小为 8 个字节,最大大小为 16 个字节,请确保监视的结构适合 8 个字节,但用另外 8 个字节填充它以达到总共 16 个字节,这样就不会从第 8 个字节开始写入到第 16 个字节发生。

在单集群系统中,以上两个值是相等的。我的都是64字节。
BIOS 负责报告高速缓存一致性线大小IA32_MONITOR_FILTER_LINE_SIZE在多集群系统中。

为了指令排序和访问权的目的,monitor是一个负载。

monitor允许程序员指定hints and 扩展.
扩展名指定于ecx当提示出现时edx.
不支持的扩展会引发 #GP 异常,不支持的提示将被忽略。
我不知道有任何扩展或提示monitor,英特尔手册报告

对于奔腾 4 处理器(系列 15,型号 3),未定义扩展或提示。

我相信这条线总体来说是正确的,只是其中有一个过时的处理器型号。
此外,伪代码为monitor报告#GPIf ECX ≠ 0.

装备显示器而不检查其状态(使用mwait)不会造成任何伤害。

其内在本质是void _mm_monitor(void const *p, unsigned extensions,unsigned hints).


一旦监视器布防,它可以由不同的条件触发:

  • 外部中断:NMI、SMM、INIT、BINIT、MCERR
  • 故障、中止,包括机器检查
  • 架构 TLB 失效,包括对 CR0、CR3、CR4 的写入和某些 MSR 写入
  • 由于快速系统调用和远程调用而导致的自愿转换
  • 屏蔽中断(如果启用)
  • 监视地址范围内的写入

监视器的状态对程序员不可见,但可以使用以下命令进行测试mwait.
mwait进入实现定义的低功耗状态,直到监视器处于触发状态。
如果监视器未进入布防状态或已被触发mwait is a nop否则它会使处理器停止执行指令,直到触发监视器为止。

mwait也可以给出扩展 and hints.
扩展名设置在ecx并提示eax.
在撰写本文时,唯一的扩展是:

Bit 0即使被屏蔽(例如,即使 EFLAGS.IF=0),也将中断视为中断事件。仅当以下情况时才可设置CPUID.05H:ECX[位 1] = 1.
位 31-1预订的

这些提示让程序员可以指定实现定义的低功耗模式。

Bits 3:0C 状态内的子 C 状态,由位 [7:4] 指示
Bits 7:4目标C状态
值为0表示C1; 1表示C2等
01111B 的值表示 C0
注意:MWAIT 扩展的目标 C 状态是处理器特定的 C 状态,而不是 ACPI C 状态

C 模式的子状态数(因此是可用性)由下式给出:CPUID.05h.EDX:

位 03 - 00:使用 MWAIT 支持的 C0* 子 C 状态数。
位 07 - 04:使用 MWAIT 支持的 C1* 子 C 状态数。
位 11 - 08:使用 MWAIT 支持的 C2* 子 C 状态数。
位 15 - 12:使用 MWAIT 支持的 C3* 子 C 状态数。
位 19 - 16:使用 MWAIT 支持的 C4* 子 C 状态数。
位 23 - 20:使用 MWAIT 支持的 C5* 子 C 状态数。
位 27 - 24:使用 MWAIT 支持的 C6* 子 C 状态数。
位 31 - 28:使用 MWAIT 支持的 C7* 子 C 状态数。

请注意,将 CPU 置于高于 C1 的状态也会禁用其他线程,因此触发监视器的写入必须来自其他代理。

其内在本质是void _mm_mwait(unsigned extensions, unsigned hints).


The monitor/mwait引入机制是为了帮助线程之间的同步,但它不太适合监视对内存范围的访问,因为触发条件包括频繁发生的事件。
之后mwait始终强制检查监视范围是否已写入。
有一个例子在这里 https://software.intel.com/en-us/articles/how-to-use-the-monitor-and-mwait-streaming-simd-extensions-3-instructions其中模式如下:

  1. 监视的结构使用特定值(例如 0)进行初始化。
  2. The monitor/mwait使用对。
  3. 在稍后的某个时刻,另一个再次将特定值(例如 1)写入所监视的结构中。
  4. 监视器被触发并且mwait“返回”,将监视的结构值与 1(发生写入)进行比较,如果不相等,则执行跳回 2。

一些样本,untested伪代码可能是:

struct MonitoredType
{
  int (*event)(struct MonitoredType const* m);              /*Return 0 to keep monitoring*/
  struct AnyType data;                                /*Less, in size, than MIN_MONITOR_RANGE*/
  char padding[MAX_MONITOR_RANGE - sizeof(AnyType)];
};

void wait_for_write(struct MonitoredType const* m)
{
   /* This may miss a write if it happens before MONITOR, beware of race conditions if necessary */
   do
   {
     _mm_monitor(&m->data, 0, 0);
     _mm_mwait(0, 0);
   } while ( ! m->event(m));
}

必须注意确保退出条件mwait是一次写入,而不是其他事件之一。
这就是函数指针的原因event.

为了监视对线性地址的写入/读取,可以使用以下替代方法:调试寄存器.
参见第 17 章英特尔手册3 https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-system-programming-manual-325384.html并检查操作系统文档以正确使用这些寄存器。


1 Meaning: Execute cpuid with eax set to 01h and test the bit 3 of ecx afterward. Note that IA32_MISC_ENABLE allows the OS or the firmware to disable monitor/mwait.

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

驱动程序如何使用 MONITOR 指令(_mm_monitor 内在函数)? 的相关文章

  • 从 DX:AX 寄存器转移到单个 32 位寄存器

    我在添加 16 位乘法的乘积时遇到问题 我想将一年 例如 2015 年 乘以 365 为此 我 mov dx 0 to clear the register mov ax cx cx holds the year such as 2015
  • termios 库中如何表示标志?

    我是 C 语言和驱动程序编程的新手 目前 我正在编写一个用户空间驱动程序 以便使用 Debian 通过 USB 与 RS232 进行通信 在研究时 我遇到了以下代码 tty c cflag PARENB No Parity tty c cf
  • 对将英特尔傲腾 DC SSD 用作 IMDT 的额外 RAM 感到困惑吗? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我对英特尔傲腾 DC 有点困惑 我希望我的 Optane DC 能够同时充当 DRAM 和存储 一方面 我了解到只有 英特尔傲腾 DC 持
  • 比“add esp, 4”更小的指令

    又是我 我的程序中有很多 add esp 4 我正在尝试减小它的大小 是否有任何更小的指令可以替代 add esp 4 pop edx 或者您不介意破坏的任何其他整数寄存器 这就是现代编译器实际上所做的 https stackoverflo
  • 为什么 mov %ax, %ds 汇编+反汇编为 mov %eax,%ds,与原来不一致?

    test S text global start start xor ax ax mov ax ds mov ax ss mov ax es mov ax fs mov ax gs 我通过这样做得到了反汇编代码文件 x86 64 elf g
  • x86 asm 图形设置的分辨率高于 640x480?

    我刚刚开始使用汇编语言 感觉像学习新东西 并且遇到了一些问题 到目前为止 我一直在浏览的所有教程都没有回答 或者太旧而无法知道 1 我尝试了一些搜索 也许我只是不知道正确的关键字 但我找不到用于更改屏幕分辨率等的图形模式的更新列表 我发现的
  • 无法在 Windows 7 上安装 Android USB 驱动程序

    所以我想使用我的新 Nexus 5 来调试我的应用程序 我尝试通过以下方式安装 Android USB 驱动程序装置经理 http developer android com tools extras oem usb html Win7但我
  • 如何使 gcc 为 -fpatchable-function-entry 发出多字节 NOP?

    gcc确实有能力使用多字节用于对齐循环和函数的 NOP 然而当我尝试 fpatchable function entry option https gcc gnu org onlinedocs gcc Instrumentation Opt
  • x86:寄存器操作为内存内容和内存地址?

    寄存器 gt 内存地址 gt 内存内容 内存地址 gt 内存内容 上面的模型正确吗 而且 如果是的话 你能建议我是否认为正确吗 movl eax ebx gt 它将 eax 的内存地址移动到 ebx 这也会导致内容移动 movl eax e
  • 跳转目的地太远:3 个字节

    我的循环有问题 其中包含的代码很长并且给了我错误jump destination too far by 3 byte s 当我删除时 mov edx offset str1 call writestring 这部分位于主过程下方 它不会给出
  • 如何使用 LOCK ASM 前缀来读取值?

    我知道如何使用 LOCK 来线程安全地递增一个值 lock inc J 但是如何以线程安全的方式读取 J 或任何值 LOCK 前缀不能与 mov 一起使用 如果我执行以下操作 xor eax eax lock add eax J mov J
  • 如何使用存储在 x64 位置的 x64 内存地址进行跳转?

    据我所知 使用 64 位地址作为操作数的 jmp 是不可能的 但我相信使用 x64 内存位置是 来自here http www tptp cc mirrors siyobik info instruction JMP htmlJMP r m
  • 给寄存器赋值并加减

    我对此完全迷失了 我需要使用寄存器来计算以下表达式的编程 varA varA varB varC varD 其中 varA varB 等是变量 将整数值分配给上述变量的 EAX EBX ECX 和 EDX 寄存器 这意味着 您可以对输入进行
  • 使用`esp*scale 时寻址内存时出错

    内存寻址一般形式 发现了here https stuff mit edu afs athena project rhel doc OldFiles 3 rhel as en 3 i386 memory html is base index
  • 调用/返回/jmp等后x86代码执行?

    我希望这个问题不会太愚蠢 因为它看起来似乎很明显 当我对缓冲区溢出进行一些研究时 我偶然发现了一个简单的问题 调用 返回 跳转后转到新指令地址后 CPU是否会执行该地址处的OP代码 然后将一个字节移动到下一个地址并执行下一个OP代码 依此类
  • MS-DOS - 是否可以对 24 位图形进行编程?

    是否可以在 DOS 机器上以 24 位颜色深度进行编程 我知道 VGA 支持 8 位色深 但是有没有办法弄出 24 位色深 谷歌的研究没有发现任何结果 我正在 FreeDOS 而不是 MS DOS 上编程 如果这会影响答案的话 对的 这是可
  • 是否可以调用驻留在 exe 中的非导出函数?

    我想调用驻留在第 3 方 exe 中的函数并获取其结果 好像有should是一种方法 只要我知道函数地址 调用约定等 但我不知道如何 有谁知道我会怎么做 我意识到任何解决方案都是非标准的黑客 但有must成为一种方式 我的非恶意用例 我正在
  • 如何检查docker中当前/默认的日志驱动程序?

    我正在尝试检查已停止的 docker 容器的日志 但是当我这样做时docker logs
  • 汇编程序中的过程调用如何工作?

    我刚刚开始摆弄 ASM 我不确定我对过程调用的理解是否正确 假设代码中的某个时刻有一个过程调用 call dword ptr 123 该过程仅包含一个命令 ret ret 0004 该过程调用的效果是什么 返回值将存储在哪里 我在某处读到
  • 我们可以使用 x86_64 CPU 原子在 PCI Express 上生成复合原子操作吗?

    如您所知 从2 0版本开始 PCI Express支持复合原子操作 FetchAdd Swap CAS https pcisig com sites default files specification documents ECN Ato

随机推荐