authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-07 12:16:34+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-07 14:28:40+02:00
log201a2142ae3c77a31c9cc274c13c5d24f4a31223
treeaa5a6f2fea85a970f58501021a213f6d7c70319e
parent99650e773abf536d6b44f33e2fa4c5e6968592f1
signature Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.zig.system.linux: add mips CPU model detection

closes https://codeberg.org/ziglang/zig/issues/36778

1 files changed, 109 insertions(+), 0 deletions(-)

lib/std/zig/system/linux.zig+109
...@@ -347,6 +347,114 @@ const m68k = struct {...@@ -347,6 +347,114 @@ const m68k = struct {
347 }347 }
348};348};
349349
350const mips = struct {
351 const cpuinfo = struct {
352 const Impl = struct {
353 model: ?*const Target.Cpu.Model = null,
354
355 const cpu_names = .{
356 .{ "Cavium Octeon III", &Target.mips.cpu.@"octeon+" },
357 .{ "Cavium Octeon II", &Target.mips.cpu.@"octeon+" },
358 .{ "Cavium Octeon+", &Target.mips.cpu.@"octeon+" },
359 .{ "Cavium Octeon", &Target.mips.cpu.octeon },
360 .{ "MIPS I6400", &Target.mips.cpu.i6400 },
361 .{ "MIPS I6500", &Target.mips.cpu.i6500 },
362 .{ "MIPS P5600", &Target.mips.cpu.p5600 },
363 .{ "R3000A", &Target.mips.cpu.r3000a },
364 };
365
366 const isa_names = .{
367 .{ "mips64r6", &Target.mips.cpu.mips64r6 },
368 .{ "mips64r5", &Target.mips.cpu.mips64r5 },
369 .{ "mips64r2", &Target.mips.cpu.mips64r2 },
370 .{ "mips64r1", &Target.mips.cpu.mips64 },
371 .{ "mips32r6", &Target.mips.cpu.mips32r6 },
372 .{ "mips32r5", &Target.mips.cpu.mips32r5 },
373 .{ "mips32r2", &Target.mips.cpu.mips32r2 },
374 .{ "mips32r1", &Target.mips.cpu.mips32 },
375 .{ "mips5", &Target.mips.cpu.mips5 },
376 .{ "mips4", &Target.mips.cpu.mips4 },
377 .{ "mips3", &Target.mips.cpu.mips3 },
378 .{ "mips2", &Target.mips.cpu.mips2 },
379 .{ "mips1", &Target.mips.cpu.mips1 },
380 };
381
382 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
383 // The `cpu model` line always comes before `isa`, which is perfect for us since we
384 // want the explicit model to take precedence over the generic ISA identifier.
385 if (mem.eql(u8, key, "cpu model")) {
386 inline for (cpu_names) |pair| {
387 if (mem.find(u8, value, pair[0]) != null) {
388 self.model = pair[1];
389 return false;
390 }
391 }
392 } else if (mem.eql(u8, key, "isa")) {
393 inline for (isa_names) |pair| {
394 if (mem.find(u8, value, pair[0]) != null) {
395 self.model = pair[1];
396 break;
397 }
398 }
399
400 // If we haven't found anything useful by here, we we may as well stop.
401 return false;
402 }
403
404 return true;
405 }
406
407 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
408 const model = self.model orelse return null;
409 return .{
410 .arch = arch,
411 .model = model,
412 .features = model.features,
413 };
414 }
415 };
416
417 const Parser = CpuinfoParser(Impl);
418 };
419
420 test cpuinfo {
421 try testParser(cpuinfo.Parser, .mips64, &Target.mips.cpu.@"octeon+",
422 \\system type : UBNT_E300
423 \\machine : Unknown
424 \\processor : 0
425 \\cpu model : Cavium Octeon III V0.2 FPU V0.0
426 \\BogoMIPS : 2000.00
427 \\wait instruction : yes
428 \\microsecond timers : yes
429 \\tlb_entries : 256
430 \\extra interrupt vector : yes
431 \\hardware watchpoint : yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
432 \\isa : mips1 mips2 mips3 mips4 mips5 mips64r2
433 \\ASEs implemented : vz
434 \\shadow register sets : 1
435 \\kscratch registers : 4
436 \\package : 0
437 \\core : 0
438 \\VCED exceptions : not available
439 \\VCEI exceptions : not available
440 );
441 }
442
443 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
444 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
445 defer file.close(io);
446
447 var buffer: [4096]u8 = undefined;
448 var file_reader = file.reader(io, &buffer);
449
450 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
451
452 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
453
454 return cpu;
455 }
456};
457
350const powerpc = struct {458const powerpc = struct {
351 const cpuinfo = struct {459 const cpuinfo = struct {
352 const Impl = struct {460 const Impl = struct {
...@@ -874,6 +982,7 @@ pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu {...@@ -874,6 +982,7 @@ pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu {
874 .arm, .armeb, .thumb, .thumbeb => arm.detectNativeCpu(io, current_arch),982 .arm, .armeb, .thumb, .thumbeb => arm.detectNativeCpu(io, current_arch),
875 .csky => csky.detectNativeCpu(io, current_arch),983 .csky => csky.detectNativeCpu(io, current_arch),
876 .m68k => m68k.detectNativeCpu(io, current_arch),984 .m68k => m68k.detectNativeCpu(io, current_arch),
985 .mips, .mipsel, .mips64, .mips64el => mips.detectNativeCpu(io, current_arch),
877 .powerpc, .powerpcle, .powerpc64, .powerpc64le => powerpc.detectNativeCpu(io, current_arch),986 .powerpc, .powerpcle, .powerpc64, .powerpc64le => powerpc.detectNativeCpu(io, current_arch),
878 .riscv64, .riscv32 => riscv.detectNativeCpuAndFeatures(io, current_arch),987 .riscv64, .riscv32 => riscv.detectNativeCpuAndFeatures(io, current_arch),
879 .s390x => s390x.detectNativeCpu(io, current_arch),988 .s390x => s390x.detectNativeCpu(io, current_arch),