今年二月我发布了一篇关于 osx-proxmox-next 的文章,该工具只需一条命令即可在 Proxmox 上创建 macOS 虚拟机,无需花费一整个下午手动编辑 OpenCore plist 文件。
大约有 1500 人读过这篇文章。其中一些人已经在他们自己的硬件上安装了它——而那些硬件我并不拥有。
也正是在那时,一些有趣的 Bug 出现了。经历了 150 次提交之后,以下是五种在任何 macOS-on-Proxmox 指南中都未曾提及的故障,以及每个故障的根本原因。
1. 安装程序卡在 100% CPU 且无任何响应
现象: macOS 安装程序进入文件复制阶段。CPU 占用率达到 100%。磁盘 IO 和网络吞吐量均为零。它会一直卡在那里。
仅发生在 Xeon E5/E7 v2-v4 的主机上。
我最初的修复是错误的。卡顿看起来像是网络问题,于是我判断 vmxnet3 的 kext 在安装过程中未能加载,并将这些主机切换到了 e1000-82545em。然后发布了更新。
随后,issue #103 由一位拥有真实硬件的用户反馈回来:使用 vmxnet3 可以正常联网,而 e1000-82545em 根本无法附加。我的修改反而让情况更糟。
真正的原因隐藏在两层之下。这些芯片是真正的 HEDT 部件,拥有双插槽/多芯片组拓扑结构,而 -cpu host 会将这种拓扑直接暴露给客户机。搭配 MacPro7,1 的 SMBIOS(macOS 将其视为支持多插槽的型号),XNU 的调度器在高负载的多线程 IO 下会发生死锁。而安装程序的复制阶段正是这种工作负载。
修复方法是停止将主机拓扑传递给客户机:
_XEON_HEDT_PATTERN = re.compile(r"Xeon.*E[57][ -]*\d+ *v([234])", re.IGNORECASE)
def _xeon_hedt_cpu_model(model_name: str) -> str:
match = _XEON_HEDT_PATTERN.search(model_name)
if not match:
return ""
if match.group(1) == "2":
return "Haswell-noTSX,model=158,stepping=3"
return "Broadwell-noTSX,model=158"
Enter fullscreen mode Exit fullscreen mode
我反复吸取的教训是:症状出现在网络层,而根本原因却在于 CPU 拓扑。从症状出发进行猜测,让我发布了一次有问题的版本。
2. 虚拟机永远引导进入恢复模式
现象: 全新安装完成后,每次后续启动都会回到恢复模式。在 OpenCore 选择器中选择 macOS 只能生效一次,之后不会保存。
原因:默认的 OpenCore 配置中 AllowSetDefault 是关闭的。该选项对应启动选择器中的 Ctrl+Enter 快捷键。关闭后,你无法将 macOS 条目固定为默认启动项,而磁盘上的恢复卷会一直赢得启动竞争。
配置补丁中的一个关键项:
Misc -> Security -> AllowSetDefault = True
Enter fullscreen mode Exit fullscreen mode
然后在启动选择器中:高亮你的 macOS 卷,按下 Ctrl+Enter。它就会被固定下来。
3. 安装后的启动顺序与直觉相反
macOS 安装完成后,正确的启动顺序应该是:
ide0;virtio0
Enter fullscreen mode Exit fullscreen mode
OpenCore(ide0)在前,macOS 磁盘(virtio0)在后。我曾发布过一个提示,建议使用 virtio0;ide0,这个顺序看起来更自然,但却是错误的:它会直接启动 macOS 磁盘,跳过 OpenCore,导致虚拟机在首次启动时无错误地卡住。
在 hypervisor 上运行的 macOS 每次启动都必须先经过 OpenCore,而不仅仅是安装时。
osx-next-cli post-install --vmid 100 --execute
Enter fullscreen mode Exit fullscreen mode
4. 每次启动都显示“内存模块配置错误”
这只是一个视觉上的问题,但每次启动都会触发,令人抓狂。
每个虚拟机都使用 MacPro7,1 的 SMBIOS,而默认的 OpenCore 镜像中没有包含 RestrictEvents.kext。macOS 会检查模拟的内存布局,判定真实 Mac Pro 不可能以这种方式配置,从而永远通知你这个问题。
搜索相关信息时,你会被告知添加 revpatch=memtab 作为启动参数。这里完全无效。 revpatch=memtab 仅对 MacBookAir 的 SMBIOS 型号有效。在 MacPro7,1 上它是一个空操作,这就是为什么很多人报告它“不起作用”。
真正的修复是直接加入该 kext。RestrictEvents 1.1.6 放入 EFI/OC/Kexts,在 config.plist 中注册,其默认的 revblock=auto 会同时屏蔽 MemorySlotNotification 和 ExpansionSlotNotification。无需任何启动参数。
5. 在 Sequoia 和 Tahoe 上无法登录 Apple ID
在旧版 macOS 上,vmgenid 和一个静态 MAC 地址足以登录 iMessage 和 FaceTime。而在 Sequoia 15 和 Tahoe 26 上,这些已经不够了。
Apple 的 DeviceCheck 现在会读取 hv_vmm_present sysctl。在虚拟机中它的返回值是 1,登录请求在验证凭据前就被拒绝了。
社区的修复方法是在内核的字符串表中进行字符串替换,由 OpenCore 在启动时应用。找到 hibernatecount sysctl 名称,将其替换为 hv_vmm_present:
Find: ...hibernatehidready\0 hibernatecount\0
Replace: ...hibernatehidready\0 hv_vmm_present\0
Enter fullscreen mode Exit fullscreen mode
查找现在会解析到休眠计数器,在全新启动时其值为 0。macOS 读取到 0,DeviceCheck 判定为物理机,登录即可成功。
这是一个针对特定字符串布局的内核补丁,因此可能会在任何 macOS 小版本更新中失效。出于这个原因,它被放在一个明确的 --apple-services 标志后面。
附加:克隆 macOS 虚拟机会悄无声息地破坏两台机器的 iCloud
Proxmox 的完整克隆是字节级复制,这意味着克隆机会继承源虚拟机的 SMBIOS 序列号、UUID、MLB 和 ROM。两台机器拥有同一个 Apple 硬件身份。Apple 会检测到这一点,你将在其中一台(身份验证失败的那台)上遇到登录问题。
osx-next-cli clone 会先执行完整克隆,然后立即重新生成 SMBIOS 四元组、vmgenid 和静态 MAC 地址,因此在 Apple 看来,克隆机是一台完全不同的设备。
所有问题都集成到了 doctor 命令中
以上每一个问题都是配置层面的错误,在 macOS 以某种看似无关的方式出现异常之前是不可见的。因此它们现在变成了可以对任何虚拟机运行的 12 项检查:
osx-next-cli doctor --vmid 100
Enter fullscreen mode Exit fullscreen mode
检查项目包括:Balloon、q35、核心数是否为 2 的幂、内存、CPU 类型、网卡型号、agent、smbios1、启动顺序,以及 virtio0 / ide0 / ide2 的存在性。它会逐行输出 OK / WARN / FAIL 并给出修复提示,且直接读取虚拟机配置,因此即使不是通过本工具创建的虚拟机也能正常工作。如果你是通过指南手动搭建的 macOS 虚拟机,可以用它来检查。
仍待解决:GPU 直通
这是我目前无法解决的问题。将真实 GPU 直通给 macOS 客户机需要我没有的硬件来进行测试,而猜测性操作正是导致像 #1 那样的 Bug 的原因。这是用户呼声最高的功能,但由于缺乏测试环境而被阻塞。
以上所有内容均已发布并合并到 main 分支:
curl -fsSL https://raw.githubusercontent.com/lucid-fabrics/osx-proxmox-next/main/install.sh | bash
Enter fullscreen mode Exit fullscreen mode
仓库地址:github.com/lucid-fabrics/osx-proxmox-next
这仍是一个个人项目。如果你在我未拥有的硬件上遇到了 Bug,请提交 issue。以上五个 Bug 中有四个就是通过这种方式被发现的。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.