srctree

Liviu Dudau parent 1fb23813 a0de0776
std.zig.system.linux: Use arm.zig detection for AArch64 CPU features

When building zig natively from source on an RK3588 SoC board, thegenerated stage3 compiler will use unsupported 'sha256h.4s' instructionsdue to mis-identified CPU features. This happens when trying tocompile a new project generated with "zig init"

$ ~/devel/zig/build/stage3/bin/zig buildthread 919 panic: Illegal instruction at address 0x1fdc0c4/home/dliviu/devel/zig/lib/std/crypto/sha2.zig:223:29: 0x1fdc0c4 in round (zig) asm volatile ( ^/home/dliviu/devel/zig/lib/std/crypto/sha2.zig:168:20: 0x1fdca87 in final (zig) d.round(&d.buf); ^/home/dliviu/devel/zig/lib/std/crypto/sha2.zig:180:20: 0x1c8bb33 in finalResult (zig) d.final(&result); ^/mnt/home/dliviu/devel/zig/src/Package/Fetch.zig:754:49: 0x1a3a8eb in relativePathDigest (zig) return Manifest.hexDigest(hasher.finalResult()); ^/mnt/home/dliviu/devel/zig/src/main.zig:5128:53: 0x1a37413 in cmdBuild (zig) Package.Fetch.relativePathDigest(build_mod.root, global_cache_directory), ^???:?:?: 0xff09ffffffffffff in ??? (???)Unwind information for ???:0xff09ffffffffffff was not available, trace may be incomplete

???:?:?: 0x3f7f137 in ??? (???)Aborted (core dumped)

system/linux.zig parses "/proc/cpuinfo" to determine the CPU features, but itseems to generate the wrong set of features from:

$ cat /proc/cpuinfoprocessor : 0BogoMIPS : 48.00Features : fp asimd evtstrm crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddpCPU implementer : 0x41CPU architecture: 8CPU variant : 0x2CPU part : 0xd05CPU revision : 0.....processor : 4BogoMIPS : 48.00Features : fp asimd evtstrm crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddpCPU implementer : 0x41CPU architecture: 8CPU variant : 0x4CPU part : 0xd0bCPU revision : 0.....

To fix this, use the Linux kernel way of reading the feature registers as documentedhere: https://www.kernel.org/doc/html/latest/arch/arm64/cpu-feature-registers.html

arm.zig already has the code to parse the feature register values, we just need tocollect them in an array and pass them for identification.

Signed-off-by: Liviu Dudau <liviu@dudau.co.uk>

inlinesplit
lib/std/zig/system/linux.zig added: 27, removed: 2, total 25
@@ -374,6 +374,12 @@ fn CpuinfoParser(comptime impl: anytype) type {
};
}
 
inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 {
return asm ("mrs %[ret], " ++ feat_reg
: [ret] "=r" (-> u64),
);
}
 
pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
var f = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) {
else => return null,
@@ -382,9 +388,28 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
 
const current_arch = builtin.cpu.arch;
switch (current_arch) {
.arm, .armeb, .thumb, .thumbeb, .aarch64, .aarch64_be, .aarch64_32 => {
.arm, .armeb, .thumb, .thumbeb => {
return ArmCpuinfoParser.parse(current_arch, f.reader()) catch null;
},
.aarch64, .aarch64_be, .aarch64_32 => {
const registers = [12]u64{
getAArch64CpuFeature("MIDR_EL1"),
getAArch64CpuFeature("ID_AA64PFR0_EL1"),
getAArch64CpuFeature("ID_AA64PFR1_EL1"),
getAArch64CpuFeature("ID_AA64DFR0_EL1"),
getAArch64CpuFeature("ID_AA64DFR1_EL1"),
getAArch64CpuFeature("ID_AA64AFR0_EL1"),
getAArch64CpuFeature("ID_AA64AFR1_EL1"),
getAArch64CpuFeature("ID_AA64ISAR0_EL1"),
getAArch64CpuFeature("ID_AA64ISAR1_EL1"),
getAArch64CpuFeature("ID_AA64MMFR0_EL1"),
getAArch64CpuFeature("ID_AA64MMFR1_EL1"),
getAArch64CpuFeature("ID_AA64MMFR2_EL1"),
};
 
const core = @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers);
return core;
},
.sparc64 => {
return SparcCpuinfoParser.parse(current_arch, f.reader()) catch null;
},