Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compiler: require ARMv8.1 #2345

Merged
merged 2 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion config_supported.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

package wazero

import "github.com/tetratelabs/wazero/internal/platform"

func newRuntimeConfig() RuntimeConfig {
return NewRuntimeConfigCompiler()
if platform.CompilerSupported() {
return NewRuntimeConfigCompiler()
}
return NewRuntimeConfigInterpreter()
}
5 changes: 5 additions & 0 deletions internal/platform/cpuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,8 @@ const (
CpuExtraFeatureAmd64ABM CpuFeature = 1 << 5
// Note: when adding new features, ensure that the feature is included in CpuFeatureFlags.Raw.
)

const (
// CpuFeatureArm64Atomic is the flag to query CpuFeatureFlags.Has for Large System Extensions capabilities on arm64
CpuFeatureArm64Atomic CpuFeature = 1 << 21
)
4 changes: 2 additions & 2 deletions internal/platform/cpuid_amd64.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build amd64 && !tinygo
//go:build gc

package platform

Expand All @@ -12,7 +12,7 @@ type cpuFeatureFlags struct {
}

// cpuid exposes the CPUID instruction to the Go layer (https://www.amd.com/system/files/TechDocs/25481.pdf)
// implemented in impl_amd64.s
// implemented in cpuid_amd64.s
func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32)

// cpuidAsBitmap combines the result of invoking cpuid to uint64 bitmap.
Expand Down
4 changes: 3 additions & 1 deletion internal/platform/cpuid_amd64.s
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//go:build gc

#include "textflag.h"

// lifted from github.com/intel-go/cpuid and src/internal/cpu/cpu_x86.s

// func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32)
TEXT ·cpuid(SB), NOSPLIT, $0-24
MOVL arg1+0(FP), AX
Expand All @@ -11,4 +14,3 @@ TEXT ·cpuid(SB), NOSPLIT, $0-24
MOVL CX, ecx+16(FP)
MOVL DX, edx+20(FP)
RET

76 changes: 76 additions & 0 deletions internal/platform/cpuid_arm64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//go:build gc
ncruces marked this conversation as resolved.
Show resolved Hide resolved

package platform

import "runtime"

// CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods.
var CpuFeatures = loadCpuFeatureFlags()

// cpuFeatureFlags implements CpuFeatureFlags interface.
type cpuFeatureFlags struct {
isar0 uint64
isar1 uint64
}

// implemented in cpuid_arm64.s
func getisar0() uint64

// implemented in cpuid_arm64.s
func getisar1() uint64

func loadCpuFeatureFlags() CpuFeatureFlags {
switch runtime.GOOS {
case "darwin", "windows":
// These OSes require ARMv8.1, which includes atomic instructions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i get why darwin requires v8.1 by default (m series is so), but not sure about windows here. any reference or pointer?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows 10 does not in fact require them, is it good enough to document this?
At least this change should not be a regression.

return &cpuFeatureFlags{
isar0: uint64(CpuFeatureArm64Atomic),
isar1: 0,
}
case "linux", "freebsd":
// These OSes allow reading the instruction set attribute registers.
return &cpuFeatureFlags{
isar0: getisar0(),
isar1: getisar1(),
}
default:
return &cpuFeatureFlags{}
}
}

// Has implements the same method on the CpuFeatureFlags interface.
func (f *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool {
return (f.isar0 & uint64(cpuFeature)) != 0
}

// HasExtra implements the same method on the CpuFeatureFlags interface.
func (f *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool {
return (f.isar1 & uint64(cpuFeature)) != 0
}

// Raw implements the same method on the CpuFeatureFlags interface.
func (f *cpuFeatureFlags) Raw() uint64 {
// Below, we only set the first 4 bits for the features we care about,
// instead of setting all the unnecessary bits obtained from the CPUID instruction.
var ret uint64
switch runtime.GOARCH {
case "arm64":
if f.Has(CpuFeatureArm64Atomic) {
ret = 1 << 0
}
case "amd64":
if f.Has(CpuFeatureAmd64SSE3) {
ret = 1 << 0
}
if f.Has(CpuFeatureAmd64SSE4_1) {
ret |= 1 << 1
}
if f.Has(CpuFeatureAmd64SSE4_2) {
ret |= 1 << 2
}
if f.HasExtra(CpuExtraFeatureAmd64ABM) {
ret |= 1 << 3
}
}
return ret
}
21 changes: 21 additions & 0 deletions internal/platform/cpuid_arm64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//go:build gc

#include "textflag.h"

// lifted from github.com/golang/sys and cpu/cpu_arm64.s

// func getisar0() uint64
TEXT ·getisar0(SB), NOSPLIT, $0-8
// get Instruction Set Attributes 0 into x0
// mrs x0, ID_AA64ISAR0_EL1 = d5380600
mathetake marked this conversation as resolved.
Show resolved Hide resolved
WORD $0xd5380600
MOVD R0, ret+0(FP)
RET

// func getisar1() uint64
TEXT ·getisar1(SB), NOSPLIT, $0-8
// get Instruction Set Attributes 1 into x0
// mrs x0, ID_AA64ISAR1_EL1 = d5380620
mathetake marked this conversation as resolved.
Show resolved Hide resolved
WORD $0xd5380620
MOVD R0, ret+0(FP)
RET
2 changes: 1 addition & 1 deletion internal/platform/cpuid_unsupported.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !amd64 || tinygo
//go:build !(amd64 || arm64) || !gc

package platform

Expand Down
2 changes: 1 addition & 1 deletion internal/platform/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
// archRequirementsVerified is set by platform-specific init to true if the platform is supported
var archRequirementsVerified bool

// CompilerSupported is exported for tests and includes constraints here and also the assembler.
// CompilerSupported includes constraints here and also the assembler.
func CompilerSupported() bool {
switch runtime.GOOS {
case "linux", "darwin", "freebsd", "netbsd", "dragonfly", "windows":
Expand Down
4 changes: 2 additions & 2 deletions internal/platform/platform_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ package platform

// init verifies that the current CPU supports the required ARM64 features
func init() {
// No further checks currently needed.
archRequirementsVerified = true
// Ensure atomic instructions are supported.
archRequirementsVerified = CpuFeatures.Has(CpuFeatureArm64Atomic)
}
Loading