diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 99a6a9bb1c9baa02544300ce86907af8299e3413..80d25ef865f6ac69fc58b711dccbed5d6cebe27a 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -3258,6 +3258,44 @@ pub fn sysinfo(info: *Sysinfo) usize { return syscall1(.sysinfo, @intFromPtr(info)); } +const VdsoSysRiscvHwprobe = *align(1) const fn ( + pairs: [*]riscv_hwprobe, + pair_count: usize, + cpusetsize: usize, + cpus: ?[*]cpu_set_t, + flags: u32, +) callconv(.c) usize; +var vdso_sys_riscv_hwprobe: ?VdsoSysRiscvHwprobe = &init_vdso_sys_riscv_hwprobe; + +fn init_vdso_sys_riscv_hwprobe( + pairs: [*]riscv_hwprobe, + pair_count: usize, + cpusetsize: usize, + cpus: ?[*]cpu_set_t, + flags: u32, +) callconv(.c) usize { + const ptr: ?VdsoSysRiscvHwprobe = @ptrFromInt(vdso.lookup(VDSO.HWPROBE_VER, VDSO.HWPROBE_SYM)); + @atomicStore(?VdsoSysRiscvHwprobe, &vdso_sys_riscv_hwprobe, ptr, .monotonic); + if (ptr) |f| return f(pairs, pair_count, cpusetsize, cpus, flags); + return @bitCast(-@as(isize, @backingInt(E.NOSYS))); +} + +pub fn sys_riscv_hwprobe( + pairs: [*]riscv_hwprobe, + pair_count: usize, + cpusetsize: usize, + cpus: ?[*]cpu_set_t, + flags: u32, +) usize { + if (VDSO != void) { + const ptr = @atomicLoad(?VdsoSysRiscvHwprobe, &vdso_sys_riscv_hwprobe, .unordered); + if (ptr) |f| { + if (f(pairs, pair_count, cpusetsize, cpus, flags) == 0) return 0; + } + } + return syscall5(.riscv_hwprobe, @intFromPtr(pairs), pair_count, cpusetsize, @intFromPtr(cpus), flags); +} + pub const E = switch (native_arch) { .mips, .mipsel, .mips64, .mips64el => enum(u16) { /// No error occurred. @@ -10920,3 +10958,127 @@ pub const cmsghdr = extern struct { level: i32, type: i32, }; + +pub const riscv_hwprobe = extern struct { + key: i64, + value: u64, +}; + +pub const RISCV_HWPROBE = struct { + pub const KEY = struct { + pub const MVENDORID = 0; + pub const MARCHID = 1; + pub const MIMPID = 2; + pub const BASE_BEHAVIOR = 3; + pub const IMA_EXT_0 = 4; + pub const CPUPERF_0 = 5; + pub const ZICBOZ_BLOCK_SIZE = 6; + pub const HIGHEST_VIRT_ADDRESS = 7; + pub const TIME_CSR_FREQ = 8; + pub const MISALIGNED_SCALAR_PERF = 9; + pub const MISALIGNED_VECTOR_PERF = 10; + pub const VENDOR_EXT_THEAD_0 = 11; + pub const ZICBOM_BLOCK_SIZE = 12; + pub const VENDOR_EXT_SIFIVE_0 = 13; + pub const VENDOR_EXT_MIPS_0 = 14; + pub const ZICBOP_BLOCK_SIZE = 15; + pub const IMA_EXT_1 = 16; + }; + + pub const FLAGS_WHICH_CPUS = 1 << 0; + + pub const BASE_BEHAVIOR_IMA = 1 << 0; + + pub const IMA_EXT_0 = struct { + pub const IMA_FD = 1 << 0; + pub const IMA_C = 1 << 1; + pub const IMA_V = 1 << 2; + pub const EXT_ZBA = 1 << 3; + pub const EXT_ZBB = 1 << 4; + pub const EXT_ZBS = 1 << 5; + pub const EXT_ZICBOZ = 1 << 6; + pub const EXT_ZBC = 1 << 7; + pub const EXT_ZBKB = 1 << 8; + pub const EXT_ZBKC = 1 << 9; + pub const EXT_ZBKX = 1 << 10; + pub const EXT_ZKND = 1 << 11; + pub const EXT_ZKNE = 1 << 12; + pub const EXT_ZKNH = 1 << 13; + pub const EXT_ZKSED = 1 << 14; + pub const EXT_ZKSH = 1 << 15; + pub const EXT_ZKT = 1 << 16; + pub const EXT_ZVBB = 1 << 17; + pub const EXT_ZVBC = 1 << 18; + pub const EXT_ZVKB = 1 << 19; + pub const EXT_ZVKG = 1 << 20; + pub const EXT_ZVKNED = 1 << 21; + pub const EXT_ZVKNHA = 1 << 22; + pub const EXT_ZVKNHB = 1 << 23; + pub const EXT_ZVKSED = 1 << 24; + pub const EXT_ZVKSH = 1 << 25; + pub const EXT_ZVKT = 1 << 26; + pub const EXT_ZFH = 1 << 27; + pub const EXT_ZFHMIN = 1 << 28; + pub const EXT_ZIHINTNTL = 1 << 29; + pub const EXT_ZVFH = 1 << 30; + pub const EXT_ZVFHMIN = 1 << 31; + pub const EXT_ZFA = 1 << 32; + pub const EXT_ZTSO = 1 << 33; + pub const EXT_ZACAS = 1 << 34; + pub const EXT_ZICOND = 1 << 35; + pub const EXT_ZIHINTPAUSE = 1 << 36; + pub const EXT_ZVE32X = 1 << 37; + pub const EXT_ZVE32F = 1 << 38; + pub const EXT_ZVE64X = 1 << 39; + pub const EXT_ZVE64F = 1 << 40; + pub const EXT_ZVE64D = 1 << 41; + pub const EXT_ZIMOP = 1 << 42; + pub const EXT_ZCA = 1 << 43; + pub const EXT_ZCB = 1 << 44; + pub const EXT_ZCD = 1 << 45; + pub const EXT_ZCF = 1 << 46; + pub const EXT_ZCMOP = 1 << 47; + pub const EXT_ZAWRS = 1 << 48; + pub const EXT_SUPM = 1 << 49; + pub const EXT_ZICNTR = 1 << 50; + pub const EXT_ZIHPM = 1 << 51; + pub const EXT_ZFBFMIN = 1 << 52; + pub const EXT_ZVFBFMIN = 1 << 53; + pub const EXT_ZVFBFWMA = 1 << 54; + pub const EXT_ZICBOM = 1 << 55; + pub const EXT_ZAAMO = 1 << 56; + pub const EXT_ZALRSC = 1 << 57; + pub const EXT_ZABHA = 1 << 58; + pub const EXT_ZALASR = 1 << 59; + pub const EXT_ZICBOP = 1 << 60; + pub const EXT_ZILSD = 1 << 61; + pub const EXT_ZCLSD = 1 << 62; + pub const EXT_ZICFILP = 1 << 63; + }; + + pub const IMA_EXT_1_EXT_ZICFISS = 1 << 0; + + pub const MISALIGNED_SCALAR = struct { + pub const UNKNOWN = 0; + pub const EMULATED = 1; + pub const SLOW = 2; + pub const FAST = 3; + pub const UNSUPPORTED = 4; + }; + + pub const MISALIGNED_VECTOR = struct { + pub const UNKNOWN = 0; + pub const SLOW = 2; + pub const FAST = 3; + pub const UNSUPPORTED = 4; + }; + + pub const MIPS_VENDOR_EXT_XMIPSEXECTL = 1 << 0; + + pub const SIFIVE_VENDOR_EXT = struct { + pub const XSFVQMACCDOD = 1 << 0; + pub const XSFVQMACCQOQ = 1 << 1; + pub const XSFVFNRCLIPXFQF = 1 << 2; + pub const XSFVFWMACCQQQ = 1 << 3; + }; +}; diff --git a/lib/std/os/linux/riscv32.zig b/lib/std/os/linux/riscv32.zig index 609e59151da3012b9de1061979767e3f94b0d3e6..278b1ff27b9f98a16f6343ae5410c32d4182042c 100644 --- a/lib/std/os/linux/riscv32.zig +++ b/lib/std/os/linux/riscv32.zig @@ -159,4 +159,7 @@ pub const time_t = i64; pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; pub const CGT_VER = "LINUX_4.15"; + + pub const HWPROBE_SYM = "__vdso_riscv_hwprobe"; + pub const HWPROBE_VER = "LINUX_4.15"; }; diff --git a/lib/std/os/linux/riscv64.zig b/lib/std/os/linux/riscv64.zig index 3d3ce7dba36dd759c5124efaebcfd6c74c588bcb..75024ec2a775c811f64d489d76918c20728dd9f4 100644 --- a/lib/std/os/linux/riscv64.zig +++ b/lib/std/os/linux/riscv64.zig @@ -159,4 +159,7 @@ pub const time_t = i64; pub const VDSO = struct { pub const CGT_SYM = "__vdso_clock_gettime"; pub const CGT_VER = "LINUX_4.15"; + + pub const HWPROBE_SYM = "__vdso_riscv_hwprobe"; + pub const HWPROBE_VER = "LINUX_4.15"; }; diff --git a/lib/std/zig/system/linux.zig b/lib/std/zig/system/linux.zig index 82f13bc7a411a65b7ad0ae6536b94824257d9038..fa80dc6c382be4ac3004612dec9ab6ee130f5101 100644 --- a/lib/std/zig/system/linux.zig +++ b/lib/std/zig/system/linux.zig @@ -447,6 +447,142 @@ inline fn getAArch64CpuFeature(comptime feat_reg: []const u8) u64 { ); } +const riscv = struct { + const linux = std.os.linux; + const RISCV_HWPROBE = linux.RISCV_HWPROBE; + + fn setFeature(cpu: *Target.Cpu, feature: Target.riscv.Feature, enabled: bool) void { + const idx = @as(Target.Cpu.Feature.Set.Index, @backingInt(feature)); + + if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx); + } + + inline fn set(value: u64, mask: u64) bool { + return (value & mask) == mask; + } + + pub fn detectCpuFeatures(cpu: *Target.Cpu) void { + var probes = [_]linux.riscv_hwprobe{ + .{ .key = RISCV_HWPROBE.KEY.BASE_BEHAVIOR, .value = 0 }, + .{ .key = RISCV_HWPROBE.KEY.IMA_EXT_0, .value = 0 }, + .{ .key = RISCV_HWPROBE.KEY.MISALIGNED_SCALAR_PERF, .value = 0 }, + .{ .key = RISCV_HWPROBE.KEY.MISALIGNED_VECTOR_PERF, .value = 0 }, + .{ .key = RISCV_HWPROBE.KEY.VENDOR_EXT_MIPS_0, .value = 0 }, + .{ .key = RISCV_HWPROBE.KEY.VENDOR_EXT_SIFIVE_0, .value = 0 }, + .{ .key = RISCV_HWPROBE.KEY.IMA_EXT_1, .value = 0 }, + }; + + const rc = linux.sys_riscv_hwprobe(&probes, probes.len, 0, null, 0); + if (linux.errno(rc) == .NOSYS) + return; + + var ima_support = false; + for (probes) |probe| { + const value = probe.value; + + switch (probe.key) { + -1 => continue, // The running kernel doesn't know this key. + RISCV_HWPROBE.KEY.BASE_BEHAVIOR => { + ima_support = set(value, RISCV_HWPROBE.BASE_BEHAVIOR_IMA); + setFeature(cpu, Target.riscv.Feature.i, ima_support); + setFeature(cpu, Target.riscv.Feature.m, ima_support); + setFeature(cpu, Target.riscv.Feature.a, ima_support); + }, + RISCV_HWPROBE.KEY.IMA_EXT_0 => { + // https://bugzilla.kernel.org/show_bug.cgi?id=221874 + const fd_support = set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_FD); + setFeature(cpu, .f, ima_support and fd_support); + setFeature(cpu, .d, ima_support and fd_support); + setFeature(cpu, .c, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_C)); + setFeature(cpu, .v, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_V)); + setFeature(cpu, .zba, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBA)); + setFeature(cpu, .zbb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBB)); + setFeature(cpu, .zbs, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBS)); + setFeature(cpu, .zicboz, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOZ)); + setFeature(cpu, .zbc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBC)); + setFeature(cpu, .zbkb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKB)); + setFeature(cpu, .zbkc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKC)); + setFeature(cpu, .zbkx, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKX)); + setFeature(cpu, .zknd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKND)); + setFeature(cpu, .zkne, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKNE)); + setFeature(cpu, .zknh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKNH)); + setFeature(cpu, .zksed, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKSED)); + setFeature(cpu, .zksh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKSH)); + setFeature(cpu, .zkt, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKT)); + setFeature(cpu, .zvbb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVBB)); + setFeature(cpu, .zvbc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVBC)); + setFeature(cpu, .zvkb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKB)); + setFeature(cpu, .zvkg, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKG)); + setFeature(cpu, .zvkned, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNED)); + setFeature(cpu, .zvknha, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNHA)); + setFeature(cpu, .zvknhb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNHB)); + setFeature(cpu, .zvksed, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKSED)); + setFeature(cpu, .zvksh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKSH)); + setFeature(cpu, .zvkt, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKT)); + setFeature(cpu, .zfh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFH)); + setFeature(cpu, .zfhmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFHMIN)); + setFeature(cpu, .zihintntl, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHINTNTL)); + setFeature(cpu, .zvfh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFH)); + setFeature(cpu, .zvfhmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFHMIN)); + setFeature(cpu, .zfa, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFA)); + setFeature(cpu, .ztso, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZTSO)); + setFeature(cpu, .zacas, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZACAS)); + setFeature(cpu, .zicntr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICNTR)); + setFeature(cpu, .zicond, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICOND)); + setFeature(cpu, .zihintpause, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHINTPAUSE)); + setFeature(cpu, .zihpm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHPM)); + setFeature(cpu, .zve32x, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE32X)); + setFeature(cpu, .zve32f, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE32F)); + setFeature(cpu, .zve64x, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64X)); + setFeature(cpu, .zve64f, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64F)); + setFeature(cpu, .zve64d, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64D)); + setFeature(cpu, .zimop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIMOP)); + setFeature(cpu, .zca, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCA)); + setFeature(cpu, .zcb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCB)); + setFeature(cpu, .zcd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCD)); + setFeature(cpu, .zcf, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCF)); + setFeature(cpu, .zcmop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCMOP)); + setFeature(cpu, .zawrs, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZAWRS)); + setFeature(cpu, .supm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_SUPM)); + setFeature(cpu, .zicntr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICNTR)); + setFeature(cpu, .zihpm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHPM)); + setFeature(cpu, .zfbfmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFBFMIN)); + setFeature(cpu, .zvfbfmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFBFMIN)); + setFeature(cpu, .zvfbfwma, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFBFWMA)); + setFeature(cpu, .zicbom, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOM)); + setFeature(cpu, .zaamo, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZAAMO)); + setFeature(cpu, .zalrsc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZALRSC)); + setFeature(cpu, .zabha, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZABHA)); + setFeature(cpu, .zalasr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZALASR)); + setFeature(cpu, .zicbop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOP)); + setFeature(cpu, .zilsd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZILSD)); + setFeature(cpu, .zclsd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCLSD)); + setFeature(cpu, .experimental_zicfilp, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICFILP)); + }, + RISCV_HWPROBE.KEY.MISALIGNED_SCALAR_PERF => { + setFeature(cpu, .unaligned_scalar_mem, value == RISCV_HWPROBE.MISALIGNED_SCALAR.FAST); + }, + RISCV_HWPROBE.KEY.MISALIGNED_VECTOR_PERF => { + setFeature(cpu, .unaligned_vector_mem, value == RISCV_HWPROBE.MISALIGNED_VECTOR.FAST); + }, + RISCV_HWPROBE.KEY.VENDOR_EXT_MIPS_0 => { + setFeature(cpu, .xmipsexectl, ima_support and set(value, RISCV_HWPROBE.MIPS_VENDOR_EXT_XMIPSEXECTL)); + }, + RISCV_HWPROBE.KEY.VENDOR_EXT_SIFIVE_0 => { + setFeature(cpu, .xsfvqmaccdod, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVQMACCDOD)); + setFeature(cpu, .xsfvqmaccqoq, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVQMACCQOQ)); + setFeature(cpu, .xsfvfnrclipxfqf, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVFNRCLIPXFQF)); + setFeature(cpu, .xsfvfwmaccqqq, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVFWMACCQQQ)); + }, + RISCV_HWPROBE.KEY.IMA_EXT_1 => { + setFeature(cpu, .experimental_zicfiss, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_1_EXT_ZICFISS)); + }, + else => unreachable, + } + } + } +}; + pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu { var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch |err| switch (err) { else => return null, @@ -457,11 +593,8 @@ pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu { var file_reader = file.reader(io, &buffer); const current_arch = builtin.cpu.arch; - switch (current_arch) { - .arm, .armeb, .thumb, .thumbeb => { - return ArmCpuinfoParser.parse(current_arch, &file_reader.interface) catch null; - }, - .aarch64, .aarch64_be => { + return switch (current_arch) { + .aarch64, .aarch64_be => b: { const registers = [12]u64{ getAArch64CpuFeature("MIDR_EL1"), getAArch64CpuFeature("ID_AA64PFR0_EL1"), @@ -477,23 +610,27 @@ pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu { getAArch64CpuFeature("ID_AA64MMFR2_EL1"), }; - const core = @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers); - return core; + break :b @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers); }, - .sparc, .sparc64 => { - return SparcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null; - }, - .powerpc, .powerpcle, .powerpc64, .powerpc64le => { - return PowerpcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null; - }, - .riscv64, .riscv32 => { - return RiscvCpuinfoParser.parse(current_arch, &file_reader.interface) catch null; - }, - .s390x => { - return S390xCpuinfoParser.parse(current_arch, &file_reader.interface) catch null; - }, - else => {}, - } + .arm, .armeb, .thumb, .thumbeb => ArmCpuinfoParser.parse(current_arch, &file_reader.interface) catch null, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => PowerpcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null, + .riscv64, .riscv32 => b: { + var cpu = (RiscvCpuinfoParser.parse(current_arch, &file_reader.interface) catch null) orelse cpu: { + const model = Target.Cpu.Model.generic(current_arch); + break :cpu Target.Cpu{ + .arch = current_arch, + .model = model, + .features = model.features, + }; + }; + + riscv.detectCpuFeatures(&cpu); + cpu.features.populateDependencies(cpu.arch.allFeaturesList()); - return null; + break :b cpu; + }, + .s390x => S390xCpuinfoParser.parse(current_arch, &file_reader.interface) catch null, + .sparc, .sparc64 => SparcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null, + else => null, + }; }