diff --git a/.codespellrc b/.codespellrc index 24a1209e2b8..1618a467c4a 100644 --- a/.codespellrc +++ b/.codespellrc @@ -6,7 +6,7 @@ skip = .git,go.mod,go.sum,*.pb.desc,*/node_modules/*,*/public/js/*,*/public/scss/* # Comma separated list of words to be ignored. Words must be lowercased. -ignore-words-list = ans,distroname,testof,hda,ststr,archtypes +ignore-words-list = ans,distroname,testof,hda,ststr,archtypes,sme # Check file names as well. check-filenames = true diff --git a/pkg/limayaml/defaults.go b/pkg/limayaml/defaults.go index 3aa84793643..c6740e06eef 100644 --- a/pkg/limayaml/defaults.go +++ b/pkg/limayaml/defaults.go @@ -14,6 +14,7 @@ import ( "slices" "strconv" "strings" + "sync" "text/template" "github.com/coreos/go-semver/semver" @@ -1173,9 +1174,44 @@ func IsAccelOS() bool { return false } +var ( + hasSMEDarwin bool + hasSMEDarwinOnce sync.Once +) + +func init() { + hasSMEDarwinOnce.Do(func() { + hasSMEDarwin = hasSMEDarwinFn() + }) +} + +func hasSMEDarwinFn() bool { + if runtime.GOOS != "darwin" || runtime.GOARCH != "arm64" { + return false + } + // golang.org/x/sys/cpu does not support inspecting the availability of SME yet + s, err := osutil.Sysctl("hw.optional.arm.FEAT_SME") + if err != nil { + logrus.WithError(err).Debug("failed to check hw.optional.arm.FEAT_SME") + } + return s == "1" +} + func HasHostCPU() bool { switch runtime.GOOS { - case "darwin", "linux": + case "darwin": + if hasSMEDarwin { + // SME is available since Apple M4 running macOS 15.2. + // + // However, QEMU is not ready to handle SME yet. + // + // https://github.com/lima-vm/lima/issues/3032 + // https://gitlab.com/qemu-project/qemu/-/issues/2665 + // https://gitlab.com/qemu-project/qemu/-/issues/2721 + return false + } + return true + case "linux": return true case "netbsd", "windows": return false @@ -1185,8 +1221,8 @@ func HasHostCPU() bool { } func HasMaxCPU() bool { - // WHPX: Unexpected VP exit code 4 - return runtime.GOOS != "windows" + // windows: WHPX: Unexpected VP exit code 4 + return HasHostCPU() } func IsNativeArch(arch Arch) bool { diff --git a/pkg/osutil/osutil_unix.go b/pkg/osutil/osutil_unix.go index 2420a8ef55a..a8764a8c8ce 100644 --- a/pkg/osutil/osutil_unix.go +++ b/pkg/osutil/osutil_unix.go @@ -3,7 +3,11 @@ package osutil import ( + "bytes" + "fmt" "os" + "os/exec" + "strings" "syscall" "golang.org/x/sys/unix" @@ -16,3 +20,15 @@ func Dup2(oldfd, newfd int) (err error) { func SignalName(sig os.Signal) string { return unix.SignalName(sig.(syscall.Signal)) } + +func Sysctl(name string) (string, error) { + var stderrBuf bytes.Buffer + cmd := exec.Command("sysctl", "-n", name) + cmd.Stderr = &stderrBuf + stdout, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("failed to run %v: %w (stdout=%q, stderr=%q)", cmd.Args, err, + string(stdout), stderrBuf.String()) + } + return strings.TrimSuffix(string(stdout), "\n"), nil +} diff --git a/pkg/osutil/osutil_windows.go b/pkg/osutil/osutil_windows.go index c2f18bdd3d7..4849597d1a4 100644 --- a/pkg/osutil/osutil_windows.go +++ b/pkg/osutil/osutil_windows.go @@ -1,6 +1,7 @@ package osutil import ( + "errors" "fmt" "io/fs" "os" @@ -48,3 +49,7 @@ func SignalName(sig os.Signal) string { return fmt.Sprintf("Signal(%d)", sig) } } + +func Sysctl(name string) (string, error) { + return "", errors.New("sysctl: unimplemented on Windows") +}