Skip to content

Commit b8f7da6

Browse files
committed
cpu: add support for detecting cpu features on loong64
Except for lasx, all other features have been implemented in the Go mainline. Change-Id: I61a09396ed23d17991b641a1265e952585cb5636 Reviewed-on: https://go-review.googlesource.com/c/sys/+/655355 Reviewed-by: David Chase <drchase@google.com> Reviewed-by: sophie zhao <zhaoxiaolin@loongson.cn> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Junyang Shao <shaojunyang@google.com> Reviewed-by: Meidan Li <limeidan@loongson.cn>
1 parent f2ce62c commit b8f7da6

File tree

6 files changed

+93
-1
lines changed

6 files changed

+93
-1
lines changed

cpu/cpu.go

+12
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,18 @@ var ARM struct {
149149
_ CacheLinePad
150150
}
151151

152+
// The booleans in Loong64 contain the correspondingly named cpu feature bit.
153+
// The struct is padded to avoid false sharing.
154+
var Loong64 struct {
155+
_ CacheLinePad
156+
HasLSX bool // support 128-bit vector extension
157+
HasLASX bool // support 256-bit vector extension
158+
HasCRC32 bool // support CRC instruction
159+
HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction
160+
HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} instruction
161+
_ CacheLinePad
162+
}
163+
152164
// MIPS64X contains the supported CPU features of the current mips64/mips64le
153165
// platforms. If the current platform is not mips64/mips64le or the current
154166
// operating system is not Linux then all feature flags are false.

cpu/cpu_linux_loong64.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2025 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package cpu
6+
7+
// HWCAP bits. These are exposed by the Linux kernel.
8+
const (
9+
hwcap_LOONGARCH_LSX = 1 << 4
10+
hwcap_LOONGARCH_LASX = 1 << 5
11+
)
12+
13+
func doinit() {
14+
// TODO: Features that require kernel support like LSX and LASX can
15+
// be detected here once needed in std library or by the compiler.
16+
Loong64.HasLSX = hwcIsSet(hwCap, hwcap_LOONGARCH_LSX)
17+
Loong64.HasLASX = hwcIsSet(hwCap, hwcap_LOONGARCH_LASX)
18+
}
19+
20+
func hwcIsSet(hwc uint, val uint) bool {
21+
return hwc&val != 0
22+
}

cpu/cpu_linux_noinit.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64
5+
//go:build linux && !arm && !arm64 && !loong64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64
66

77
package cpu
88

cpu/cpu_loong64.go

+38
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,43 @@ package cpu
88

99
const cacheLineSize = 64
1010

11+
// Bit fields for CPUCFG registers, Related reference documents:
12+
// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cpucfg
13+
const (
14+
// CPUCFG1 bits
15+
cpucfg1_CRC32 = 1 << 25
16+
17+
// CPUCFG2 bits
18+
cpucfg2_LAM_BH = 1 << 27
19+
cpucfg2_LAMCAS = 1 << 28
20+
)
21+
1122
func initOptions() {
23+
options = []option{
24+
{Name: "lsx", Feature: &Loong64.HasLSX},
25+
{Name: "lasx", Feature: &Loong64.HasLASX},
26+
{Name: "crc32", Feature: &Loong64.HasCRC32},
27+
{Name: "lam_bh", Feature: &Loong64.HasLAM_BH},
28+
{Name: "lamcas", Feature: &Loong64.HasLAMCAS},
29+
}
30+
31+
// The CPUCFG data on Loong64 only reflects the hardware capabilities,
32+
// not the kernel support status, so features such as LSX and LASX that
33+
// require kernel support cannot be obtained from the CPUCFG data.
34+
//
35+
// These features only require hardware capability support and do not
36+
// require kernel specific support, so they can be obtained directly
37+
// through CPUCFG
38+
cfg1 := get_cpucfg(1)
39+
cfg2 := get_cpucfg(2)
40+
41+
Loong64.HasCRC32 = cfgIsSet(cfg1, cpucfg1_CRC32)
42+
Loong64.HasLAMCAS = cfgIsSet(cfg2, cpucfg2_LAMCAS)
43+
Loong64.HasLAM_BH = cfgIsSet(cfg2, cpucfg2_LAM_BH)
44+
}
45+
46+
func get_cpucfg(reg uint32) uint32
47+
48+
func cfgIsSet(cfg uint32, val uint32) bool {
49+
return cfg&val != 0
1250
}

cpu/cpu_loong64.s

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2025 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
#include "textflag.h"
6+
7+
// func get_cpucfg(reg uint32) uint32
8+
TEXT ·get_cpucfg(SB), NOSPLIT|NOFRAME, $0
9+
MOVW reg+0(FP), R5
10+
CPUCFG R5, R4
11+
MOVW R4, ret+8(FP)
12+
RET

cpu/cpu_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ func TestARM64minimalFeatures(t *testing.T) {
8787
}
8888
}
8989

90+
func TestLOONG64Initialized(t *testing.T) {
91+
if runtime.GOARCH == "loong64" {
92+
if !cpu.Initialized {
93+
t.Fatal("Initialized expected true, got false")
94+
}
95+
}
96+
}
97+
9098
func TestMIPS64Initialized(t *testing.T) {
9199
if runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" {
92100
if !cpu.Initialized {

0 commit comments

Comments
 (0)