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) {...@@ -10533,8 +10533,134 @@ pub const sendfile = switch (native_os) {
10533 .linux => private.sendfile,10533 .linux => private.sendfile,
10534 else => {},10534 else => {},
10535};10535};
10536/// See std.elf for constants for this10536
10537pub extern "c" fn getauxval(__type: c_ulong) c_ulong;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
10539pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*anyopaque) c_int;10665pub 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 @@...@@ -1,56 +1,238 @@
1//! Executable and Linkable Format.1//! Executable and Linkable Format.
22
3const builtin = @import("builtin");
3const std = @import("std.zig");4const std = @import("std.zig");
4const Io = std.Io;5const Io = std.Io;
5const math = std.math;6const math = std.math;
6const mem = std.mem;7const mem = std.mem;
7const assert = std.debug.assert;8const assert = std.debug.assert;
8const Endian = std.builtin.Endian;9const Endian = std.builtin.Endian;
9const native_endian = @import("builtin").target.cpu.arch.endian();10
1011const native_endian = builtin.target.cpu.arch.endian();
11pub const AT_NULL = 0;12const native_os = builtin.target.os.tag;
12pub const AT_IGNORE = 1;13
13pub const AT_EXECFD = 2;14pub const AT = switch (native_os) {
14pub const AT_PHDR = 3;15 .dragonfly => struct {
15pub const AT_PHENT = 4;16 pub const NULL = 0;
16pub const AT_PHNUM = 5;17 pub const IGNORE = 1;
17pub const AT_PAGESZ = 6;18 pub const EXECFD = 2;
18pub const AT_BASE = 7;19 pub const PHDR = 3;
19pub const AT_FLAGS = 8;20 pub const PHENT = 4;
20pub const AT_ENTRY = 9;21 pub const PHNUM = 5;
21pub const AT_NOTELF = 10;22 pub const PAGESZ = 6;
22pub const AT_UID = 11;23 pub const BASE = 7;
23pub const AT_EUID = 12;24 pub const FLAGS = 8;
24pub const AT_GID = 13;25 pub const ENTRY = 9;
25pub const AT_EGID = 14;26 pub const NOTELF = 10;
26pub const AT_CLKTCK = 17;27 pub const UID = 11;
27pub const AT_PLATFORM = 15;28 pub const EUID = 12;
28pub const AT_HWCAP = 16;29 pub const GID = 13;
29pub const AT_FPUCW = 18;30 pub const EGID = 14;
30pub const AT_DCACHEBSIZE = 19;31 pub const EXECPATH = 15;
31pub const AT_ICACHEBSIZE = 20;32 pub const CANARY = 16;
32pub const AT_UCACHEBSIZE = 21;33 pub const CANARYLEN = 17;
33pub const AT_IGNOREPPC = 22;34 pub const OSRELDATE = 18;
34pub const AT_SECURE = 23;35 pub const NCPUS = 19;
35pub const AT_BASE_PLATFORM = 24;36 pub const PAGESIZES = 20;
36pub const AT_RANDOM = 25;37 pub const PAGESIZESLEN = 21;
37pub const AT_HWCAP2 = 26;38 pub const STACKPROT = 23;
38pub const AT_EXECFN = 31;39 },
39pub const AT_SYSINFO = 32;40 .freebsd => struct {
40pub const AT_SYSINFO_EHDR = 33;41 pub const NULL = 0;
41pub const AT_L1I_CACHESHAPE = 34;42 pub const IGNORE = 1;
42pub const AT_L1D_CACHESHAPE = 35;43 pub const EXECFD = 2;
43pub const AT_L2_CACHESHAPE = 36;44 pub const PHDR = 3;
44pub const AT_L3_CACHESHAPE = 37;45 pub const PHENT = 4;
45pub const AT_L1I_CACHESIZE = 40;46 pub const PHNUM = 5;
46pub const AT_L1I_CACHEGEOMETRY = 41;47 pub const PAGESZ = 6;
47pub const AT_L1D_CACHESIZE = 42;48 pub const BASE = 7;
48pub const AT_L1D_CACHEGEOMETRY = 43;49 pub const FLAGS = 8;
49pub const AT_L2_CACHESIZE = 44;50 pub const ENTRY = 9;
50pub const AT_L2_CACHEGEOMETRY = 45;51 pub const NOTELF = 10;
51pub const AT_L3_CACHESIZE = 46;52 pub const UID = 11;
52pub const AT_L3_CACHEGEOMETRY = 47;53 pub const EUID = 12;
53pub const AT_MINSIGSTKSZ = 51;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
55pub const DT_NULL = 0;237pub const DT_NULL = 0;
56pub const DT_NEEDED = 1;238pub const DT_NEEDED = 1;
lib/std/heap.zig+1-1
...@@ -80,7 +80,7 @@ pub fn defaultQueryPageSize() usize {...@@ -80,7 +80,7 @@ pub fn defaultQueryPageSize() usize {
80 .linux => if (builtin.link_libc)80 .linux => if (builtin.link_libc)
81 @max(std.c.sysconf(@backingInt(std.c._SC.PAGESIZE)), 0)81 @max(std.c.sysconf(@backingInt(std.c._SC.PAGESIZE)), 0)
82 else82 else
83 std.os.linux.getauxval(std.elf.AT_PAGESZ),83 std.os.linux.getauxval(std.elf.AT.PAGESZ),
84 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => {84 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => {
85 const task_port = std.c.mach_task_self();85 const task_port = std.c.mach_task_self();
86 // mach_task_self may fail "if there are any resource failures or other errors".86 // 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) {...@@ -619,6 +619,138 @@ pub const O = switch (native_arch) {
619};619};
620620
621pub const HWCAP = switch (native_arch) {621pub 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 },
622 .arm, .armeb, .thumb, .thumbeb => struct {754 .arm, .armeb, .thumb, .thumbeb => struct {
623 pub const SWP = 1 << 0;755 pub const SWP = 1 << 0;
624 pub const HALF = 1 << 1;756 pub const HALF = 1 << 1;
...@@ -643,6 +775,22 @@ pub const HWCAP = switch (native_arch) {...@@ -643,6 +775,22 @@ pub const HWCAP = switch (native_arch) {
643 pub const IDIV = IDIVA | IDIVT;775 pub const IDIV = IDIVA | IDIVT;
644 pub const LPAE = 1 << 20;776 pub const LPAE = 1 << 20;
645 pub const EVTSTRM = 1 << 21;777 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 };
646 },794 },
647 .loongarch32, .loongarch64 => struct {795 .loongarch32, .loongarch64 => struct {
648 pub const CPUCFG = 1 << 0;796 pub const CPUCFG = 1 << 0;
...@@ -661,6 +809,144 @@ pub const HWCAP = switch (native_arch) {...@@ -661,6 +809,144 @@ pub const HWCAP = switch (native_arch) {
661 pub const PTW = 1 << 13;809 pub const PTW = 1 << 13;
662 pub const LSPW = 1 << 14;810 pub const LSPW = 1 << 14;
663 pub const SCQ = 1 << 15;811 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 };
664 },950 },
665 else => struct {},951 else => struct {},
666};952};
...@@ -705,7 +991,7 @@ fn getauxvalImpl(index: usize) callconv(.c) usize {...@@ -705,7 +991,7 @@ fn getauxvalImpl(index: usize) callconv(.c) usize {
705 @disableInstrumentation();991 @disableInstrumentation();
706 const auxv = elf_aux_maybe orelse return 0;992 const auxv = elf_aux_maybe orelse return 0;
707 var i: usize = 0;993 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) {
709 if (auxv[i].a_type == index)995 if (auxv[i].a_type == index)
710 return auxv[i].a_un.a_val;996 return auxv[i].a_un.a_val;
711 }997 }
lib/std/os/linux/test.zig+4-4
...@@ -106,10 +106,10 @@ test "statx" {...@@ -106,10 +106,10 @@ test "statx" {
106106
107test "user and group ids" {107test "user and group ids" {
108 if (builtin.link_libc) return error.SkipZigTest;108 if (builtin.link_libc) return error.SkipZigTest;
109 try expectEqual(linux.getauxval(elf.AT_UID), linux.getuid());109 try expectEqual(linux.getauxval(elf.AT.UID), linux.getuid());
110 try expectEqual(linux.getauxval(elf.AT_GID), linux.getgid());110 try expectEqual(linux.getauxval(elf.AT.GID), linux.getgid());
111 try expectEqual(linux.getauxval(elf.AT_EUID), linux.geteuid());111 try expectEqual(linux.getauxval(elf.AT.EUID), linux.geteuid());
112 try expectEqual(linux.getauxval(elf.AT_EGID), linux.getegid());112 try expectEqual(linux.getauxval(elf.AT.EGID), linux.getegid());
113}113}
114114
115test "fadvise" {115test "fadvise" {
lib/std/os/linux/vdso.zig+1-1
...@@ -5,7 +5,7 @@ const mem = std.mem;...@@ -5,7 +5,7 @@ const mem = std.mem;
5const maxInt = std.math.maxInt;5const maxInt = std.math.maxInt;
66
7pub fn lookup(vername: []const u8, name: []const u8) usize {7pub 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);
9 if (vdso_addr == 0) return 0;9 if (vdso_addr == 0) return 0;
1010
11 const eh = @as(*elf.Ehdr, @ptrFromInt(vdso_addr));11 const eh = @as(*elf.Ehdr, @ptrFromInt(vdso_addr));
lib/std/posix.zig+4-4
...@@ -775,9 +775,9 @@ pub fn sysctl(...@@ -775,9 +775,9 @@ pub fn sysctl(
775775
776pub fn getSelfPhdrs() []std.elf.ElfN.Phdr {776pub fn getSelfPhdrs() []std.elf.ElfN.Phdr {
777 const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval;777 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));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));779 const phdrs: [*]std.elf.ElfN.Phdr = @ptrFromInt(getauxval(std.elf.AT.PHDR));
780 return phdrs[0..getauxval(std.elf.AT_PHNUM)];780 return phdrs[0..getauxval(std.elf.AT.PHNUM)];
781}781}
782782
783pub fn dl_iterate_phdr(783pub fn dl_iterate_phdr(
...@@ -819,7 +819,7 @@ pub fn dl_iterate_phdr(...@@ -819,7 +819,7 @@ pub fn dl_iterate_phdr(
819 .PHDR => break @intFromPtr(phdrs.ptr) - phdr.vaddr,819 .PHDR => break @intFromPtr(phdrs.ptr) - phdr.vaddr,
820 else => {},820 else => {},
821 } else unreachable,821 } else unreachable,
822 .name = switch (getauxval(std.elf.AT_EXECFN)) {822 .name = switch (getauxval(std.elf.AT.EXECFN)) {
823 0 => "/proc/self/exe",823 0 => "/proc/self/exe",
824 else => |name| @ptrFromInt(name),824 else => |name| @ptrFromInt(name),
825 },825 },
lib/std/start.zig+6-6
...@@ -617,11 +617,11 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {...@@ -617,11 +617,11 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
617 var i: usize = 0;617 var i: usize = 0;
618 var at_phdr: usize = 0;618 var at_phdr: usize = 0;
619 var at_phnum: usize = 0;619 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) {
621 switch (auxv[i].a_type) {621 switch (auxv[i].a_type) {
622 elf.AT_PHNUM => at_phnum = 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,623 elf.AT.PHDR => at_phdr = auxv[i].a_un.a_val,
624 elf.AT_HWCAP => at_hwcap = auxv[i].a_un.a_val,624 elf.AT.HWCAP => at_hwcap = auxv[i].a_un.a_val,
625 else => continue,625 else => continue,
626 }626 }
627 }627 }
...@@ -736,8 +736,8 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal...@@ -736,8 +736,8 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal
736736
737 switch (builtin.os.tag) {737 switch (builtin.os.tag) {
738 .linux => {738 .linux => {
739 const at_phdr = std.c.getauxval(elf.AT_PHDR);739 const at_phdr = std.c.getauxval(elf.AT.PHDR);
740 const at_phnum = std.c.getauxval(elf.AT_PHNUM);740 const at_phnum = std.c.getauxval(elf.AT.PHNUM);
741 const phdrs = (@as([*]elf.ElfN.Phdr, @ptrFromInt(at_phdr)))[0..at_phnum];741 const phdrs = (@as([*]elf.ElfN.Phdr, @ptrFromInt(at_phdr)))[0..at_phnum];
742 expandStackSize(phdrs);742 expandStackSize(phdrs);
743 },743 },
lib/std/zig/system/linux.zig+809-499
...@@ -9,449 +9,587 @@ const testing = std.testing;...@@ -9,449 +9,587 @@ const testing = std.testing;
9const Target = std.Target;9const Target = std.Target;
10const assert = std.debug.assert;10const assert = std.debug.assert;
1111
12const SparcCpuinfoImpl = struct {12// The generic implementation of a /proc/cpuinfo parser.
13 model: ?*const Target.Cpu.Model = null,13// For every line it invokes the lineHook method with the key and value strings
1414// as first and second parameters. Returning false from the hook function stops
15 const cpu_names = .{15// the iteration without raising an error.
16 .{ "SuperSparc", &Target.sparc.cpu.supersparc },16// When all the lines have been analyzed the finalize method is called.
17 .{ "HyperSparc", &Target.sparc.cpu.hypersparc },17fn CpuinfoParser(comptime impl: anytype) type {
18 .{ "SpitFire", &Target.sparc.cpu.ultrasparc },18 return struct {
19 .{ "BlackBird", &Target.sparc.cpu.ultrasparc },19 fn parse(arch: Target.Cpu.Arch, reader: *Io.Reader) !?Target.Cpu {
20 .{ "Sabre", &Target.sparc.cpu.ultrasparc },20 var obj: impl = .{};
21 .{ "Hummingbird", &Target.sparc.cpu.ultrasparc },21 while (try reader.takeDelimiter('\n')) |line| {
22 .{ "Cheetah", &Target.sparc.cpu.ultrasparc3 },22 const colon_pos = mem.findScalar(u8, line, ':') orelse continue;
23 .{ "Jalapeno", &Target.sparc.cpu.ultrasparc3 },23 const key = mem.trimEnd(u8, line[0..colon_pos], " \t");
24 .{ "Jaguar", &Target.sparc.cpu.ultrasparc3 },24 const value = mem.trimStart(u8, line[colon_pos + 1 ..], " \t");
25 .{ "Panther", &Target.sparc.cpu.ultrasparc3 },25 if (!try obj.lineHook(key, value)) break;
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 }
42 }26 }
27 return obj.finalize(arch);
43 }28 }
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 );
46 }49 }
4750
48 fn finalize(self: *const SparcCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {51 pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch) ?Target.Cpu {
49 const model = self.model orelse return null;52 const registers = [12]u64{
50 return Target.Cpu{53 mrs("MIDR_EL1"),
51 .arch = arch,54 mrs("ID_AA64PFR0_EL1"),
52 .model = model,55 mrs("ID_AA64PFR1_EL1"),
53 .features = model.features,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"),
54 };65 };
66
67 return @import("arm.zig").aarch64.detectNativeCpuAndFeatures(arch, registers);
55 }68 }
56};69};
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" {97 return true;
61 try testParser(SparcCpuinfoParser, .sparc64, &Target.sparc.cpu.niagara2,98 }
62 \\cpu : UltraSparc T2 (Niagara2)
63 \\fpu : UltraSparc T2 integrated FPU
64 \\pmu : niagara2
65 \\type : sun4v
66 );
67}
6899
69const RiscvCpuinfoImpl = struct {100 fn finalize(self: *Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
70 model: ?*const Target.Cpu.Model = null,101 if (self.have_fields != 3) return 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 };
84102
85 fn line_hook(self: *RiscvCpuinfoImpl, key: []const u8, value: []const u8) !bool {103 const model = cpu_models.isKnown(.{
86 if (mem.eql(u8, key, "uarch")) {104 .architecture = undefined, // unused for the lookup
87 inline for (cpu_names) |pair| {105 .implementer = self.implementer,
88 if (mem.eql(u8, value, pair[0])) {106 .variant = self.variant,
89 self.model = pair[1];107 .part = self.part,
90 break;108 }, false) orelse return null;
91 }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 };
92 }116 }
93 return false;117 };
94 }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 );
97 }165 }
98166
99 fn finalize(self: *const RiscvCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {167 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
100 const model = self.model orelse return null;168 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
101 return Target.Cpu{169 defer file.close(io);
102 .arch = arch,170
103 .model = model,171 var buffer: [4096]u8 = undefined;
104 .features = model.features,172 var file_reader = file.reader(io, &buffer);
105 };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;
106 }179 }
107};180};
108181
109const RiscvCpuinfoParser = CpuinfoParser(RiscvCpuinfoImpl);182const csky = struct {
110183 const cpuinfo = struct {
111test "cpuinfo: RISC-V" {184 const Impl = struct {
112 try testParser(RiscvCpuinfoParser, .riscv64, &Target.riscv.cpu.sifive_u74,185 model: ?*const Target.Cpu.Model = null,
113 \\processor : 0186
114 \\hart : 1187 const cpu_names = .{
115 \\isa : rv64imafdc188 .{ "ck807", &Target.csky.cpu.ck807 },
116 \\mmu : sv39189 .{ "ck807f", &Target.csky.cpu.ck807f },
117 \\isa-ext :190 .{ "ck810", &Target.csky.cpu.ck810 },
118 \\uarch : sifive,u74-mc191 .{ "ck810f", &Target.csky.cpu.ck810f },
119 );192 .{ "ck810t", &Target.csky.cpu.ck810t },
120}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 {199 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
123 model: ?*const Target.Cpu.Model = null,200 if (mem.eql(u8, key, "C-SKY CPU model")) {
124201 inline for (cpu_names) |pair| {
125 const cpu_names = .{202 if (mem.eql(u8, value, pair[0])) {
126 .{ "604e", &Target.powerpc.cpu.@"604e" },203 self.model = pair[1];
127 .{ "604", &Target.powerpc.cpu.@"604" },204 break;
128 .{ "7400", &Target.powerpc.cpu.@"7400" },205 }
129 .{ "7410", &Target.powerpc.cpu.@"7400" },206 }
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 };
148207
149 fn line_hook(self: *PowerpcCpuinfoImpl, key: []const u8, value: []const u8) !bool {208 return false;
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;
158 }209 }
210
211 return true;
159 }212 }
160213
161 // Stop the detection once we've seen the first core.214 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
162 return false;215 const model = self.model orelse return null;
163 }216 return .{
217 .arch = arch,
218 .model = model,
219 .features = model.features,
220 };
221 }
222 };
164223
165 return true;224 const Parser = CpuinfoParser(Impl);
166 }225 };
167226
168 fn finalize(self: *const PowerpcCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {227 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
169 const model = self.model orelse return null;228 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
170 return Target.Cpu{229 defer file.close(io);
171 .arch = arch,230
172 .model = model,231 var buffer: [4096]u8 = undefined;
173 .features = model.features,232 var file_reader = file.reader(io, &buffer);
174 };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;
175 }239 }
176};240};
177241
178const PowerpcCpuinfoParser = CpuinfoParser(PowerpcCpuinfoImpl);242const m68k = struct {
179243 const cpuinfo = struct {
180test "cpuinfo: PowerPC" {244 const Impl = struct {
181 try testParser(PowerpcCpuinfoParser, .powerpc, &Target.powerpc.cpu.@"970",245 model: ?*const Target.Cpu.Model = null,
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}
194246
195const S390xCpuinfoImpl = struct {247 const cpu_names = .{
196 model: ?*const Target.Cpu.Model = null,248 .{ "68020", &Target.m68k.cpu.M68020 },
197249 .{ "68030", &Target.m68k.cpu.M68030 },
198 const cpu_names = .{250 .{ "68040", &Target.m68k.cpu.M68040 },
199 // z900: 2064, 2066251 .{ "68060", &Target.m68k.cpu.M68060 },
200 // z990: 2084, 2086252 };
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 };
220253
221 fn line_hook(self: *S390xCpuinfoImpl, key: []const u8, value: []const u8) !bool {254 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
222 if (mem.eql(u8, key, "machine")) {255 if (mem.eql(u8, key, "CPU")) {
223 inline for (cpu_names) |pair| {256 inline for (cpu_names) |pair| {
224 if (mem.eql(u8, value, pair[0])) {257 if (mem.eql(u8, value, pair[0])) {
225 self.model = pair[1];258 self.model = pair[1];
226 break;259 break;
260 }
261 }
262
263 return false;
227 }264 }
265
266 return true;
228 }267 }
229268
230 return false;269 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
231 }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;279 const Parser = CpuinfoParser(Impl);
234 }280 };
235281
236 fn finalize(self: *const S390xCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {282 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
237 const model = self.model orelse return null;283 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
238 return Target.Cpu{284 defer file.close(io);
239 .arch = arch,
240 .model = model,
241 .features = model.features,
242 };
243 }
244};
245285
246const S390xCpuinfoParser = CpuinfoParser(S390xCpuinfoImpl);286 var buffer: [4096]u8 = undefined;
247287 var file_reader = file.reader(io, &buffer);
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}
265288
266const ArmCpuinfoImpl = struct {289 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
267 const num_cores = 4;
268290
269 cores: [num_cores]CoreInfo = undefined,291 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
270 core_no: usize = 0,
271 have_fields: usize = 0,
272292
273 const CoreInfo = struct {293 return cpu;
274 architecture: u8 = 0,294 }
275 implementer: u8 = 0,295};
276 variant: u8 = 0,
277 part: u16 = 0,
278 is_really_v6: bool = false,
279 };
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 {329 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
284 if (self.have_fields == 4 and self.core_no < num_cores) {330 // The `cpu model` line always comes before `isa`, which is perfect for us since we
285 if (self.core_no > 0) {331 // want the explicit model to take precedence over the generic ISA identifier.
286 // Deduplicate the core info.332 if (mem.eql(u8, key, "cpu model")) {
287 for (self.cores[0..self.core_no]) |it| {333 inline for (cpu_names) |pair| {
288 if (std.meta.eql(it, self.cores[self.core_no]))334 if (mem.find(u8, value, pair[0]) != null) {
289 return;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;
290 }349 }
350
351 return true;
291 }352 }
292 self.core_no += 1;
293 }
294 }
295353
296 fn line_hook(self: *ArmCpuinfoImpl, key: []const u8, value: []const u8) !bool {354 fn finalize(self: *const Impl, arch: Target.Cpu.Arch) ?Target.Cpu {
297 const info = &self.cores[self.core_no];355 const model = self.model orelse return null;
298356 return .{
299 if (mem.eql(u8, key, "processor")) {357 .arch = arch,
300 // Handle both old-style and new-style cpuinfo formats.358 .model = model,
301 // The former prints a sequence of "processor: N" lines for each359 .features = model.features,
302 // core and then the info for the core that's executing this code(!)360 };
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;
327 }361 }
328 } else if (mem.eql(u8, key, "CPU revision")) {362 };
329 // This field is always the last one for each CPU section.
330 _ = self.addOne();
331 }
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 );
334 }388 }
335389
336 fn finalize(self: *ArmCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {390 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
337 if (self.core_no == 0) return null;391 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
392 defer file.close(io);
338393
339 const is_64bit = switch (arch) {394 var buffer: [4096]u8 = undefined;
340 .aarch64, .aarch64_be => true,395 var file_reader = file.reader(io, &buffer);
341 else => false,
342 };
343396
344 var known_models: [num_cores]?*const Target.Cpu.Model = undefined;397 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
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 }
353398
354 // XXX We pick the first core on big.LITTLE systems, hopefully the399 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
355 // LITTLE one.400
356 const model = known_models[0] orelse return null;401 return cpu;
357 return Target.Cpu{
358 .arch = arch,
359 .model = model,
360 .features = model.features,
361 };
362 }402 }
363};403};
364404
365const ArmCpuinfoParser = CpuinfoParser(ArmCpuinfoImpl);405const powerpc = struct {
366406 const cpuinfo = struct {
367test "cpuinfo: ARM" {407 const Impl = struct {
368 try testParser(ArmCpuinfoParser, .arm, &Target.arm.cpu.arm1176jz_s,408 model: ?*const Target.Cpu.Model = null,
369 \\processor : 0409
370 \\model name : ARMv6-compatible processor rev 7 (v6l)410 const cpu_names = .{
371 \\BogoMIPS : 997.08411 .{ "440EPX", &Target.powerpc.cpu.@"440" },
372 \\Features : half thumb fastmult vfp edsp java tls412 .{ "440EP", &Target.powerpc.cpu.@"440" },
373 \\CPU implementer : 0x41413 .{ "460EX", &Target.powerpc.cpu.@"440" },
374 \\CPU architecture: 7414 .{ "440GP", &Target.powerpc.cpu.@"440" },
375 \\CPU variant : 0x0415 .{ "440GRX", &Target.powerpc.cpu.@"440" },
376 \\CPU part : 0xb76416 .{ "440GR", &Target.powerpc.cpu.@"440" },
377 \\CPU revision : 7417 .{ "460GT", &Target.powerpc.cpu.@"440" },
378 );418 .{ "440GX", &Target.powerpc.cpu.@"440" },
379 try testParser(ArmCpuinfoParser, .arm, &Target.arm.cpu.cortex_a7,419 .{ "440SPe", &Target.powerpc.cpu.@"440" },
380 \\processor : 0420 .{ "440SP", &Target.powerpc.cpu.@"440" },
381 \\model name : ARMv7 Processor rev 3 (v7l)421 .{ "460SX", &Target.powerpc.cpu.@"440" },
382 \\BogoMIPS : 18.00422 .{ "603ev", &Target.powerpc.cpu.@"603ev" },
383 \\Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae423 .{ "603e", &Target.powerpc.cpu.@"603e" },
384 \\CPU implementer : 0x41424 .{ "603", &Target.powerpc.cpu.@"603" },
385 \\CPU architecture: 7425 .{ "604ev", &Target.powerpc.cpu.@"604e" },
386 \\CPU variant : 0x0426 .{ "604e", &Target.powerpc.cpu.@"604e" },
387 \\CPU part : 0xc07427 .{ "604r", &Target.powerpc.cpu.@"603e" },
388 \\CPU revision : 3428 .{ "604", &Target.powerpc.cpu.@"604" },
389 \\429 .{ "7400", &Target.powerpc.cpu.@"7400" },
390 \\processor : 4430 .{ "7410", &Target.powerpc.cpu.@"7400" },
391 \\model name : ARMv7 Processor rev 3 (v7l)431 .{ "7447/7457", &Target.powerpc.cpu.@"7450" },
392 \\BogoMIPS : 90.00432 .{ "7447A", &Target.powerpc.cpu.@"7450" },
393 \\Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae433 .{ "7448", &Target.powerpc.cpu.@"7450" },
394 \\CPU implementer : 0x41434 .{ "7450", &Target.powerpc.cpu.@"7450" },
395 \\CPU architecture: 7435 .{ "7455", &Target.powerpc.cpu.@"7450" },
396 \\CPU variant : 0x2436 .{ "740/750", &Target.powerpc.cpu.@"750" },
397 \\CPU part : 0xc0f437 .{ "745/755", &Target.powerpc.cpu.@"750" },
398 \\CPU revision : 3438 .{ "750CL", &Target.powerpc.cpu.@"750" },
399 );439 .{ "750CXe", &Target.powerpc.cpu.@"750" },
400 try testParser(ArmCpuinfoParser, .aarch64, &Target.aarch64.cpu.cortex_a72,440 .{ "750CX", &Target.powerpc.cpu.@"750" },
401 \\processor : 0441 .{ "750FX", &Target.powerpc.cpu.@"750" },
402 \\BogoMIPS : 108.00442 .{ "750GX", &Target.powerpc.cpu.@"750" },
403 \\Features : fp asimd evtstrm crc32 cpuid443 .{ "82xx", &Target.powerpc.cpu.@"603e" },
404 \\CPU implementer : 0x41444 .{ "APM821XX", &Target.powerpc.cpu.@"440" },
405 \\CPU architecture: 8445 .{ "Cell", &Target.powerpc.cpu.ppc64 }, // TODO: Change with LLVM 23.
406 \\CPU variant : 0x0446 .{ "e300c1", &Target.powerpc.cpu.@"603e" },
407 \\CPU part : 0xd08447 .{ "e300c2", &Target.powerpc.cpu.@"603e" },
408 \\CPU revision : 3448 .{ "e300c3", &Target.powerpc.cpu.@"603e" },
409 );449 .{ "e300c4", &Target.powerpc.cpu.@"603e" },
410}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(475 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
413 parser: anytype,476 if (mem.eql(u8, key, "cpu")) {
414 arch: Target.Cpu.Arch,477 // The model name is often followed by a comma or space and extra
415 expected_model: *const Target.Cpu.Model,478 // info.
416 input: []const u8,479 inline for (cpu_names) |pair| {
417) !void {480 const end_index = mem.findAny(u8, value, ", ") orelse value.len;
418 var r: Io.Reader = .fixed(input);481 if (mem.eql(u8, value[0..end_index], pair[0])) {
419 const result = try parser.parse(arch, &r);482 self.model = pair[1];
420 try testing.expectEqual(expected_model, result.?.model);483 break;
421 try testing.expect(expected_model.features.eql(result.?.features));484 }
422}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.491 return true;
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;
438 }492 }
439 return obj.finalize(arch);493
440 }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);
441 };505 };
442}
443506
444const aarch64 = struct {507 test cpuinfo {
445 inline fn mrs(comptime feat_reg: []const u8) u64 {508 try testParser(cpuinfo.Parser, .powerpc, &Target.powerpc.cpu.@"970",
446 return asm ("mrs %[ret], " ++ feat_reg509 \\processor : 0
447 : [ret] "=r" (-> u64),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)
448 );519 );
449 }520 }
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 }
450};535};
451536
452const riscv = struct {537const riscv = struct {
453 const linux = std.os.linux;538 const cpuinfo = struct {
454 const RISCV_HWPROBE = linux.RISCV_HWPROBE;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
456 fn setFeature(cpu: *Target.Cpu, feature: Target.riscv.Feature, enabled: bool) void {594 fn setFeature(cpu: *Target.Cpu, feature: Target.riscv.Feature, enabled: bool) void {
457 const idx = @as(Target.Cpu.Feature.Set.Index, @backingInt(feature));595 const idx = @as(Target.Cpu.Feature.Set.Index, @backingInt(feature));
...@@ -463,8 +601,18 @@ const riscv = struct {...@@ -463,8 +601,18 @@ const riscv = struct {
463 return (value & mask) == mask;601 return (value & mask) == mask;
464 }602 }
465603
466 pub fn detectCpuFeatures(cpu: *Target.Cpu) void {604 pub fn detectNativeCpuAndFeatures(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
467 var probes = [_]linux.riscv_hwprobe{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{
468 .{ .key = RISCV_HWPROBE.KEY.BASE_BEHAVIOR, .value = 0 },616 .{ .key = RISCV_HWPROBE.KEY.BASE_BEHAVIOR, .value = 0 },
469 .{ .key = RISCV_HWPROBE.KEY.IMA_EXT_0, .value = 0 },617 .{ .key = RISCV_HWPROBE.KEY.IMA_EXT_0, .value = 0 },
470 .{ .key = RISCV_HWPROBE.KEY.MISALIGNED_SCALAR_PERF, .value = 0 },618 .{ .key = RISCV_HWPROBE.KEY.MISALIGNED_SCALAR_PERF, .value = 0 },
...@@ -474,9 +622,25 @@ const riscv = struct {...@@ -474,9 +622,25 @@ const riscv = struct {
474 .{ .key = RISCV_HWPROBE.KEY.IMA_EXT_1, .value = 0 },622 .{ .key = RISCV_HWPROBE.KEY.IMA_EXT_1, .value = 0 },
475 };623 };
476624
477 const rc = linux.sys_riscv_hwprobe(&probes, probes.len, 0, null, 0);625 const rc = std.os.linux.sys_riscv_hwprobe(&probes, probes.len, 0, null, 0);
478 if (linux.errno(rc) == .NOSYS)626 if (std.os.linux.errno(rc) == .NOSYS) {
479 return;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
481 var ima_support = false;645 var ima_support = false;
482 for (probes) |probe| {646 for (probes) |probe| {
...@@ -486,153 +650,299 @@ const riscv = struct {...@@ -486,153 +650,299 @@ const riscv = struct {
486 -1 => continue, // The running kernel doesn't know this key.650 -1 => continue, // The running kernel doesn't know this key.
487 RISCV_HWPROBE.KEY.BASE_BEHAVIOR => {651 RISCV_HWPROBE.KEY.BASE_BEHAVIOR => {
488 ima_support = set(value, RISCV_HWPROBE.BASE_BEHAVIOR_IMA);652 ima_support = set(value, RISCV_HWPROBE.BASE_BEHAVIOR_IMA);
489 setFeature(cpu, Target.riscv.Feature.i, ima_support);653 setFeature(&cpu, Target.riscv.Feature.i, ima_support);
490 setFeature(cpu, Target.riscv.Feature.m, ima_support);654 setFeature(&cpu, Target.riscv.Feature.m, ima_support);
491 setFeature(cpu, Target.riscv.Feature.a, ima_support);655 setFeature(&cpu, Target.riscv.Feature.a, ima_support);
492 },656 },
493 RISCV_HWPROBE.KEY.IMA_EXT_0 => {657 RISCV_HWPROBE.KEY.IMA_EXT_0 => {
494 // https://bugzilla.kernel.org/show_bug.cgi?id=221874658 // https://bugzilla.kernel.org/show_bug.cgi?id=221874
495 const fd_support = set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_FD);659 const fd_support = set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_FD);
496 setFeature(cpu, .f, ima_support and fd_support);660 setFeature(&cpu, .f, ima_support and fd_support);
497 setFeature(cpu, .d, ima_support and fd_support);661 setFeature(&cpu, .d, ima_support and fd_support);
498 setFeature(cpu, .c, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.IMA_C));662 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));663 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));664 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));665 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));666 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));667 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));668 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));669 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));670 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));671 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));672 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));673 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));674 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));675 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));676 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));677 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));678 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));679 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));680 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));681 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));682 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));683 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));684 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));685 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));686 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));687 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));688 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));689 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));690 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));691 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));692 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));693 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));694 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));695 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));696 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));697 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));698 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));699 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));700 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));701 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));702 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));703 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));704 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));705 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));706 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));707 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));708 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));709 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));710 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));711 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));712 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));713 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));714 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));715 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));716 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));717 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));718 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));719 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));720 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));721 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));722 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));723 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));724 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));725 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));726 setFeature(&cpu, .experimental_zicfilp, ima_support and set(value, RISCV_HWPROBE.IMA_EXT_0.EXT_ZICFILP));
563 },727 },
564 RISCV_HWPROBE.KEY.MISALIGNED_SCALAR_PERF => {728 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);
566 },730 },
567 RISCV_HWPROBE.KEY.MISALIGNED_VECTOR_PERF => {731 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);
569 },733 },
570 RISCV_HWPROBE.KEY.VENDOR_EXT_MIPS_0 => {734 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));
572 },736 },
573 RISCV_HWPROBE.KEY.VENDOR_EXT_SIFIVE_0 => {737 RISCV_HWPROBE.KEY.VENDOR_EXT_SIFIVE_0 => {
574 setFeature(cpu, .xsfvqmaccdod, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVQMACCDOD));738 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));739 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));740 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));741 setFeature(&cpu, .xsfvfwmaccqqq, ima_support and set(value, RISCV_HWPROBE.SIFIVE_VENDOR_EXT.XSFVFWMACCQQQ));
578 },742 },
579 RISCV_HWPROBE.KEY.IMA_EXT_1 => {743 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));
581 },745 },
582 else => unreachable,746 else => unreachable,
583 }747 }
584 }748 }
749
750 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
751
752 return cpu;
585 }753 }
586};754};
587755
588pub fn detectNativeCpuAndFeatures(io: Io) ?Target.Cpu {756const s390x = struct {
589 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch |err| switch (err) {757 const cpuinfo = struct {
590 else => return null,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);
591 };806 };
592 defer file.close(io);
593807
594 var buffer: [4096]u8 = undefined; // "flags" lines can get pretty long.808 test cpuinfo {
595 var file_reader = file.reader(io, &buffer);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;826 pub fn detectNativeCpu(io: Io, arch: Target.Cpu.Arch) ?Target.Cpu {
598 return switch (current_arch) {827 var file = Io.Dir.openFileAbsolute(io, "/proc/cpuinfo", .{}) catch return null;
599 .aarch64, .aarch64_be => b: {828 defer file.close(io);
600 const registers = [12]u64{829
601 aarch64.mrs("MIDR_EL1"),830 var buffer: [4096]u8 = undefined;
602 aarch64.mrs("ID_AA64PFR0_EL1"),831 var file_reader = file.reader(io, &buffer);
603 aarch64.mrs("ID_AA64PFR1_EL1"),832
604 aarch64.mrs("ID_AA64DFR0_EL1"),833 var cpu = (cpuinfo.Parser.parse(arch, &file_reader.interface) catch null) orelse return null;
605 aarch64.mrs("ID_AA64DFR1_EL1"),834
606 aarch64.mrs("ID_AA64AFR0_EL1"),835 cpu.features.populateDependencies(cpu.arch.allFeaturesList());
607 aarch64.mrs("ID_AA64AFR1_EL1"),836
608 aarch64.mrs("ID_AA64ISAR0_EL1"),837 return cpu;
609 aarch64.mrs("ID_AA64ISAR1_EL1"),838 }
610 aarch64.mrs("ID_AA64MMFR0_EL1"),839};
611 aarch64.mrs("ID_AA64MMFR1_EL1"),840
612 aarch64.mrs("ID_AA64MMFR2_EL1"),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 },
613 };873 };
614874
615 break :b @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers);875 fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool {
616 },876 if (mem.eql(u8, key, "cpu")) {
617 .arm, .armeb, .thumb, .thumbeb => ArmCpuinfoParser.parse(current_arch, &file_reader.interface) catch null,877 inline for (cpu_names) |pair| {
618 .powerpc, .powerpcle, .powerpc64, .powerpc64le => PowerpcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null,878 if (mem.findPos(u8, value, 0, pair[0]) != null) {
619 .riscv64, .riscv32 => b: {879 self.model = pair[1];
620 var cpu = (RiscvCpuinfoParser.parse(current_arch, &file_reader.interface) catch null) orelse cpu: {880 break;
621 const model = Target.Cpu.Model.generic(current_arch);881 }
622 break :cpu Target.Cpu{882 }
623 .arch = current_arch,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,
624 .model = model,892 .model = model,
625 .features = model.features,893 .features = model.features,
626 };894 };
627 };895 }
896 };
628897
629 riscv.detectCpuFeatures(&cpu);898 const Parser = CpuinfoParser(Impl);
630 cpu.features.populateDependencies(cpu.arch.allFeaturesList());899 };
631900
632 break :b cpu;901 test cpuinfo {
633 },902 try testParser(cpuinfo.Parser, .sparc64, &Target.sparc.cpu.niagara2,
634 .s390x => S390xCpuinfoParser.parse(current_arch, &file_reader.interface) catch null,903 \\cpu : UltraSparc T2 (Niagara2)
635 .sparc, .sparc64 => SparcCpuinfoParser.parse(current_arch, &file_reader.interface) catch null,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),
636 else => null,937 else => null,
637 };938 };
638}939}
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(...@@ -52,9 +52,9 @@ pub fn detectNativeCpuAndFeatures(
52 if (builtin.os.tag == .linux) {52 if (builtin.os.tag == .linux) {
53 const HWCAP = std.os.linux.HWCAP;53 const HWCAP = std.os.linux.HWCAP;
54 const hwcap_bits: usize = if (builtin.link_libc)54 const hwcap_bits: usize = if (builtin.link_libc)
55 std.c.getauxval(std.elf.AT_HWCAP)55 std.c.getauxval(std.elf.AT.HWCAP)
56 else56 else
57 std.os.linux.getauxval(std.elf.AT_HWCAP);57 std.os.linux.getauxval(std.elf.AT.HWCAP);
5858
59 setFeature(&cpu, .ual, (hwcap_bits & HWCAP.UAL) != 0);59 setFeature(&cpu, .ual, (hwcap_bits & HWCAP.UAL) != 0);
6060
...@@ -66,6 +66,8 @@ pub fn detectNativeCpuAndFeatures(...@@ -66,6 +66,8 @@ pub fn detectNativeCpuAndFeatures(
6666
67 setFeature(&cpu, .lvz, (hwcap_bits & HWCAP.LVZ) != 0);67 setFeature(&cpu, .lvz, (hwcap_bits & HWCAP.LVZ) != 0);
68 setFeature(&cpu, .lbt, (hwcap_bits & HWCAP.LBT_X86) != 0 and (hwcap_bits & HWCAP.LBT_ARM) != 0 and (hwcap_bits & HWCAP.LBT_MIPS) != 0);68 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);
69 } else {71 } else {
70 setFeature(&cpu, .ual, false);72 setFeature(&cpu, .ual, false);
7173
...@@ -76,11 +78,12 @@ pub fn detectNativeCpuAndFeatures(...@@ -76,11 +78,12 @@ pub fn detectNativeCpuAndFeatures(
7678
77 setFeature(&cpu, .lvz, false);79 setFeature(&cpu, .lvz, false);
78 setFeature(&cpu, .lbt, false);80 setFeature(&cpu, .lbt, false);
81
82 setFeature(&cpu, .lam_bh, false);
79 }83 }
8084
81 setFeature(&cpu, .frecipe, bit(cfg2, 25));85 setFeature(&cpu, .frecipe, bit(cfg2, 25));
82 setFeature(&cpu, .div32, bit(cfg2, 26));86 setFeature(&cpu, .div32, bit(cfg2, 26));
83 setFeature(&cpu, .lam_bh, bit(cfg2, 27));
84 setFeature(&cpu, .lamcas, bit(cfg2, 28));87 setFeature(&cpu, .lamcas, bit(cfg2, 28));
85 setFeature(&cpu, .scq, bit(cfg2, 30));88 setFeature(&cpu, .scq, bit(cfg2, 30));
8689
lib/std/zig/system/openbsd.zig+22-16
...@@ -113,32 +113,38 @@ const aarch64 = struct {...@@ -113,32 +113,38 @@ const aarch64 = struct {
113 }113 }
114114
115 fn detectNativeCpuAndFeatures(arch: std.Target.Cpu.Arch) ?std.Target.Cpu {115 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: {
117 var buf: [64:0]u8 = undefined;117 var buf: [64:0]u8 = undefined;
118 const name = hwModelName(&buf) orelse return null;118 const name = hwModelName(&buf) orelse break :blk null;
119119
120 inline for (models) |pair| {120 inline for (models) |pair| {
121 if (std.mem.startsWith(u8, name, pair[0])) break :blk pair[1];121 if (std.mem.startsWith(u8, name, pair[0])) break :blk pair[1];
122 }122 }
123123
124 break :blk .generic(arch);124 break :blk null;
125 };125 };
126126
127 const registers = [11]u64{127 const registers = blk: {
128 sysctlReg(std.c.CPU.AA64PFR0) orelse return null,128 break :blk [11]u64{
129 sysctlReg(std.c.CPU.AA64PFR1) orelse return null,129 sysctlReg(std.c.CPU.AA64PFR0) orelse break :blk null,
130 0, // ID_AA64DFR0_EL1130 sysctlReg(std.c.CPU.AA64PFR1) orelse break :blk null,
131 0, // ID_AA64DFR1_EL1131 0, // ID_AA64DFR0_EL1
132 0, // ID_AA64AFR0_EL1132 0, // ID_AA64DFR1_EL1
133 0, // ID_AA64AFR1_EL1133 0, // ID_AA64AFR0_EL1
134 sysctlReg(std.c.CPU.ID_AA64ISAR0) orelse return null,134 0, // ID_AA64AFR1_EL1
135 sysctlReg(std.c.CPU.ID_AA64ISAR1) orelse return null,135 sysctlReg(std.c.CPU.ID_AA64ISAR0) orelse break :blk null,
136 sysctlReg(std.c.CPU.ID_AA64MMFR0) orelse return null,136 sysctlReg(std.c.CPU.ID_AA64ISAR1) orelse break :blk null,
137 sysctlReg(std.c.CPU.ID_AA64MMFR1) orelse return null,137 sysctlReg(std.c.CPU.ID_AA64MMFR0) orelse break :blk null,
138 sysctlReg(std.c.CPU.ID_AA64MMFR2) orelse return 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;
139 };145 };
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);
142 }148 }
143};149};
144150
test/standalone/glibc_compat/glibc_runtime_check.zig+2-2
...@@ -65,8 +65,8 @@ fn checkGetAuxVal() !void {...@@ -65,8 +65,8 @@ fn checkGetAuxVal() !void {
65}65}
6666
67fn checkGetAuxVal_v2_16() !void {67fn checkGetAuxVal_v2_16() !void {
68 const base = std.c.getauxval(std.elf.AT_BASE);68 const base = std.c.getauxval(std.elf.AT.BASE);
69 const pgsz = std.c.getauxval(std.elf.AT_PAGESZ);69 const pgsz = std.c.getauxval(std.elf.AT.PAGESZ);
7070
71 assert(base != 0);71 assert(base != 0);
72 assert(pgsz != 0);72 assert(pgsz != 0);