@@ -12,6 +12,7 @@ import (
12
12
"strconv"
13
13
"strings"
14
14
15
+ "github.com/coreos/go-semver/semver"
15
16
"github.com/docker/go-units"
16
17
"github.com/lima-vm/lima/pkg/downloader"
17
18
"github.com/lima-vm/lima/pkg/iso9660util"
@@ -246,6 +247,63 @@ func showDarwinARM64HVFQEMU620Warning(exe, accel string, features *features) {
246
247
logrus .Warn (w )
247
248
}
248
249
250
+ func getMacOSProductVersion () (* semver.Version , error ) {
251
+ cmd := exec .Command ("sw_vers" , "-productVersion" )
252
+ // output is like "12.3.1\n"
253
+ b , err := cmd .Output ()
254
+ if err != nil {
255
+ return nil , fmt .Errorf ("failed to execute %v: %w" , cmd .Args , err )
256
+ }
257
+ verTrimmed := strings .TrimSpace (string (b ))
258
+ verSem , err := semver .NewVersion (verTrimmed )
259
+ if err != nil {
260
+ return nil , fmt .Errorf ("failed to parse macOS version %q: %w" , verTrimmed , err )
261
+ }
262
+ return verSem , nil
263
+ }
264
+
265
+ // adjustMemBytesDarwinARM64HVF adjusts the memory to be <= 3 GiB, only when the following conditions are met:
266
+ //
267
+ // - Host OS < macOS 12.4
268
+ // - Host Arch == arm64
269
+ // - Accel == hvf
270
+ // - QEMU >= 7.0
271
+ //
272
+ // This adjustment is required for avoiding host kernel panic. The issue was fixed in macOS 12.4 Beta 1.
273
+ // See https://github.com/lima-vm/lima/issues/795 https://gitlab.com/qemu-project/qemu/-/issues/903#note_911000975
274
+ func adjustMemBytesDarwinARM64HVF (memBytes int64 , accel string , features * features ) int64 {
275
+ const safeSize = 3 * 1024 * 1024 * 1024 // 3 GiB
276
+ if memBytes <= safeSize {
277
+ return memBytes
278
+ }
279
+ if runtime .GOOS != "darwin" {
280
+ return memBytes
281
+ }
282
+ if runtime .GOARCH != "arm64" {
283
+ return memBytes
284
+ }
285
+ if accel != "hvf" {
286
+ return memBytes
287
+ }
288
+ if ! features .VersionGEQ7 {
289
+ return memBytes
290
+ }
291
+ macOSProductVersion , err := getMacOSProductVersion ()
292
+ if err != nil {
293
+ logrus .Warn (err )
294
+ return memBytes
295
+ }
296
+ if ! macOSProductVersion .LessThan (* semver .New ("12.4.0" )) {
297
+ return memBytes
298
+ }
299
+ logrus .Warnf ("Reducing the guest memory from %s to %s, to avoid host kernel panic on macOS <= 12.3 with QEMU >= 7.0; " +
300
+ "Please update macOS to 12.4 or later, or downgrade QEMU to 6.2; " +
301
+ "See https://github.com/lima-vm/lima/issues/795 for the further background." ,
302
+ units .BytesSize (float64 (memBytes )), units .BytesSize (float64 (safeSize )))
303
+ memBytes = safeSize
304
+ return memBytes
305
+ }
306
+
249
307
func Cmdline (cfg Config ) (string , []string , error ) {
250
308
y := cfg .LimaYAML
251
309
exe , args , err := getExe (* y .Arch )
@@ -265,6 +323,15 @@ func Cmdline(cfg Config) (string, []string, error) {
265
323
}
266
324
showDarwinARM64HVFQEMU620Warning (exe , accel , features )
267
325
326
+ // Memory
327
+ memBytes , err := units .RAMInBytes (* y .Memory )
328
+ if err != nil {
329
+ return "" , nil , err
330
+ }
331
+ memBytes = adjustMemBytesDarwinARM64HVF (memBytes , accel , features )
332
+ args = appendArgsIfNoConflict (args , "-m" , strconv .Itoa (int (memBytes >> 20 )))
333
+
334
+ // CPU
268
335
cpu := y .CPUType [* y .Arch ]
269
336
args = appendArgsIfNoConflict (args , "-cpu" , cpu )
270
337
switch * y .Arch {
@@ -288,7 +355,8 @@ func Cmdline(cfg Config) (string, []string, error) {
288
355
// QEMU < 7.0 requires highmem=off to be set, otherwise fails with "VCPU supports less PA bits (36) than requested by the memory map (40)"
289
356
// https://github.com/lima-vm/lima/issues/680
290
357
// https://github.com/lima-vm/lima/pull/24
291
- if ! features .VersionGEQ7 {
358
+ // But when the memory size is <= 3 GiB, we can always set highmem=off.
359
+ if ! features .VersionGEQ7 || memBytes <= 3 * 1024 * 1024 * 1024 {
292
360
machine += ",highmem=off"
293
361
}
294
362
args = appendArgsIfNoConflict (args , "-machine" , machine )
@@ -298,13 +366,6 @@ func Cmdline(cfg Config) (string, []string, error) {
298
366
args = appendArgsIfNoConflict (args , "-smp" ,
299
367
fmt .Sprintf ("%d,sockets=1,cores=%d,threads=1" , * y .CPUs , * y .CPUs ))
300
368
301
- // Memory
302
- memBytes , err := units .RAMInBytes (* y .Memory )
303
- if err != nil {
304
- return "" , nil , err
305
- }
306
- args = appendArgsIfNoConflict (args , "-m" , strconv .Itoa (int (memBytes >> 20 )))
307
-
308
369
// Firmware
309
370
legacyBIOS := * y .Firmware .LegacyBIOS
310
371
if legacyBIOS && * y .Arch != limayaml .X8664 {
0 commit comments