Repository: lima-vm/lima
Pull request #643 (2022-02-10 04:13:18)

add cpuType for specify cpu
closes: https://github.com/lima-vm/lima/issues/592

- [x] doc


Patch:
diff --git a/README.md b/README.md
index fb013e1c..863d2e83 100644
--- a/README.md
+++ b/README.md
@@ -234,8 +234,6 @@ The current default spec:
   - ["permission denied" for `limactl cp` command](#permission-denied-for-limactl-cp-command)
 - [Networking](#networking)
   - ["Cannot access the guest IP 192.168.5.15 from the host"](#cannot-access-the-guest-ip-192168515-from-the-host)
-- [External projects](#external-projects)
-  - ["I am using Rancher Desktop. How to deal with the underlying Lima?"](#i-am-using-rancher-desktop-how-to-deal-with-the-underlying-lima)
 - ["Hints for debugging other problems?"](#hints-for-debugging-other-problems)
 
 <!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -370,31 +368,6 @@ To add another IP address that is accessible from the host and other virtual mac
 
 See [`./docs/network.md`](./docs/network.md).
 
-### External projects
-#### "I am using Rancher Desktop. How to deal with the underlying Lima?"
-
-On macOS hosts, Rancher Desktop (as of v1.0) launches Lima with the following configuration:
-
-- `$LIMA_HOME` directory: `$HOME/Library/Application Support/rancher-desktop/lima`
-- `limactl` binary: `/Applications/Rancher Desktop.app/Contents/Resources/resources/darwin/lima/bin/limactl`
-- Lima instance name: `0`
-
-To open a shell, run the following command:
-
-```shell
-LIMA_HOME="$HOME/Library/Application Support/rancher-desktop/lima" "/Applications/Rancher Desktop.app/Contents/Resources/resources/darwin/lima/bin/limactl" shell 0
-```
-
-On Linux hosts, try the following command:
-```shell
-LIMA_HOME="$HOME/.local/share/rancher-desktop/lima" /opt/rancher-desktop/resources/resources/linux/lima/bin/limactl shell 0
-```
-
-If you have installed Rancher Desktop as an AppImage:
-```shell
-LIMA_HOME="$HOME/.local/share/rancher-desktop/lima" "$(ls -d /tmp/.mount_ranche*/opt/rancher-desktop/resources/resources/linux/lima/bin)/limactl" shell 0
-```
-
 ### "Hints for debugging other problems?"
 - Inspect logs:
   - `limactl --debug start`
diff --git a/examples/podman.yaml b/examples/podman.yaml
index 819982eb..28402606 100644
--- a/examples/podman.yaml
+++ b/examples/podman.yaml
@@ -51,9 +51,6 @@ portForwards:
 - guestSocket: "/run/user/{{.UID}}/podman/podman.sock"
   hostSocket: "{{.Dir}}/sock/podman.sock"
 message: |
-  To run `podman` on the host (assumes podman-remote is installed), run the following commands:
-  ------
-  podman system connection add lima "unix://{{.Dir}}/sock/podman.sock"
-  podman system connection default lima
-  podman{{if eq .HostOS "linux"}} --remote{{end}} run quay.io/podman/hello
-  ------
+  To run `podman` on the host (assumes podman-remote is installed):
+  $ export CONTAINER_HOST=unix://{{.Dir}}/sock/podman.sock
+  $ podman{{if eq .HostOS "linux"}} --remote{{end}} ...
diff --git a/pkg/cidata/cidata.TEMPLATE.d/boot.sh b/pkg/cidata/cidata.TEMPLATE.d/boot.sh
index 525b9e27..c883a7fc 100644
--- a/pkg/cidata/cidata.TEMPLATE.d/boot.sh
+++ b/pkg/cidata/cidata.TEMPLATE.d/boot.sh
@@ -14,15 +14,7 @@ while read -r line; do export "$line"; done <"${LIMA_CIDATA_MNT}"/lima.env
 
 # shellcheck disable=SC2163
 while read -r line; do
-	# pam_env implementation:
-	# - '#' is treated the same as newline; terminates value
-	# - skip leading tabs and spaces
-	# - skip leading "export " prefix (only single space)
-	# - skip leading quote ('\'' or '"') on the value side
-	# - skip trailing quote only if leading quote has been skipped;
-	#   quotes don't need to match; trailing quote may be omitted
-	line="$(echo "$line" | sed -E "s/^[ \\t]*(export )?//; s/#.*//; s/(^[^=]+=)[\"'](.*[^\"'])?[\"']?$/\1\2/")"
-	[ -n "$line" ] && export "$line"
+	[ "$(expr "$line" : '#')" -eq 0 ] && export "$line"
 done <"${LIMA_CIDATA_MNT}"/etc_environment
 
 CODE=0
diff --git a/pkg/limayaml/default.yaml b/pkg/limayaml/default.yaml
index 51775a05..abd92130 100644
--- a/pkg/limayaml/default.yaml
+++ b/pkg/limayaml/default.yaml
@@ -27,6 +27,12 @@ images:
 - location: "https://cloud-images.ubuntu.com/impish/current/impish-server-cloudimg-arm64.img"
   arch: "aarch64"
 
+# Specify QEMU CPU emulation, e.g., "host", "qemu64", "Haswell".
+# You can see what options are available for host emulation with: `qemu-system-$(arch) -cpu help`.
+# Setting of instructions is supported like this: "qemu64,+ssse3".
+# Default: "host" (native arch), "qemu64" (Intel on ARM), or "cortex-a72" (ARM on Intel)
+cpuType: null
+
 # CPUs: if you see performance issues, try limiting cpus to 1.
 # Default: 4
 cpus: null
diff --git a/pkg/limayaml/defaults.go b/pkg/limayaml/defaults.go
index 769770c1..32f53cb5 100644
--- a/pkg/limayaml/defaults.go
+++ b/pkg/limayaml/defaults.go
@@ -81,6 +81,25 @@ func FillDefault(y, d, o *LimaYAML, filePath string) {
 		}
 	}
 
+	if y.CPUType == nil {
+		y.CPUType = d.CPUType
+	}
+	if o.CPUType != nil {
+		y.CPUType = o.CPUType
+	}
+	if y.CPUType == nil || *y.CPUType == "" {
+		if IsNativeArch(*y.Arch) {
+			y.CPUType = pointer.String("host")
+		} else if *y.Arch == X8664 {
+			// Intel on ARM
+			// Since https://github.com/lima-vm/lima/pull/494, we use qemu64 cpu for better emulation of x86_64.
+			y.CPUType = pointer.String("qemu64")
+		} else {
+			// ARM on Intel
+			y.CPUType = pointer.String("cortex-a72")
+		}
+	}
+
 	if y.CPUs == nil {
 		y.CPUs = d.CPUs
 	}
@@ -461,3 +480,9 @@ func ResolveArch(s *string) Arch {
 	}
 	return *s
 }
+
+func IsNativeArch(arch Arch) bool {
+	nativeX8664 := arch == X8664 && runtime.GOARCH == "amd64"
+	nativeAARCH64 := arch == AARCH64 && runtime.GOARCH == "arm64"
+	return nativeX8664 || nativeAARCH64
+}
diff --git a/pkg/limayaml/limayaml.go b/pkg/limayaml/limayaml.go
index 8a478d0b..374dd0a7 100644
--- a/pkg/limayaml/limayaml.go
+++ b/pkg/limayaml/limayaml.go
@@ -9,6 +9,7 @@ import (
 type LimaYAML struct {
 	Arch              *Arch             `yaml:"arch,omitempty" json:"arch,omitempty"`
 	Images            []File            `yaml:"images" json:"images"` // REQUIRED
+	CPUType           *string           `yaml:"cpuType,omitempty" json:"cpuType,omitempty"`
 	CPUs              *int              `yaml:"cpus,omitempty" json:"cpus,omitempty"`
 	Memory            *string           `yaml:"memory,omitempty" json:"memory,omitempty"` // go-units.RAMInBytes
 	Disk              *string           `yaml:"disk,omitempty" json:"disk,omitempty"`     // go-units.RAMInBytes
diff --git a/pkg/limayaml/validate.go b/pkg/limayaml/validate.go
index aa619052..ddf8642c 100644
--- a/pkg/limayaml/validate.go
+++ b/pkg/limayaml/validate.go
@@ -50,6 +50,10 @@ func Validate(y LimaYAML, warn bool) error {
 		}
 	}
 
+	if *y.CPUType == "" {
+		return fmt.Errorf("field `cpuType` must be set")
+	}
+
 	if *y.CPUs == 0 {
 		return errors.New("field `cpus` must be set")
 	}
diff --git a/pkg/qemu/qemu.go b/pkg/qemu/qemu.go
index 04a1cbdb..6154e5ec 100644
--- a/pkg/qemu/qemu.go
+++ b/pkg/qemu/qemu.go
@@ -206,16 +206,12 @@ func Cmdline(cfg Config) (string, []string, error) {
 		}
 		return "", nil, errors.New(errStr)
 	}
+
+	cpu := *y.CPUType
+	args = appendArgsIfNoConflict(args, "-cpu", cpu)
 	switch *y.Arch {
 	case limayaml.X8664:
-		cpu := "qemu64"
-		if isNativeArch(*y.Arch) {
-			cpu = "host"
-		}
-		args = appendArgsIfNoConflict(args, "-cpu", cpu)
-		if isNativeArch(*y.Arch) {
-			args = appendArgsIfNoConflict(args, "-machine", "q35,accel="+accel)
-		} else {
+		if strings.HasPrefix(cpu, "qemu64") {
 			// use q35 machine with vmware io port disabled.
 			args = appendArgsIfNoConflict(args, "-machine", "q35,vmport=off")
 			// use tcg accelerator with multi threading with 512MB translation block size
@@ -225,13 +221,10 @@ func Cmdline(cfg Config) (string, []string, error) {
 			args = appendArgsIfNoConflict(args, "-accel", "tcg,thread=multi,tb-size=512")
 			// This will disable CPU S3 state.
 			args = append(args, "-global", "ICH9-LPC.disable_s3=1")
+		} else {
+			args = appendArgsIfNoConflict(args, "-machine", "q35,accel="+accel)
 		}
 	case limayaml.AARCH64:
-		cpu := "cortex-a72"
-		if isNativeArch(*y.Arch) {
-			cpu = "host"
-		}
-		args = appendArgsIfNoConflict(args, "-cpu", cpu)
 		args = appendArgsIfNoConflict(args, "-machine", "virt,accel="+accel+",highmem=off")
 	}
 
@@ -396,14 +389,8 @@ func getExe(arch limayaml.Arch) (string, []string, error) {
 	return exe, args, nil
 }
 
-func isNativeArch(arch limayaml.Arch) bool {
-	nativeX8664 := arch == limayaml.X8664 && runtime.GOARCH == "amd64"
-	nativeAARCH64 := arch == limayaml.AARCH64 && runtime.GOARCH == "arm64"
-	return nativeX8664 || nativeAARCH64
-}
-
 func getAccel(arch limayaml.Arch) string {
-	if isNativeArch(arch) {
+	if limayaml.IsNativeArch(arch) {
 		switch runtime.GOOS {
 		case "darwin":
 			return "hvf"
diff --git a/pkg/store/instance.go b/pkg/store/instance.go
index e46f39ca..f96f0e43 100644
--- a/pkg/store/instance.go
+++ b/pkg/store/instance.go
@@ -33,6 +33,7 @@ type Instance struct {
 	Status       Status             `json:"status"`
 	Dir          string             `json:"dir"`
 	Arch         limayaml.Arch      `json:"arch"`
+	CPUType      string             `json:"cpuType"`
 	CPUs         int                `json:"cpus,omitempty"`
 	Memory       int64              `json:"memory,omitempty"` // bytes
 	Disk         int64              `json:"disk,omitempty"`   // bytes
@@ -75,6 +76,7 @@ func Inspect(instName string) (*Instance, error) {
 	}
 	inst.Dir = instDir
 	inst.Arch = *y.Arch
+	inst.CPUType = *y.CPUType
 	inst.CPUs = *y.CPUs
 	memory, err := units.RAMInBytes(*y.Memory)
 	if err == nil {


Test patch:
diff --git a/pkg/limayaml/defaults_test.go b/pkg/limayaml/defaults_test.go
index f3a2e84b..b8ae1423 100644
--- a/pkg/limayaml/defaults_test.go
+++ b/pkg/limayaml/defaults_test.go
@@ -47,10 +47,11 @@ func TestFillDefault(t *testing.T) {
 
 	// Builtin default values
 	builtin := LimaYAML{
-		Arch:   pointer.String(arch),
-		CPUs:   pointer.Int(4),
-		Memory: pointer.String("4GiB"),
-		Disk:   pointer.String("100GiB"),
+		Arch:    pointer.String(arch),
+		CPUType: pointer.String("host"),
+		CPUs:    pointer.Int(4),
+		Memory:  pointer.String("4GiB"),
+		Disk:    pointer.String("100GiB"),
 		Containerd: Containerd{
 			System:   pointer.Bool(false),
 			User:     pointer.Bool(true),
@@ -168,10 +169,11 @@ func TestFillDefault(t *testing.T) {
 
 	// Choose values that are different from the "builtin" defaults
 	d = LimaYAML{
-		Arch:   pointer.String("unknown"),
-		CPUs:   pointer.Int(7),
-		Memory: pointer.String("5GiB"),
-		Disk:   pointer.String("105GiB"),
+		Arch:    pointer.String("unknown"),
+		CPUType: pointer.String("host"),
+		CPUs:    pointer.Int(7),
+		Memory:  pointer.String("5GiB"),
+		Disk:    pointer.String("105GiB"),
 		Containerd: Containerd{
 			System: pointer.Bool(true),
 			User:   pointer.Bool(false),
@@ -280,10 +282,11 @@ func TestFillDefault(t *testing.T) {
 	// User-provided overrides should override user-provided config settings
 
 	o = LimaYAML{
-		Arch:   pointer.String(arch),
-		CPUs:   pointer.Int(12),
-		Memory: pointer.String("7GiB"),
-		Disk:   pointer.String("117GiB"),
+		Arch:    pointer.String(arch),
+		CPUType: pointer.String("host"),
+		CPUs:    pointer.Int(12),
+		Memory:  pointer.String("7GiB"),
+		Disk:    pointer.String("117GiB"),
 		Containerd: Containerd{
 			System: pointer.Bool(true),
 			User:   pointer.Bool(false),