authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-07 22:05:26+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-07 22:05:26+02:00
log5e36170b5ff1cb7710aa9b1c5540b7d11aa62537
tree3c29995346299d3fddfc0942cb6089e296d81f43
parent1b8f1a852821c125a91b0859a95d5eb05b23461e
parentf4c38a3686f190ec2b9c58cfeea1636d19e5c896

Merge pull request '`std.zig.system`: yet more CPU detection enhancements' (#36781) from alexrp/zig:yet-more-cpu-detection into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36781

12 files changed, 1497 insertions(+), 584 deletions(-)

lib/std/c.zig+128-2
......@@ -10533,8 +10533,134 @@ pub const sendfile = switch (native_os) {
1053310533 .linux => private.sendfile,
1053410534 else => {},
1053510535};
10536/// See std.elf for constants for this
10537pub extern "c" fn getauxval(__type: c_ulong) c_ulong;
10536
10537pub extern "c" fn getauxval(type: c_ulong) c_ulong;
10538pub extern "c" fn elf_aux_info(aux: c_int, buf: *anyopaque, buflen: c_int) c_int;
10539
10540pub const HWCAP = switch (native_os) {
10541 .freebsd => switch (native_arch) {
10542 // FreeBSD deliberately matches the Linux ABI for AT_HWCAP...
10543 else => std.os.linux.HWCAP,
10544 // ... but because Linux went the SYS_riscv_hwprobe route, FreeBSD
10545 // defines more bits than Linux does:
10546 .riscv64 => struct {
10547 pub const ISA_A = 1 << 0;
10548 pub const ISA_B = 1 << 1;
10549 pub const ISA_C = 1 << 2;
10550 pub const ISA_D = 1 << 3;
10551 pub const ISA_F = 1 << 5;
10552 pub const ISA_H = 1 << 7;
10553 pub const ISA_I = 1 << 8;
10554 pub const ISA_M = 1 << 12;
10555 pub const ISA_V = 1 << 21;
10556 },
10557 },
10558 .illumos => switch (native_arch) {
10559 .x86, .x86_64 => struct {
10560 pub const FPU = 1 << 0;
10561 pub const TSC = 1 << 1;
10562 pub const CX8 = 1 << 2;
10563 pub const SEP = 1 << 3;
10564 pub const AMD_SYSC = 1 << 4;
10565 pub const CMOV = 1 << 5;
10566 pub const MMX = 1 << 6;
10567 pub const AMD_MMX = 1 << 7;
10568 pub const AMD_3DNow = 1 << 8;
10569 pub const AMD_3DNowx = 1 << 9;
10570 pub const FXSR = 1 << 10;
10571 pub const SSE = 1 << 11;
10572 pub const SSE2 = 1 << 12;
10573 pub const PAUSE = 1 << 13;
10574 pub const SSE3 = 1 << 14;
10575 pub const MON = 1 << 15;
10576 pub const CX16 = 1 << 16;
10577 pub const AHF = 1 << 17;
10578 pub const TSCP = 1 << 18;
10579 pub const AMD_SSE4A = 1 << 19;
10580 pub const POPCNT = 1 << 20;
10581 pub const AMD_LZCNT = 1 << 21;
10582 pub const SSSE3 = 1 << 22;
10583 pub const SSE4_1 = 1 << 23;
10584 pub const SSE4_2 = 1 << 24;
10585 pub const MOVBE = 1 << 25;
10586 pub const AES = 1 << 26;
10587 pub const PCLMULQDQ = 1 << 27;
10588 pub const XSAVE = 1 << 28;
10589 pub const AVX = 1 << 29;
10590 pub const VMX = 1 << 30;
10591 pub const AMD_SVM = 1 << 31;
10592
10593 pub const @"2" = struct {
10594 pub const F16C = 1 << 0;
10595 pub const RDRAND = 1 << 1;
10596 pub const BMI1 = 1 << 2;
10597 pub const BMI2 = 1 << 3;
10598 pub const FMA = 1 << 4;
10599 pub const AVX2 = 1 << 5;
10600 pub const ADX = 1 << 6;
10601 pub const RDSEED = 1 << 7;
10602 pub const AVX512F = 1 << 8;
10603 pub const AVX512DQ = 1 << 9;
10604 pub const AVX512IFMA = 1 << 10;
10605 pub const AVX512PF = 1 << 11;
10606 pub const AVX512ER = 1 << 12;
10607 pub const AVX512CD = 1 << 13;
10608 pub const AVX512BW = 1 << 14;
10609 pub const AVX512VL = 1 << 15;
10610 pub const AVX512VBMI = 1 << 16;
10611 pub const AVX512VPOPCDQ = 1 << 17;
10612 pub const AVX512_4NNIW = 1 << 18;
10613 pub const AVX512_4FMAPS = 1 << 19;
10614 pub const SHA = 1 << 20;
10615 pub const FSGSBASE = 1 << 21;
10616 pub const CLFLUSHOPT = 1 << 22;
10617 pub const CLWB = 1 << 23;
10618 pub const MONITORX = 1 << 24;
10619 pub const CLZERO = 1 << 25;
10620 pub const AVX512_VNNI = 1 << 26;
10621 pub const VPCLMULQDQ = 1 << 27;
10622 pub const VAES = 1 << 28;
10623 };
10624 },
10625 else => struct {},
10626 },
10627 .linux => std.os.linux.HWCAP,
10628 .openbsd => switch (native_arch) {
10629 // Same deal as for FreeBSD.
10630 else => std.os.linux.HWCAP,
10631 .riscv64 => struct {
10632 pub const ISA_A = 1 << 0;
10633 pub const ISA_B = 1 << 1;
10634 pub const ISA_C = 1 << 2;
10635 pub const ISA_D = 1 << 3;
10636 pub const ISA_F = 1 << 5;
10637 pub const ISA_H = 1 << 7;
10638 pub const ISA_I = 1 << 8;
10639 pub const ISA_M = 1 << 12;
10640 pub const ISA_V = 1 << 21;
10641
10642 pub const @"2" = struct {
10643 pub const ISA_ZBA = 1 << 0;
10644 pub const ISA_ZBB = 1 << 1;
10645 pub const ISA_ZBC = 1 << 2;
10646 pub const ISA_ZBS = 1 << 3;
10647 pub const ISA_ZFH = 1 << 4;
10648 pub const ISA_ZKT = 1 << 5;
10649 pub const ISA_ZVBB = 1 << 6;
10650 pub const ISA_ZVBC = 1 << 7;
10651 pub const ISA_ZVFH = 1 << 8;
10652 pub const ISA_ZVKG = 1 << 9;
10653 pub const ISA_ZVKNED = 1 << 10;
10654 pub const ISA_ZVKNHA = 1 << 11;
10655 pub const ISA_ZVKNHB = 1 << 12;
10656 pub const ISA_ZVKSED = 1 << 13;
10657 pub const ISA_ZVKSH = 1 << 14;
10658 pub const ISA_ZVKT = 1 << 15;
10659 };
10660 },
10661 },
10662 else => struct {},
10663};
1053810664
1053910665pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*anyopaque) c_int;
1054010666
lib/std/elf.zig+227-45
......@@ -1,56 +1,238 @@
11//! Executable and Linkable Format.
22
3const builtin = @import("builtin");
34const std = @import("std.zig");
45const Io = std.Io;
56const math = std.math;
67const mem = std.mem;
78const assert = std.debug.assert;
89const Endian = std.builtin.Endian;
9const native_endian = @import("builtin").target.cpu.arch.endian();
10
11pub const AT_NULL = 0;
12pub const AT_IGNORE = 1;
13pub const AT_EXECFD = 2;
14pub const AT_PHDR = 3;
15pub const AT_PHENT = 4;
16pub const AT_PHNUM = 5;
17pub const AT_PAGESZ = 6;
18pub const AT_BASE = 7;
19pub const AT_FLAGS = 8;
20pub const AT_ENTRY = 9;
21pub const AT_NOTELF = 10;
22pub const AT_UID = 11;
23pub const AT_EUID = 12;
24pub const AT_GID = 13;
25pub const AT_EGID = 14;
26pub const AT_CLKTCK = 17;
27pub const AT_PLATFORM = 15;
28pub const AT_HWCAP = 16;
29pub const AT_FPUCW = 18;
30pub const AT_DCACHEBSIZE = 19;
31pub const AT_ICACHEBSIZE = 20;
32pub const AT_UCACHEBSIZE = 21;
33pub const AT_IGNOREPPC = 22;
34pub const AT_SECURE = 23;
35pub const AT_BASE_PLATFORM = 24;
36pub const AT_RANDOM = 25;
37pub const AT_HWCAP2 = 26;
38pub const AT_EXECFN = 31;
39pub const AT_SYSINFO = 32;
40pub const AT_SYSINFO_EHDR = 33;
41pub const AT_L1I_CACHESHAPE = 34;
42pub const AT_L1D_CACHESHAPE = 35;
43pub const AT_L2_CACHESHAPE = 36;
44pub const AT_L3_CACHESHAPE = 37;
45pub const AT_L1I_CACHESIZE = 40;
46pub const AT_L1I_CACHEGEOMETRY = 41;
47pub const AT_L1D_CACHESIZE = 42;
48pub const AT_L1D_CACHEGEOMETRY = 43;
49pub const AT_L2_CACHESIZE = 44;
50pub const AT_L2_CACHEGEOMETRY = 45;
51pub const AT_L3_CACHESIZE = 46;
52pub const AT_L3_CACHEGEOMETRY = 47;
53pub const AT_MINSIGSTKSZ = 51;
10
11const native_endian = builtin.target.cpu.arch.endian();
12const native_os = builtin.target.os.tag;
13
14pub const AT = switch (native_os) {
15 .dragonfly => struct {
16 pub const NULL = 0;
17 pub const IGNORE = 1;
18 pub const EXECFD = 2;
19 pub const PHDR = 3;
20 pub const PHENT = 4;
21 pub const PHNUM = 5;
22 pub const PAGESZ = 6;
23 pub const BASE = 7;
24 pub const FLAGS = 8;
25 pub const ENTRY = 9;
26 pub const NOTELF = 10;
27 pub const UID = 11;
28 pub const EUID = 12;
29 pub const GID = 13;
30 pub const EGID = 14;
31 pub const EXECPATH = 15;
32 pub const CANARY = 16;
33 pub const CANARYLEN = 17;
34 pub const OSRELDATE = 18;
35 pub const NCPUS = 19;
36 pub const PAGESIZES = 20;
37 pub const PAGESIZESLEN = 21;
38 pub const STACKPROT = 23;
39 },
40 .freebsd => struct {
41 pub const NULL = 0;
42 pub const IGNORE = 1;
43 pub const EXECFD = 2;
44 pub const PHDR = 3;
45 pub const PHENT = 4;
46 pub const PHNUM = 5;
47 pub const PAGESZ = 6;
48 pub const BASE = 7;
49 pub const FLAGS = 8;
50 pub const ENTRY = 9;
51 pub const NOTELF = 10;
52 pub const UID = 11;
53 pub const EUID = 12;
54 pub const GID = 13;
55 pub const EGID = 14;
56 pub const EXECPATH = 15;
57 pub const CANARY = 16;
58 pub const CANARYLEN = 17;
59 pub const OSRELDATE = 18;
60 pub const NCPUS = 19;
61 pub const PAGESIZES = 20;
62 pub const PAGESIZESLEN = 21;
63 pub const TIMEKEEP = 22;
64 pub const STACKPROT = 23;
65 pub const EHDRFLAGS = 24;
66 pub const HWCAP = 25;
67 pub const HWCAP2 = 26;
68 pub const BSDFLAGS = 27;
69 pub const ARGC = 28;
70 pub const ARGV = 29;
71 pub const ENVC = 30;
72 pub const ENVV = 31;
73 pub const PS_STRINGS = 32;
74 pub const FXRNG = 33;
75 pub const KPRELOAD = 34;
76 pub const USRSTACKBASE = 35;
77 pub const USRSTACKLIM = 36;
78 pub const CHERI_STATS = 37;
79 pub const HWCAP3 = 38;
80 pub const HWCAP4 = 39;
81 },
82 .illumos => struct {
83 pub const NULL = 0;
84 pub const IGNORE = 1;
85 pub const EXECFD = 2;
86 pub const PHDR = 3;
87 pub const PHENT = 4;
88 pub const PHNUM = 5;
89 pub const PAGESZ = 6;
90 pub const BASE = 7;
91 pub const FLAGS = 8;
92 pub const ENTRY = 9;
93 pub const NOTELF = 10;
94 pub const UID = 11;
95 pub const EUID = 12;
96 pub const GID = 13;
97 pub const EGID = 14;
98 pub const EXECPATH = 15;
99 pub const CANARY = 16;
100 pub const CANARYLEN = 17;
101 pub const OSRELDATE = 18;
102 pub const NCPUS = 19;
103 pub const PAGESIZES = 20;
104 pub const PAGESIZESLEN = 21;
105 pub const TIMEKEEP = 22;
106 pub const STACKPROT = 23;
107 },
108 .linux => struct {
109 pub const NULL = 0;
110 pub const IGNORE = 1;
111 pub const EXECFD = 2;
112 pub const PHDR = 3;
113 pub const PHENT = 4;
114 pub const PHNUM = 5;
115 pub const PAGESZ = 6;
116 pub const BASE = 7;
117 pub const FLAGS = 8;
118 pub const ENTRY = 9;
119 pub const NOTELF = 10;
120 pub const UID = 11;
121 pub const EUID = 12;
122 pub const GID = 13;
123 pub const EGID = 14;
124 pub const CLKTCK = 17;
125 pub const PLATFORM = 15;
126 pub const HWCAP = 16;
127 pub const FPUCW = 18;
128 pub const DCACHEBSIZE = 19;
129 pub const ICACHEBSIZE = 20;
130 pub const UCACHEBSIZE = 21;
131 pub const IGNOREPPC = 22;
132 pub const SECURE = 23;
133 pub const BASE_PLATFORM = 24;
134 pub const RANDOM = 25;
135 pub const HWCAP2 = 26;
136 pub const RSEQ_FEATURE_SIZE = 27;
137 pub const RSEQ_ALIGN = 28;
138 pub const HWCAP3 = 29;
139 pub const HWCAP4 = 30;
140 pub const EXECFN = 31;
141 pub const SYSINFO = 32;
142 pub const SYSINFO_EHDR = 33;
143 pub const L1I_CACHESHAPE = 34;
144 pub const L1D_CACHESHAPE = 35;
145 pub const L2_CACHESHAPE = 36;
146 pub const L3_CACHESHAPE = 37;
147 pub const L1I_CACHESIZE = 40;
148 pub const L1I_CACHEGEOMETRY = 41;
149 pub const L1D_CACHESIZE = 42;
150 pub const L1D_CACHEGEOMETRY = 43;
151 pub const L2_CACHESIZE = 44;
152 pub const L2_CACHEGEOMETRY = 45;
153 pub const L3_CACHESIZE = 46;
154 pub const L3_CACHEGEOMETRY = 47;
155 pub const MINSIGSTKSZ = 51;
156 },
157 .netbsd => struct {
158 pub const NULL = 0;
159 pub const IGNORE = 1;
160 pub const EXECFD = 2;
161 pub const PHDR = 3;
162 pub const PHENT = 4;
163 pub const PHNUM = 5;
164 pub const PAGESZ = 6;
165 pub const BASE = 7;
166 pub const FLAGS = 8;
167 pub const ENTRY = 9;
168 pub const MIPS_NOTELF = 10;
169 pub const DCACHEBSIZE = 10;
170 pub const ICACHEBSIZE = 11;
171 pub const UCACHEBSIZE = 12;
172 pub const STACKBASE = 13;
173 pub const EUID = 2000;
174 pub const RUID = 2001;
175 pub const EGID = 2002;
176 pub const RGID = 2003;
177 pub const SUN_LDELF = 2004;
178 pub const SUN_LDSHDR = 2005;
179 pub const SUN_LDNAME = 2006;
180 pub const SUN_LPGSIZE = 2007;
181 pub const SUN_PLATFORM = 2008;
182 pub const SUN_HWCAP = 2009;
183 pub const SUN_IFLUSH = 2010;
184 pub const SUN_CPU = 2011;
185 pub const SUN_EMUL_ENTRY = 2012;
186 pub const SUN_EMUL_EXECFD = 2013;
187 pub const SUN_EXECNAME = 2014;
188 },
189 .openbsd => struct {
190 pub const NULL = 0;
191 pub const IGNORE = 1;
192 pub const PAGESZ = 6;
193 pub const HWCAP = 25;
194 pub const HWCAP2 = 26;
195 },
196 .serenity => struct {
197 pub const NULL = 0;
198 pub const IGNORE = 1;
199 pub const EXECFD = 2;
200 pub const PHDR = 3;
201 pub const PHENT = 4;
202 pub const PHNUM = 5;
203 pub const PAGESZ = 6;
204 pub const BASE = 7;
205 pub const FLAGS = 8;
206 pub const ENTRY = 9;
207 pub const NOTELF = 10;
208 pub const UID = 11;
209 pub const EUID = 12;
210 pub const GID = 13;
211 pub const PLATFORM = 15;
212 pub const HWCAP = 16;
213 pub const CLKTCK = 17;
214 pub const SECURE = 23;
215 pub const BASE_PLATFORM = 24;
216 pub const RANDOM = 25;
217 pub const HWCAP2 = 26;
218 pub const EXECFN = 31;
219 pub const EXE_BASE = 32;
220 pub const EXE_SIZE = 33;
221 },
222 else => struct {
223 pub const NULL = 0;
224 pub const IGNORE = 1;
225 pub const EXECFD = 2;
226 pub const PHDR = 3;
227 pub const PHENT = 4;
228 pub const PHNUM = 5;
229 pub const PAGESZ = 6;
230 pub const BASE = 7;
231 pub const FLAGS = 8;
232 pub const ENTRY = 9;
233 pub const NOTELF = 10;
234 },
235};
54236
55237pub const DT_NULL = 0;
56238pub const DT_NEEDED = 1;
lib/std/heap.zig+1-1
......@@ -80,7 +80,7 @@ pub fn defaultQueryPageSize() usize {
8080 .linux => if (builtin.link_libc)
8181 @max(std.c.sysconf(@backingInt(std.c._SC.PAGESIZE)), 0)
8282 else
83 std.os.linux.getauxval(std.elf.AT_PAGESZ),
83 std.os.linux.getauxval(std.elf.AT.PAGESZ),
8484 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => {
8585 const task_port = std.c.mach_task_self();
8686 // mach_task_self may fail "if there are any resource failures or other errors".
lib/std/os/linux.zig+287-1
......@@ -619,6 +619,138 @@ pub const O = switch (native_arch) {
619619};
620620
621621pub const HWCAP = switch (native_arch) {
622 .aarch64, .aarch64_be => struct {
623 pub const FP = 1 << 0;
624 pub const ASIMD = 1 << 1;
625 pub const EVTSTRM = 1 << 2;
626 pub const AES = 1 << 3;
627 pub const PMULL = 1 << 4;
628 pub const SHA1 = 1 << 5;
629 pub const SHA2 = 1 << 6;
630 pub const CRC32 = 1 << 7;
631 pub const ATOMICS = 1 << 8;
632 pub const FPHP = 1 << 9;
633 pub const ASIMDHP = 1 << 10;
634 pub const CPUID = 1 << 11;
635 pub const ASIMDRDM = 1 << 12;
636 pub const JSCVT = 1 << 13;
637 pub const FCMA = 1 << 14;
638 pub const LRCPC = 1 << 15;
639 pub const DCPOP = 1 << 16;
640 pub const SHA3 = 1 << 17;
641 pub const SM3 = 1 << 18;
642 pub const SM4 = 1 << 19;
643 pub const ASIMDDP = 1 << 20;
644 pub const SHA512 = 1 << 21;
645 pub const SVE = 1 << 22;
646 pub const ASIMDFHM = 1 << 23;
647 pub const DIT = 1 << 24;
648 pub const USCAT = 1 << 25;
649 pub const ILRCPC = 1 << 26;
650 pub const FLAGM = 1 << 27;
651 pub const SSBS = 1 << 28;
652 pub const SB = 1 << 29;
653 pub const PACA = 1 << 30;
654 pub const PACG = 1 << 31;
655 pub const GCS = 1 << 32;
656 pub const CMPBR = 1 << 33;
657 pub const FPRCVT = 1 << 34;
658 pub const F8MM8 = 1 << 35;
659 pub const F8MM4 = 1 << 36;
660 pub const SVE_F16MM = 1 << 37;
661 pub const SVE_ELTPERM = 1 << 38;
662 pub const SVE_AES2 = 1 << 39;
663 pub const SVE_BFSCALE = 1 << 40;
664 pub const SVE2P2 = 1 << 41;
665 pub const SME2P2 = 1 << 42;
666 pub const SME_SBITPERM = 1 << 43;
667 pub const SME_AES = 1 << 44;
668 pub const SME_SFEXPA = 1 << 45;
669 pub const SME_STMOP = 1 << 46;
670 pub const SME_SMOP4 = 1 << 47;
671
672 pub const @"2" = struct {
673 pub const DCPODP = 1 << 0;
674 pub const SVE2 = 1 << 1;
675 pub const SVEAES = 1 << 2;
676 pub const SVEPMULL = 1 << 3;
677 pub const SVEBITPERM = 1 << 4;
678 pub const SVESHA3 = 1 << 5;
679 pub const SVESM4 = 1 << 6;
680 pub const FLAGM2 = 1 << 7;
681 pub const FRINT = 1 << 8;
682 pub const SVEI8MM = 1 << 9;
683 pub const SVEF32MM = 1 << 10;
684 pub const SVEF64MM = 1 << 11;
685 pub const SVEBF16 = 1 << 12;
686 pub const I8MM = 1 << 13;
687 pub const BF16 = 1 << 14;
688 pub const DGH = 1 << 15;
689 pub const RNG = 1 << 16;
690 pub const BTI = 1 << 17;
691 pub const MTE = 1 << 18;
692 pub const ECV = 1 << 19;
693 pub const AFP = 1 << 20;
694 pub const RPRES = 1 << 21;
695 pub const MTE3 = 1 << 22;
696 pub const SME = 1 << 23;
697 pub const SME_I16I64 = 1 << 24;
698 pub const SME_F64F64 = 1 << 25;
699 pub const SME_I8I32 = 1 << 26;
700 pub const SME_F16F32 = 1 << 27;
701 pub const SME_B16F32 = 1 << 28;
702 pub const SME_F32F32 = 1 << 29;
703 pub const SME_FA64 = 1 << 30;
704 pub const WFXT = 1 << 31;
705 pub const EBF16 = 1 << 32;
706 pub const SVE_EBF16 = 1 << 33;
707 pub const CSSC = 1 << 34;
708 pub const RPRFM = 1 << 35;
709 pub const SVE2P1 = 1 << 36;
710 pub const SME2 = 1 << 37;
711 pub const SME2P1 = 1 << 38;
712 pub const SME_I16I32 = 1 << 39;
713 pub const SME_BI32I32 = 1 << 40;
714 pub const SME_B16B16 = 1 << 41;
715 pub const SME_F16F16 = 1 << 42;
716 pub const MOPS = 1 << 43;
717 pub const HBC = 1 << 44;
718 pub const SVE_B16B16 = 1 << 45;
719 pub const LRCPC3 = 1 << 46;
720 pub const LSE128 = 1 << 47;
721 pub const FPMR = 1 << 48;
722 pub const LUT = 1 << 49;
723 pub const FAMINMAX = 1 << 50;
724 pub const F8CVT = 1 << 51;
725 pub const F8FMA = 1 << 52;
726 pub const F8DP4 = 1 << 53;
727 pub const F8DP2 = 1 << 54;
728 pub const F8E4M3 = 1 << 55;
729 pub const F8E5M2 = 1 << 56;
730 pub const SME_LUTV2 = 1 << 57;
731 pub const SME_F8F16 = 1 << 58;
732 pub const SME_F8F32 = 1 << 59;
733 pub const SME_SF8FMA = 1 << 60;
734 pub const SME_SF8DP4 = 1 << 61;
735 pub const SME_SF8DP2 = 1 << 62;
736 pub const POE = 1 << 63;
737 };
738
739 pub const @"3" = struct {
740 pub const MTE_FAR = 1 << 0;
741 pub const MTE_STORE_ONLY = 1 << 1;
742 pub const LSFE = 1 << 2;
743 pub const LS64 = 1 << 3;
744 pub const SVE_B16MM = 1 << 4;
745 pub const SVE2P3 = 1 << 5;
746 pub const SME_LUT6 = 1 << 6;
747 pub const SME2P3 = 1 << 7;
748 pub const F16MM = 1 << 8;
749 pub const F16F32DOT = 1 << 9;
750 pub const F16F32MM = 1 << 10;
751 pub const SVE_LUT6 = 1 << 11;
752 };
753 },
622754 .arm, .armeb, .thumb, .thumbeb => struct {
623755 pub const SWP = 1 << 0;
624756 pub const HALF = 1 << 1;
......@@ -643,6 +775,22 @@ pub const HWCAP = switch (native_arch) {
643775 pub const IDIV = IDIVA | IDIVT;
644776 pub const LPAE = 1 << 20;
645777 pub const EVTSTRM = 1 << 21;
778 pub const FPHP = 1 << 22;
779 pub const ASIMDHP = 1 << 23;
780 pub const ASIMDDP = 1 << 24;
781 pub const ASIMDFHM = 1 << 25;
782 pub const ASIMDBF16 = 1 << 26;
783 pub const I8MM = 1 << 27;
784
785 pub const @"2" = struct {
786 pub const AES = 1 << 0;
787 pub const PMULL = 1 << 1;
788 pub const SHA1 = 1 << 2;
789 pub const SHA2 = 1 << 3;
790 pub const CRC32 = 1 << 4;
791 pub const SB = 1 << 5;
792 pub const SSBS = 1 << 6;
793 };
646794 },
647795 .loongarch32, .loongarch64 => struct {
648796 pub const CPUCFG = 1 << 0;
......@@ -661,6 +809,144 @@ pub const HWCAP = switch (native_arch) {
661809 pub const PTW = 1 << 13;
662810 pub const LSPW = 1 << 14;
663811 pub const SCQ = 1 << 15;
812 pub const LAM_BH = 1 << 16;
813 },
814 .mips, .mipsel, .mips64, .mips64el => struct {
815 pub const R6 = 1 << 0;
816 pub const MSA = 1 << 1;
817 pub const CRC32 = 1 << 2;
818 pub const MIPS16 = 1 << 3;
819 pub const MDMX = 1 << 4;
820 pub const MIPS3D = 1 << 5;
821 pub const SMARTMIPS = 1 << 6;
822 pub const DSP = 1 << 7;
823 pub const DSP2 = 1 << 8;
824 pub const DSP3 = 1 << 9;
825 pub const MIPS16E2 = 1 << 10;
826 pub const LOONGSON_MMI = 1 << 11;
827 pub const LOONGSON_EXT = 1 << 12;
828 pub const LOONGSON_EXT2 = 1 << 13;
829 pub const LOONGSON_CPUCFG = 1 << 14;
830 },
831 .powerpc, .powerpcle, .powerpc64, .powerpc64le => struct {
832 pub const PPC_LE = 1 << 0;
833 pub const TRUE_LE = 1 << 1;
834 pub const PSERIES_PERFMON_COMPAT = 1 << 6;
835 pub const HAS_VSX = 1 << 7;
836 pub const ARCH_2_06 = 1 << 8;
837 pub const POWER6_EXT = 1 << 9;
838 pub const HAS_DFP = 1 << 10;
839 pub const PA6T = 1 << 11;
840 pub const ARCH_2_05 = 1 << 12;
841 pub const ICACHE_SNOOP = 1 << 13;
842 pub const SMT = 1 << 14;
843 pub const BOOKE = 1 << 15;
844 pub const CELL = 1 << 16;
845 pub const POWER5_PLUS = 1 << 17;
846 pub const POWER5 = 1 << 18;
847 pub const POWER4 = 1 << 19;
848 pub const NO_TB = 1 << 20;
849 pub const HAS_EFP_DOUBLE = 1 << 21;
850 pub const HAS_EFP_SINGLE = 1 << 22;
851 pub const HAS_SPE = 1 << 23;
852 pub const UNIFIED_CACHE = 1 << 24;
853 pub const HAS_4xxMAC = 1 << 25;
854 pub const HAS_MMU = 1 << 26;
855 pub const HAS_FPU = 1 << 27;
856 pub const HAS_ALTIVEC = 1 << 28;
857 pub const @"601_INSTR" = 1 << 29;
858 pub const @"64" = 1 << 30;
859 pub const @"32" = 1 << 31;
860
861 pub const @"2" = struct {
862 pub const DMF = 1 << 15;
863 pub const ARCH_3_2 = 1 << 16;
864 pub const MMA = 1 << 17;
865 pub const ARCH_3_1 = 1 << 18;
866 pub const HTM_NO_SUSPEND = 1 << 19;
867 pub const SCV = 1 << 20;
868 pub const DARN = 1 << 21;
869 pub const HAS_IEEE128 = 1 << 22;
870 pub const ARCH_3_00 = 1 << 23;
871 pub const HTM_NOSC = 1 << 24;
872 pub const VEC_CRYPTO = 1 << 25;
873 pub const TAR = 1 << 26;
874 pub const ISEL = 1 << 27;
875 pub const EBB = 1 << 28;
876 pub const DSCR = 1 << 29;
877 pub const HTM = 1 << 30;
878 pub const ARCH_2_07 = 1 << 31;
879 };
880 },
881 .riscv32, .riscv64 => struct {
882 pub const ISA_A = 1 << 0;
883 pub const ISA_C = 1 << 2;
884 pub const ISA_D = 1 << 3;
885 pub const ISA_F = 1 << 5;
886 pub const ISA_I = 1 << 8;
887 pub const ISA_M = 1 << 12;
888 pub const ISA_V = 1 << 21;
889 },
890 .s390x => struct {
891 pub const ESAN3 = 1 << 0;
892 pub const ZARCH = 1 << 1;
893 pub const STFLE = 1 << 2;
894 pub const MSA = 1 << 3;
895 pub const LDISP = 1 << 4;
896 pub const EIMM = 1 << 5;
897 pub const DFP = 1 << 6;
898 pub const HPAGE = 1 << 7;
899 pub const ETF3EH = 1 << 8;
900 pub const HIGH_GPRS = 1 << 9;
901 pub const TE = 1 << 10;
902 pub const VXRS = 1 << 11;
903 pub const VXRS_BCD = 1 << 12;
904 pub const VXRS_EXT = 1 << 13;
905 pub const GS = 1 << 14;
906 pub const VXRS_EXT2 = 1 << 15;
907 pub const VXRS_PDE = 1 << 16;
908 pub const SORT = 1 << 17;
909 pub const DFLT = 1 << 18;
910 pub const VXRS_PDE2 = 1 << 19;
911 pub const NNPA = 1 << 20;
912 pub const PCI_MIO = 1 << 21;
913 pub const SIE = 1 << 22;
914 },
915 .sparc, .sparc64 => struct {
916 pub const FLUSH = 1 << 0;
917 pub const STBAR = 1 << 1;
918 pub const SWAP = 1 << 2;
919 pub const MULDIV = 1 << 3;
920 pub const V9 = 1 << 4;
921 pub const ULTRA3 = 1 << 5;
922 pub const BLKINIT = 1 << 6;
923 pub const N2 = 1 << 7;
924 pub const MUL32 = 1 << 8;
925 pub const DIV32 = 1 << 9;
926 pub const FSMULD = 1 << 10;
927 pub const V8PLUS = 1 << 11;
928 pub const POPC = 1 << 12;
929 pub const VIS = 1 << 13;
930 pub const VIS2 = 1 << 14;
931 pub const ASI_BLK_INIT = 1 << 15;
932 pub const FMAF = 1 << 16;
933 pub const VIS3 = 1 << 17;
934 pub const HPC = 1 << 18;
935 pub const RANDOM = 1 << 19;
936 pub const TRANS = 1 << 20;
937 pub const FJFMAU = 1 << 21;
938 pub const IMA = 1 << 22;
939 pub const ASI_CACHE_SPARING = 1 << 23;
940 pub const PAUSE = 1 << 24;
941 pub const CBCOND = 1 << 25;
942 pub const CRYPTO = 1 << 26;
943 pub const ADI = 1 << 27;
944 },
945 .x86, .x86_64 => struct {
946 pub const @"2" = struct {
947 pub const RING3MWAIT = 1 << 0;
948 pub const FSGSBASE = 1 << 1;
949 };
664950 },
665951 else => struct {},
666952};
......@@ -705,7 +991,7 @@ fn getauxvalImpl(index: usize) callconv(.c) usize {
705991 @disableInstrumentation();
706992 const auxv = elf_aux_maybe orelse return 0;
707993 var i: usize = 0;
708 while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
994 while (auxv[i].a_type != std.elf.AT.NULL) : (i += 1) {
709995 if (auxv[i].a_type == index)
710996 return auxv[i].a_un.a_val;
711997 }
lib/std/os/linux/test.zig+4-4
......@@ -106,10 +106,10 @@ test "statx" {
106106
107107test "user and group ids" {
108108 if (builtin.link_libc) return error.SkipZigTest;
109 try expectEqual(linux.getauxval(elf.AT_UID), linux.getuid());
110 try expectEqual(linux.getauxval(elf.AT_GID), linux.getgid());
111 try expectEqual(linux.getauxval(elf.AT_EUID), linux.geteuid());
112 try expectEqual(linux.getauxval(elf.AT_EGID), linux.getegid());
109 try expectEqual(linux.getauxval(elf.AT.UID), linux.getuid());
110 try expectEqual(linux.getauxval(elf.AT.GID), linux.getgid());
111 try expectEqual(linux.getauxval(elf.AT.EUID), linux.geteuid());
112 try expectEqual(linux.getauxval(elf.AT.EGID), linux.getegid());
113113}
114114
115115test "fadvise" {
lib/std/os/linux/vdso.zig+1-1
......@@ -5,7 +5,7 @@ const mem = std.mem;
55const maxInt = std.math.maxInt;
66
77pub fn lookup(vername: []const u8, name: []const u8) usize {
8 const vdso_addr = linux.getauxval(std.elf.AT_SYSINFO_EHDR);
8 const vdso_addr = linux.getauxval(std.elf.AT.SYSINFO_EHDR);
99 if (vdso_addr == 0) return 0;
1010
1111 const eh = @as(*elf.Ehdr, @ptrFromInt(vdso_addr));
lib/std/posix.zig+4-4
......@@ -775,9 +775,9 @@ pub fn sysctl(
775775
776776pub fn getSelfPhdrs() []std.elf.ElfN.Phdr {
777777 const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval;
778 assert(getauxval(std.elf.AT_PHENT) == @sizeOf(std.elf.ElfN.Phdr));
779 const phdrs: [*]std.elf.ElfN.Phdr = @ptrFromInt(getauxval(std.elf.AT_PHDR));
780 return phdrs[0..getauxval(std.elf.AT_PHNUM)];
778 assert(getauxval(std.elf.AT.PHENT) == @sizeOf(std.elf.ElfN.Phdr));
779 const phdrs: [*]std.elf.ElfN.Phdr = @ptrFromInt(getauxval(std.elf.AT.PHDR));
780 return phdrs[0..getauxval(std.elf.AT.PHNUM)];
781781}
782782
783783pub fn dl_iterate_phdr(
......@@ -819,7 +819,7 @@ pub fn dl_iterate_phdr(
819819 .PHDR => break @intFromPtr(phdrs.ptr) - phdr.vaddr,
820820 else => {},
821821 } else unreachable,
822 .name = switch (getauxval(std.elf.AT_EXECFN)) {
822 .name = switch (getauxval(std.elf.AT.EXECFN)) {
823823 0 => "/proc/self/exe",
824824 else => |name| @ptrFromInt(name),
825825 },
lib/std/start.zig+6-6
......@@ -617,11 +617,11 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
617617 var i: usize = 0;
618618 var at_phdr: usize = 0;
619619 var at_phnum: usize = 0;
620 while (auxv[i].a_type != elf.AT_NULL) : (i += 1) {
620 while (auxv[i].a_type != elf.AT.NULL) : (i += 1) {
621621 switch (auxv[i].a_type) {
622 elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
623 elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
624 elf.AT_HWCAP => at_hwcap = auxv[i].a_un.a_val,
622 elf.AT.PHNUM => at_phnum = auxv[i].a_un.a_val,
623 elf.AT.PHDR => at_phdr = auxv[i].a_un.a_val,
624 elf.AT.HWCAP => at_hwcap = auxv[i].a_un.a_val,
625625 else => continue,
626626 }
627627 }
......@@ -736,8 +736,8 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal
736736
737737 switch (builtin.os.tag) {
738738 .linux => {
739 const at_phdr = std.c.getauxval(elf.AT_PHDR);
740 const at_phnum = std.c.getauxval(elf.AT_PHNUM);
739 const at_phdr = std.c.getauxval(elf.AT.PHDR);
740 const at_phnum = std.c.getauxval(elf.AT.PHNUM);
741741 const phdrs = (@as([*]elf.ElfN.Phdr, @ptrFromInt(at_phdr)))[0..at_phnum];
742742 expandStackSize(phdrs);
743743 },
lib/std/zig/system/linux.zig+809-499
......@@ -9,449 +9,587 @@ const testing = std.testing;
99const Target = std.Target;
1010const assert = std.debug.assert;
1111
12const SparcCpuinfoImpl = struct {
13 model: ?*const Target.Cpu.Model = null,
14
15 const cpu_names = .{
16 .{ "SuperSparc", &Target.sparc.cpu.supersparc },
17 .{ "HyperSparc", &Target.sparc.cpu.hypersparc },
18 .{ "SpitFire", &Target.sparc.cpu.ultrasparc },
19 .{ "BlackBird", &Target.sparc.cpu.ultrasparc },
20 .{ "Sabre", &Target.sparc.cpu.ultrasparc },
21 .{ "Hummingbird", &Target.sparc.cpu.ultrasparc },
22 .{ "Cheetah", &Target.sparc.cpu.ultrasparc3 },
23 .{ "Jalapeno", &Target.sparc.cpu.ultrasparc3 },
24 .{ "Jaguar", &Target.sparc.cpu.ultrasparc3 },
25 .{ "Panther", &Target.sparc.cpu.ultrasparc3 },
26 .{ "Serrano", &Target.sparc.cpu.ultrasparc3 },
27 .{ "UltraSparc T1", &Target.sparc.cpu.niagara },
28 .{ "UltraSparc T2", &Target.sparc.cpu.niagara2 },
29 .{ "UltraSparc T3", &Target.sparc.cpu.niagara3 },
30 .{ "UltraSparc T4", &Target.sparc.cpu.niagara4 },
31 .{ "UltraSparc T5", &Target.sparc.cpu.niagara4 },
32 .{ "LEON", &Target.sparc.cpu.leon3 },
33 };
34
35 fn line_hook(self: *SparcCpuinfoImpl, key: []const u8, value: []const u8) !bool {
36 if (mem.eql(u8, key, "cpu")) {
37 inline for (cpu_names) |pair| {
38 if (mem.findPos(u8, value, 0, pair[0]) != null) {
39 self.model = pair[1];
40 break;
41 }
12// The generic implementation of a /proc/cpuinfo parser.
13// For every line it invokes the lineHook method with the key and value strings
14// as first and second parameters. Returning false from the hook function stops
15// the iteration without raising an error.
16// When all the lines have been analyzed the finalize method is called.
17fn CpuinfoParser(comptime impl: anytype) type {
18 return struct {
19 fn parse(arch: Target.Cpu.Arch, reader: *Io.Reader) !?Target.Cpu {
20 var obj: impl = .{};
21 while (try reader.takeDelimiter('\n')) |line| {
22 const colon_pos = mem.findScalar(u8, line, ':') orelse continue;
23 const key = mem.trimEnd(u8, line[0..colon_pos], " \t");
24 const value = mem.trimStart(u8, line[colon_pos + 1 ..], " \t");
25 if (!try obj.lineHook(key, value)) break;
4226 }
27 return obj.finalize(arch);
4328 }
29 };
30}
31
32fn testParser(
33 parser: anytype,
34 arch: Target.Cpu.Arch,
35 expected_model: *const Target.Cpu.Model,
36 input: []const u8,
37) !void {
38 var r: Io.Reader = .fixed(input);
39 const result = try parser.parse(arch, &r);
40 try testing.expectEqual(expected_model, result.?.model);
41 try testing.expect(expected_model.features.eql(result.?.features));
42}
4443
45 return true;
44const aarch64 = struct {
45 inline fn mrs(comptime feat_reg: []const u8) u64 {
46 return asm ("mrs %[ret], " ++ feat_reg
47 : [ret] "=r" (-> u64),
48 );
4649 }
4750
48 fn finalize(self: *const SparcCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {
49 const model = self.model orelse return null;
50 return Target.Cpu{
51 .arch = arch,
52 .model = model,
53 .features = model.features,
51 pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch) ?Target.Cpu {
52 const registers = [12]u64{
53 mrs("MIDR_EL1"),
54 mrs("ID_AA64PFR0_EL1"),
55 mrs("ID_AA64PFR1_EL1"),
56 mrs("ID_AA64DFR0_EL1"),
57 mrs("ID_AA64DFR1_EL1"),
58 mrs("ID_AA64AFR0_EL1"),
59 mrs("ID_AA64AFR1_EL1"),
60 mrs("ID_AA64ISAR0_EL1"),
61 mrs("ID_AA64ISAR1_EL1"),
62 mrs("ID_AA64MMFR0_EL1"),
63 mrs("ID_AA64MMFR1_EL1"),
64 mrs("ID_AA64MMFR2_EL1"),
5465 };
66
67 return @import("arm.zig").aarch64.detectNativeCpuAndFeatures(arch, registers);
5568 }
5669};
5770
58const SparcCpuinfoParser = CpuinfoParser(SparcCpuinfoImpl);
71const arm = struct {
72 const cpuinfo = struct {
73 const Impl = struct {
74 implementer: u8 = 0,
75 variant: u8 = 0,
76 part: u16 = 0,
77
78 have_fields: u8 = 0,
79
80 const cpu_models = @import("arm.zig").cpu_models;
81
82 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
83 if (mem.eql(u8, key, "CPU implementer")) {
84 self.implementer = try fmt.parseInt(u8, value, 0);
85 self.have_fields += 1;
86 } else if (mem.eql(u8, key, "CPU variant")) {
87 self.variant = try fmt.parseInt(u8, value, 0);
88 self.have_fields += 1;
89 } else if (mem.eql(u8, key, "CPU part")) {
90 self.part = try fmt.parseInt(u16, value, 0);
91 self.have_fields += 1;
92 } else if (mem.eql(u8, key, "CPU revision")) {
93 // This field is always the last one for each CPU section.
94 return false;
95 }
5996
60test "cpuinfo: SPARC" {
61 try testParser(SparcCpuinfoParser, .sparc64, &Target.sparc.cpu.niagara2,
62 \\cpu : UltraSparc T2 (Niagara2)
63 \\fpu : UltraSparc T2 integrated FPU
64 \\pmu : niagara2
65 \\type : sun4v
66 );
67}
97 return true;
98 }
6899
69const RiscvCpuinfoImpl = struct {
70 model: ?*const Target.Cpu.Model = null,
71
72 const cpu_names = .{
73 .{ "andestech,ax45mp", &Target.riscv.cpu.andes_ax45 },
74 .{ "sifive,p550", &Target.riscv.cpu.sifive_p550 },
75 .{ "sifive,u54", &Target.riscv.cpu.sifive_u54 },
76 .{ "sifive,u54-mc", &Target.riscv.cpu.sifive_u54 },
77 .{ "sifive,u7", &Target.riscv.cpu.sifive_7_series },
78 .{ "sifive,u74", &Target.riscv.cpu.sifive_u74 },
79 .{ "sifive,u74-mc", &Target.riscv.cpu.sifive_u74 },
80 .{ "sifive,x280", &Target.riscv.cpu.sifive_x280 },
81 .{ "spacemit,x60", &Target.riscv.cpu.spacemit_x60 },
82 .{ "spacemit,x100", &Target.riscv.cpu.spacemit_x100 },
83 };
100 fn finalize(self: *Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
101 if (self.have_fields != 3) return null;
84102
85 fn line_hook(self: *RiscvCpuinfoImpl, key: []const u8, value: []const u8) !bool {
86 if (mem.eql(u8, key, "uarch")) {
87 inline for (cpu_names) |pair| {
88 if (mem.eql(u8, value, pair[0])) {
89 self.model = pair[1];
90 break;
91 }
103 const model = cpu_models.isKnown(.{
104 .architecture = undefined, // unused for the lookup
105 .implementer = self.implementer,
106 .variant = self.variant,
107 .part = self.part,
108 }, false) orelse return null;
109
110 // We pick the first core on big.LITTLE systems, hopefully the LITTLE one.
111 return .{
112 .arch = arch,
113 .model = model,
114 .features = model.features,
115 };
92116 }
93 return false;
94 }
117 };
118
119 const Parser = CpuinfoParser(Impl);
120 };
95121
96 return true;
122 test cpuinfo {
123 try testParser(cpuinfo.Parser, .arm, &Target.arm.cpu.arm1176jz_s,
124 \\processor : 0
125 \\model name : ARMv6-compatible processor rev 7 (v6l)
126 \\BogoMIPS : 997.08
127 \\Features : half thumb fastmult vfp edsp java tls
128 \\CPU implementer : 0x41
129 \\CPU architecture: 7
130 \\CPU variant : 0x0
131 \\CPU part : 0xb76
132 \\CPU revision : 7
133 );
134 try testParser(cpuinfo.Parser, .arm, &Target.arm.cpu.cortex_a7,
135 \\processor : 0
136 \\model name : ARMv7 Processor rev 3 (v7l)
137 \\BogoMIPS : 18.00
138 \\Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
139 \\CPU implementer : 0x41
140 \\CPU architecture: 7
141 \\CPU variant : 0x0
142 \\CPU part : 0xc07
143 \\CPU revision : 3
144 \\
145 \\processor : 4
146 \\model name : ARMv7 Processor rev 3 (v7l)
147 \\BogoMIPS : 90.00
148 \\Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
149 \\CPU implementer : 0x41
150 \\CPU architecture: 7
151 \\CPU variant : 0x2
152 \\CPU part : 0xc0f
153 \\CPU revision : 3
154 );
155 try testParser(cpuinfo.Parser, .arm, &Target.arm.cpu.cortex_a72,
156 \\processor : 0
157 \\BogoMIPS : 108.00
158 \\Features : fp asimd evtstrm crc32 cpuid
159 \\CPU implementer : 0x41
160 \\CPU architecture: 8
161 \\CPU variant : 0x0
162 \\CPU part : 0xd08
163 \\CPU revision : 3
164 );
97165 }
98166
99 fn finalize(self: *const RiscvCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {
100 const model = self.model orelse return null;
101 return Target.Cpu{
102 .arch = arch,
103 .model = model,
104 .features = model.features,
105 };
167 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
168 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
169 defer file.close(io);
170
171 var buffer: [4096]u8 = undefined;
172 var file_reader = file.reader(io, &buffer);
173
174 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
175
176 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
177
178 return cpu;
106179 }
107180};
108181
109const RiscvCpuinfoParser = CpuinfoParser(RiscvCpuinfoImpl);
110
111test "cpuinfo: RISC-V" {
112 try testParser(RiscvCpuinfoParser, .riscv64, &Target.riscv.cpu.sifive_u74,
113 \\processor : 0
114 \\hart : 1
115 \\isa : rv64imafdc
116 \\mmu : sv39
117 \\isa-ext :
118 \\uarch : sifive,u74-mc
119 );
120}
182const csky = struct {
183 const cpuinfo = struct {
184 const Impl = struct {
185 model: ?*const Target.Cpu.Model = null,
186
187 const cpu_names = .{
188 .{ "ck807", &Target.csky.cpu.ck807 },
189 .{ "ck807f", &Target.csky.cpu.ck807f },
190 .{ "ck810", &Target.csky.cpu.ck810 },
191 .{ "ck810f", &Target.csky.cpu.ck810f },
192 .{ "ck810t", &Target.csky.cpu.ck810t },
193 .{ "ck810ft", &Target.csky.cpu.ck810ft },
194 .{ "ck860", &Target.csky.cpu.ck860 },
195 .{ "ck860f", &Target.csky.cpu.ck860f },
196 .{ "ck860fv", &Target.csky.cpu.ck860fv },
197 };
121198
122const PowerpcCpuinfoImpl = struct {
123 model: ?*const Target.Cpu.Model = null,
124
125 const cpu_names = .{
126 .{ "604e", &Target.powerpc.cpu.@"604e" },
127 .{ "604", &Target.powerpc.cpu.@"604" },
128 .{ "7400", &Target.powerpc.cpu.@"7400" },
129 .{ "7410", &Target.powerpc.cpu.@"7400" },
130 .{ "7447", &Target.powerpc.cpu.@"7400" },
131 .{ "7455", &Target.powerpc.cpu.@"7450" },
132 .{ "G4", &Target.powerpc.cpu.g4 },
133 .{ "POWER4", &Target.powerpc.cpu.@"970" },
134 .{ "PPC970FX", &Target.powerpc.cpu.@"970" },
135 .{ "PPC970MP", &Target.powerpc.cpu.@"970" },
136 .{ "G5", &Target.powerpc.cpu.g5 },
137 .{ "POWER5", &Target.powerpc.cpu.g5 },
138 .{ "A2", &Target.powerpc.cpu.a2 },
139 .{ "POWER6", &Target.powerpc.cpu.pwr6 },
140 .{ "POWER7", &Target.powerpc.cpu.pwr7 },
141 .{ "POWER8", &Target.powerpc.cpu.pwr8 },
142 .{ "POWER8E", &Target.powerpc.cpu.pwr8 },
143 .{ "POWER8NVL", &Target.powerpc.cpu.pwr8 },
144 .{ "POWER9", &Target.powerpc.cpu.pwr9 },
145 .{ "POWER10", &Target.powerpc.cpu.pwr10 },
146 .{ "POWER11", &Target.powerpc.cpu.pwr11 },
147 };
199 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
200 if (mem.eql(u8, key, "C-SKY CPU model")) {
201 inline for (cpu_names) |pair| {
202 if (mem.eql(u8, value, pair[0])) {
203 self.model = pair[1];
204 break;
205 }
206 }
148207
149 fn line_hook(self: *PowerpcCpuinfoImpl, key: []const u8, value: []const u8) !bool {
150 if (mem.eql(u8, key, "cpu")) {
151 // The model name is often followed by a comma or space and extra
152 // info.
153 inline for (cpu_names) |pair| {
154 const end_index = mem.findAny(u8, value, ", ") orelse value.len;
155 if (mem.eql(u8, value[0..end_index], pair[0])) {
156 self.model = pair[1];
157 break;
208 return false;
158209 }
210
211 return true;
159212 }
160213
161 // Stop the detection once we've seen the first core.
162 return false;
163 }
214 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
215 const model = self.model orelse return null;
216 return .{
217 .arch = arch,
218 .model = model,
219 .features = model.features,
220 };
221 }
222 };
164223
165 return true;
166 }
224 const Parser = CpuinfoParser(Impl);
225 };
167226
168 fn finalize(self: *const PowerpcCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {
169 const model = self.model orelse return null;
170 return Target.Cpu{
171 .arch = arch,
172 .model = model,
173 .features = model.features,
174 };
227 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
228 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
229 defer file.close(io);
230
231 var buffer: [4096]u8 = undefined;
232 var file_reader = file.reader(io, &buffer);
233
234 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
235
236 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
237
238 return cpu;
175239 }
176240};
177241
178const PowerpcCpuinfoParser = CpuinfoParser(PowerpcCpuinfoImpl);
179
180test "cpuinfo: PowerPC" {
181 try testParser(PowerpcCpuinfoParser, .powerpc, &Target.powerpc.cpu.@"970",
182 \\processor : 0
183 \\cpu : PPC970MP, altivec supported
184 \\clock : 1250.000000MHz
185 \\revision : 1.1 (pvr 0044 0101)
186 );
187 try testParser(PowerpcCpuinfoParser, .powerpc64le, &Target.powerpc.cpu.pwr8,
188 \\processor : 0
189 \\cpu : POWER8 (raw), altivec supported
190 \\clock : 2926.000000MHz
191 \\revision : 2.0 (pvr 004d 0200)
192 );
193}
242const m68k = struct {
243 const cpuinfo = struct {
244 const Impl = struct {
245 model: ?*const Target.Cpu.Model = null,
194246
195const S390xCpuinfoImpl = struct {
196 model: ?*const Target.Cpu.Model = null,
197
198 const cpu_names = .{
199 // z900: 2064, 2066
200 // z990: 2084, 2086
201 // z9: 2094, 2096
202
203 .{ "2097", &Target.s390x.cpu.z10 },
204 .{ "2098", &Target.s390x.cpu.z10 },
205 .{ "2817", &Target.s390x.cpu.z196 },
206 .{ "2818", &Target.s390x.cpu.z196 },
207 .{ "2827", &Target.s390x.cpu.zEC12 },
208 .{ "2828", &Target.s390x.cpu.zEC12 },
209 .{ "2964", &Target.s390x.cpu.z13 },
210 .{ "2965", &Target.s390x.cpu.z13 },
211 .{ "3906", &Target.s390x.cpu.z14 },
212 .{ "3907", &Target.s390x.cpu.z14 },
213 .{ "8561", &Target.s390x.cpu.z15 },
214 .{ "8562", &Target.s390x.cpu.z15 },
215 .{ "3931", &Target.s390x.cpu.z16 },
216 .{ "3932", &Target.s390x.cpu.z16 },
217 .{ "9175", &Target.s390x.cpu.z17 },
218 .{ "9176", &Target.s390x.cpu.z17 },
219 };
247 const cpu_names = .{
248 .{ "68020", &Target.m68k.cpu.M68020 },
249 .{ "68030", &Target.m68k.cpu.M68030 },
250 .{ "68040", &Target.m68k.cpu.M68040 },
251 .{ "68060", &Target.m68k.cpu.M68060 },
252 };
220253
221 fn line_hook(self: *S390xCpuinfoImpl, key: []const u8, value: []const u8) !bool {
222 if (mem.eql(u8, key, "machine")) {
223 inline for (cpu_names) |pair| {
224 if (mem.eql(u8, value, pair[0])) {
225 self.model = pair[1];
226 break;
254 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
255 if (mem.eql(u8, key, "CPU")) {
256 inline for (cpu_names) |pair| {
257 if (mem.eql(u8, value, pair[0])) {
258 self.model = pair[1];
259 break;
260 }
261 }
262
263 return false;
227264 }
265
266 return true;
228267 }
229268
230 return false;
231 }
269 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
270 const model = self.model orelse return null;
271 return .{
272 .arch = arch,
273 .model = model,
274 .features = model.features,
275 };
276 }
277 };
232278
233 return true;
234 }
279 const Parser = CpuinfoParser(Impl);
280 };
235281
236 fn finalize(self: *const S390xCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {
237 const model = self.model orelse return null;
238 return Target.Cpu{
239 .arch = arch,
240 .model = model,
241 .features = model.features,
242 };
243 }
244};
282 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
283 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
284 defer file.close(io);
245285
246const S390xCpuinfoParser = CpuinfoParser(S390xCpuinfoImpl);
247
248test "cpuinfo: S390x" {
249 try testParser(S390xCpuinfoParser, .s390x, &Target.s390x.cpu.z15,
250 \\physical id : 5
251 \\core id : 5
252 \\book id : 5
253 \\drawer id : 5
254 \\dedicated : 0
255 \\address : 5
256 \\siblings : 1
257 \\cpu cores : 1
258 \\version : FF
259 \\identification : 09DD98
260 \\machine : 8561
261 \\cpu MHz dynamic : 5200
262 \\cpu MHz static : 5200
263 );
264}
286 var buffer: [4096]u8 = undefined;
287 var file_reader = file.reader(io, &buffer);
265288
266const ArmCpuinfoImpl = struct {
267 const num_cores = 4;
289 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
268290
269 cores: [num_cores]CoreInfo = undefined,
270 core_no: usize = 0,
271 have_fields: usize = 0,
291 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
272292
273 const CoreInfo = struct {
274 architecture: u8 = 0,
275 implementer: u8 = 0,
276 variant: u8 = 0,
277 part: u16 = 0,
278 is_really_v6: bool = false,
279 };
293 return cpu;
294 }
295};
280296
281 const cpu_models = @import("arm.zig").cpu_models;
297const mips = struct {
298 const cpuinfo = struct {
299 const Impl = struct {
300 model: ?*const Target.Cpu.Model = null,
301
302 const cpu_names = .{
303 .{ "Cavium Octeon III", &Target.mips.cpu.@"octeon+" },
304 .{ "Cavium Octeon II", &Target.mips.cpu.@"octeon+" },
305 .{ "Cavium Octeon+", &Target.mips.cpu.@"octeon+" },
306 .{ "Cavium Octeon", &Target.mips.cpu.octeon },
307 .{ "MIPS I6400", &Target.mips.cpu.i6400 },
308 .{ "MIPS I6500", &Target.mips.cpu.i6500 },
309 .{ "MIPS P5600", &Target.mips.cpu.p5600 },
310 .{ "R3000A", &Target.mips.cpu.r3000a },
311 };
312
313 const isa_names = .{
314 .{ "mips64r6", &Target.mips.cpu.mips64r6 },
315 .{ "mips64r5", &Target.mips.cpu.mips64r5 },
316 .{ "mips64r2", &Target.mips.cpu.mips64r2 },
317 .{ "mips64r1", &Target.mips.cpu.mips64 },
318 .{ "mips32r6", &Target.mips.cpu.mips32r6 },
319 .{ "mips32r5", &Target.mips.cpu.mips32r5 },
320 .{ "mips32r2", &Target.mips.cpu.mips32r2 },
321 .{ "mips32r1", &Target.mips.cpu.mips32 },
322 .{ "mips5", &Target.mips.cpu.mips5 },
323 .{ "mips4", &Target.mips.cpu.mips4 },
324 .{ "mips3", &Target.mips.cpu.mips3 },
325 .{ "mips2", &Target.mips.cpu.mips2 },
326 .{ "mips1", &Target.mips.cpu.mips1 },
327 };
282328
283 fn addOne(self: *ArmCpuinfoImpl) void {
284 if (self.have_fields == 4 and self.core_no < num_cores) {
285 if (self.core_no > 0) {
286 // Deduplicate the core info.
287 for (self.cores[0..self.core_no]) |it| {
288 if (std.meta.eql(it, self.cores[self.core_no]))
289 return;
329 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
330 // The `cpu model` line always comes before `isa`, which is perfect for us since we
331 // want the explicit model to take precedence over the generic ISA identifier.
332 if (mem.eql(u8, key, "cpu model")) {
333 inline for (cpu_names) |pair| {
334 if (mem.find(u8, value, pair[0]) != null) {
335 self.model = pair[1];
336 return false;
337 }
338 }
339 } else if (mem.eql(u8, key, "isa")) {
340 inline for (isa_names) |pair| {
341 if (mem.find(u8, value, pair[0]) != null) {
342 self.model = pair[1];
343 break;
344 }
345 }
346
347 // If we haven't found anything useful by here, we we may as well stop.
348 return false;
290349 }
350
351 return true;
291352 }
292 self.core_no += 1;
293 }
294 }
295353
296 fn line_hook(self: *ArmCpuinfoImpl, key: []const u8, value: []const u8) !bool {
297 const info = &self.cores[self.core_no];
298
299 if (mem.eql(u8, key, "processor")) {
300 // Handle both old-style and new-style cpuinfo formats.
301 // The former prints a sequence of "processor: N" lines for each
302 // core and then the info for the core that's executing this code(!)
303 // while the latter prints the infos for each core right after the
304 // "processor" key.
305 self.have_fields = 0;
306 self.cores[self.core_no] = .{};
307 } else if (mem.eql(u8, key, "CPU implementer")) {
308 info.implementer = try fmt.parseInt(u8, value, 0);
309 self.have_fields += 1;
310 } else if (mem.eql(u8, key, "CPU architecture")) {
311 // "AArch64" on older kernels.
312 info.architecture = if (mem.startsWith(u8, value, "AArch64"))
313 8
314 else
315 try fmt.parseInt(u8, value, 0);
316 self.have_fields += 1;
317 } else if (mem.eql(u8, key, "CPU variant")) {
318 info.variant = try fmt.parseInt(u8, value, 0);
319 self.have_fields += 1;
320 } else if (mem.eql(u8, key, "CPU part")) {
321 info.part = try fmt.parseInt(u16, value, 0);
322 self.have_fields += 1;
323 } else if (mem.eql(u8, key, "model name")) {
324 // ARMv6 cores report "CPU architecture" equal to 7.
325 if (mem.find(u8, value, "(v6l)")) |_| {
326 info.is_really_v6 = true;
354 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
355 const model = self.model orelse return null;
356 return .{
357 .arch = arch,
358 .model = model,
359 .features = model.features,
360 };
327361 }
328 } else if (mem.eql(u8, key, "CPU revision")) {
329 // This field is always the last one for each CPU section.
330 _ = self.addOne();
331 }
362 };
332363
333 return true;
364 const Parser = CpuinfoParser(Impl);
365 };
366
367 test cpuinfo {
368 try testParser(cpuinfo.Parser, .mips64, &Target.mips.cpu.@"octeon+",
369 \\system type : UBNT_E300
370 \\machine : Unknown
371 \\processor : 0
372 \\cpu model : Cavium Octeon III V0.2 FPU V0.0
373 \\BogoMIPS : 2000.00
374 \\wait instruction : yes
375 \\microsecond timers : yes
376 \\tlb_entries : 256
377 \\extra interrupt vector : yes
378 \\hardware watchpoint : yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
379 \\isa : mips1 mips2 mips3 mips4 mips5 mips64r2
380 \\ASEs implemented : vz
381 \\shadow register sets : 1
382 \\kscratch registers : 4
383 \\package : 0
384 \\core : 0
385 \\VCED exceptions : not available
386 \\VCEI exceptions : not available
387 );
334388 }
335389
336 fn finalize(self: *ArmCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {
337 if (self.core_no == 0) return null;
390 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
391 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
392 defer file.close(io);
338393
339 const is_64bit = switch (arch) {
340 .aarch64, .aarch64_be => true,
341 else => false,
342 };
394 var buffer: [4096]u8 = undefined;
395 var file_reader = file.reader(io, &buffer);
343396
344 var known_models: [num_cores]?*const Target.Cpu.Model = undefined;
345 for (self.cores[0..self.core_no], 0..) |core, i| {
346 known_models[i] = cpu_models.isKnown(.{
347 .architecture = core.architecture,
348 .implementer = core.implementer,
349 .variant = core.variant,
350 .part = core.part,
351 }, is_64bit);
352 }
397 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
353398
354 // XXX We pick the first core on big.LITTLE systems, hopefully the
355 // LITTLE one.
356 const model = known_models[0] orelse return null;
357 return Target.Cpu{
358 .arch = arch,
359 .model = model,
360 .features = model.features,
361 };
399 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
400
401 return cpu;
362402 }
363403};
364404
365const ArmCpuinfoParser = CpuinfoParser(ArmCpuinfoImpl);
366
367test "cpuinfo: ARM" {
368 try testParser(ArmCpuinfoParser, .arm, &Target.arm.cpu.arm1176jz_s,
369 \\processor : 0
370 \\model name : ARMv6-compatible processor rev 7 (v6l)
371 \\BogoMIPS : 997.08
372 \\Features : half thumb fastmult vfp edsp java tls
373 \\CPU implementer : 0x41
374 \\CPU architecture: 7
375 \\CPU variant : 0x0
376 \\CPU part : 0xb76
377 \\CPU revision : 7
378 );
379 try testParser(ArmCpuinfoParser, .arm, &Target.arm.cpu.cortex_a7,
380 \\processor : 0
381 \\model name : ARMv7 Processor rev 3 (v7l)
382 \\BogoMIPS : 18.00
383 \\Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
384 \\CPU implementer : 0x41
385 \\CPU architecture: 7
386 \\CPU variant : 0x0
387 \\CPU part : 0xc07
388 \\CPU revision : 3
389 \\
390 \\processor : 4
391 \\model name : ARMv7 Processor rev 3 (v7l)
392 \\BogoMIPS : 90.00
393 \\Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
394 \\CPU implementer : 0x41
395 \\CPU architecture: 7
396 \\CPU variant : 0x2
397 \\CPU part : 0xc0f
398 \\CPU revision : 3
399 );
400 try testParser(ArmCpuinfoParser, .aarch64, &Target.aarch64.cpu.cortex_a72,
401 \\processor : 0
402 \\BogoMIPS : 108.00
403 \\Features : fp asimd evtstrm crc32 cpuid
404 \\CPU implementer : 0x41
405 \\CPU architecture: 8
406 \\CPU variant : 0x0
407 \\CPU part : 0xd08
408 \\CPU revision : 3
409 );
410}
405const powerpc = struct {
406 const cpuinfo = struct {
407 const Impl = struct {
408 model: ?*const Target.Cpu.Model = null,
409
410 const cpu_names = .{
411 .{ "440EPX", &Target.powerpc.cpu.@"440" },
412 .{ "440EP", &Target.powerpc.cpu.@"440" },
413 .{ "460EX", &Target.powerpc.cpu.@"440" },
414 .{ "440GP", &Target.powerpc.cpu.@"440" },
415 .{ "440GRX", &Target.powerpc.cpu.@"440" },
416 .{ "440GR", &Target.powerpc.cpu.@"440" },
417 .{ "460GT", &Target.powerpc.cpu.@"440" },
418 .{ "440GX", &Target.powerpc.cpu.@"440" },
419 .{ "440SPe", &Target.powerpc.cpu.@"440" },
420 .{ "440SP", &Target.powerpc.cpu.@"440" },
421 .{ "460SX", &Target.powerpc.cpu.@"440" },
422 .{ "603ev", &Target.powerpc.cpu.@"603ev" },
423 .{ "603e", &Target.powerpc.cpu.@"603e" },
424 .{ "603", &Target.powerpc.cpu.@"603" },
425 .{ "604ev", &Target.powerpc.cpu.@"604e" },
426 .{ "604e", &Target.powerpc.cpu.@"604e" },
427 .{ "604r", &Target.powerpc.cpu.@"603e" },
428 .{ "604", &Target.powerpc.cpu.@"604" },
429 .{ "7400", &Target.powerpc.cpu.@"7400" },
430 .{ "7410", &Target.powerpc.cpu.@"7400" },
431 .{ "7447/7457", &Target.powerpc.cpu.@"7450" },
432 .{ "7447A", &Target.powerpc.cpu.@"7450" },
433 .{ "7448", &Target.powerpc.cpu.@"7450" },
434 .{ "7450", &Target.powerpc.cpu.@"7450" },
435 .{ "7455", &Target.powerpc.cpu.@"7450" },
436 .{ "740/750", &Target.powerpc.cpu.@"750" },
437 .{ "745/755", &Target.powerpc.cpu.@"750" },
438 .{ "750CL", &Target.powerpc.cpu.@"750" },
439 .{ "750CXe", &Target.powerpc.cpu.@"750" },
440 .{ "750CX", &Target.powerpc.cpu.@"750" },
441 .{ "750FX", &Target.powerpc.cpu.@"750" },
442 .{ "750GX", &Target.powerpc.cpu.@"750" },
443 .{ "82xx", &Target.powerpc.cpu.@"603e" },
444 .{ "APM821XX", &Target.powerpc.cpu.@"440" },
445 .{ "Cell", &Target.powerpc.cpu.ppc64 }, // TODO: Change with LLVM 23.
446 .{ "e300c1", &Target.powerpc.cpu.@"603e" },
447 .{ "e300c2", &Target.powerpc.cpu.@"603e" },
448 .{ "e300c3", &Target.powerpc.cpu.@"603e" },
449 .{ "e300c4", &Target.powerpc.cpu.@"603e" },
450 .{ "e500mc", &Target.powerpc.cpu.e500mc },
451 .{ "e500v2", &Target.powerpc.cpu.e500 }, // TODO: Change with LLVM 23.
452 .{ "e500", &Target.powerpc.cpu.e500 },
453 .{ "e5500", &Target.powerpc.cpu.e5500 },
454 .{ "e6500", &Target.powerpc.cpu.e5500 }, // TODO: Change with LLVM 23.
455 .{ "G2_LE", &Target.powerpc.cpu.@"603e" },
456 .{ "HX-C2000", &Target.powerpc.cpu.pwr8 },
457 .{ "POWER5+", &Target.powerpc.cpu.pwr5x },
458 .{ "POWER5", &Target.powerpc.cpu.pwr5 },
459 .{ "POWER6", &Target.powerpc.cpu.pwr6 },
460 .{ "POWER7+", &Target.powerpc.cpu.pwr7 },
461 .{ "POWER7", &Target.powerpc.cpu.pwr7 },
462 .{ "POWER8E", &Target.powerpc.cpu.pwr8 },
463 .{ "POWER8NVL", &Target.powerpc.cpu.pwr8 },
464 .{ "POWER8", &Target.powerpc.cpu.pwr8 },
465 .{ "POWER9P", &Target.powerpc.cpu.pwr9 },
466 .{ "POWER9", &Target.powerpc.cpu.pwr9 },
467 .{ "POWER10", &Target.powerpc.cpu.pwr10 },
468 .{ "Power11", &Target.powerpc.cpu.pwr11 },
469 .{ "PPC970FX", &Target.powerpc.cpu.@"970" },
470 .{ "PPC970GX", &Target.powerpc.cpu.@"970" },
471 .{ "PPC970MP", &Target.powerpc.cpu.@"970" },
472 .{ "PPC970", &Target.powerpc.cpu.@"970" },
473 };
411474
412fn testParser(
413 parser: anytype,
414 arch: Target.Cpu.Arch,
415 expected_model: *const Target.Cpu.Model,
416 input: []const u8,
417) !void {
418 var r: Io.Reader = .fixed(input);
419 const result = try parser.parse(arch, &r);
420 try testing.expectEqual(expected_model, result.?.model);
421 try testing.expect(expected_model.features.eql(result.?.features));
422}
475 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
476 if (mem.eql(u8, key, "cpu")) {
477 // The model name is often followed by a comma or space and extra
478 // info.
479 inline for (cpu_names) |pair| {
480 const end_index = mem.findAny(u8, value, ", ") orelse value.len;
481 if (mem.eql(u8, value[0..end_index], pair[0])) {
482 self.model = pair[1];
483 break;
484 }
485 }
486
487 // Stop the detection once we've seen the first core.
488 return false;
489 }
423490
424// The generic implementation of a /proc/cpuinfo parser.
425// For every line it invokes the line_hook method with the key and value strings
426// as first and second parameters. Returning false from the hook function stops
427// the iteration without raising an error.
428// When all the lines have been analyzed the finalize method is called.
429fn CpuinfoParser(comptime impl: anytype) type {
430 return struct {
431 fn parse(arch: Target.Cpu.Arch, reader: *Io.Reader) !?Target.Cpu {
432 var obj: impl = .{};
433 while (try reader.takeDelimiter('\n')) |line| {
434 const colon_pos = mem.findScalar(u8, line, ':') orelse continue;
435 const key = mem.trimEnd(u8, line[0..colon_pos], " \t");
436 const value = mem.trimStart(u8, line[colon_pos + 1 ..], " \t");
437 if (!try obj.line_hook(key, value)) break;
491 return true;
438492 }
439 return obj.finalize(arch);
440 }
493
494 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
495 const model = self.model orelse return null;
496 return Target.Cpu{
497 .arch = arch,
498 .model = model,
499 .features = model.features,
500 };
501 }
502 };
503
504 const Parser = CpuinfoParser(Impl);
441505 };
442}
443506
444const aarch64 = struct {
445 inline fn mrs(comptime feat_reg: []const u8) u64 {
446 return asm ("mrs %[ret], " ++ feat_reg
447 : [ret] "=r" (-> u64),
507 test cpuinfo {
508 try testParser(cpuinfo.Parser, .powerpc, &Target.powerpc.cpu.@"970",
509 \\processor : 0
510 \\cpu : PPC970MP, altivec supported
511 \\clock : 1250.000000MHz
512 \\revision : 1.1 (pvr 0044 0101)
513 );
514 try testParser(cpuinfo.Parser, .powerpc64le, &Target.powerpc.cpu.pwr8,
515 \\processor : 0
516 \\cpu : POWER8 (raw), altivec supported
517 \\clock : 2926.000000MHz
518 \\revision : 2.0 (pvr 004d 0200)
448519 );
449520 }
521
522 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
523 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
524 defer file.close(io);
525
526 var buffer: [4096]u8 = undefined;
527 var file_reader = file.reader(io, &buffer);
528
529 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
530
531 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
532
533 return cpu;
534 }
450535};
451536
452537const riscv = struct {
453 const linux = std.os.linux;
454 const RISCV_HWPROBE = linux.RISCV_HWPROBE;
538 const cpuinfo = struct {
539 const Impl = struct {
540 model: ?*const Target.Cpu.Model = null,
541
542 const cpu_names = .{
543 .{ "andestech,ax45mp", &Target.riscv.cpu.andes_ax45 },
544 .{ "sifive,bullet0", &Target.riscv.cpu.sifive_u74 },
545 .{ "sifive,p550", &Target.riscv.cpu.sifive_p550 },
546 .{ "sifive,u54", &Target.riscv.cpu.sifive_u54 },
547 .{ "sifive,u54-mc", &Target.riscv.cpu.sifive_u54 },
548 .{ "sifive,u7", &Target.riscv.cpu.sifive_u74 },
549 .{ "sifive,u74", &Target.riscv.cpu.sifive_u74 },
550 .{ "sifive,u74-mc", &Target.riscv.cpu.sifive_u74 },
551 .{ "sifive,x280", &Target.riscv.cpu.sifive_x280 },
552 .{ "spacemit,x60", &Target.riscv.cpu.spacemit_x60 },
553 .{ "spacemit,x100", &Target.riscv.cpu.spacemit_x100 },
554 };
555
556 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
557 if (mem.eql(u8, key, "uarch")) {
558 inline for (cpu_names) |pair| {
559 if (mem.eql(u8, value, pair[0])) {
560 self.model = pair[1];
561 break;
562 }
563 }
564 return false;
565 }
566
567 return true;
568 }
569
570 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
571 const model = self.model orelse return null;
572 return Target.Cpu{
573 .arch = arch,
574 .model = model,
575 .features = model.features,
576 };
577 }
578 };
579
580 const Parser = CpuinfoParser(Impl);
581 };
582
583 test cpuinfo {
584 try testParser(cpuinfo.Parser, .riscv64, &Target.riscv.cpu.sifive_u74,
585 \\processor : 0
586 \\hart : 1
587 \\isa : rv64imafdc
588 \\mmu : sv39
589 \\isa-ext :
590 \\uarch : sifive,u74-mc
591 );
592 }
455593
456594 fn setFeature(cpu: *Target.Cpu, feature: Target.riscv.Feature, enabled: bool) void {
457595 const idx = @as(Target.Cpu.Feature.Set.Index, @backingInt(feature));
......@@ -463,8 +601,18 @@ const riscv = struct {
463601 return (value & mask) == mask;
464602 }
465603
466 pub fn detectCpuFeatures(cpu: *Target.Cpu) void {
467 var probes = [_]linux.riscv_hwprobe{
604 pub fn detectNativeCpuAndFeatures(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
605 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
606 defer file.close(io);
607
608 var buffer: [4096]u8 = undefined;
609 var file_reader = file.reader(io, &buffer);
610
611 const maybe_cpu = cpuinfo.Parser.parse(arch, &file_reader.interface) catch null;
612
613 const RISCV_HWPROBE = std.os.linux.RISCV_HWPROBE;
614
615 var probes = [_]std.os.linux.riscv_hwprobe{
468616 .{ .key = RISCV_HWPROBE.KEY.BASE_BEHAVIOR, .value = 0 },
469617 .{ .key = RISCV_HWPROBE.KEY.IMA_EXT_0, .value = 0 },
470618 .{ .key = RISCV_HWPROBE.KEY.MISALIGNED_SCALAR_PERF, .value = 0 },
......@@ -474,9 +622,25 @@ const riscv = struct {
474622 .{ .key = RISCV_HWPROBE.KEY.IMA_EXT_1, .value = 0 },
475623 };
476624
477 const rc = linux.sys_riscv_hwprobe(&probes, probes.len, 0, null, 0);
478 if (linux.errno(rc) == .NOSYS)
479 return;
625 const rc = std.os.linux.sys_riscv_hwprobe(&probes, probes.len, 0, null, 0);
626 if (std.os.linux.errno(rc) == .NOSYS) {
627 // Even if SYS_riscv_hwprobe is unavailable, we should still return
628 // the model if we managed to detect it.
629 var cpu = maybe_cpu orelse return null;
630
631 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
632
633 return cpu;
634 }
635
636 var cpu: Target.Cpu = maybe_cpu orelse cpu: {
637 const model = Target.Cpu.Model.generic(arch);
638 break :cpu .{
639 .arch = arch,
640 .model = model,
641 .features = model.features,
642 };
643 };
480644
481645 var ima_support = false;
482646 for (probes) |probe| {
......@@ -486,153 +650,299 @@ const riscv = struct {
486650 -1 => continue, // The running kernel doesn't know this key.
487651 RISCV_HWPROBE.KEY.BASE_BEHAVIOR => {
488652 ima_support = set(value, RISCV_HWPROBE.BASE_BEHAVIOR_IMA);
489 setFeature(cpu, Target.riscv.Feature.i, ima_support);
490 setFeature(cpu, Target.riscv.Feature.m, ima_support);
491 setFeature(cpu, Target.riscv.Feature.a, ima_support);
653 setFeature(&cpu, Target.riscv.Feature.i, ima_support);
654 setFeature(&cpu, Target.riscv.Feature.m, ima_support);
655 setFeature(&cpu, Target.riscv.Feature.a, ima_support);
492656 },
493657 RISCV_HWPROBE.KEY.IMA_EXT_0 => {
494658 // https://bugzilla.kernel.org/show_bug.cgi?id=221874
495659 const fd_support = set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_FD);
496 setFeature(cpu, .f, ima_support and fd_support);
497 setFeature(cpu, .d, ima_support and fd_support);
498 setFeature(cpu, .c, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_C));
499 setFeature(cpu, .v, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_V));
500 setFeature(cpu, .zba, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBA));
501 setFeature(cpu, .zbb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBB));
502 setFeature(cpu, .zbs, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBS));
503 setFeature(cpu, .zicboz, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOZ));
504 setFeature(cpu, .zbc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBC));
505 setFeature(cpu, .zbkb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKB));
506 setFeature(cpu, .zbkc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKC));
507 setFeature(cpu, .zbkx, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKX));
508 setFeature(cpu, .zknd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKND));
509 setFeature(cpu, .zkne, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKNE));
510 setFeature(cpu, .zknh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKNH));
511 setFeature(cpu, .zksed, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKSED));
512 setFeature(cpu, .zksh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKSH));
513 setFeature(cpu, .zkt, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKT));
514 setFeature(cpu, .zvbb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVBB));
515 setFeature(cpu, .zvbc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVBC));
516 setFeature(cpu, .zvkb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKB));
517 setFeature(cpu, .zvkg, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKG));
518 setFeature(cpu, .zvkned, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNED));
519 setFeature(cpu, .zvknha, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNHA));
520 setFeature(cpu, .zvknhb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNHB));
521 setFeature(cpu, .zvksed, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKSED));
522 setFeature(cpu, .zvksh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKSH));
523 setFeature(cpu, .zvkt, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKT));
524 setFeature(cpu, .zfh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFH));
525 setFeature(cpu, .zfhmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFHMIN));
526 setFeature(cpu, .zihintntl, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHINTNTL));
527 setFeature(cpu, .zvfh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFH));
528 setFeature(cpu, .zvfhmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFHMIN));
529 setFeature(cpu, .zfa, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFA));
530 setFeature(cpu, .ztso, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZTSO));
531 setFeature(cpu, .zacas, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZACAS));
532 setFeature(cpu, .zicntr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICNTR));
533 setFeature(cpu, .zicond, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICOND));
534 setFeature(cpu, .zihintpause, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHINTPAUSE));
535 setFeature(cpu, .zihpm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHPM));
536 setFeature(cpu, .zve32x, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE32X));
537 setFeature(cpu, .zve32f, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE32F));
538 setFeature(cpu, .zve64x, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64X));
539 setFeature(cpu, .zve64f, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64F));
540 setFeature(cpu, .zve64d, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64D));
541 setFeature(cpu, .zimop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIMOP));
542 setFeature(cpu, .zca, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCA));
543 setFeature(cpu, .zcb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCB));
544 setFeature(cpu, .zcd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCD));
545 setFeature(cpu, .zcf, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCF));
546 setFeature(cpu, .zcmop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCMOP));
547 setFeature(cpu, .zawrs, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZAWRS));
548 setFeature(cpu, .supm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_SUPM));
549 setFeature(cpu, .zicntr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICNTR));
550 setFeature(cpu, .zihpm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHPM));
551 setFeature(cpu, .zfbfmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFBFMIN));
552 setFeature(cpu, .zvfbfmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFBFMIN));
553 setFeature(cpu, .zvfbfwma, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFBFWMA));
554 setFeature(cpu, .zicbom, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOM));
555 setFeature(cpu, .zaamo, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZAAMO));
556 setFeature(cpu, .zalrsc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZALRSC));
557 setFeature(cpu, .zabha, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZABHA));
558 setFeature(cpu, .zalasr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZALASR));
559 setFeature(cpu, .zicbop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOP));
560 setFeature(cpu, .zilsd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZILSD));
561 setFeature(cpu, .zclsd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCLSD));
562 setFeature(cpu, .experimental_zicfilp, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICFILP));
660 setFeature(&cpu, .f, ima_support and fd_support);
661 setFeature(&cpu, .d, ima_support and fd_support);
662 setFeature(&cpu, .c, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_C));
663 setFeature(&cpu, .v, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_V));
664 setFeature(&cpu, .zba, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBA));
665 setFeature(&cpu, .zbb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBB));
666 setFeature(&cpu, .zbs, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBS));
667 setFeature(&cpu, .zicboz, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOZ));
668 setFeature(&cpu, .zbc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBC));
669 setFeature(&cpu, .zbkb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKB));
670 setFeature(&cpu, .zbkc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKC));
671 setFeature(&cpu, .zbkx, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZBKX));
672 setFeature(&cpu, .zknd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKND));
673 setFeature(&cpu, .zkne, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKNE));
674 setFeature(&cpu, .zknh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKNH));
675 setFeature(&cpu, .zksed, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKSED));
676 setFeature(&cpu, .zksh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKSH));
677 setFeature(&cpu, .zkt, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZKT));
678 setFeature(&cpu, .zvbb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVBB));
679 setFeature(&cpu, .zvbc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVBC));
680 setFeature(&cpu, .zvkb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKB));
681 setFeature(&cpu, .zvkg, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKG));
682 setFeature(&cpu, .zvkned, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNED));
683 setFeature(&cpu, .zvknha, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNHA));
684 setFeature(&cpu, .zvknhb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKNHB));
685 setFeature(&cpu, .zvksed, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKSED));
686 setFeature(&cpu, .zvksh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKSH));
687 setFeature(&cpu, .zvkt, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVKT));
688 setFeature(&cpu, .zfh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFH));
689 setFeature(&cpu, .zfhmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFHMIN));
690 setFeature(&cpu, .zihintntl, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHINTNTL));
691 setFeature(&cpu, .zvfh, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFH));
692 setFeature(&cpu, .zvfhmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFHMIN));
693 setFeature(&cpu, .zfa, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFA));
694 setFeature(&cpu, .ztso, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZTSO));
695 setFeature(&cpu, .zacas, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZACAS));
696 setFeature(&cpu, .zicntr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICNTR));
697 setFeature(&cpu, .zicond, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICOND));
698 setFeature(&cpu, .zihintpause, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHINTPAUSE));
699 setFeature(&cpu, .zihpm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHPM));
700 setFeature(&cpu, .zve32x, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE32X));
701 setFeature(&cpu, .zve32f, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE32F));
702 setFeature(&cpu, .zve64x, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64X));
703 setFeature(&cpu, .zve64f, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64F));
704 setFeature(&cpu, .zve64d, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVE64D));
705 setFeature(&cpu, .zimop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIMOP));
706 setFeature(&cpu, .zca, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCA));
707 setFeature(&cpu, .zcb, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCB));
708 setFeature(&cpu, .zcd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCD));
709 setFeature(&cpu, .zcf, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCF));
710 setFeature(&cpu, .zcmop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCMOP));
711 setFeature(&cpu, .zawrs, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZAWRS));
712 setFeature(&cpu, .supm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_SUPM));
713 setFeature(&cpu, .zicntr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICNTR));
714 setFeature(&cpu, .zihpm, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZIHPM));
715 setFeature(&cpu, .zfbfmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZFBFMIN));
716 setFeature(&cpu, .zvfbfmin, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFBFMIN));
717 setFeature(&cpu, .zvfbfwma, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZVFBFWMA));
718 setFeature(&cpu, .zicbom, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOM));
719 setFeature(&cpu, .zaamo, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZAAMO));
720 setFeature(&cpu, .zalrsc, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZALRSC));
721 setFeature(&cpu, .zabha, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZABHA));
722 setFeature(&cpu, .zalasr, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZALASR));
723 setFeature(&cpu, .zicbop, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICBOP));
724 setFeature(&cpu, .zilsd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZILSD));
725 setFeature(&cpu, .zclsd, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZCLSD));
726 setFeature(&cpu, .experimental_zicfilp, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICFILP));
563727 },
564728 RISCV_HWPROBE.KEY.MISALIGNED_SCALAR_PERF => {
565 setFeature(cpu, .unaligned_scalar_mem, value == RISCV_HWPROBE.MISALIGNED_SCALAR.FAST);
729 setFeature(&cpu, .unaligned_scalar_mem, value == RISCV_HWPROBE.MISALIGNED_SCALAR.FAST);
566730 },
567731 RISCV_HWPROBE.KEY.MISALIGNED_VECTOR_PERF => {
568 setFeature(cpu, .unaligned_vector_mem, value == RISCV_HWPROBE.MISALIGNED_VECTOR.FAST);
732 setFeature(&cpu, .unaligned_vector_mem, value == RISCV_HWPROBE.MISALIGNED_VECTOR.FAST);
569733 },
570734 RISCV_HWPROBE.KEY.VENDOR_EXT_MIPS_0 => {
571 setFeature(cpu, .xmipsexectl, ima_support and set(value, RISCV_HWPROBE.MIPS_VENDOR_EXT_XMIPSEXECTL));
735 setFeature(&cpu, .xmipsexectl, ima_support and set(value, RISCV_HWPROBE.MIPS_VENDOR_EXT_XMIPSEXECTL));
572736 },
573737 RISCV_HWPROBE.KEY.VENDOR_EXT_SIFIVE_0 => {
574 setFeature(cpu, .xsfvqmaccdod, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVQMACCDOD));
575 setFeature(cpu, .xsfvqmaccqoq, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVQMACCQOQ));
576 setFeature(cpu, .xsfvfnrclipxfqf, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVFNRCLIPXFQF));
577 setFeature(cpu, .xsfvfwmaccqqq, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVFWMACCQQQ));
738 setFeature(&cpu, .xsfvqmaccdod, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVQMACCDOD));
739 setFeature(&cpu, .xsfvqmaccqoq, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVQMACCQOQ));
740 setFeature(&cpu, .xsfvfnrclipxfqf, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVFNRCLIPXFQF));
741 setFeature(&cpu, .xsfvfwmaccqqq, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVFWMACCQQQ));
578742 },
579743 RISCV_HWPROBE.KEY.IMA_EXT_1 => {
580 setFeature(cpu, .experimental_zicfiss, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_1_EXT_ZICFISS));
744 setFeature(&cpu, .experimental_zicfiss, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_1_EXT_ZICFISS));
581745 },
582746 else => unreachable,
583747 }
584748 }
749
750 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
751
752 return cpu;
585753 }
586754};
587755
588pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu {
589 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch |err| switch (err) {
590 else => return null,
756const s390x = struct {
757 const cpuinfo = struct {
758 const Impl = struct {
759 model: ?*const Target.Cpu.Model = null,
760
761 const cpu_names = .{
762 .{ "2097", &Target.s390x.cpu.z10 },
763 .{ "2098", &Target.s390x.cpu.z10 },
764 .{ "2817", &Target.s390x.cpu.z196 },
765 .{ "2818", &Target.s390x.cpu.z196 },
766 .{ "2827", &Target.s390x.cpu.zEC12 },
767 .{ "2828", &Target.s390x.cpu.zEC12 },
768 .{ "2964", &Target.s390x.cpu.z13 },
769 .{ "2965", &Target.s390x.cpu.z13 },
770 .{ "3906", &Target.s390x.cpu.z14 },
771 .{ "3907", &Target.s390x.cpu.z14 },
772 .{ "8561", &Target.s390x.cpu.z15 },
773 .{ "8562", &Target.s390x.cpu.z15 },
774 .{ "3931", &Target.s390x.cpu.z16 },
775 .{ "3932", &Target.s390x.cpu.z16 },
776 .{ "9175", &Target.s390x.cpu.z17 },
777 .{ "9176", &Target.s390x.cpu.z17 },
778 };
779
780 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
781 if (mem.eql(u8, key, "machine")) {
782 inline for (cpu_names) |pair| {
783 if (mem.eql(u8, value, pair[0])) {
784 self.model = pair[1];
785 break;
786 }
787 }
788
789 return false;
790 }
791
792 return true;
793 }
794
795 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
796 const model = self.model orelse return null;
797 return Target.Cpu{
798 .arch = arch,
799 .model = model,
800 .features = model.features,
801 };
802 }
803 };
804
805 const Parser = CpuinfoParser(Impl);
591806 };
592 defer file.close(io);
593807
594 var buffer: [4096]u8 = undefined; // "flags" lines can get pretty long.
595 var file_reader = file.reader(io, &buffer);
808 test cpuinfo {
809 try testParser(cpuinfo.Parser, .s390x, &Target.s390x.cpu.z15,
810 \\physical id : 5
811 \\core id : 5
812 \\book id : 5
813 \\drawer id : 5
814 \\dedicated : 0
815 \\address : 5
816 \\siblings : 1
817 \\cpu cores : 1
818 \\version : FF
819 \\identification : 09DD98
820 \\machine : 8561
821 \\cpu MHz dynamic : 5200
822 \\cpu MHz static : 5200
823 );
824 }
596825
597 const current_arch = builtin.cpu.arch;
598 return switch (current_arch) {
599 .aarch64, .aarch64_be => b: {
600 const registers = [12]u64{
601 aarch64.mrs("MIDR_EL1"),
602 aarch64.mrs("ID_AA64PFR0_EL1"),
603 aarch64.mrs("ID_AA64PFR1_EL1"),
604 aarch64.mrs("ID_AA64DFR0_EL1"),
605 aarch64.mrs("ID_AA64DFR1_EL1"),
606 aarch64.mrs("ID_AA64AFR0_EL1"),
607 aarch64.mrs("ID_AA64AFR1_EL1"),
608 aarch64.mrs("ID_AA64ISAR0_EL1"),
609 aarch64.mrs("ID_AA64ISAR1_EL1"),
610 aarch64.mrs("ID_AA64MMFR0_EL1"),
611 aarch64.mrs("ID_AA64MMFR1_EL1"),
612 aarch64.mrs("ID_AA64MMFR2_EL1"),
826 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
827 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
828 defer file.close(io);
829
830 var buffer: [4096]u8 = undefined;
831 var file_reader = file.reader(io, &buffer);
832
833 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
834
835 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
836
837 return cpu;
838 }
839};
840
841const sparc = struct {
842 const cpuinfo = struct {
843 const Impl = struct {
844 model: ?*const Target.Cpu.Model = null,
845
846 const cpu_names = .{
847 .{ "BlackBird", &Target.sparc.cpu.ultrasparc },
848 .{ "Cheetah", &Target.sparc.cpu.ultrasparc3 },
849 .{ "Hummingbird", &Target.sparc.cpu.ultrasparc },
850 .{ "HyperSparc", &Target.sparc.cpu.hypersparc },
851 .{ "Jaguar", &Target.sparc.cpu.ultrasparc3 },
852 .{ "Jalapeno", &Target.sparc.cpu.ultrasparc3 },
853 .{ "LEON", &Target.sparc.cpu.leon3 },
854 .{ "MB86904", &Target.sparc.cpu.v8 },
855 .{ "MB86907", &Target.sparc.cpu.v8 },
856 .{ "MicroSparc II", &Target.sparc.cpu.v8 },
857 .{ "MicroSparc", &Target.sparc.cpu.v8 },
858 .{ "Panther", &Target.sparc.cpu.ultrasparc3 },
859 .{ "Sabre", &Target.sparc.cpu.ultrasparc },
860 .{ "Serrano", &Target.sparc.cpu.ultrasparc3 },
861 .{ "SPARC-M6", &Target.sparc.cpu.niagara4 },
862 .{ "SPARC-M7", &Target.sparc.cpu.niagara4 },
863 .{ "SPARC-M8", &Target.sparc.cpu.niagara4 },
864 .{ "SPARC-SN", &Target.sparc.cpu.niagara4 },
865 .{ "SPARC64-X", &Target.sparc.cpu.ultrasparc3 },
866 .{ "SpitFire", &Target.sparc.cpu.ultrasparc },
867 .{ "SuperSparc", &Target.sparc.cpu.supersparc },
868 .{ "UltraSparc T1", &Target.sparc.cpu.niagara },
869 .{ "UltraSparc T2", &Target.sparc.cpu.niagara2 },
870 .{ "UltraSparc T3", &Target.sparc.cpu.niagara3 },
871 .{ "UltraSparc T4", &Target.sparc.cpu.niagara4 },
872 .{ "UltraSparc T5", &Target.sparc.cpu.niagara4 },
613873 };
614874
615 break :b @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers);
616 },
617 .arm, .armeb, .thumb, .thumbeb => ArmCpuinfoParser.parse(current_arch, &file_reader.interface) catch null,
618 .powerpc, .powerpcle, .powerpc64, .powerpc64le => PowerpcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null,
619 .riscv64, .riscv32 => b: {
620 var cpu = (RiscvCpuinfoParser.parse(current_arch, &file_reader.interface) catch null) orelse cpu: {
621 const model = Target.Cpu.Model.generic(current_arch);
622 break :cpu Target.Cpu{
623 .arch = current_arch,
875 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
876 if (mem.eql(u8, key, "cpu")) {
877 inline for (cpu_names) |pair| {
878 if (mem.findPos(u8, value, 0, pair[0]) != null) {
879 self.model = pair[1];
880 break;
881 }
882 }
883 }
884
885 return true;
886 }
887
888 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
889 const model = self.model orelse return null;
890 return Target.Cpu{
891 .arch = arch,
624892 .model = model,
625893 .features = model.features,
626894 };
627 };
895 }
896 };
628897
629 riscv.detectCpuFeatures(&cpu);
630 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
898 const Parser = CpuinfoParser(Impl);
899 };
631900
632 break :b cpu;
633 },
634 .s390x => S390xCpuinfoParser.parse(current_arch, &file_reader.interface) catch null,
635 .sparc, .sparc64 => SparcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null,
901 test cpuinfo {
902 try testParser(cpuinfo.Parser, .sparc64, &Target.sparc.cpu.niagara2,
903 \\cpu : UltraSparc T2 (Niagara2)
904 \\fpu : UltraSparc T2 integrated FPU
905 \\pmu : niagara2
906 \\type : sun4v
907 );
908 }
909
910 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
911 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
912 defer file.close(io);
913
914 var buffer: [4096]u8 = undefined;
915 var file_reader = file.reader(io, &buffer);
916
917 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
918
919 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
920
921 return cpu;
922 }
923};
924
925pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu {
926 const current_arch = builtin.cpu.arch;
927 return switch (current_arch) {
928 .aarch64, .aarch64_be => aarch64.detectNativeCpuAndFeatures(current_arch),
929 .arm, .armeb, .thumb, .thumbeb => arm.detectNativeCpu(io, current_arch),
930 .csky => csky.detectNativeCpu(io, current_arch),
931 .m68k => m68k.detectNativeCpu(io, current_arch),
932 .mips, .mipsel, .mips64, .mips64el => mips.detectNativeCpu(io, current_arch),
933 .powerpc, .powerpcle, .powerpc64, .powerpc64le => powerpc.detectNativeCpu(io, current_arch),
934 .riscv64, .riscv32 => riscv.detectNativeCpuAndFeatures(io, current_arch),
935 .s390x => s390x.detectNativeCpu(io, current_arch),
936 .sparc, .sparc64 => sparc.detectNativeCpu(io, current_arch),
636937 else => null,
637938 };
638939}
940
941test {
942 _ = aarch64;
943 _ = arm;
944 _ = powerpc;
945 _ = riscv;
946 _ = s390x;
947 _ = sparc;
948}
lib/std/zig/system/loongarch.zig+6-3
......@@ -52,9 +52,9 @@ pub fn detectNativeCpuAndFeatures(
5252 if (builtin.os.tag == .linux) {
5353 const HWCAP = std.os.linux.HWCAP;
5454 const hwcap_bits: usize = if (builtin.link_libc)
55 std.c.getauxval(std.elf.AT_HWCAP)
55 std.c.getauxval(std.elf.AT.HWCAP)
5656 else
57 std.os.linux.getauxval(std.elf.AT_HWCAP);
57 std.os.linux.getauxval(std.elf.AT.HWCAP);
5858
5959 setFeature(&cpu, .ual, (hwcap_bits & HWCAP.UAL) != 0);
6060
......@@ -66,6 +66,8 @@ pub fn detectNativeCpuAndFeatures(
6666
6767 setFeature(&cpu, .lvz, (hwcap_bits & HWCAP.LVZ) != 0);
6868 setFeature(&cpu, .lbt, (hwcap_bits & HWCAP.LBT_X86) != 0 and (hwcap_bits & HWCAP.LBT_ARM) != 0 and (hwcap_bits & HWCAP.LBT_MIPS) != 0);
69
70 setFeature(&cpu, .lam_bh, (hwcap_bits & HWCAP.LAM_BH) != 0);
6971 } else {
7072 setFeature(&cpu, .ual, false);
7173
......@@ -76,11 +78,12 @@ pub fn detectNativeCpuAndFeatures(
7678
7779 setFeature(&cpu, .lvz, false);
7880 setFeature(&cpu, .lbt, false);
81
82 setFeature(&cpu, .lam_bh, false);
7983 }
8084
8185 setFeature(&cpu, .frecipe, bit(cfg2, 25));
8286 setFeature(&cpu, .div32, bit(cfg2, 26));
83 setFeature(&cpu, .lam_bh, bit(cfg2, 27));
8487 setFeature(&cpu, .lamcas, bit(cfg2, 28));
8588 setFeature(&cpu, .scq, bit(cfg2, 30));
8689
lib/std/zig/system/openbsd.zig+22-16
......@@ -113,32 +113,38 @@ const aarch64 = struct {
113113 }
114114
115115 fn detectNativeCpuAndFeatures(arch: std.Target.Cpu.Arch) ?std.Target.Cpu {
116 const model: *const std.Target.Cpu.Model = blk: {
116 const maybe_model: ?*const std.Target.Cpu.Model = blk: {
117117 var buf: [64:0]u8 = undefined;
118 const name = hwModelName(&buf) orelse return null;
118 const name = hwModelName(&buf) orelse break :blk null;
119119
120120 inline for (models) |pair| {
121121 if (std.mem.startsWith(u8, name, pair[0])) break :blk pair[1];
122122 }
123123
124 break :blk .generic(arch);
124 break :blk null;
125125 };
126126
127 const registers = [11]u64{
128 sysctlReg(std.c.CPU.AA64PFR0) orelse return null,
129 sysctlReg(std.c.CPU.AA64PFR1) orelse return null,
130 0, // ID_AA64DFR0_EL1
131 0, // ID_AA64DFR1_EL1
132 0, // ID_AA64AFR0_EL1
133 0, // ID_AA64AFR1_EL1
134 sysctlReg(std.c.CPU.ID_AA64ISAR0) orelse return null,
135 sysctlReg(std.c.CPU.ID_AA64ISAR1) orelse return null,
136 sysctlReg(std.c.CPU.ID_AA64MMFR0) orelse return null,
137 sysctlReg(std.c.CPU.ID_AA64MMFR1) orelse return null,
138 sysctlReg(std.c.CPU.ID_AA64MMFR2) orelse return null,
127 const registers = blk: {
128 break :blk [11]u64{
129 sysctlReg(std.c.CPU.AA64PFR0) orelse break :blk null,
130 sysctlReg(std.c.CPU.AA64PFR1) orelse break :blk null,
131 0, // ID_AA64DFR0_EL1
132 0, // ID_AA64DFR1_EL1
133 0, // ID_AA64AFR0_EL1
134 0, // ID_AA64AFR1_EL1
135 sysctlReg(std.c.CPU.ID_AA64ISAR0) orelse break :blk null,
136 sysctlReg(std.c.CPU.ID_AA64ISAR1) orelse break :blk null,
137 sysctlReg(std.c.CPU.ID_AA64MMFR0) orelse break :blk null,
138 sysctlReg(std.c.CPU.ID_AA64MMFR1) orelse break :blk null,
139 sysctlReg(std.c.CPU.ID_AA64MMFR2) orelse break :blk null,
140 };
141 } orelse {
142 // Even if the registers are unavailable, we should still return the
143 // model if we managed to detect it.
144 return if (maybe_model) |m| m.toCpu(arch) else null;
139145 };
140146
141 return @import("arm.zig").aarch64.detectNativeFeatures(arch, model, registers);
147 return @import("arm.zig").aarch64.detectNativeFeatures(arch, maybe_model orelse .generic(arch), registers);
142148 }
143149};
144150
test/standalone/glibc_compat/glibc_runtime_check.zig+2-2
......@@ -65,8 +65,8 @@ fn checkGetAuxVal() !void {
6565}
6666
6767fn checkGetAuxVal_v2_16() !void {
68 const base = std.c.getauxval(std.elf.AT_BASE);
69 const pgsz = std.c.getauxval(std.elf.AT_PAGESZ);
68 const base = std.c.getauxval(std.elf.AT.BASE);
69 const pgsz = std.c.getauxval(std.elf.AT.PAGESZ);
7070
7171 assert(base != 0);
7272 assert(pgsz != 0);