Skip to content

Commit 7046952

Browse files
committed
Clean up codes for QEMU < 7.0
- QEMU 7.0 is documented as the minimum requirement since 9eb1396 (Dec 2022) - Also clean up the hint for QEMU 8.2.0, as QEMU 8.2.0 users should have already updated QEMU to 8.2.1+ - QEMU 4.0 is still exceptionally allowed on linux/amd64 for the compatibility reason, but not tested - QEMU 6.2 is added to the CI Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
1 parent 56874c3 commit 7046952

File tree

4 files changed

+88
-86
lines changed

4 files changed

+88
-86
lines changed

.github/workflows/test.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,3 +523,34 @@ jobs:
523523
go-version: 1.24.x
524524
- run: GOOS=netbsd go build ./...
525525
- run: GOOS=dragonfly go build ./...
526+
527+
qemu-linux-old:
528+
name: "Smoke tests (QEMU, old Linux host)"
529+
runs-on: ubuntu-22.04 # QEMU 6.2
530+
timeout-minutes: 30
531+
steps:
532+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
533+
with:
534+
# To avoid "failed to load YAML file \"templates/experimental/riscv64.yaml\": can't parse builtin Lima version \"3f3a6f6\": 3f3a6f6 is not in dotted-tri format"
535+
fetch-depth: 0
536+
- uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
537+
with:
538+
go-version: 1.24.x
539+
- name: Make
540+
run: make
541+
- name: Install
542+
run: sudo make install
543+
- name: Cache image used by templates/default.yaml
544+
uses: ./.github/actions/setup_cache_for_template
545+
with:
546+
template: templates/default.yaml
547+
- name: Install test dependencies
548+
run: |
549+
sudo apt-get update
550+
sudo apt-get install -y --no-install-recommends ovmf qemu-system-x86 qemu-utils
551+
qemu-system-x86_64 --version
552+
sudo modprobe kvm
553+
# `sudo usermod -aG kvm $(whoami)` does not take an effect on GHA
554+
sudo chown $(whoami) /dev/kvm
555+
- name: Smoke test
556+
run: limactl start --tty=false

pkg/qemu/qemu.go

Lines changed: 52 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,42 @@ type Config struct {
4747
VirtioGA bool
4848
}
4949

50-
// MinimumQemuVersion is the minimum supported QEMU version.
51-
const (
52-
MinimumQemuVersion = "4.0.0"
53-
)
50+
// minimumQemuVersion returns hardMin and softMin.
51+
//
52+
// hardMin is the hard minimum version of QEMU.
53+
// The driver immediately returns the error when QEMU is older than this version.
54+
//
55+
// softMin is the oldest recommended version of QEMU.
56+
// softMin must be >= hardMin.
57+
//
58+
// When updating this function, make sure to update
59+
// `website/content/en/docs/config/vmtype.md` too.
60+
func minimumQemuVersion() (hardMin, softMin semver.Version) {
61+
var h, s string
62+
switch runtime.GOOS {
63+
case "darwin":
64+
switch runtime.GOARCH {
65+
case "arm64":
66+
// https://gitlab.com/qemu-project/qemu/-/issues/1990
67+
h, s = "8.2.1", "8.2.1"
68+
default:
69+
// The code specific to QEMU < 7.0 on macOS (https://github.com/lima-vm/lima/pull/703)
70+
// was removed in https://github.com/lima-vm/lima/pull/3491
71+
h, s = "7.0.0", "8.2.1"
72+
}
73+
default:
74+
// hardMin: Untested and maybe does not even work.
75+
// softMin: Ubuntu 22.04's QEMU. The oldest version that can be easily tested on GitHub Actions.
76+
h, s = "4.0.0", "6.2.0"
77+
}
78+
hardMin, softMin = *semver.New(h), *semver.New(s)
79+
if softMin.LessThan(hardMin) {
80+
// NOTREACHED
81+
logrus.Fatalf("internal error: QEMU: soft minimum version %v must be >= hard minimum version %v",
82+
softMin, hardMin)
83+
}
84+
return hardMin, softMin
85+
}
5486

