macOS KVM 虚拟机配置小记(下)—— SELinux + libvirt + virt-manager 环境下基于 OSX-KVM 实现 Hackintosh

在上一篇博文中,已经简要阐述了 Fedora 43 KDE Plasma 的安装步骤。在本篇博文中,将从安装好的 Fedora 系统开始,基于 OSX-KVM 安装 macOS 虚拟机。

更新提示

在持续运行 macOS 几天后,发现基于 KVM 虚拟化的 macOS 还是存在较大的性能问题,CPU 功耗长时间在 15W 以上,同时风扇转速长时间保持在 80% PWM 以上,对于无机柜的家用环境是难以接受的。考虑到 OpenClaw 现在已有基于 KDE 的桌面 Automation,故建议使用 Linux 宿主环境运行。本文不作删除,以供后来者参考。

准备工作

首先,我们需要安装必要的虚拟机软件:

1
sudo dnf install virt-manager libvirt

安装成功后,启动 libvirtd 服务

1
sudo systemctl enable --now libvirtd

在过去,安装 macOS 虚拟机需要复杂的配置步骤,但是 OSX-KVM 项目整合了 OpenCore EFI、系统镜像下载器、虚拟机 libvirt XML 定义等资源,提供了简单快捷的 macOS 安装体验。

首先,获得 OSX-KVM 的源代码:

1
2
3
cd ~
git clone --depth 1 --recursive https://github.com/kholia/OSX-KVM.git
cd OSX-KVM

由于 macOS 的特殊性,需要对 KVM 内核模块进行配置。对于 Intel 平台,运行

1
sudo cp kvm.conf /etc/modprobe.d/kvm.conf

对于 AMD 平台,运行

1
sudo cp kvm_amd.conf /etc/modprobe.d/kvm.conf

此外,在 AMD 平台上,还需要修改内核参数以使 macOS 正确启动。修改 /etc/default/grub,在 GRUB_CMDLINE_LINUX_DEFAULT 变量中,添加 tsc=reliable

最后,进行权限配置:

1
2
3
sudo usermod -aG kvm $(whoami)
sudo usermod -aG libvirt $(whoami)
sudo usermod -aG input $(whoami)

完成后,需要重启计算机,以使内核 modprobe 参数和 cmdline 生效。

获取和安装 macOS

重启后,在 OSX-KVM 目录中运行 ./fetch-macOS-v2.py,获取 macOS 恢复镜像。由于从 Apple 服务器获得的镜像为 DMG 格式,无法直接给 QEMU 使用,因此,我们还需要使用 dmg2img 转换镜像格式。

1
2
dnf install dmg2img
dmg2img -i BaseSystem.dmg BaseSystem.img

创建 macOS 磁盘,建议至少 64G:

1
qemu-img create -f qcow2 mac_hdd_ng.img 128G

OSX-KVM 的 安装脚本存在一定问题,因此我们需要先对其进行编辑。打开 OpenCore-Boot.sh,修改如下:

  • ALLOCATED_RAM 根据实际情况修改,推荐 8192
  • CPU_CORESCPU_THREADS 建议修改为相同的数值,建议为宿主机的核心数(非线程数)
  • -cpu 参数:Skylake-Client 修改为 Skylake-Client-v4

备份 EFI 变量文件:

1
2
3
cp OVMF_VARS.fd OVMF_VARS.fd.template
cp OVMF_VARS-1920x1080.fd OVMF_VARS-1920x1080.fd.template
cp OVMF_VARS-1024x768.fd OVMF_VARS-1024x768.fd.template

运行 ./OpenCore-Boot.sh 启动 macOS 安装。在虚拟机中:

  • 在 OpenCore 磁盘选择界面,选择 macOS 磁盘。注意此时鼠标可能无法移动,需要使用键盘进行选择。
  • 首先使用 Disk Utility 对磁盘进行分区,创建分区图格式为 GUID,分区格式为 APFS,名称随意。
  • 然后全新安装 macOS 系统。建议在安装系统时,不要开启代理,或将 swcdn.apple.com 设为直连,否则可能下载失败。

将系统导入 libvirtd

确保 macOS 已经安装成功。现在,我们使用 virsh 导入虚拟机的 XML 定义。

首先复制必要的文件,假设你想将虚拟机的磁盘放在 /vm

