gpt4 book ai didi

linux-kernel - mwait x86 指令不等待 DMA

转载 作者:行者123 更新时间:2023-12-04 02:49:02 25 4
gpt4 key购买 nike

我正在尝试使用 monitor / mwait 监视从设备到内存位置的 DMA 写入的指令。在内核模块(字符设备)中,我有以下代码(非常类似于内核代码的this piece)在内核线程中运行:

static int do_monitor(void *arg)
{
struct page *p = arg; // p is a 'struct page *'; it's also remapped to user space
uint32_t *location_p = phys_to_virt(page_to_phys(p));
uint32_t prev = 0;
int i = 0;
while (i++ < 20) // to avoid infinite loop
{
if (*location_p == prev)
{
__monitor(location_p, 0, 0);
if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
clflush(location_p);
if (*location_p == prev)
__mwait(0, 0);
}
prev = *location_p;
printk(KERN_NOTICE "%d", prev);
}
}

在用户空间中,我有以下测试代码:
int fd = open("/dev/mon_test_dev", O_RDWR);
unsigned char *mapped = (unsigned char *)mmap(0, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
for (int i = 1; i <= 5; ++i)
*mapped = i;
munmap(mapped, mmap_size);
close(fd);

内核日志如下所示:
1
2
3
4
5
5
5
5
5
5
5 5 5 5 5 5 5 5 5 5

IE。似乎 mwait根本不等。
可能是什么原因?

最佳答案

MONITOR/MWAIT 语义的定义没有明确指定 DMA 事务是否可以触发它。假设触发发生在逻辑处理器的存储上。

英特尔官方软件开发人员手册中当前对 MONITOR 和 MWAIT 的描述在这方面相当模糊。但是,MONITOR 部分中有两个子句引起了我的注意:

  • EAX 的内容是一个有效地址(在 64 位模式下,使用 RAX)。默认情况下,DS 段用于创建受监控的线性地址。
  • 地址范围必须使用回写类型的内存。只有回写存储器才能正确触发
    监控硬件。

  • 第一个子句指出 MONITOR 旨在用于线性地址,而不是物理地址。设备及其 DMA 仅适用于物理地址。所以基本上这意味着依赖于相同 MONITOR 范围的所有代理都应该在相同的虚拟内存空间域中运行。

    第二个子句要求被监控的内存区域是可缓存的(回写,WB)。对于 DMA,通常必须将相应的内存范围标记为不可缓存,或者最好是写组合(UC 或 WC)。这甚至是一个更强有力的指标,表明您使用 DMA 触发的 MONITOR/MWAIT 的意图不太可能在当前硬件上工作。

    考虑到您的高级目标——能够判断设备何时写入给定的内存范围——除了对设备使用虚拟化(VTd、IOMMU 等)之外,我不记得有任何可靠的方法来实现它。基本上,经典的方法外围设备将在写入内存完成时发出中断。在中断到达之前,CPU 无法判断所有 DMA 字节是否已成功到达内存中的目的地。

    设备虚拟化允许以透明的方式从设备中抽象出物理地址,并且当它尝试从内存中写入/读取时具有等效的页面错误。

    关于linux-kernel - mwait x86 指令不等待 DMA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21671807/

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