internal/cpu,cmd/internal/obj/arm64: add SB

Add the SB (speculation barrier) instruction, and an internal/cpu
feature bit to check its availability.

Change-Id: I7c2d887ae75598f7c11cc875ec15ec3be76c09f5
Reviewed-on: https://go-review.googlesource.com/c/go/+/729501
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Roland Shoemaker
2025-12-11 21:19:38 -05:00
parent bdd4c38ce3
commit b7db3246a6
10 changed files with 37 additions and 3 deletions

View File

@@ -836,6 +836,7 @@ const (
AREVW
AROR
ARORW
ASB
ASBC
ASBCS
ASBCSW

View File

@@ -353,6 +353,7 @@ var Anames = []string{
"REVW",
"ROR",
"RORW",
"SB",
"SBC",
"SBCS",
"SBCSW",

View File

@@ -877,6 +877,7 @@ var optab = []Optab{
{ATLBI, C_SPOP, C_NONE, C_NONE, C_ZREG, C_NONE, 107, 4, 0, 0, 0},
{ABTI, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 108, 4, 0, 0, 0},
{ABTI, C_SPOP, C_NONE, C_NONE, C_NONE, C_NONE, 108, 4, 0, 0, 0},
{ASB, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
/* encryption instructions */
{AAESD, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 26, 4, 0, 0, 0}, // for compatibility with old code
@@ -3242,6 +3243,9 @@ func buildop(ctxt *obj.Link) {
case AVTBL:
oprangeset(AVTBX, t)
case ASB:
break
case AVCNT,
AVMOV,
AVLD1,
@@ -6841,6 +6845,9 @@ func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
case ACLREX:
return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
case ASB:
return SYSOP(0, 0, 3, 3, 0, 0, 0xFF)
}
c.ctxt.Diag("%v: bad imm %v", p, a)

View File

@@ -84,6 +84,7 @@ var ARM64 struct {
HasATOMICS bool
HasCPUID bool
HasDIT bool
HasSB bool
IsNeoverse bool
_ CacheLinePad
}

View File

@@ -29,6 +29,8 @@ func doinit() {
func getisar0() uint64
func getisar1() uint64
func getpfr0() uint64
func getMIDR() uint64
@@ -37,7 +39,7 @@ func extractBits(data uint64, start, end uint) uint {
return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
}
func parseARM64SystemRegisters(isar0, pfr0 uint64) {
func parseARM64SystemRegisters(isar0, isa1, pfr0 uint64) {
// ID_AA64ISAR0_EL1
// https://developer.arm.com/documentation/ddi0601/2025-03/AArch64-Registers/ID-AA64ISAR0-EL1--AArch64-Instruction-Set-Attribute-Register-0
switch extractBits(isar0, 4, 7) {
@@ -76,6 +78,11 @@ func parseARM64SystemRegisters(isar0, pfr0 uint64) {
ARM64.HasSHA3 = true
}
switch extractBits(isa1, 36, 39) {
case 1:
ARM64.HasSB = true
}
switch extractBits(pfr0, 48, 51) {
case 1:
ARM64.HasDIT = true

View File

@@ -11,6 +11,13 @@ TEXT ·getisar0(SB),NOSPLIT,$0
MOVD R0, ret+0(FP)
RET
// func getisar1() uint64
TEXT ·getisar1(SB),NOSPLIT,$0-8
// get Instruction Set Attributes 1 into R0
MRS ID_AA64ISAR1_EL1, R0
MOVD R0, ret+0(FP)
RET
// func getpfr0() uint64
TEXT ·getpfr0(SB),NOSPLIT,$0-8
// get Processor Feature Register 0 into R0

View File

@@ -18,6 +18,8 @@ func osInit() {
ARM64.HasDIT = sysctlEnabled([]byte("hw.optional.arm.FEAT_DIT\x00"))
ARM64.HasSB = sysctlEnabled([]byte("hw.optional.arm.FEAT_SB\x00"))
// There are no hw.optional sysctl values for the below features on macOS 11
// to detect their supported state dynamically (although they are available
// in the hw.optional.arm tree on macOS 12). Assume the CPU features that

View File

@@ -9,7 +9,8 @@ package cpu
func osInit() {
// Retrieve info from system register ID_AA64ISAR0_EL1.
isar0 := getisar0()
isar1 := getisar1()
prf0 := getpfr0()
parseARM64SystemRegisters(isar0, prf0)
parseARM64SystemRegisters(isar0, isar1, prf0)
}

View File

@@ -34,6 +34,7 @@ const (
hwcap_SHA3 = 1 << 17
hwcap_SHA512 = 1 << 21
hwcap_DIT = 1 << 24
hwcap_SB = 1 << 29
)
func hwcapInit(os string) {
@@ -50,6 +51,7 @@ func hwcapInit(os string) {
ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID)
ARM64.HasSHA512 = isSet(HWCap, hwcap_SHA512)
ARM64.HasDIT = isSet(HWCap, hwcap_DIT)
ARM64.HasSB = isSet(HWCap, hwcap_SB)
// The Samsung S9+ kernel reports support for atomics, but not all cores
// actually support them, resulting in SIGILL. See issue #28431.

View File

@@ -25,11 +25,16 @@ func osInit() {
if !ok {
return
}
// Get ID_AA64ISAR1 from sysctl.
isar1, ok := sysctlUint64([]uint32{_CTL_MACHDEP, _CPU_ID_AA64ISAR1})
if !ok {
return
}
// Get ID_AA64PFR0 from sysctl.
pfr0, ok := sysctlUint64([]uint32{_CTL_MACHDEP, _CPU_ID_AA64PFR0})
if !ok {
return
}
parseARM64SystemRegisters(isar0, pfr0)
parseARM64SystemRegisters(isar0, isar1, pfr0)
}