驱动程序将如何使用MONITOR指令(_mm_monitor内部函数)? [英] How would the MONITOR instruction (_mm_monitor intrinsic) be used by a driver?

查看:154
本文介绍了驱动程序将如何使用MONITOR指令(_mm_monitor内部函数)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



任何人都可以分享一个示例说明/本意的示例吗?用在司机?本质上,我想用它来监视内存范围。

解决方案



mwait 也可以被赋予扩展名提示

扩展名设置在 ecx eax 中的提示。

在编写本文时,唯一的扩展名是:


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

位31-1 保留


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


位3:0 C状态中的子C状态,由位[7:4 ]

位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:
支持的C2 *子C状态数15-12 :使用MWAIT支持的C3 *子C状态数。

位19-16:使用MWAIT支持的C4 *子C状态数。
第23-20位:数MWAIT支持的C5 *子C状态的数量。

位MWAIT支持的C6 *子C状态的数量。

位31-28:C7的数量*使用MWAIT支持的子C状态。


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



内在函数是 void _mm_mwait(未签名的扩展名,未签名的提示)






监视器 / mwait <引入了/ code>机制来帮助线程之间的同步,由于触发条件包括频繁发生的事件,因此它不太适合监视内存范围的访问。

mwait
始终是强制性的,以检查是否将监视范围写入到其中。

有一个此处的示例,其模式如下:


  1. 被监视的结构初始化为特定值(例如0)。

  2. 使用监视器 / mwait 对。

  3. 在稍后的某个时刻,另一个再次向受监视的结构写入一个特定值(例如1)。

  4. 监视器已触发,并且 mwait 返回,将观察到的结构值与1(发生写操作)进行比较,如果不相等,则执行跳转回2。

一些示例,未经测试的伪代码可能是:

  struct MonitoredType 
{
int(* event)(struct MonitoredType const * m); / *返回0以继续监视* /
结构AnyType数据; / *大小小于MIN_MONITOR_RANGE * /
char padding [MAX_MONITOR_RANGE-sizeof(AnyType)];
};

void wait_for_write(struct MonitoredType const * m)
{
/ *如果在MONITOR之前发生,这可能会丢失写操作,必要时请注意竞争条件* /

{
_mm_monitor(& m-> data,0,0);
_mm_mwait(0,0);
} while(!m-> event(m));
}

必须注意确保退出条件 mwait 是写操作,而不是其他任何事件。

这就是函数指针 event 的原因。



要监视对线性地址的写入/读取,可以使用调试寄存器

请参阅本章英特尔手册3 ,并检查操作系统文档以确保这些寄存器的正确使用。






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


I am exploring the usage of MONITOR instruction (or the equivalent intrinsic, _mm_monitor). Although I found literature describing them, I could not find any concrete examples/samples on how to use it.

Can anyone share an example of how this instruction/intrinsic would be used in a driver? Essentially, I would like to use it to watch memory ranges.

解决方案

The monitor 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.

The effective address size used (16, 32 or 64-bit) depends on the effective address size of the encoded instruction (i.e. it can be overridden with the 67h prefix and by default it is the same as the code size).

The address given in rax/eax/ax is the offset part of the logical address from which the linear address used to arm the monitor is computed.
The segment part is ds by default, segment override prefixes can be applied to change segment.
Being a linear address used for the monitor, paging doesn't affect the monitoring.

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:

The instructions are conditionally available at levels greater than 0.

The suggested method to detect such condition is to try to execute monitor and handle the eventual #UD exception (in the custom way to OS reports it to a userland program).

The address range monitored must be write-back cacheable.
Due to the involvement with the cache and cache coherence subsystems the size of the address range is given in term of the minimal and maximal sizes.
CPUID.01H:EAX[bit 15:0] gives the minimal range size. This is the length of the region monitored by the hardware monitor.
However, cache coherence traffic may work with "chunks" (lines) of bigger size and a write adjacent to the monitored region would trigger it nonetheless if the latter is included in the former.
This gives rise to the maximum range size, it can be found in CPUID.01H:EBX[bit 15:0].
To properly use monitor make sure that the data structure monitored fits the minimal range size but also make sure that no agents write in the addresses next to it up to the maximal range size.

