'1'
,0x31)存储到物理线性地址B8000
处的VGA文本(模式03)帧缓冲区时,在以16位传统BIOS MBR模式引导的现代PC硬件上会发生什么?如果该区域的MTRR设置为UC,mov [es:di], eax
存储有多慢?(在一台Kaby Lake iGPU笔记本电脑上进行的实验测试表明,对于VGA内存,WC上的clflushopt速度大约与UC相同。但是,没有clflushopt,对于WC存储器的mov
存储从不离开CPU,根本不更新屏幕,运行非常快。)如果不是每个存储都是SMI,是否有任何方法在用户空间的一块WB内存上近似计算这个成本,以进行性能实验而无需重新启动到实模式?(例如使用BSS页作为虚拟帧缓冲区,它实际上不会显示在任何地方)。
相应的字形将在下一个刷新中出现在屏幕上,但是硬件扫描输出真的从VRAM(或iGPU的DRAM)读取该ASCII字符并即时映射到位图字体吗?还是每次存储或每个vblank拦截一次软件,以便真正的硬件只需处理位图帧缓冲区?
传统BIOS引导众所周知使用系统管理模式(SMM)来模拟USB键盘/鼠标作为PS / 2设备。 我想知道它是否也用于VGA文本模式帧缓冲区。我假设它用于VGA I/O端口进行模式设置,但硬件可能支持文本帧缓冲区。然而,大多数计算机都在图形模式下花费所有时间,因此省略文本模式的HW支持似乎是供应商可能要做的事情。(另一方面,这篇博客表明自制Verilog VGA控制器可以相当简单地实现文本模式。) 我特别关注使用Intel Skylake中的iGPU的系统,但对来自Intel和AMD的早期/后期iGPU以及新旧独立GPU也感兴趣。
(包括除AMD和NVidia之外的其他供应商;有些Skylake主板具有PCI插槽,而不是PCIe。如果现代GPU固件驱动程序确实模拟文本模式,则可能存在一些具有硬件VGA文本模式的旧PCI视频卡。并且可能这样的卡可以使存储仅成为PCI事务,而不是SMI。)
我的桌面是一个i7-6700k,安装在Asus Z170 Pro Gaming主板上,没有附加卡片,只有一个连接在DVI-D输出上的1920x1200监视器。我不知道@Eldan正在测试的Kaby Lake i5-7300HQ系统的详细信息,只知道CPU型号。
我在2011年找到了Phoenix BIOS的专利US20120159520,标题为“使用UEFI模拟遗留视频”。他们提出了一种真实模式VGA驱动程序(int 10h函数等),通过SMM钩子调用供应商提供的UEFI视频驱动程序,而不是要求视频硬件供应商提供UEFI和本机16位实模式选项ROM驱动程序。
摘要:通用视频选项ROM通知通用视频SMM驱动程序请求视频服务。此类通知可以使用软件系统管理中断(SMI)执行。收到通知后,通用视频SMM驱动程序会通知第三方UEFI视频驱动程序请求视频服务。第三方视频驱动程序向操作系统提供所需的视频服务。通过这种方式,第三方UEFI图形驱动程序可以支持各种操作系统,即使这些操作系统没有本地支持UEFI显示协议。
大部分描述涵盖处理int 10h调用和诸如此类的内容,这些内容已经明显地通过IVT陷阱运行自定义代码,从而可以故意触发SMI。相关部分是他们描述的直接存储到文本模式帧缓冲区的内容,即使对于不触发任何软件或硬件中断的代码也需要正常工作。(除了硬件触发SMI这样的存储器,如果支持,他们说他们可以使用。)
文本缓冲区支持:在某些实施例中,应用程序可以直接操作VGA的文本缓冲区。在这种情况下,通用视频SMM驱动程序130以以下两种方式之一支持此操作,具体取决于硬件是否提供SMI陷阱来读/写访问740 KB-768 KB内存区域(文本缓冲区所在的位置)。当可用时,硬件在每个读取或写入访问上生成SMI。使用SMI陷阱的陷阱地址,可以计算出确切的文本列和行,并访问虚拟文本屏幕中的相应行和列。
或者,对于该区域,启用普通内存,并使用定期SMI,通用视频SMM驱动程序130扫描模拟硬件文本缓冲区中的更改,并更新由视频驱动程序维护的相应虚拟文本屏幕。在两种情况下,检测到更改时,字符会重新绘制在虚拟文本屏幕上。
这只是一个BIOS供应商的专利,并没有告诉我们大多数硬件实际上的工作方式,或者其他供应商是否做了不同的事情。它基本上确认了存在一些硬件可以陷入该范围的存储器中,尽管这可能只是他们决定在其专利中涵盖的一种假设可能性。
对于我考虑的使用情况,仅在屏幕刷新时进行捕获比在每次存储时进行捕获要快得多,因此我想知道哪些硬件/固件是这样工作的。
问题的动机
在第七代Intel Core上优化一个递增的ASCII十进制计数器在视频RAM中- 将ASCII文本计数器的新数字重复存储到视频RAM的同几个字节中。
我在Linux的32位用户空间下测试了代码的一个版本,使用WB内存,希望通过movnti
和不同的方式让CPU在每次存储后将其WC缓冲区与视频RAM同步(或者在定时器中断时偶尔同步)。但是,如果实模式引导加载程序不仅仅是存储到DRAM,而是触发SMI,那么这种情况就不现实。
在WB内存上,使用lock xor byte [esp], 0
刷新movnti
存储比使用clflushopt
刷新略快。但是@Eldan报告称,在编程MTRR将其变为WC后,对于VGA内存上的那些操作没有速度提升。(并且与原始执行普通存储的速度相同,表明默认情况下VGA帧缓冲区为UC。一些旧的BIOS有一个选项可以将VGA内存变为WC,他们称之为USWC =未缓存的推测写结合。)
这不是一个真实的问题,所以我不在寻找实际的解决方案; 虽然了解手动将像素字节存储到VGA图形模式是否可以更快速会很有趣。
摘要
- 是否所有现代系统在向文本模式帧缓冲区存储时都会触发SMI?
- 如果不是,我们能否使用用户空间中的movnti +某些内容来近似一个WC store+clflush到帧缓冲区?以便我们可以轻松地使用
perf
进行性能计数器分析。 - 如果不同的BIOS和/或硬件使用不同的策略,那么这些策略是什么?(我不需要细节,只需要高级别的策略,例如“每个vblank触发SMI以将VGA帧缓冲区与实际硬件帧缓冲区同步”)
- 具有硬件VGA文本模式的PCIe或PCI视频卡是否比集成GPU实际执行的更快?我猜想实际的PCIe写事务速度会比等待存储器访问慢,但PCIe写入的成本会比每次存储器访问时都触发SMI低。一个大致的数量级比较将是有趣的。
这些问题都高度相关,但如果没有我所期望的那么多重叠,我可以将其拆分。
RDMSR
来获取“MSR_SMI_COUNT = 0x34”,而无需编程计数器。 - Peter Cordes