1
2
3
4
5
6
7
8
sudo cp OVMF_VARS*.fd.template OVMF_CODE*.fd /var/lib/libvirt/images
sudo chown root:root /var/lib/libvirt/images/OVMF_VARS*.fd.template
sudo chmod 644 /var/lib/libvirt/images/OVMF_VARS*.fd.template
sudo cp mac_hdd_ng.img /vm/macOS_Sonoma.qcow2
sudo cp OVMF_VARS-1920x1080.fd /vm/macOS_Sonoma.nvram
sudo chown qemu:qemu /vm/macOS_Sonoma*
sudo chmod 600 /vm/macOS_Sonoma*
sed "s/CHANGEME/$USER/g" macOS-libvirt-Catalina.xml > macOS.xml

如果虚拟机磁盘在非标准路径,还需要配置 SELinux 规则:

1
2
sudo semanage fcontext -a -t svirt_image_t "/vm(/.*)?"
sudo restorecon -Rv /vm /vm/*

编辑 macOS.xml

  • 修改 <title><name><memory>(需要一同修改 <currentMemory>)、<vcpu> 为你需要的值
  • 使用 uuidgen 生成一个新的 UUID,替换 <uuid> 标签的内容
  • 修改 <loader> 的值为 /var/lib/libvirt/images/OVMF_CODE_4M.fd
  • 修改 <nvram> 的值为 /vm/macOS_Sonoma.nvram

添加下面的内容进行 CPU 绑核:

1
2
3
4
5
<cputune>
<vcpupin vcpu="0" cpuset="0"/>
<vcpupin vcpu="1" cpuset="1"/>
<!-- 有多少核心就写多少个,左边是虚拟核心序号,右边是物理核心序号 -->
</cputune>

删除所有的磁盘(<disk>),替换为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<disk type="file" device="disk">
<driver name="qemu" type="qcow2" cache="writeback" io="threads"/>
<source file="/vm/macOS_Sonoma_OC.qcow2"/>
<target dev="sda" bus="sata"/>
<boot order="1"/>
<address type="drive" controller="0" bus="0" target="0" unit="0"/>
</disk>
<disk type="file" device="disk">
<driver name="qemu" type="qcow2" cache="writeback" io="threads"/>
<source file="/vm/macOS_Sonoma.qcow2"/>
<target dev="sdb" bus="sata"/>
<boot order="2"/>
<address type="drive" controller="0" bus="0" target="0" unit="1"/>
</disk>

为了绕过 Apple 验证机制,使设备能登录 Apple ID,需要修改网卡,替换 MAC 地址为一个苹果的地址 — 1c:57:dc:XX:XX:XX

修改 <video> 段落,删除 VirtIO 显卡,以启用 VMware 显卡:

1
2
3
<video>
<model type="none"/>
</video>

在 SELinux 开启的设备上,为了兼容 SELinux,需要取消注释这一行:

1
<seclabel type="dynamic" model="selinux" relabel="yes"/>

修改 <qemu:arg value="-cpu"/> 的下一行,将 CPU 从 Penryn 替换为下面的值,获得更好的兼容性:

1
<qemu:arg value="Skylake-Client,-hle,-rtm,kvm=on,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on,+ssse3,+sse4.2,+popcnt,+avx,+aes,+xsave,+xsaveopt,check"/>

修改 <qemu:arg value="-cpu"/> 之前插入以下内容,以添加 VMware 显卡:

1
2
<qemu:arg value="-device"/>
<qemu:arg value="vmware-svga,id=video0,vgamem_mb=256,bus=pcie.0,addr=0x2"/>

验证 XML 有效性:

1
virt-xml-validate macOS.xml

然后,将虚拟机导入 libvirtd:

1
virsh --connect qemu:///system define macOS.xml

修改虚拟机默认网络的DHCP范围

1
EDITOR=vim sudo virsh net-edit default

可以将 EDITOR= 后面的编辑器改为你所使用的编辑器。在编辑器界面中,修改 IP Address 为你想要的宿主机地址,以及 DHCP Range 为你想要的 DHCP 范围。

配置 OpenCore

为了自定义分辨率并正常使用 Apple ID,我们需要修改 OpenCore 分辨率配置,并向 OpenCore 中注入机器序列号,并重新生成 OpenCore 镜像。

首先进入 ~/OSX-KVM/OpenCore,编辑 config.plist 文件。找到以下行:

1
2
<key>Resolution</key>
<string></string>

修改为你想要的分辨率,例如:

1
2
<key>Resolution</key>
<string>1920x1080</string>

要正常使用 Apple ID,则需要生成有效的 macOS 序列号。在 OpenCore GitHub Release 页面 获取最新版的 OpenCore 并解压,然后打开 Utilities/macserial 文件夹,运行其中的 macserial.linux,注意需要替换 iMac19,1 为你 config.plist 中的 SystemProductName 的值:

1
./macserial.linux --model "iMac19,1"

生成的结果以 序列号 | MLB 表示。

打开 苹果保修检查网页,如果跳出选择区域,请务必选择美国 (United States),(注意:苹果中国官网无法检测!)。输入生成的序列号:

  • 如果显示 _The serial number you’ve entered isn’t valid. Please try again._,则序列号不可用
  • 如果显示 _We’re sorry, we’re unable to check coverage for this serial number._,则序列号可用
  • 如果显示 _Valid Purchase Date_,则序列号不可用
  • 如果显示 _Purchase Date not Validated_,则序列号可用,但不推荐,有被正主抢走的风险
  • 重复生成序列号,直到找到可用的序列号

然后找到 <key>MLB</key> 相关段落,替换相关值为:

  • MLB: 生成的序列号对应的 MLB 值
  • ROM: 虚拟机的网卡 MAC,要求不带冒号、全小写。可以使用 echo $VM_MACADDR | tr -d : | tr "[:upper:]" "[:lower:]" 转换。
  • SystemSerialNumber: 生成的有效可用的序列号
  • SystemUUID: 在 libvirtd XML 中 <uuid> 标签的内容,需要为全大写形式,可以使用 echo $VM_SMBIOS_UUID | tr "[:lower:]" "[:upper:]" 转换。

下面是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
<key>MLB</key>
<string>C02733401J9JG36A8</string>
<key>ROM</key>
<data>0016cb001122</data>
<key>SpoofVendor</key>
<true/>
<key>SystemProductName</key>
<string>iMacPro1,1</string>
<key>SystemSerialNumber</key>
<string>C02V7UYGHX87</string>
<key>SystemUUID</key>
<string>976AA603-75FC-456B-BC6D-9011BFB4968E</string>

保存 config.plist,回到 ~/OSX-KVM/OpenCore,重新生成 OpenCore 并复制到 VM 文件夹:

1
2
3
4
5
sudo mv OpenCore.qcow2 OpenCore.qcow2.bak
sudo ./opencore-image-ng.sh --cfg config.plist --img OpenCore.qcow2
sudo cp OpenCore.qcow2 /vm/macOS_Sonoma_OC.qcow2
sudo chown qemu:qemu /vm/macOS_Sonoma_OC.qcow2
sudo chmod 600 /vm/macOS_Sonoma_OC.qcow2

启动虚拟机之后的工作

由于 macOS 不支持使用虚拟显卡进行 3D 加速和视频解码,需要更改默认的动态壁纸为静态图片,否则桌面将由于显存不足显示为白色。

清空 Apple ID 相关配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sudo rm -rf ~/Library/Caches/com.apple.iCloudHelper*
sudo rm -rf ~/Library/Caches/com.apple.Messages*
sudo rm -rf ~/Library/Caches/com.apple.imfoundation.IMRemoteURLConnectionAgent*
sudo rm -rf ~/Library/Preferences/com.apple.iChat*
sudo rm -rf ~/Library/Preferences/com.apple.icloud*
sudo rm -rf ~/Library/Preferences/com.apple.imagent*
sudo rm -rf ~/Library/Preferences/com.apple.imessage*
sudo rm -rf ~/Library/Preferences/com.apple.imservice*
sudo rm -rf ~/Library/Preferences/com.apple.ids.service*
sudo rm -rf ~/Library/Preferences/com.apple.madrid.plist*
sudo rm -rf ~/Library/Preferences/com.apple.imessage.bag.plist*
sudo rm -rf ~/Library/Preferences/com.apple.identityserviced*
sudo rm -rf ~/Library/Preferences/com.apple.ids.service*
sudo rm -rf ~/Library/Preferences/com.apple.security*
sudo rm -rf ~/Library/Messages

对于 macOS 15 以上版本,还需要安装 VMHide.kext

至此,基于 libvirt KVM 的 macOS 安装完毕。