]> Cypherpunks repositories - gostls13.git/commitdiff
internal/cpu: add CPU feature LAMCAS and LAM_BH detection on loong64
authorGuoqi Chen <chenguoqi@loongson.cn>
Fri, 13 Sep 2024 10:50:03 +0000 (18:50 +0800)
committerabner chenc <chenguoqi@loongson.cn>
Fri, 4 Oct 2024 14:49:31 +0000 (14:49 +0000)
Change-Id: Ic5580c4ee006d87b3152ae5de7b25fb532c6a33f
Reviewed-on: https://go-review.googlesource.com/c/go/+/612976
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Martin Möhrmann <martin@golang.org>
src/internal/cpu/cpu.go
src/internal/cpu/cpu_loong64.go
src/internal/cpu/cpu_loong64.s [new file with mode: 0644]
src/internal/cpu/cpu_loong64_hwcap.go

index d6437a566ba23e52928b19c41951919db8da6d58..a3b92db9975d92799fb99fa86e85692a3ab39938 100644 (file)
@@ -81,9 +81,11 @@ var ARM64 struct {
 // The booleans in Loong64 contain the correspondingly named cpu feature bit.
 // The struct is padded to avoid false sharing.
 var Loong64 struct {
-       _        CacheLinePad
-       HasCRC32 bool
-       _        CacheLinePad
+       _         CacheLinePad
+       HasCRC32  bool // support CRC instruction
+       HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D}
+       HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction
+       _         CacheLinePad
 }
 
 var MIPS64X struct {
@@ -137,6 +139,7 @@ var S390X struct {
 //go:linkname X86
 //go:linkname ARM
 //go:linkname ARM64
+//go:linkname Loong64
 //go:linkname MIPS64X
 //go:linkname PPC64
 //go:linkname S390X
index c4709cc158974afde185914746d4c3eca2c21693..5ade180e0dd9323e1877d13a0db814c3b736a160 100644 (file)
@@ -10,10 +10,44 @@ package cpu
 // We choose 64 because Loongson 3A5000 the L1 Dcache is 4-way 256-line 64-byte-per-line.
 const CacheLinePadSize = 64
 
+// Bit fields for CPUCFG registers, Related reference documents:
+// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cpucfg
+const (
+       // CPUCFG1 bits
+       cpucfg1_CRC32 = 1 << 25
+
+       // CPUCFG2 bits
+       cpucfg2_LAM_BH = 1 << 27
+       cpucfg2_LAMCAS = 1 << 28
+)
+
+// get_cpucfg is implemented in cpu_loong64.s.
+func get_cpucfg(reg uint32) uint32
+
 func doinit() {
        options = []option{
                {Name: "crc32", Feature: &Loong64.HasCRC32},
+               {Name: "lamcas", Feature: &Loong64.HasLAMCAS},
+               {Name: "lam_bh", Feature: &Loong64.HasLAM_BH},
        }
 
+       // The CPUCFG data on Loong64 only reflects the hardware capabilities,
+       // not the kernel support status, so features such as LSX and LASX that
+       // require kernel support cannot be obtained from the CPUCFG data.
+       //
+       // These features only require hardware capability support and do not
+       // require kernel specific support, so they can be obtained directly
+       // through CPUCFG
+       cfg1 := get_cpucfg(1)
+       cfg2 := get_cpucfg(2)
+
+       Loong64.HasCRC32 = isSet(cfg1, cpucfg1_CRC32)
+       Loong64.HasLAMCAS = isSet(cfg2, cpucfg2_LAM_BH)
+       Loong64.HasLAM_BH = isSet(cfg2, cpucfg2_LAMCAS)
+
        osInit()
 }
+
+func isSet(cfg uint32, val uint32) bool {
+       return cfg&val != 0
+}
diff --git a/src/internal/cpu/cpu_loong64.s b/src/internal/cpu/cpu_loong64.s
new file mode 100644 (file)
index 0000000..f02a278
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// func get_cpucfg(reg uint32) uint32
+TEXT ·get_cpucfg(SB), NOSPLIT|NOFRAME, $0-12
+       MOVW    reg+0(FP), R5
+       CPUCFG  R5, R4
+       MOVW    R4, ret+8(FP)
+       RET
index b55fde6761ef52ad2a078d5a2462c316fa74c88b..c6005c4e6eb660f9934ecd312d9cad213ba01a36 100644 (file)
@@ -10,21 +10,7 @@ package cpu
 // initialized.
 var HWCap uint
 
-// HWCAP bits. These are exposed by the Linux kernel.
-const (
-       hwcap_LOONGARCH_CRC32 = 1 << 6
-)
-
 func hwcapInit() {
-       // It is not taken from CPUCFG data regardless of availability of
-       // CPUCFG, because the CPUCFG data only reflects capabilities of the
-       // hardware, but not kernel support.
-       //
-       // As of 2023, we do not know for sure if the CPUCFG data can be
-       // patched in software, nor does any known LoongArch kernel do that.
-       Loong64.HasCRC32 = isSet(HWCap, hwcap_LOONGARCH_CRC32)
-}
-
-func isSet(hwc uint, value uint) bool {
-       return hwc&value != 0
+       // TODO: Features that require kernel support like LSX and LASX can
+       // be detected here once needed in std library or by the compiler.
 }