Skip to content

Commit 130b300

Browse files
committed
qemu: adjust the memory size for workarounding M1 panic
Adjust the memory to be <= 3 GiB, only when the following conditions are met: - Host OS < macOS 12.4 - Host Arch == arm64 - Accel == hvf - QEMU >= 7.0 This adjustment is required for avoiding host kernel panic. The issue was fixed in macOS 12.4 Beta 1. See https://gitlab.com/qemu-project/qemu/-/issues/903#note_911000975 Signed-off-by: Akihiro Suda <[email protected]>
1 parent 04fd06c commit 130b300

File tree

1 file changed

+69
-8
lines changed

1 file changed

+69
-8
lines changed

pkg/qemu/qemu.go

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"strconv"
1313
"strings"
1414

15+
"github.com/coreos/go-semver/semver"
1516
"github.com/docker/go-units"
1617
"github.com/lima-vm/lima/pkg/downloader"
1718
"github.com/lima-vm/lima/pkg/iso9660util"
@@ -246,6 +247,63 @@ func showDarwinARM64HVFQEMU620Warning(exe, accel string, features *features) {
246247
logrus.Warn(w)
247248
}
248249

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+
249307
func Cmdline(cfg Config) (string, []string, error) {
250308
y := cfg.LimaYAML
251309
exe, args, err := getExe(*y.Arch)
@@ -265,6 +323,15 @@ func Cmdline(cfg Config) (string, []string, error) {
265323
}
266324
showDarwinARM64HVFQEMU620Warning(exe, accel, features)
267325

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
268335
cpu := y.CPUType[*y.Arch]
269336
args = appendArgsIfNoConflict(args, "-cpu", cpu)
270337
switch *y.Arch {
@@ -288,7 +355,8 @@ func Cmdline(cfg Config) (string, []string, error) {
288355
// 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)"
289356
// https://github.com/lima-vm/lima/issues/680
290357
// 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 {
292360
machine += ",highmem=off"
293361
}
294362
args = appendArgsIfNoConflict(args, "-machine", machine)
@@ -298,13 +366,6 @@ func Cmdline(cfg Config) (string, []string, error) {
298366
args = appendArgsIfNoConflict(args, "-smp",
299367
fmt.Sprintf("%d,sockets=1,cores=%d,threads=1", *y.CPUs, *y.CPUs))
300368

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-
308369
// Firmware
309370
legacyBIOS := *y.Firmware.LegacyBIOS
310371
if legacyBIOS && *y.Arch != limayaml.X8664 {

0 commit comments

Comments
 (0)