gpt4 book ai didi

x86 - 驱动程序将如何使用MONITOR指令(_mm_monitor内部函数)?

转载 作者:行者123 更新时间:2023-12-01 23:09:42 25 4
gpt4 key购买 nike

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

任何人都可以分享在驾驶员中如何使用此指令/本征的示例吗?本质上,我想用它来监视内存范围。

最佳答案

monitor 指令使用RAX/EAX/AX中指定的地址武装地址监视硬件。
监控器的状态由mwait指令使用。

使用的有效地址大小(16位,32位或64位)取决于编码指令的有效地址大小(即可以用67h前缀覆盖,默认情况下与代码大小相同)。
rax/eax/ax中给出的地址是逻辑地址的偏移部分,将从该逻辑地址中计算用于武装监视器的线性地址。
细分部分默认为ds,可以使用细分覆盖前缀来更改细分。
作为用于监视器的线性地址,分页不会影响监视。

CPUID.01H:ECX.MONITOR [bit 3] 1位指示monitor(和mwait)指令的可用性。
这是一个特权说明,但英特尔声称:

该指令有条件地以大于0的级别提供。

建议的检测这种情况的方法是尝试执行monitor并处理最终的#UD异常(以自定义方式向OS报告给Userland程序)。

监视的地址范围必须是可写回缓存的。
由于涉及高速缓存和高速缓存一致性子系统,因此以最小和最大大小给出了地址范围的大小。
CPUID.01H:EAX [bit 15:0]给出最小范围大小。这是由硬件监视器监视的区域的长度。
但是,高速缓存一致性流量可能会与较大的“块”(行)一起工作,并且如果监视区域中包含后者,则与受监视区域相邻的写操作仍将触发它。
这会导致最大范围大小,可以在CPUID.01H:EBX [bit 15:0]中找到它。
要正确使用monitor,请确保所监视的数据结构适合最小范围大小,但还要确保没有代理在其旁边的地址中写入最大范围大小的数据。

例如,如果最小范围为8个字节,最大范围为16个字节,请确保观察的结构适合8个字节,但再填充8个字节以达到总计16个字节,以便从第8个字节开始写入到第16个字节。

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

出于指令订购和访问权的目的,monitor是一种负载。
monitor允许程序员指定提示和扩展名。
扩展名在ecx中指定,而提示则在edx中指定。
不支持的扩展引发#GP异常,不支持的提示将被忽略。
我不知道monitor的任何扩展名或提示,英特尔手册报告

对于奔腾4
处理器(系列15,模型3), undefined 任何扩展名或提示。

我认为这条线通常是正确的,只是其中包含了过时的处理器模型。
此外,monitor的伪代码报告为#GP If 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进入实现定义的低功耗状态,直到监视器处于触发状态。
    如果监视器未处于布防状态或已被触发,则 mwaitnop,否则它将使处理器停止执行指令,直到触发监视器为止。

    Hardware monitor status and MONITOR/MWAIT interaction

    还可以给 mwait扩展名和提示。
    扩展名在 ecx中设置,提示在 eax中。
    在撰写本文时,唯一的扩展是:

    位0 即使将其屏蔽(例如,即使EFLAGS.IF = 0),也将中断视为中断事件。仅在以下情况下可以设置
    CPUID.05H:ECX [bit 1] = 1。
    位31-1 保留

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

    位3:0 C状态中的子C状态,由位[7:4]指示
    位7:4 objective-c 状态
    值为0表示C1; 1表示C2,依此类推
    值01111B表示C0
    注意:MWAIT扩展的 objective-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)

    引入了 monitor / mwait机制来帮助线程之间的同步,由于触发条件包括频繁发生的事件,因此它不太适合监视内存范围的访问。
    mwait之后,始终必须检查是否写入了监视范围。
    有一个 example here,其模式如下:
  • 被监视的结构被初始化为特定值(例如0)。
  • 使用monitor / mwait对。
  • 在稍后的某个时刻,另一个再次将特定的值(例如1)写入监视的结构。
  • 触发监视器,并返回mwait,将观察到的结构值与1(发生写入)进行比较,如果不相等,则执行跳转回2。

  • 一些未经测试的伪代码 示例可能是:
    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的原因。

    为了监视对线性地址的写入/读取,可以选择使用调试寄存器。
    请参阅Intel manual 3的第17章,并检查您的OS文档以正确使用这些寄存器。

    1含义:在将cpuid设置为01h的情况下执行eax,然后测试ecx的第3位。请注意,IA32_MISC_ENABLE允许操作系统或固件禁用monitor/mwait

    关于x86 - 驱动程序将如何使用MONITOR指令(_mm_monitor内部函数)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44994106/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com