先说结论:一台海光(Hygon)CPU的服务器,装VMware ESXi 7.0的时候,安装阶段一切正常,第一次重启进系统却直接紫屏。这种“装得上、启动崩”的问题,在非官方硬件列表(HCL)里的机器上非常典型。这篇记录从紫屏信息定位、根因分析到修复步骤,完整复现一遍我当时的处理过程,给同样在x86信创硬件上碰vSphere的朋友一条可复用的排查路径。
先说明一下,海光CPU本质上是x86架构,所以VMware产品能安装,但不代表它在这个CPU平台上被官方验证过。紫屏(Purple Screen of Death,PSOD)就是ESXi的VMkernel崩溃界面,功能和Windows的蓝屏差不多:一旦出现,整个Hypervisor停摆,上面所有虚拟机全部断电。所以遇到紫屏,重点不是“能不能重启”,而是搞清楚VMkernel到底死在了哪里,以及为什么死在这个CPU上。
1. 紫屏现场:看懂PSOD上的关键信息
1.1 紫屏信息怎么读
ESXi的紫屏界面看起来很吓人,满屏十六进制、寄存器dump、一堆CPU堆栈,但其实真正有用的信息就集中在最上面几行。PSOD顶部通常是一个类似这样的报错段:
WARNING: Purple screen exception: 0x0N Exception 14 in world ... vmkernel module backtrace: ... @ BlueScreen: 0x4106ac...这里需要抓住的几个信息是:
- 异常类型:Exception 14是Page Fault,Exception 6是Invalid Opcode,Exception 18是Machine Check。不同异常类型指向的方向完全不同。
- 触发位置所在模块:比如vmklinux、vmw_ahci、pvscsi等,如果是VMkernel模块崩溃,一般会显示模块名和偏移地址,这能直接指向是不是驱动问题。
- 世界ID和CPU编号:可以看到是哪个vCPU在什么world里崩溃的。
- 栈顶地址:配合VMware的符号服务器可以解析出具体函数名,不过这一步普通人用不到。
我当时抓到的紫屏,报错信息里反复出现MCE相关内容,并且CPU 0和CPU 1的寄存器dump都有异常状态。这就让我把排查重心放在了CPU微码和硬件feature检测上,而不是先去翻驱动。
1.2 第一时间该做的三件事
遇到紫屏,我强烈建议在机器复位前先做三件事,这三件事每次都能大幅缩短定位时间:
第一件事是拍照。用手机把整个屏幕拍清晰,尤其拍下顶部报错段和中间Backtrace段。重启之后日志不会默认落盘,如果没配置转储服务器,内存里那点线索会全部丢掉。
第二件事是检查启动介质。如果ESXi装在U盘或SD卡上,紫屏后重启经常出现根文件系统只读或少量文件损坏,这会造成后续问题排查时误判。建议准备一个备用启动盘。
第三件事是随机应变做交叉对比。如果机器支持,在BIOS里临时禁用掉一半CPU核心或者换成单路,连续做几次启动测试,看紫屏是否跟CPU核心数相关。这个动作能很快区分是CPU微架构层面的兼容问题,还是软件层面的调度问题。
记住,紫屏不是“死给你看”,而是“想告诉你它死前看到了什么”。信息抓取越及时,后面定位越省力。
2. 根因判断:海光CPU和ESXi之间到底哪里不对付
2.1 不在HCL里的硬件,问题只能自己扛
VMware对硬件有一套严格的兼容性认证体系,官方支持的CPU、主板、存储控制器、网卡都会列在兼容性指南里,只有被列入HCL的硬件组合才算是“官方支持”。海光CPU目前并不在VMware兼容性列表里,这意味着vSphere可以在它上面运行,但一旦出问题,VMware官方支持大概率会以“非兼容配置”为由拒绝介入。
所以在这个平台上做虚拟化,所有排查都要靠社区案例和自己的技术能力支撑,心态上需要先接受这一点。这不是说不能用于生产,而是要有预案、有快速回退手段,并且对紫屏类问题有一套自己的定位方法。
2.2 CPU微码与虚拟化特性检测不匹配
海光处理器在指令集层面上兼容x86,但它在微架构细节上与AMD的EPYC并不完全相同。ESXi启动阶段有一个CPU特性枚举和微码加载的过程,VMkernel会向CPU索取CPUID信息,比对功能位,再决定启用哪些内核机制。如果某些feature位返回的值和VMware预期不一致,VMkernel可能走进一个没有准备好的分支,触发非法指令异常或机器检查异常,最终表现为紫屏。
我当时遇到的机器检查(MCE)类崩溃,最常见的原因之一就是ESXi尝试加载自己的CPU微码补丁,但对应的CPU型号在VMware的微码表里不存在匹配项。加载失败之后,CPU进入了一种不确定状态,任何一个敏感指令都可能触发异常。
2.3 主板固件和ACPI表也是重要变量
CPU微码只是其中一个变数,主板固件(BIOS/UEFI)对ESXi的兼容性影响同样巨大。AMI和Insyde的固件在一些国产主板上会根据销售区域或者定制需求修改ACPI表、调整PCIe枚举顺序,这会让ESXi在探测设备时产生偏差。紫屏如果集中在PCI device扫描阶段,大概率就是ACPI或PCIe配置空间的问题。
所以修这个问题的整体思路就是:先看微码,再看电源管理,再看虚拟化扩展,最后才考虑驱动和存储控制器。顺序不能反,否则容易被表象带到沟里去。
3. 修复实操:从BIOS到ESXi引导选项到版本升级
3.1 升级BIOS与关闭节能状态
第一刀,先给主板BIOS升级到最新版。海光平台的固件更新迭代很快,新固件通常会把CPU微码表、ACPI表、PCIe枚举问题一并修掉。当时我手里这颗CPU的服务器,出厂固件是2022年中的版本,升级到2023年末的版本后,紫屏频率明显下降。
紧接着在BIOS里关闭几个电源管理项:
Power Management -> C6 State -> Disabled CPU Enhanced Halt (C1E) -> Disabled SVM Mode -> Enabled关闭C6和C1E的目的是减少CPU在深度睡眠状态与唤醒状态之间的切换。ESXi本身对C-state管理有自己的逻辑,但在非认可平台上,C6深度睡眠的进入/退出偶尔会踩到微码实现的边缘情况,造成MCE。当时我关闭这两个选项之后,紫屏从“每次必现”变成“偶尔才现”,这让我确认方向是对的。
SVM(Secure Virtual Machine,即AMD的虚拟化扩展)必须保持开启,否则ESXi虚拟机连创建都跑不动。如果为了测试开了又关、关了又开,记得在同一配置下至少做三轮重启验证。
3.2 关掉Microcode更新选项,绕开紫屏触发点
这一步是整个修复过程中最关键的一步,也是我踩了几天坑才找到的突破口。
ESXi在启动早期会调用cpu_microcode模块给CPU刷一遍微码。问题在于海光CPU的微码patch数据并未完整出现在VMware的微码库中,ESXi刷写失败后并不会停下来,但CPU内部状态已经受影响,后续执行任何复杂指令都可能触发MCE。现象就是:安装没问题,第一次启动没多久就紫屏。
针对这个情况,我在BIOS里找到了一项“CPU Microcode Load”或“Microcode Patch Enable”的选项,把它改为Disabled。这样ESXi启动时就不会试图继续打补丁,CPU直接使用出厂固件里烧录的微码运行,反而稳定了。
注意:关闭主板的微码自动加载,可能会让CPU错过部分安全更新,只适合在排查定位阶段使用。如果后续确认关掉它才能稳定运行,建议先咨询整机厂商有没有包含已验证微码的新版固件,不能为了一时稳定放弃安全修复。
这台机器关闭Microcode Load之后,连续重启,紫屏没有再出现。当时我把系统稳定运行24小时作为判断节点,过了这个时间,基本可以认同该方案有效。
3.3 用引导参数排除IOMMU的干扰
还有一个值得一提的参数。海光平台的高速IO设备经常挂在IOMMU后面,而ESXi对IOMMU的默认处理是基于AMD IOMMU驱动的。如果这个驱动在检测设备时没有识别到预期的BDF(Bus Device Function)结构,会直接panic。这种情况下的紫屏通常出现在PCIe设备初始化阶段,和MCE的表现并不一样。
定位方法是在ESXi引导控制台停留时,按下Shift+O(7.0/8.0版本都是这个快捷键),会显示一条引导选项命令,可以在里面临时追加参数:
noIOMMU这个参数表示禁用IOMMU驱动,绕过DMA重映射。它只对本次启动有效,重启后不保留。如果加了noIOMMU之后紫屏不再出现,就能锁定问题在PCIe设备与IOMMU的配合上。后续可以再逐一插拔PCIe设备来确定具体是哪张卡触发的。
我测试过一次,在插着某国产HBA卡时,加了noIOMMU确实能稳定启动,但拔掉卡后原样启动也没问题。这说明是设备侧对DMA重映射支持不完善导致,与ESXi本身关系不大。生产环境遇到这种情况,优先考虑更换兼容性更好的卡,而不是长期关闭IOMMU。
3.4 直接换新版本ESXi
如果前面的微码和BIOS手段都不彻底,最后一招是换ESXi版本。
海光CPU基于的微架构在ESXi 8.0里得到了更多识别和适配,新版本的内核在CPU feature检测上比7.0更宽容,也补充了更多AMD平台的微码表。当时为了验证8.0是否更稳,我在测试分区安装了一台ESXi 8.0 U1,跑同样的负载和重启压力,紫屏完全没发生。最终生产环境也是直接切到了ESXi 8.0,彻底告别了紫屏。
版本升级需要注意一个细节:不能跨版本直跳,先从7.0 U3升到7.0 U3 latest,再从7.0跨到8.0,步骤尽量不要省。ESXi升级本身的失败处理,可以参考VMware官方Upgrade Path文档。
4. 验证稳定性与后续监测手段
4.1 长时间压力测试怎么做
修完之后不能直接认为自己“修好了”,必须做一轮持续验证。我在64GB内存的测试机上开了8台Linux虚拟机,每台各分配2个vCPU和2GB内存,再逐台执行下面这样的压力任务:
stress-ng --cpu 4 --vm 2 --vm-bytes 768M --timeout 3600s同时让ESXi主机的CPU负载长期保持在80%左右,持续跑满24小时。这能充分抬高CPU的P-state切换频率、内存控制器负载和SVM嵌套页表压力,是比较严谨的功能性回归。
压力测试期间如果再次出现紫屏,需要立刻检查系统在崩溃前有没有通过事件日志留下记录。如果又出现了MCE相关信息,就要回头确认BIOS关闭Microcode Load选项是否在CMOS复位后失效。
4.2 日志与传感器监测
验证期我会同时监听两个层面的日志:ESXi自身的日志和IPMI传感器日志。
ESXi日志查看比较常用的是esxcli命令:
esxcli system syslog log get options tail -f /var/log/vmkernel.logvmkernel.log里如果出现mce、mca、machine check等关键字,说明问题还在,只是触发的频率变低了。传感器层面则可以通过ipmitool读取:
ipmitool sel elist ipmitool sensor list | grep -E "CPU|Temp|Power"当时我在监控日志里看到一个规律:紫屏前几分钟,CPU的Tctl温度会快速飙到85度以上,接着MCE产生。这就不仅是微码兼容问题,还叠加了散热瓶颈。更换散热硅脂并改善机箱风道后,温度稳定在65度以下,紫屏再也没复现。
5. 常见问题排查速查与经验总结
5.1 紫屏特征对照表
| 紫屏特征 | 可能原因 | 处理方向 |
|---|---|---|
| Exception 18 + MCE | CPU微码加载失败或MCE异常 | 关闭BIOS微码加载、升级整机固件 |
| Exception 14 + 模块名带vmw_ahci | SATA/RAID控制器驱动异常 | 调整磁盘控制器模式,改用直通或多路径 |
| 初始化PCI设备阶段紫屏 | IOMMU或PCIe枚举异常 | 引导参数加noIOMMU测试,确认后换卡 |
| 随机紫屏且发生在负载高峰 | 电源管理或散热问题 | 关闭C6/C1E,检查散热和供电 |
| 频繁发生在虚拟机启动时 | SVM/Nested虚拟化特性不匹配 | BIOS重建SVM设置,升级ESXi版本 |
这个表格并不是标准答案库,而是给你一个筛选方向。真正定位时还是要结合紫屏第一行报错和现场截图来判断。
5.2 我的几个实操心得
第一个心得:海光平台折腾VMware,不要把时间花在“调无数个内核参数”上。参数只是临时的探针,不是根本解法。我排查过程中试过maxVMs、mem.ScrubPeriod、tpsShrinkUtil这类千奇百怪的参数,真正生效的核心还是固件版本、微码策略和ESXi版本这三件事。
第二个心得:BIOS里的“CPU Microcode Load”选项在不同主板上的名称差别很大,有的叫“Microcode Patch”,有的叫“CPU uCode Update”,有的隐藏在“Advanced -> CPU Configuration”里。如果怎么都找不到,可以先升级BIOS再重新找,新版固件的选项描述一般更直白。实在找不到,就直接把ESXi引导选项加一行跳过CPU微码处理的参数,不过这个参数在不同版本里写法不同,不能在这里瞎给,以你当前版本的官方引导选项文档为准。
第三个心得:如果公司有大量同型号海光服务器要部署vSphere,先花两天时间做“单机完整验证”,全部通过后再批量装。我在批量部署前验证了几轮,把可复现的配置整理成一份checklist,后续新开机器照着做,基本都是半小时内完成装机,再也没有遇到紫屏困扰。
另外再提一句:不是所有虚拟化负载都非得用VMware。如果团队的虚拟化重度依赖vCenter的高级功能,那确实应该坚持把ESXi跑稳;如果只是要把一堆服务容器化起来,Hyper-V或者KVM会省心很多,不必在HCL之外的硬件上硬磕。选择没有对错,看业务需要什么。
最后,紫屏问题并不可怕,它只是ESXi在用一种比较生硬的方式提示你:这里有不匹配的地方,请确认一下。拿着PSOD信息按“日志定位 -> 固件更新 -> 模块锁定 -> 参数验证”的顺序来,大多数问题都能找到出路。别在第一次崩溃后就重装系统,那样大概率只会得到一台重复崩溃的主机。