| ... | @@ -71,97 +71,44 @@ const aarch64 = struct { | ... | @@ -71,97 +71,44 @@ const aarch64 = struct { |
| 71 | const arm = struct { | 71 | const arm = struct { |
| 72 | const cpuinfo = struct { | 72 | const cpuinfo = struct { |
| 73 | const Impl = struct { | 73 | const Impl = struct { |
| 74 | const num_cores = 4; | 74 | implementer: u8 = 0, |
| 75 | | 75 | variant: u8 = 0, |
| 76 | cores: [num_cores]CoreInfo = undefined, | 76 | part: u16 = 0, |
| 77 | core_no: usize = 0, | | |
| 78 | have_fields: usize = 0, | | |
| 79 | | | |
| 80 | const CoreInfo = struct { | | |
| 81 | architecture: u8 = 0, | | |
| 82 | implementer: u8 = 0, | | |
| 83 | variant: u8 = 0, | | |
| 84 | part: u16 = 0, | | |
| 85 | is_really_v6: bool = false, | | |
| 86 | }; | | |
| 87 | | 77 | |
| 88 | const cpu_models = @import("arm.zig").cpu_models; | 78 | have_fields: u8 = 0, |
| 89 | | 79 | |
| 90 | fn addOne(self: *Impl) void { | 80 | const cpu_models = @import("arm.zig").cpu_models; |
| 91 | if (self.have_fields == 4 and self.core_no < num_cores) { | | |
| 92 | if (self.core_no > 0) { | | |
| 93 | // Deduplicate the core info. | | |
| 94 | for (self.cores[0..self.core_no]) |it| { | | |
| 95 | if (std.meta.eql(it, self.cores[self.core_no])) | | |
| 96 | return; | | |
| 97 | } | | |
| 98 | } | | |
| 99 | self.core_no += 1; | | |
| 100 | } | | |
| 101 | } | | |
| 102 | | 81 | |
| 103 | fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool { | 82 | fn lineHook(self: *Impl, key: []const u8, value: []const u8) !bool { |
| 104 | const info = &self.cores[self.core_no]; | 83 | if (mem.eql(u8, key, "CPU implementer")) { |
| 105 | | 84 | self.implementer = try fmt.parseInt(u8, value, 0); |
| 106 | if (mem.eql(u8, key, "processor")) { | | |
| 107 | // Handle both old-style and new-style cpuinfo formats. | | |
| 108 | // The former prints a sequence of "processor: N" lines for each | | |
| 109 | // core and then the info for the core that's executing this code(!) | | |
| 110 | // while the latter prints the infos for each core right after the | | |
| 111 | // "processor" key. | | |
| 112 | self.have_fields = 0; | | |
| 113 | self.cores[self.core_no] = .{}; | | |
| 114 | } else if (mem.eql(u8, key, "CPU implementer")) { | | |
| 115 | info.implementer = try fmt.parseInt(u8, value, 0); | | |
| 116 | self.have_fields += 1; | | |
| 117 | } else if (mem.eql(u8, key, "CPU architecture")) { | | |
| 118 | // "AArch64" on older kernels. | | |
| 119 | info.architecture = if (mem.startsWith(u8, value, "AArch64")) | | |
| 120 | 8 | | |
| 121 | else | | |
| 122 | try fmt.parseInt(u8, value, 0); | | |
| 123 | self.have_fields += 1; | 85 | self.have_fields += 1; |
| 124 | } else if (mem.eql(u8, key, "CPU variant")) { | 86 | } else if (mem.eql(u8, key, "CPU variant")) { |
| 125 | info.variant = try fmt.parseInt(u8, value, 0); | 87 | self.variant = try fmt.parseInt(u8, value, 0); |
| 126 | self.have_fields += 1; | 88 | self.have_fields += 1; |
| 127 | } else if (mem.eql(u8, key, "CPU part")) { | 89 | } else if (mem.eql(u8, key, "CPU part")) { |
| 128 | info.part = try fmt.parseInt(u16, value, 0); | 90 | self.part = try fmt.parseInt(u16, value, 0); |
| 129 | self.have_fields += 1; | 91 | self.have_fields += 1; |
| 130 | } else if (mem.eql(u8, key, "model name")) { | | |
| 131 | // ARMv6 cores report "CPU architecture" equal to 7. | | |
| 132 | if (mem.find(u8, value, "(v6l)")) |_| { | | |
| 133 | info.is_really_v6 = true; | | |
| 134 | } | | |
| 135 | } else if (mem.eql(u8, key, "CPU revision")) { | 92 | } else if (mem.eql(u8, key, "CPU revision")) { |
| 136 | // This field is always the last one for each CPU section. | 93 | // This field is always the last one for each CPU section. |
| 137 | _ = self.addOne(); | 94 | return false; |
| 138 | } | 95 | } |
| 139 | | 96 | |
| 140 | return true; | 97 | return true; |
| 141 | } | 98 | } |
| 142 | | 99 | |
| 143 | fn finalize(self: *Impl, arch: Target.Cpu.Arch) ?Target.Cpu { | 100 | fn finalize(self: *Impl, arch: Target.Cpu.Arch) ?Target.Cpu { |
| 144 | if (self.core_no == 0) return null; | 101 | if (self.have_fields != 3) return null; |
| 145 | | 102 | |
| 146 | const is_64bit = switch (arch) { | 103 | const model = cpu_models.isKnown(.{ |
| 147 | .aarch64, .aarch64_be => true, | 104 | .architecture = undefined, // unused for the lookup |
| 148 | else => false, | 105 | .implementer = self.implementer, |
| 149 | }; | 106 | .variant = self.variant, |
| | 107 | .part = self.part, |
| | 108 | }, false) orelse return null; |
| 150 | | 109 | |
| 151 | var known_models: [num_cores]?*const Target.Cpu.Model = undefined; | 110 | // We pick the first core on big.LITTLE systems, hopefully the LITTLE one. |
| 152 | for (self.cores[0..self.core_no], 0..) |core, i| { | 111 | return .{ |
| 153 | known_models[i] = cpu_models.isKnown(.{ | | |
| 154 | .architecture = core.architecture, | | |
| 155 | .implementer = core.implementer, | | |
| 156 | .variant = core.variant, | | |
| 157 | .part = core.part, | | |
| 158 | }, is_64bit); | | |
| 159 | } | | |
| 160 | | | |
| 161 | // XXX We pick the first core on big.LITTLE systems, hopefully the | | |
| 162 | // LITTLE one. | | |
| 163 | const model = known_models[0] orelse return null; | | |
| 164 | return Target.Cpu{ | | |
| 165 | .arch = arch, | 112 | .arch = arch, |
| 166 | .model = model, | 113 | .model = model, |
| 167 | .features = model.features, | 114 | .features = model.features, |
| ... | @@ -205,7 +152,7 @@ const arm = struct { | ... | @@ -205,7 +152,7 @@ const arm = struct { |
| 205 | \\CPU part : 0xc0f | 152 | \\CPU part : 0xc0f |
| 206 | \\CPU revision : 3 | 153 | \\CPU revision : 3 |
| 207 | ); | 154 | ); |
| 208 | try testParser(cpuinfo.Parser, .aarch64, &Target.aarch64.cpu.cortex_a72, | 155 | try testParser(cpuinfo.Parser, .arm, &Target.arm.cpu.cortex_a72, |
| 209 | \\processor : 0 | 156 | \\processor : 0 |
| 210 | \\BogoMIPS : 108.00 | 157 | \\BogoMIPS : 108.00 |
| 211 | \\Features : fp asimd evtstrm crc32 cpuid | 158 | \\Features : fp asimd evtstrm crc32 cpuid |