5587
// EnsureDisk also ensures the kernel and the initrd.
5688
func EnsureDisk(ctx context.Context, cfg Config) error {
@@ -287,9 +319,6 @@ type features struct {
287319
// e.g. "Available CPUs:\n...\nx86 base...\nx86 host...\n...\n"
288320
// Not machine-readable, but checking strings.Contains() should be fine.
289321
CPUHelp []byte
290-
291-
// VersionGEQ7 is true when the QEMU version seems v7.0.0 or later
292-
VersionGEQ7 bool
293322
}
294323

295324
func inspectFeatures(exe, machine string) (*features, error) {
@@ -333,7 +362,6 @@ func inspectFeatures(exe, machine string) (*features, error) {
333362
f.MachineHelp = stderr.Bytes()
334363
}
335364
}
336-
f.VersionGEQ7 = strings.Contains(string(f.MachineHelp), "-7.0")
337365

338366
// Avoid error: "No machine specified, and there is no default"
339367
cmd = exec.Command(exe, "-cpu", "help", "-machine", machine)
@@ -351,56 +379,15 @@ func inspectFeatures(exe, machine string) (*features, error) {
351379
return &f, nil
352380
}
353381

354-
// showDarwinARM64HVFQEMU620Warning shows a warning on M1 macOS when QEMU is older than 6.2.0_1.
355-
//
356-
// See:
357-
// - https://gitlab.com/qemu-project/qemu/-/issues/899
358-
// - https://github.com/Homebrew/homebrew-core/pull/96743
359-
// - https://github.com/lima-vm/lima/issues/712
360-
func showDarwinARM64HVFQEMU620Warning(exe, accel string, features *features) {
361-
if runtime.GOOS != "darwin" {
362-
return
363-
}
364-
if runtime.GOARCH != "arm64" {
365-
return
366-
}
367-
if accel != "hvf" {
368-
return
369-
}
370-
if features.VersionGEQ7 {
371-
return
372-
}
373-
if exeFull, err := exec.LookPath(exe); err == nil {
374-
if exeResolved, err2 := filepath.EvalSymlinks(exeFull); err2 == nil {
375-
if strings.Contains(exeResolved, "Cellar/qemu/6.2.0_") {
376-
// Homebrew's QEMU 6.2.0_1 or later
377-
return
378-
}
379-
}
380-
}
381-
w := "This version of QEMU might not be able to boot recent Linux guests on M1 macOS hosts."
382-
if _, err := exec.LookPath("brew"); err == nil {
383-
w += "Run `brew upgrade` and make sure your QEMU version is 6.2.0_1 or later."
384-
} else {
385-
w += `Reinstall QEMU with the following commits (included in QEMU 7.0.0):
386-
- https://github.com/qemu/qemu/commit/ad99f64f "hvf: arm: Use macros for sysreg shift/masking"
387-
- https://github.com/qemu/qemu/commit/7f6c295c "hvf: arm: Handle unknown ID registers as RES0"
388-
`
389-
w += "See https://github.com/Homebrew/homebrew-core/pull/96743 for the further information."
390-
}
391-
logrus.Warn(w)
392-
}
393-
394382
// adjustMemBytesDarwinARM64HVF adjusts the memory to be <= 3 GiB, only when the following conditions are met:
395383
//
396384
// - Host OS < macOS 12.4
397385
// - Host Arch == arm64
398386
// - Accel == hvf
399-
// - QEMU >= 7.0
400387
//
401388
// This adjustment is required for avoiding host kernel panic. The issue was fixed in macOS 12.4 Beta 1.
402389
// See https://github.com/lima-vm/lima/issues/795 https://gitlab.com/qemu-project/qemu/-/issues/903#note_911000975
403-
func adjustMemBytesDarwinARM64HVF(memBytes int64, accel string, features *features) int64 {
390+
func adjustMemBytesDarwinARM64HVF(memBytes int64, accel string) int64 {
404391
const safeSize = 3 * 1024 * 1024 * 1024 // 3 GiB
405392
if memBytes <= safeSize {
406393
return memBytes
@@ -414,9 +401,6 @@ func adjustMemBytesDarwinARM64HVF(memBytes int64, accel string, features *featur
414401
if accel != "hvf" {
415402
return memBytes
416403
}
417-
if !features.VersionGEQ7 {
418-
return memBytes
419-
}
420404
macOSProductVersion, err := osutil.ProductVersion()
421405
if err != nil {
422406
logrus.Warn(err)
@@ -425,8 +409,8 @@ func adjustMemBytesDarwinARM64HVF(memBytes int64, accel string, features *featur
425409
if !macOSProductVersion.LessThan(*semver.New("12.4.0")) {
426410
return memBytes
427411
}
428-
logrus.Warnf("Reducing the guest memory from %s to %s, to avoid host kernel panic on macOS <= 12.3 with QEMU >= 7.0; "+
429-
"Please update macOS to 12.4 or later, or downgrade QEMU to 6.2; "+
412+
logrus.Warnf("Reducing the guest memory from %s to %s, to avoid host kernel panic on macOS <= 12.3; "+
413+
"Please update macOS to 12.4 or later; "+
430414
"See https://github.com/lima-vm/lima/issues/795 for the further background.",
431415
units.BytesSize(float64(memBytes)), units.BytesSize(float64(safeSize)))
432416
memBytes = safeSize
@@ -471,31 +455,30 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er
471455
logrus.WithError(err).Warning("Failed to detect QEMU version")
472456
} else {
473457
logrus.Debugf("QEMU version %s detected", version.String())
474-
if version.LessThan(*semver.New(MinimumQemuVersion)) {
475-
logrus.Fatalf("QEMU %v is too old, %v or later required", version, MinimumQemuVersion)
458+
hardMin, softMin := minimumQemuVersion()
459+
if version.LessThan(hardMin) {
460+
logrus.Fatalf("QEMU %v is too old, %v or later required", version, hardMin)
461+
}
462+
if version.LessThan(softMin) {
463+
logrus.Warnf("QEMU %v is too old, %v or later is recommended", version, softMin)
476464
}
477465
if y.VMOpts.QEMU.MinimumVersion != nil && version.LessThan(*semver.New(*y.VMOpts.QEMU.MinimumVersion)) {
478466
logrus.Fatalf("QEMU %v is too old, template requires %q or later", version, *y.VMOpts.QEMU.MinimumVersion)
479467
}
480-
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" && version.Equal(*semver.New("8.2.0")) {
481-
logrus.Fatal("QEMU 8.2.0 is no longer supported on ARM Mac due to <https://gitlab.com/qemu-project/qemu/-/issues/1990>. " +
482-
"Please upgrade QEMU to v8.2.1 (or downgrade to v8.1.x).")
483-
}
484468
}
485469

486470
// Architecture
487471
accel := Accel(*y.Arch)
488472
if !strings.Contains(string(features.AccelHelp), accel) {
489473
return "", nil, fmt.Errorf("accelerator %q is not supported by %s", accel, exe)
490474
}
491-
showDarwinARM64HVFQEMU620Warning(exe, accel, features)
492475

493476
// Memory
494477
memBytes, err := units.RAMInBytes(*y.Memory)
495478
if err != nil {
496479
return "", nil, err
497480
}
498-
memBytes = adjustMemBytesDarwinARM64HVF(memBytes, accel, features)
481+
memBytes = adjustMemBytesDarwinARM64HVF(memBytes, accel)
499482
args = appendArgsIfNoConflict(args, "-m", strconv.Itoa(int(memBytes>>20)))
500483

501484
if *y.MountType == limayaml.VIRTIOFS {
@@ -543,14 +526,6 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er
543526
}
544527
case limayaml.AARCH64:
545528
machine := "virt,accel=" + accel
546-
// QEMU >= 7.0 requires highmem=off NOT to be set, otherwise fails with "Addressing limited to 32 bits, but memory exceeds it by 1073741824 bytes"
547-
// 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)"
548-
// https://github.com/lima-vm/lima/issues/680
549-
// https://github.com/lima-vm/lima/pull/24
550-
// But when the memory size is <= 3 GiB, we can always set highmem=off.
551-
if !features.VersionGEQ7 || memBytes <= 3*1024*1024*1024 {
552-
machine += ",highmem=off"
553-
}
554529
args = appendArgsIfNoConflict(args, "-machine", machine)
555530
case limayaml.RISCV64:
556531
// https://github.com/tianocore/edk2/blob/edk2-stable202408/OvmfPkg/RiscVVirt/README.md#test
@@ -850,23 +825,15 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er
850825
}
851826

852827
switch *y.Arch {
828+
// FIXME: use virtio-gpu on all the architectures
853829
case limayaml.X8664, limayaml.RISCV64:
854830
args = append(args, "-device", "virtio-vga")
855-
args = append(args, "-device", "virtio-keyboard-pci")
856-
args = append(args, "-device", "virtio-"+input+"-pci")
857-
args = append(args, "-device", "qemu-xhci,id=usb-bus")
858-
case limayaml.AARCH64, limayaml.ARMV7L, limayaml.PPC64LE, limayaml.S390X:
859-
if features.VersionGEQ7 {
860-
args = append(args, "-device", "virtio-gpu")
861-
args = append(args, "-device", "virtio-keyboard-pci")
862-
args = append(args, "-device", "virtio-"+input+"-pci")
863-
} else { // kernel panic with virtio and old versions of QEMU
864-
args = append(args, "-vga", "none", "-device", "ramfb")
865-
args = append(args, "-device", "usb-kbd,bus=usb-bus")
866-
args = append(args, "-device", "usb-"+input+",bus=usb-bus")
867-
}
868-
args = append(args, "-device", "qemu-xhci,id=usb-bus")
831+
default:
832+
args = append(args, "-device", "virtio-gpu")
869833
}
834+
args = append(args, "-device", "virtio-keyboard-pci")
835+
args = append(args, "-device", "virtio-"+input+"-pci")
836+
args = append(args, "-device", "qemu-xhci,id=usb-bus")
870837

871838
// Parallel
872839
args = append(args, "-parallel", "none")

website/content/en/docs/config/vmtype.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ unless the config is incompatible with VZ. (e.g., legacyBIOS or 9p is enabled)
2929
## QEMU
3030
"qemu" option makes use of QEMU to run guest operating system.
3131

32+
Recommended QEMU version:
33+
- v8.2.1 or later (macOS)
34+
- v6.2.0 or later (Linux)
35+
3236
## VZ
3337

3438
| ⚡ Requirement | Lima >= 0.14, macOS >= 13.0 |

website/content/en/docs/installation/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Supported host OS:
1010
- Windows (untested)
1111

1212
Prerequisite:
13-
- QEMU 7.1 or later (Required, only if QEMU driver is used)
13+
- QEMU (Required, only if [QEMU]({{< ref "/docs/config/vmtype#qemu" >}}) driver is used)
1414

1515
{{< tabpane text=true >}}
1616

0 commit comments

Comments
 (0)