From 34c2b5e9d1b15ab9d8988f7919df967f3c405187 Mon Sep 17 00:00:00 2001 From: xtex Date: Sun, 8 Mar 2026 08:53:48 +0800 Subject: [PATCH 1/3] std.os.linux: add LoongArch HWCAP bits See also arch/loongarch/include/uapi/asm/hwcap.h in Linux kernel. SC.Q was added in kernel v7.0. Change-Id: Ib4ddd451ab16d52b2578f8b97c9c3365286719cd Signed-off-by: xtex --- lib/std/os/linux/loongarch32.zig | 19 +++++++++++++++++++ lib/std/os/linux/loongarch64.zig | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/lib/std/os/linux/loongarch32.zig b/lib/std/os/linux/loongarch32.zig index c5d1589aa3df476dbb638ae7dce6bb28a3e3bd39..0be8dc5465eaf01142c974b3a0d51faef2659b49 100644 --- a/lib/std/os/linux/loongarch32.zig +++ b/lib/std/os/linux/loongarch32.zig @@ -161,3 +161,22 @@ pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; pub const CGT_VER = "LINUX_5.10"; }; + +pub const HWCAP = struct { + pub const CPUCFG = 1 << 0; + pub const LAM = 1 << 1; + pub const UAL = 1 << 2; + pub const FPU = 1 << 3; + pub const LSX = 1 << 4; + pub const LASX = 1 << 5; + pub const CRC32 = 1 << 6; + pub const COMPLEX = 1 << 7; + pub const CRYPTO = 1 << 8; + pub const LVZ = 1 << 9; + pub const LBT_X86 = 1 << 10; + pub const LBT_ARM = 1 << 11; + pub const LBT_MIPS = 1 << 12; + pub const PTW = 1 << 13; + pub const LSPW = 1 << 14; + pub const SCQ = 1 << 15; +}; diff --git a/lib/std/os/linux/loongarch64.zig b/lib/std/os/linux/loongarch64.zig index 283a4de13484c7489bca7a48d3714ae5136291f4..08d2c486ee027dc1f92e1a9c79099ae4f446471b 100644 --- a/lib/std/os/linux/loongarch64.zig +++ b/lib/std/os/linux/loongarch64.zig @@ -160,3 +160,22 @@ pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; pub const CGT_VER = "LINUX_5.10"; }; + +pub const HWCAP = struct { + pub const CPUCFG = 1 << 0; + pub const LAM = 1 << 1; + pub const UAL = 1 << 2; + pub const FPU = 1 << 3; + pub const LSX = 1 << 4; + pub const LASX = 1 << 5; + pub const CRC32 = 1 << 6; + pub const COMPLEX = 1 << 7; + pub const CRYPTO = 1 << 8; + pub const LVZ = 1 << 9; + pub const LBT_X86 = 1 << 10; + pub const LBT_ARM = 1 << 11; + pub const LBT_MIPS = 1 << 12; + pub const PTW = 1 << 13; + pub const LSPW = 1 << 14; + pub const SCQ = 1 << 15; +}; -- 2.54.0 From 8b220cd746384c43e8406b70e93f76afe7a6db48 Mon Sep 17 00:00:00 2001 From: xtex Date: Sun, 8 Mar 2026 09:40:23 +0800 Subject: [PATCH 2/3] std.zig.system.loongarch: take HWCAP into consideration We prefer information from HWCAP than CPUCFG and assume those features unavailable if HWCAP is not available. This is because many features require kernel support (e.g. context switching support). Follow-up: 37288e53ae4e ("std.zig.system.loongarch: implement individual cpu feature bit tests (#30915)") Change-Id: I0a610b2c4fc751f0f159e79e01bb9f6fb7588ccf Signed-off-by: xtex --- lib/std/zig/system/loongarch.zig | 34 +++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/lib/std/zig/system/loongarch.zig b/lib/std/zig/system/loongarch.zig index 7a2c62279131a70dafe52759fdb754b48d5e90fc..c5930340dea96e2aad563e82335030e0b38b61c6 100644 --- a/lib/std/zig/system/loongarch.zig +++ b/lib/std/zig/system/loongarch.zig @@ -31,21 +31,37 @@ pub fn detectNativeCpuAndFeatures( cpu.features.addFeatureSet(cpu.model.features); - const cfg1 = cpucfg(1); const cfg2 = cpucfg(2); const cfg3 = cpucfg(3); - setFeature(&cpu, .ual, bit(cfg1, 20)); + if (builtin.os.tag == .linux) { + const HWCAP = std.os.linux.HWCAP; + const hwcap_bits: usize = if (builtin.link_libc) + std.c.getauxval(std.elf.AT_HWCAP) + else + std.os.linux.getauxval(std.elf.AT_HWCAP); - const has_fpu = bit(cfg2, 0); - setFeature(&cpu, .f, has_fpu and bit(cfg2, 1)); - setFeature(&cpu, .d, has_fpu and bit(cfg2, 2)); + setFeature(&cpu, .ual, (hwcap_bits & HWCAP.UAL) != 0); - setFeature(&cpu, .lsx, bit(cfg2, 6)); - setFeature(&cpu, .lasx, bit(cfg2, 7)); - setFeature(&cpu, .lvz, bit(cfg2, 10)); + const has_fpu = (hwcap_bits & HWCAP.FPU) != 0; + setFeature(&cpu, .f, has_fpu and bit(cfg2, 1)); + setFeature(&cpu, .d, has_fpu and bit(cfg2, 2)); + setFeature(&cpu, .lsx, (hwcap_bits & HWCAP.LSX) != 0); + setFeature(&cpu, .lasx, (hwcap_bits & HWCAP.LASX) != 0); - setFeature(&cpu, .lbt, bit(cfg2, 18) and bit(cfg2, 19) and bit(cfg2, 20)); + setFeature(&cpu, .lvz, (hwcap_bits & HWCAP.LVZ) != 0); + setFeature(&cpu, .lbt, (hwcap_bits & HWCAP.LBT_X86) != 0 and (hwcap_bits & HWCAP.LBT_ARM) != 0 and (hwcap_bits & HWCAP.LBT_MIPS) != 0); + } else { + setFeature(&cpu, .ual, false); + + setFeature(&cpu, .f, false); + setFeature(&cpu, .d, false); + setFeature(&cpu, .lsx, false); + setFeature(&cpu, .lasx, false); + + setFeature(&cpu, .lvz, false); + setFeature(&cpu, .lbt, false); + } setFeature(&cpu, .frecipe, bit(cfg2, 25)); setFeature(&cpu, .div32, bit(cfg2, 26)); -- 2.54.0 From 8fe6d5a48e97ec1b3260c86832baa707271d0f8b Mon Sep 17 00:00:00 2001 From: xtex Date: Sat, 25 Apr 2026 21:49:21 +0800 Subject: [PATCH 3/3] std.os.linux: move HWCAP bits to linux.zig Change-Id: Ic06feeeec9d04b540cf4efc931df4f4b7e327c5f --- lib/std/os/linux.zig | 48 +++++++++++++++++++++++++++++++- lib/std/os/linux/arm.zig | 26 ----------------- lib/std/os/linux/loongarch32.zig | 19 ------------- lib/std/os/linux/loongarch64.zig | 19 ------------- 4 files changed, 47 insertions(+), 65 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 8e6ec0dec4bb2f60a8340835dc367ffae5f74eed..0df906340ef804685e6bca37df379b1fddb8ec4d 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -96,7 +96,6 @@ pub fn clone( } pub const ARCH = arch_bits.ARCH; -pub const HWCAP = arch_bits.HWCAP; pub const SC = arch_bits.SC; pub const VDSO = arch_bits.VDSO; pub const user_desc = arch_bits.user_desc; @@ -524,6 +523,53 @@ pub const O = switch (native_arch) { else => @compileError("missing std.os.linux.O constants for this architecture"), }; +pub const HWCAP = switch (native_arch) { + .arm, .armeb, .thumb, .thumbeb => struct { + pub const SWP = 1 << 0; + pub const HALF = 1 << 1; + pub const THUMB = 1 << 2; + pub const @"26BIT" = 1 << 3; + pub const FAST_MULT = 1 << 4; + pub const FPA = 1 << 5; + pub const VFP = 1 << 6; + pub const EDSP = 1 << 7; + pub const JAVA = 1 << 8; + pub const IWMMXT = 1 << 9; + pub const CRUNCH = 1 << 10; + pub const THUMBEE = 1 << 11; + pub const NEON = 1 << 12; + pub const VFPv3 = 1 << 13; + pub const VFPv3D16 = 1 << 14; + pub const TLS = 1 << 15; + pub const VFPv4 = 1 << 16; + pub const IDIVA = 1 << 17; + pub const IDIVT = 1 << 18; + pub const VFPD32 = 1 << 19; + pub const IDIV = IDIVA | IDIVT; + pub const LPAE = 1 << 20; + pub const EVTSTRM = 1 << 21; + }, + .loongarch32, .loongarch64 => struct { + pub const CPUCFG = 1 << 0; + pub const LAM = 1 << 1; + pub const UAL = 1 << 2; + pub const FPU = 1 << 3; + pub const LSX = 1 << 4; + pub const LASX = 1 << 5; + pub const CRC32 = 1 << 6; + pub const COMPLEX = 1 << 7; + pub const CRYPTO = 1 << 8; + pub const LVZ = 1 << 9; + pub const LBT_X86 = 1 << 10; + pub const LBT_ARM = 1 << 11; + pub const LBT_MIPS = 1 << 12; + pub const PTW = 1 << 13; + pub const LSPW = 1 << 14; + pub const SCQ = 1 << 15; + }, + else => struct {}, +}; + pub const RENAME = packed struct(u32) { /// Cannot be set together with `EXCHANGE`. NOREPLACE: bool = false, diff --git a/lib/std/os/linux/arm.zig b/lib/std/os/linux/arm.zig index 87e3b48b3726a3fd225ffd6745b72492597037c4..c40f2f4031393630d9b8d42213c3ddcf55673f6a 100644 --- a/lib/std/os/linux/arm.zig +++ b/lib/std/os/linux/arm.zig @@ -182,30 +182,4 @@ pub const VDSO = struct { pub const CGT_VER = "LINUX_2.6"; }; -pub const HWCAP = struct { - pub const SWP = 1 << 0; - pub const HALF = 1 << 1; - pub const THUMB = 1 << 2; - pub const @"26BIT" = 1 << 3; - pub const FAST_MULT = 1 << 4; - pub const FPA = 1 << 5; - pub const VFP = 1 << 6; - pub const EDSP = 1 << 7; - pub const JAVA = 1 << 8; - pub const IWMMXT = 1 << 9; - pub const CRUNCH = 1 << 10; - pub const THUMBEE = 1 << 11; - pub const NEON = 1 << 12; - pub const VFPv3 = 1 << 13; - pub const VFPv3D16 = 1 << 14; - pub const TLS = 1 << 15; - pub const VFPv4 = 1 << 16; - pub const IDIVA = 1 << 17; - pub const IDIVT = 1 << 18; - pub const VFPD32 = 1 << 19; - pub const IDIV = IDIVA | IDIVT; - pub const LPAE = 1 << 20; - pub const EVTSTRM = 1 << 21; -}; - pub const time_t = i32; diff --git a/lib/std/os/linux/loongarch32.zig b/lib/std/os/linux/loongarch32.zig index 0be8dc5465eaf01142c974b3a0d51faef2659b49..c5d1589aa3df476dbb638ae7dce6bb28a3e3bd39 100644 --- a/lib/std/os/linux/loongarch32.zig +++ b/lib/std/os/linux/loongarch32.zig @@ -161,22 +161,3 @@ pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; pub const CGT_VER = "LINUX_5.10"; }; - -pub const HWCAP = struct { - pub const CPUCFG = 1 << 0; - pub const LAM = 1 << 1; - pub const UAL = 1 << 2; - pub const FPU = 1 << 3; - pub const LSX = 1 << 4; - pub const LASX = 1 << 5; - pub const CRC32 = 1 << 6; - pub const COMPLEX = 1 << 7; - pub const CRYPTO = 1 << 8; - pub const LVZ = 1 << 9; - pub const LBT_X86 = 1 << 10; - pub const LBT_ARM = 1 << 11; - pub const LBT_MIPS = 1 << 12; - pub const PTW = 1 << 13; - pub const LSPW = 1 << 14; - pub const SCQ = 1 << 15; -}; diff --git a/lib/std/os/linux/loongarch64.zig b/lib/std/os/linux/loongarch64.zig index 08d2c486ee027dc1f92e1a9c79099ae4f446471b..283a4de13484c7489bca7a48d3714ae5136291f4 100644 --- a/lib/std/os/linux/loongarch64.zig +++ b/lib/std/os/linux/loongarch64.zig @@ -160,22 +160,3 @@ pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; pub const CGT_VER = "LINUX_5.10"; }; - -pub const HWCAP = struct { - pub const CPUCFG = 1 << 0; - pub const LAM = 1 << 1; - pub const UAL = 1 << 2; - pub const FPU = 1 << 3; - pub const LSX = 1 << 4; - pub const LASX = 1 << 5; - pub const CRC32 = 1 << 6; - pub const COMPLEX = 1 << 7; - pub const CRYPTO = 1 << 8; - pub const LVZ = 1 << 9; - pub const LBT_X86 = 1 << 10; - pub const LBT_ARM = 1 << 11; - pub const LBT_MIPS = 1 << 12; - pub const PTW = 1 << 13; - pub const LSPW = 1 << 14; - pub const SCQ = 1 << 15; -}; -- 2.54.0