本文的背景是,出于需要搭建一套能充分使用GPGPU硬件加速的macOS环境。而本人家境贫寒,无力负担起搭载高性能AMD GPU的Mac,需要找到一套更加廉价的方案。安装完成的效果图如下,左边是Windows PC,右边是虚拟机中的macOS:
Proxmox VE (PVE) 是一个基于KVM和QEMU的开源虚拟化平台,搭建非授权的macOS也就是黑苹果相对直接使用物理机有不少优势:
遇到引导问题时不用重启物理机,节约了大量时间
PVE本体是个修改后的Debian 10,有大量linux下的实用工具可以使用
Host可以直接挂载macOS硬盘分区,便于修改引导
以下默认读者已经基本熟悉PVE的操作,需要用到的软件有:
ProxmoxVE 7.1+
OpenCore 0.6.1
任意文本编辑器
7-Zip
OpenCore Configurator
本文从已经完成安装,配置好vim, parted, kpartx等工具的PVE环境开始
强烈建议在PVE中使用Samba将工作目录共享给另一台有桌面环境的电脑(Win或Mac都行)
1.准备安装镜像
首先下载OSX-KVM,解压后将其中的fetch-macOS.py放到任意存储的template/iso下,然后执行脚本:
python3 ./fetch-macOS-v2.py
选择当前最新版的macOS,下载得到一个约600M的BaseSystem.dmg
使用qemu-img 将BaseSystem.dmg转换为PVE可以加载的格式。
qemu-img convert BaseSystem.dmg -O raw Catalina-installer.iso
然后下载kholia/OSX-KVM,用7-Zip打开
OpenCore-Catalina/OpenCore.qcow2
,解压出第一个EFI System的primary.img
primary.img重命名为OpenCore.iso,放到template/iso下,准备好安装镜像后就可以创建虚拟机了。
2.创建虚拟机
点击创建虚拟机,勾选高级,随意设置VM ID和名称。
选择OpenCore.iso,访客OS选择Other
显卡设为VMWare兼容,BIOS设为OVMF(UEFI),机器设为q35,存储随意
选择SATA,缓存Write back(不安全),丢弃,SSD仿真。
CPU设置到4核心以上,选择host(因特尔)或者Penryn(AMD)
内存8G以上,关闭Ballooning
网络选择WMware wmxnet3
点击完成后,为虚拟机添加光驱,载入Catalina-installer.iso
修改/etc/pve/qemu-server/下的虚拟机配置文件,与创建时的VM ID同名,比如文中的是100.conf,在文本开头添加一行:
args: -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" -smbios type=2 -device usb-kbd,bus=ehci.0,port=2
如果cpu是intel,则在同一行行末加上:
-cpu host,kvm=on,vendor=GenuineIntel,+kvm_pv_unhalt,+kvm_pv_eoi,+hypervisor,+invtsc
如果cpu是amd,则在同一行行末加上:
-cpu Penryn,kvm=on,vendor=GenuineIntel,+kvm_pv_unhalt,+kvm_pv_eoi,+hypervisor,+invtsc,+pcid,+ssse3,+sse4.2,+popcnt,+avx,+avx2,+aes,+fma,+fma4,+bmi1,+bmi2,+xsave,+xsaveopt,check
将两处media=cdrom修改为cache=unsafe,最终100.conf为(Intel平台);
args: -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" -smbios type=2 -device usb-kbd,bus=ehci.0,port=2 -cpu host,kvm=on,vendor=GenuineIntel,+kvm_pv_unhalt,+kvm_pv_eoi,+hypervisor,+invtsc balloon: 0 bios: ovmf boot: cdn bootdisk: ide2 cores: 4 cpu: Penryn efidisk0: local-lvm:vm-100-disk-1,size=4M ide0: MediaCache0:iso/Catalina-installer.iso,cache=unsafe,size=2086412K ide2: MediaCache0:iso/OpenCore.iso,cache=unsafe machine: q35 memory: 8192 name: macOS
修改启动顺序为OpenCore.iso在最上面
最后修改kvm设置,激活ignore_msrs,更新initramfs后重启Host。
echo "options kvm ignore_msrs=Y" >> /etc/modprobe.d/kvm.conf update-initramfs -k all -u reboot
3.安装macOS
虚拟机启动后按ecs键,进入BIOS设置
Device Manager/OVMF Platform Configuration下的分辨率改为1920x1080,按F10保存后,退出BIOS。
进入OpenCore引导后,选择macOS Base System进入安装
进入安装后不会显示选择语言,在菜单里选择修改语言,会卡一段时间
用磁盘工具抹掉虚拟硬盘
选择重新安装macOS
一路继续下去,选择刚才格式化的硬盘
等待一段时间
重启后选择macOS Installer继续
安装完毕后自动重启,选择macOS引导进系统
安装向导记得跳过登录Apple ID
此时需要把OpenCore安装到虚拟硬盘中。打开终端,输入diskutil list,得到当前磁盘列表
disk0是OpenCore.iso中的EFI分区,disk2s1是虚拟磁盘中的EFI分区,使用dd命令将OpenCorex写入虚拟硬盘,实际分区id可能会不同
sudo dd if=/dev/disk0 of=/dev/disk2s1
提示Resources busy的话就先diskutil umount对应的分区
写入完成后就可以关机分离挂载的iso,记得修改引导顺序。
4.在Host上挂载虚拟硬盘的方法
为了编辑OpenCore的配置文件,需要将guest的虚拟磁盘挂载到host的目录中。
由于使用了lvm,所以需要先用kpartx装载虚拟文件系统。
kpartx -a /dev/mapper/pve-vm--100--disk--0
会产生pve-vm--100--disk--0p1和pve-vm--100--disk--0p2两个设备文件,我们需要挂载EFI分区也就是pve-vm--100--disk--0p1,这里推荐在共享目录下创建挂载点
mount /dev/mapper/pve-vm--100--disk--0p1 /mnt/pve/MediaCache0/efi
之后在连接共享目录的Windows中也可编辑EFI分区了。
5.PVE中PCIe穿通设置
首先得确认host平台支持IOMMU,先编辑grub引导配置/etc/default/grub,填入intel_iommu=on或者amd_iommu=on,以及video=efifb:off防止host加载显卡:
... GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on video=efifb:off" ...
然后运行
pve-efiboot-tool refresh update-grub reboot
使用
dmesg | grep -e DMAR -e IOMMU
查看IOMMU是否启用:
之后修改/etc/modules加入vfio模块:
vfio vfio_iommu_type1 vfio_pci vfio_virqfd
使用lspci -nn查看显卡的设备id:
记下设备id 1002:7341和1002:ab38,编辑/etc/modprobe.d/vfio.conf
options vfio-pci ids=1002:7341,1002:ab38 disable_vga=1
编辑/etc/modprobe.d/blacklist.conf,将显卡驱动加入黑名单:
blacklist nvidiafb blacklist nouveau blacklist nvidia blacklist radeon blacklist amdgpu blacklist snd_hda_intel blacklist snd_hda_codec_hdmi blacklist snd_hda_codec blacklist snd_hda_core
再次确保四个文件都正确编辑:
/etc/default/grub /etc/modules /etc/modprobe.d/vfio.conf /etc/modprobe.d/blacklist.conf
然后更新
update-initramfs -k all -u
,然后关机。重启后使用lspci查看显卡是否已经启用vfio-pci
lspci -v
6.将显卡穿通给虚拟机
在网页中为虚拟机添加pcie设备
勾选全部选项
关闭虚拟显示输出
记得添加键鼠的直通。然后挂载EFI分区,删除里面的内容,将 OpenCore-Catalina\OpenCore-Passthrough.qcow2 中的EFI镜像解压到EFI分区中:
然后关闭host,把显示器插到独显上,然后开机,由于显卡驱动被屏蔽,所以这时显示器没有输出,从这里开始一定要使用ssh连接host进行操作。
尝试启动macOS,如果苹果标读条读到70%左右时黑屏,就删除config.plist中的WhateverGreen.kext项目。
理论上现在已经可以正常进入macOS桌面了。
使用VideoProc查看显卡是否成功驱动:
GeekBench5 Compute跑分达到了39000分,为苹果官方Pro W5700X MPX模块的56%,而售价仅为后者的40%,性价比较高。
8.常见问题
由于Vega和Navi GPU缺少Function Level Reset(FLR)的支持,会导致虚拟机关机后显卡睡死而无法重新启动虚拟机。解决方法是卸载显卡和板载声卡后,休眠物理机,然后重新扫描pcie设备,可以制作如下脚本:
echo "1" > /sys/bus/pci/devices/0000\:03\:00.0/remove echo "1" > /sys/bus/pci/devices/0000\:03\:00.1/remove echo mem > /sys/power/state echo "1" > /sys/bus/pci/rescan
在第三行执行后虚拟机会进入休眠,此时需要手动按下开关恢复运行,这对运维有了一定的阻碍。另一个方法是给kernel打补丁,链接留在这里本文暂不展开。
https://forum.level1techs.com/t/navi-reset-kernel-patch/147547