现代个人电脑的视频硬件是否支持VGA文本模式的硬件实现,还是通过BIOS进行模拟(使用系统管理模式)?

22
当您将一个字节(例如'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图形模式是否可以更快速会很有趣。


摘要

  1. 是否所有现代系统在向文本模式帧缓冲区存储时都会触发SMI?
  2. 如果不是,我们能否使用用户空间中的movnti +某些内容来近似一个WC store+clflush到帧缓冲区?以便我们可以轻松地使用perf进行性能计数器分析。
  3. 如果不同的BIOS和/或硬件使用不同的策略,那么这些策略是什么?(我不需要细节,只需要高级别的策略,例如“每个vblank触发SMI以将VGA帧缓冲区与实际硬件帧缓冲区同步”)
  4. 具有硬件VGA文本模式的PCIe或PCI视频卡是否比集成GPU实际执行的更快?我猜想实际的PCIe写事务速度会比等待存储器访问慢,但PCIe写入的成本会比每次存储器访问时都触发SMI低。一个大致的数量级比较将是有趣的。

这些问题都高度相关,但如果没有我所期望的那么多重叠,我可以将其拆分。


难道SMIs没有性能计数器吗? - prl
1
@prl:实际上,计算SMI更容易:显然有一个MSR而不是性能计数器,所以只需先进行RDMSR来获取“MSR_SMI_COUNT = 0x34”,而无需编程计数器。 - Peter Cordes
这比我的另一个想法容易得多,那就是使用第34.15节中描述的技术来检测SMI。 - prl
@prl:34.15 是指 Intel 的第三卷 SDM 吗?https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-1269.html 似乎描述的是在虚拟机退出时 SMM 导致或参与的计数情况,而不仅仅是“裸机”上的 SMM(或遗留 BIOS 引导通过 SMM 陷阱呈现的“伪裸机”)。总之,如果我有时间下次重启我的台式机,我可能会编写一个16位的引导加载程序,并在我的系统上测试它...... 或者希望其他人有兴趣为我测试。 - Peter Cordes
这个问题曾经因为不够专注而被关闭,然后又重新开放;如果有人有任何建议,哪些部分可以留下或拆分成另一个问题,那就好了。我的感觉是,关于具体细节的副问题有助于集中我所问的整体方向;否则,“现代VGA硬件如何工作/表现”会是广义的教科书。第一次关闭的投票者都没有显著的asm / x86标签得分,所以希望我们中对这个主题感兴趣的人认为这是一个可以接受的问题。我知道它不是很好。 :/ - Peter Cordes
显示剩余2条评论
2个回答

11
所有现代系统是否都会在将数据存储到文本模式帧缓冲区时触发SMI?
对于视频卡,我非常怀疑。自1980年代以来,视频卡制造商就已经在硬件中内置了“从字符+属性获取像素数据”的逻辑(它早先于VGA,并且自CGA以来几乎没有改变),并且只是将该逻辑剪切/复制粘贴到每个更新的设计中而不太关心它。
对于根本不是视频卡的东西(例如使用LAN的远程系统管理工具),我不知道但怀疑不会(通常它们使用特殊的管理CPU而不是主CPU,因此即使计算机关闭也可以使用)。
如果不是,我们能否通过在WB内存上使用movnti +用户空间中的某些内容来近似WC存储+clflush到帧缓冲区?
如果您不在用户空间,则可以更改MTTR(在所有CPU上-MTRR必须匹配,并涉及一系列特殊序列)以使RAM区域“不缓存”;或在页面表中使用PAT(比使用MTRR轻松得多,尤其是如果您已经在使用分页,但是由于仍需要缓存一致性,因此行为略有不同)。如果您在用户空间,则必须依赖于操作系统/内核提供的任何内容,而(取决于是哪个操作系统)操作系统/内核可能根本不提供任何这样做的方法。

然而,即使你找到了一种方法使(某个区域的)RAM变为未缓存状态,它仍然不会非常相似,因为你将直接写入内置在CPU中的内存控制器所连接的东西(CPU可以非常快地写入),而不是与位于PCI链另一端的某些东西交互(从CPU方面看会有更高的延迟和更低的带宽)。即使对于集成视频(在最终上仍然使用相同的RAM芯片),向VRAM写入也需要经过非常不同的路径(受到视频卡中的重映射/GART/分页的影响,由“写入模式”VGA寄存器和位/平面掩码VGA寄存器所影响等)。

使用硬件VGA文本模式的PCIe或PCI视频卡是否比实际集成GPU执行的任务更快?

对于从CPU到VRAM的写操作,通常来说,集成视频比独立显卡要快得多(至少对于从CPU到线性帧缓冲区的简单写操作,在此情况下,没有涉及任何VGA的“写入逻辑”)。

对于非常粗略的估计; 我会预计单次写入RAM大约需要150个周期,而单次写入PCI接口则接近1000个周期。对于SMI(系统管理中断),我会预计在SMI到达CPU之前需要几百个周期的延迟,然后需要成本来刷新CPU流水线状态,然后需要约500个周期来保存CPU的状态(并在返回路径上加载相同的状态); 然后固件的代码需要查找SMI的原因(另外几百个周期?)才能知道它是对VRAM的写入,而不是其他什么;然后它必须检查已保存的CPU状态,并找到并解码进行写入的指令(因为它无法知道正在写入什么数据,如果是字节/字/双字写入等),同时考虑先前的CPU状态(CPU处于哪种模式,代码大小等),并跟踪模拟指令如何影响未来的CPU状态(推进RIP等 - 不要忘记他们将模拟每个可能引起写入的指令,包括诸如XADD等)。接下来,它将分析(模拟的)VGA寄存器的状态(写入模式,写入掩码,平面使能,控制哪个64 KiB的存储器映射到传统区域,字体高度等)。

基本上来说,对于SMI模拟写入文本模式帧缓冲区,我会预计需要数万个周期才能让固件的代码在巨大的复杂性中忽略一个微小但重要的细节,从而做出错误的决策并不可用。

其他备注

我在2011年找到了Phoenix BIOS的专利US20120159520,它使用UEFI模拟传统视频。

我怀疑这从未得到实现,因为我怀疑它永远不可能实现。传统接口有太多(常见和晦涩)的事情可以做(例如检测垂直刷新,设置非标准视频模式如“Mode X”,调整“显示起始点”来实现平滑滚动和/或页面翻转,使用VBE中的“CRTC信息”来更改视频时序等),这些都不受UEFI支持,也无法通过第三方UEFI视频驱动程序完成。

相反,大约10年来,显卡制造商没有费心提供UEFI驱动程序,UEFI固件使用传统界面来模拟UEFI服务(往往在此过程中破坏安全启动);直到几乎所有东西都是UEFI。

我认为(SMM)用于VGA I/O端口进行模式设置。

我认为不是。与视频有关的唯一与SMM相关的事情是在早期引导时(在操作系统接管之前),控制笔记本电脑屏幕背光的亮度(尤其是对于旧笔记本电脑,特别是在“盖上/盖下事件”期间)。

……省略文本模式的硬件支持似乎是供应商想要做的事情

我仍然相信,在已经太长的“混合BIOS + UEFI”过渡阶段之后,从硬件中清除30多年的积累遗留问题(A20、VGA、PS/2、PIT、PIC等),是硬件制造商(如Intel)推动UEFI采用的主要原因之一。


看起来,旧的VGA范围只是通过L3缓存片直接解码为处理器图形、DMI或基于配置寄存器中的VGA转向位的PCIe链路。如果没有VGA,我不确定处理器图形会如何处理这个范围;可能它只是缓冲并将其转换为HDMI帧缓冲区,然后将其发送到HDMI FDI管道,但我一点都不清楚。 - Lewis Kelsey
谢谢,我忽略了仍然有硬件支持但通过系统代理比直接到内存控制器慢的可能性。这和打败内存控制器写合并一样,所以我们会在实际DRAM吞吐量上瓶颈,而不仅仅是核心->非核心->内存控制器环形总线吞吐量,这可以解释VGA写入完全支配运行时并隐藏clflushoptlock xor byte [esp], 0之间触发刷新的差异。 - Peter Cordes
你提到的在任何模式下都必须模拟x86才能存储数据的观点是很好的,这确实使得它相当不可行,并且性能会不可接受,或者至少在滚动文本控制台时会有明显的感觉,而这种控制台使用VGA文本模式,而不是Linux默认使用的帧缓冲控制台。我忘记了即使在多核系统上启动所有内核后,VGA文本模式仍然必须继续工作。 - Peter Cordes

7
阅读多个现代英特尔CPU和平台控制器枢纽(PCH)数据手册,似乎没有实现必要的硬件。似乎没有任何方法可以在处理器访问VGA帧缓冲区(物理地址0xA0000-0xBFFFF)时生成SMI(系统管理中断)。
CPU中的内存控制器将把对VGA帧缓冲区的访问路由到集成图形控制器、直接连接到CPU的PCI Express端口或连接CPU与PCH的DMI接口。虽然可能单独路由部分VGA帧缓冲区,但这似乎仅用于支持单独的MDA(单色显示适配器)设备。集成图形控制器没有很好地记录,因此有可能配置它以在VGA帧缓冲区访问时生成SMI,但这似乎不太可能。无论如何,它将无法与独立显卡一起工作。
英特尔PCH还似乎没有支持根据VGA帧缓冲区访问生成SMI的功能。这将是最自然的地方,因为它已经支持根据对键盘控制器、IDE控制器和其他旧设备的I/O访问生成SMI。可能存在某些未记录的功能来执行此操作,但在PCH数据手册中列出的可能SMI来源列表中未包含此功能。
理论上,主板制造商可以通过PCI Express端口将虚拟VGA设备连接到PCH,然后使用PCH GPIO引脚生成SMI。但是,我不确定这在实践中是否有效。当CPU接收到SMI时,它可能已经执行其他指令,因此无法检查帧缓冲区访问时的CPU状态。
(类似问题发生在SoundBlaster Live的SoundBlaster 16仿真中。当访问旧SoundBlaster端口时,它会生成PCI SERR#,这将在CPU上生成NMI。不幸的是,此仿真在许多Pentium 4 主板上会出现故障,因为NMI会在下一条或后续指令上到达。)

感谢您的关注。这并不排除每个垂直空白期同步/渲染VGA文本帧缓冲区到真实像素帧缓冲区的SMI处理程序(专利提出的另一种机制),但它排除了每个存储器的SMI。'out'指令有点同步和大部分串行化,但UC存储器仍然通过存储器缓冲区,并且在存储器提交之前已经退役,我想。如果P4上的“out”端口访问存在问题,则普通存储将是灾难性的。 - Peter Cordes
如果系统使用SMI处理程序来扫描文本帧缓冲区,那么这意味着即使cli正常中断被禁用,它仍然可以是WB可缓存的并更新屏幕。因此,这将是我们可以用来排除或大部分确认其他可能性的可测试内容。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接