For example, if the minimal range size is 8 bytes and the maximal size is 16 bytes, make sure that the structure watched fits 8 bytes but pad it with eight more bytes to reach a total of sixteen so that no write from the 8-th to the 16-th byte occurs.

In a single cluster system, the two values above are equal. Mine are both 64 bytes.
The BIOS is responsible for reporting the cache coherence line size in IA32_MONITOR_FILTER_LINE_SIZE in multi-clustered systems.

For the purpose of instruction ordering and access right, monitor is a load.

monitor allows the programmer to specify hints and extensions.
Extensions are specified in ecx while hints are in edx.
Unsupported extensions raise a #GP exception, unsupported hints are ignored.
I'm not aware of any extension or hint for monitor, the Intel manual reports

For the Pentium 4 processor (family 15, model 3), no extensions or hints are defined.

I believe that line is true in general, it just has an outdated processor model in it.
Further, the pseudo code for monitor report a #GP If ECX ≠ 0.

Arming the monitor without checking its state afterwards (with mwait) doesn't cause any harm.

The intrinsic is void _mm_monitor(void const *p, unsigned extensions,unsigned hints).


Once the monitor is armed, it can be trigger by different conditions:

  • External interrupts: NMI, SMM, INIT, BINIT, MCERR
  • Faults, Aborts including Machine Check
  • Architectural TLB invalidations, including writes to CR0, CR3, CR4 and certain MSR writes
  • Voluntary transitions due to fast system call and far calls
  • Masked interrupt (if enabled)
  • A write in the monitored address range

The state of the monitor is not visible to the programmer but it can be tested with mwait.
mwait enters an implementation-defined low power state until the monitor is in a triggered state.
If the monitor is not into an armed state or if it is already triggered mwait is a nop otherwise it makes the processor stop executing instructions until the monitor is triggered.

mwait can also be given extensions and hints.
Extensions are set in ecx and hints in eax.
At the time of writing the only extension is:

Bit 0 Treat interrupts as break events even if masked (e.g., even if EFLAGS.IF=0). May be set only if CPUID.05H:ECX[bit 1] = 1.
Bits 31-1 Reserved

The hints lets the programmer specify the implementation defined low power mode.

Bits 3:0 Sub C-state within a C-state, indicated by bits [7:4]
Bits 7:4 Target C-state
Value of 0 means C1; 1 means C2 and so on
Value of 01111B means C0
Note: Target C states for MWAIT extensions are processor-specific C-states, not ACPI C-states

The number of sub-states of a C-mode (and thus is availability) is given in CPUID.05h.EDX:

Bits 03 - 00: Number of C0* sub C-states supported using MWAIT.
Bits 07 - 04: Number of C1* sub C-states supported using MWAIT.
Bits 11 - 08: Number of C2* sub C-states supported using MWAIT.
Bits 15 - 12: Number of C3* sub C-states supported using MWAIT.
Bits 19 - 16: Number of C4* sub C-states supported using MWAIT.
Bits 23 - 20: Number of C5* sub C-states supported using MWAIT.
Bits 27 - 24: Number of C6* sub C-states supported using MWAIT.
Bits 31 - 28: Number of C7* sub C-states supported using MWAIT.

Note that putting the CPU into a state higher than C1 disable other threads too, so the write that triggers the monitor must come from other agents.

The intrinsic is void _mm_mwait(unsigned extensions, unsigned hints).


The monitor/mwait machinery was introduced to help synchronisation between threads, it is not well suited for monitoring accesses to a memory range because the trigger conditions include frequently occurring events.
After a mwait is always mandatory to check if the monitored range was written to.
There is an example here where the pattern is as follow:

  1. The watched structure is initialized with a specific value (say 0).
  2. The monitor/mwait pair is used.
  3. At some point later, another again write a specific value (say 1) to the watched structure.
  4. The monitor is triggered and mwait "returns", the watched structure value is compared to 1 (a write occurred) and if it is not equal execution jump back to 2.

Some sample, untested pseudo-code may be:

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));
}

Care must be taken to ensure that the exit condition of mwait was a write and not one of the other events.
That's the reason for the function pointer event.

For monitoring writes/reads to linear address an alternative can be the use of the debugging registers.
See chapter 17 of Intel manual 3 and check your OS documentation for the proper use of those registers.


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.

这篇关于驱动程序将如何使用MONITOR指令(_mm_monitor内部函数)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