- macOS trên nền tảng Apple Silicon giới hạn tối đa 2 máy ảo macOS có thể chạy bằng
Virtualization.framework, dựa trên điều khoản trong thỏa thuận cấp phép sử dụng macOS
- Kết quả phân tích cho thấy giới hạn này được quản lý bởi biến không công khai
hv_apple_isa_vm_quota bên trong nhân XNU, và có thể ghi đè bằng tham số khởi động
- Để vượt qua kiểm tra
AppleInternal của System Integrity Protection, quy trình build và khởi động nhân phát triển (Development Kernel) được sử dụng
- Sau khi cấu hình, đã chạy thành công tối đa 9 máy ảo macOS đồng thời trên UTM, Viable, Parallels
- Điều đáng chú ý là Apple đã để lại khả năng ghi đè giới hạn VM bên trong nhân, mở ra khả năng cải tiến sau này thông qua công cụ tự động hóa hoặc kernel extension
Quá trình gỡ bỏ giới hạn 2 máy ảo macOS trên Apple Silicon
- Khi chạy máy ảo macOS bằng
Virtualization.framework trên máy Mac dùng Apple Silicon, có giới hạn chỉ tối đa 2 máy ảo có thể hoạt động cùng lúc
- Giới hạn này được đặt theo điều khoản 2.B.iii trong thỏa thuận cấp phép phần mềm macOS (SLA)
- Điều khoản này cho phép chạy tối đa 2 phiên bản macOS chỉ cho mục đích phát triển, kiểm thử, dùng macOS Server hoặc sử dụng cá nhân phi thương mại
- Kết quả phân tích cho thấy giới hạn này được triển khai không phải ở user space mà trong vùng không công khai của nhân (XNU)
- Nhân Intel không có cùng đoạn mã này, còn nhóm hàm
hv_vm_* trong nhân Apple Silicon phụ trách ngăn xếp ảo hóa
- Biến
hv_apple_isa_vm_quota trong mã khởi tạo hv_init() quản lý số lượng VM và được tăng/giảm khi tạo hoặc xóa VM
- Trong nhân có các tham số khởi động
hypervisor= và hv_apple_isa_vm_quota=, trong đó tham số sau có thể ghi đè giới hạn VM
- Trên nhân phát hành, thay vì chỉ dùng tham số
hypervisor, việc này còn bị giới hạn bởi kiểm tra AppleInternal của System Integrity Protection (SIP)
- Tham số
hv_apple_isa_vm_quota chỉ được áp dụng khi cờ CSR_ALLOW_APPLE_INTERNAL được bật
- Để vượt qua điều này, phương pháp được dùng là khởi động nhân phát triển (Development Kernel) của Apple
Build kernel collection phát triển
- Cần tải và cài đặt Kernel Debug Kit (KDK) từ trang Apple Developer
- KDK phải khớp chính xác với bản build macOS của máy chủ, nếu không có thể xảy ra lỗi liên kết kernel/kext và lỗi khởi động
- Sau khi kiểm tra kiến trúc nhân bằng lệnh
uname, dùng lệnh kmutil create để tạo kernel collection phát triển (VirtualMachine.kc)
- Ví dụ sử dụng macOS 14.0 (build 23A5301h) và nhân T6020
- Tùy chọn
--variant-suffix development chỉ định nhân phát triển và bao gồm nhiều kho lưu trữ system extension
Cấu hình khởi động nhân phát triển
- Tắt máy Mac rồi khởi động vào recoveryOS, sau đó thực hiện các thiết lập sau trong Terminal
- Vô hiệu hóa System Integrity Protection (
csrutil disable)
- Gỡ giới hạn tham số khởi động (
bputil --disable-boot-args-restriction)
- Chỉ định kernel collection tùy chỉnh (
kmutil configure-boot)
- Thiết lập tham số khởi động (truyền bằng lệnh
nvram)
kcsuffix=development : khởi động nhân phát triển
hypervisor=0x1 : bật các tính năng đặc biệt của ngăn xếp ảo hóa
hv_apple_isa_vm_quota=0xFF : đặt số VM tối đa là 255
- Sau khi khởi động lại, có thể kiểm tra việc áp dụng bằng
sysctl kern.osbuildconfig và nvram boot-args
Kết quả chạy nhiều VM
- Sau khi hoàn tất cấu hình, đã thử nghiệm với các giải pháp dựa trên Virtualization.framework như UTM, Viable, Parallels
- Trên MacBook Pro M2 Pro, đã chạy thành công 9 máy ảo macOS đồng thời
- Hệ thống vẫn hoạt động ở mức có thể kiểm thử được
Thời điểm tính năng được thêm vào và cấu trúc bên trong
- Tham số khởi động
hv_apple_isa_vm_quota được thêm từ macOS 12 Monterey cùng với ngăn xếp Virtualization
- Ở các phiên bản sau đó (bao gồm macOS Sonoma), kiểm tra
AppleInternal vẫn còn tồn tại
- Điều này cho thấy Apple vẫn duy trì nhiều tính năng không công khai bên trong XNU
Lưu ý khi cập nhật OS
- Khi dùng kernel collection tùy chỉnh, tính năng tự động cập nhật OS sẽ bị vô hiệu hóa
- Do có thể phát sinh lỗi sau khi cập nhật, cần khôi phục về kernel collection mặc định
- Trong chế độ khôi phục, có thể dùng
bputil để tạo chính sách khởi động mới nhằm quay lại nhân mặc định
- Ví dụ: dùng các tùy chọn
bputil --full-security hoặc --disable-boot-args-restriction
Kết luận và ý tưởng cải tiến trong tương lai
- Bài viết xác nhận cách Apple triển khai giới hạn VM và kiểm chứng bằng thực nghiệm một phương pháp gỡ giới hạn không chính thức
- Dù nhóm Virtualization chưa tài liệu hóa chính thức, việc Apple để lại chức năng ghi đè giới hạn VM trong nhân là điểm đáng chú ý
- Các hướng cải tiến trong tương lai
- Phát triển công cụ tự động hóa build KC và cấu hình khởi động
- Tự động tạo kernel collection phát triển theo từng máy chủ và hỗ trợ thiết lập trong chế độ khôi phục
- Triển khai chức năng ghi đè biến
hv_apple_isa_vm_quota thông qua kernel extension (kext)
- Khảo sát khả năng gỡ giới hạn mà không cần khởi động nhân phát triển
- Chủ đề nghiên cứu tiếp theo là khả năng đăng ký DEP và ghi đè số serial của VM trên Apple Silicon
1 bình luận
Ý kiến trên Hacker News
Một giới hạn như thế này áp dụng giống nhau cho mọi máy Mac là quá vô lý
Nếu đã mua Mac mạnh hơn thì phải có thể ảo hóa được nhiều phiên bản macOS hơn
Ví dụ giới hạn kiểu M5 là 2, M5 Pro là 4, M5 Max là 8 có vẻ sẽ hợp lý hơn
Hiệu năng phần cứng mới là giới hạn tự nhiên, người dùng tự khắc sẽ dừng lại
Khả năng cao là để chặn các dịch vụ Mac VPS giá rẻ
Hyper‑V có thể chạy đồng thời tối đa 1024 VM nếu phần cứng chịu nổi
Ngay cả chiếc laptop Windows ARM nhỏ của tôi cũng chạy 4 cái không vấn đề gì
Tôi chạy VM để thử openclaw, nhưng rồi ngỡ ngàng khi thấy bị hạn chế truy cập iCloud và App Store
Khá thú vị khi 2 năm sau khi viết bài blog này, Mykola Grymalyuk lại vào làm ở Apple
Tự nhiên nhớ đến meme “chết như một anh hùng hoặc...”
Từ M3 trở lên có thể chạy nested VM bằng Hypervisor.framework / Virtualization.framework
Nếu cách này vượt được giới hạn thì khá thú vị đấy
macOS chỉ đi được một tầng, nên không thể chạy thêm một macOS guest khác bên trong macOS guest
Tôi lười quá nhưng mong ai đó thử hộ
Tôi thật sự tò mò vì sao Apple lại đặt giới hạn kiểu này
Doanh số phần cứng tài trợ cho việc phát triển phần mềm, nên họ không muốn người không mua phần cứng vẫn dùng macOS
Việc Apple giữ quyền kiểm soát luôn được ưu tiên hơn tự do của người dùng
Việc có thể biên dịch kernel tùy chỉnh, khởi động nó và thậm chí lên được GUI thật đáng ngạc nhiên
Bản thân bài viết rất thú vị, nhưng dùng một nền tảng có những giới hạn tùy tiện như vậy cho mục đích phát triển thì thật kỳ lạ
Nhiều lập trình viên dùng vì phần cứng cao cấp, nhưng macOS lúc nào cũng là “gần giống Linux nhưng là một OS do công ty lấy iTunes làm trung tâm kiểm soát”
Trên Apple Silicon, dùng custom kernel collection sẽ khiến không thể cập nhật OS tự động
Nhưng biết đâu đây lại là một phúc lành trá hình
Không rõ cái này có hoạt động với lume không
Hiện tại nó cũng có giới hạn tương tự
Theo tôi biết thì lume là wrapper mỏng quanh Virtualization.framework của Apple
Tôi nghe nói chỉ cần tắt SIP và đặt boot arg là làm được, không cần custom kernel
Apple giới hạn VM ở 2 cái à?
Còn guest dùng OS khác thì có thể chạy không giới hạn