diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/zig/system/windows.zig | 169 |
1 files changed, 86 insertions, 83 deletions
diff --git a/lib/std/zig/system/windows.zig b/lib/std/zig/system/windows.zig index 9b0956dee8..00f4363439 100644 --- a/lib/std/zig/system/windows.zig +++ b/lib/std/zig/system/windows.zig @@ -51,23 +51,22 @@ pub fn detectRuntimeVersion() WindowsVersion { // https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-element-size-limits const max_value_len = 2048; -const RegistryPair = struct { - key: []const u8, - value: std.os.windows.ULONG, -}; +fn getCpuInfoFromRegistry(core: usize, args: anytype) !void { + const ArgsType = @TypeOf(args); + const args_type_info = @typeInfo(ArgsType); + + if (args_type_info != .Struct) { + @compileError("expected tuple or struct argument, found " ++ @typeName(ArgsType)); + } + + const fields_info = args_type_info.Struct.fields; -fn getCpuInfoFromRegistry( - core: usize, - comptime pairs_num: comptime_int, - comptime pairs: [pairs_num]RegistryPair, - out_buf: *[pairs_num][max_value_len]u8, -) !void { // Originally, I wanted to issue a single call with a more complex table structure such that we // would sequentially visit each CPU#d subkey in the registry and pull the value of interest into // a buffer, however, NT seems to be expecting a single buffer per each table meaning we would // end up pulling only the last CPU core info, overwriting everything else. // If anyone can come up with a solution to this, please do! - const table_size = 1 + pairs.len; + const table_size = 1 + fields_info.len; var table: [table_size + 1]std.os.windows.RTL_QUERY_REGISTRY_TABLE = undefined; const topkey = std.unicode.utf8ToUtf16LeStringLiteral("\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor"); @@ -90,9 +89,9 @@ fn getCpuInfoFromRegistry( .DefaultLength = 0, }; - inline for (pairs) |pair, i| { + inline for (fields_info) |field, i| { const ctx: *anyopaque = blk: { - switch (pair.value) { + switch (@field(args, field.name).value_type) { REG.SZ, REG.EXPAND_SZ, REG.MULTI_SZ, @@ -121,12 +120,15 @@ fn getCpuInfoFromRegistry( else => unreachable, } }; - const key_name = std.unicode.utf8ToUtf16LeStringLiteral(pair.key); + + var key_buf: [max_value_len / 2 + 1]u16 = undefined; + const key_len = try std.unicode.utf8ToUtf16Le(&key_buf, @field(args, field.name).key); + key_buf[key_len] = 0; table[i + 1] = .{ .QueryRoutine = null, .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED, - .Name = @intToPtr([*:0]u16, @ptrToInt(key_name)), + .Name = key_buf[0..key_len :0], .EntryContext = ctx, .DefaultType = REG.NONE, .DefaultData = null, @@ -154,14 +156,15 @@ fn getCpuInfoFromRegistry( ); switch (res) { .SUCCESS => { - inline for (pairs) |pair, i| switch (pair.value) { + inline for (fields_info) |field, i| switch (@field(args, field.name).value_type) { REG.SZ, REG.EXPAND_SZ, REG.MULTI_SZ, => { + var buf = @field(args, field.name).value_buf; const entry = @ptrCast(*align(1) const std.os.windows.UNICODE_STRING, table[i + 1].EntryContext); - const len = try std.unicode.utf16leToUtf8(out_buf[i][0..], entry.Buffer[0 .. entry.Length / 2]); - out_buf[i][len] = 0; + const len = try std.unicode.utf16leToUtf8(buf, entry.Buffer[0 .. entry.Length / 2]); + buf[len] = 0; }, REG.DWORD, @@ -169,12 +172,12 @@ fn getCpuInfoFromRegistry( REG.QWORD, => { const entry = @ptrCast([*]align(1) const u8, table[i + 1].EntryContext); - switch (pair.value) { + switch (@field(args, field.name).value_type) { REG.DWORD, REG.DWORD_BIG_ENDIAN => { - mem.copy(u8, out_buf[i][0..4], entry[0..4]); + mem.copy(u8, @field(args, field.name).value_buf[0..4], entry[0..4]); }, REG.QWORD => { - mem.copy(u8, out_buf[i][0..8], entry[0..8]); + mem.copy(u8, @field(args, field.name).value_buf[0..8], entry[0..8]); }, else => unreachable, } @@ -197,7 +200,7 @@ fn getCpuCount() usize { return std.os.windows.peb().NumberOfProcessors; } -const ArmCpuInfoImpl = struct { +const ArmCpuInfoParser = struct { cores: [4]CoreInfo = undefined, core_no: usize = 0, have_fields: usize = 0, @@ -205,38 +208,26 @@ const ArmCpuInfoImpl = struct { const CoreInfo = @import("arm.zig").CoreInfo; const cpu_models = @import("arm.zig").cpu_models; - const Data = struct { - cp_4000: []const u8, - identifier: []const u8, - }; - - fn parseDataHook(self: *ArmCpuInfoImpl, data: Data) !void { + fn parseFeaturesFromRegisters(self: *ArmCpuInfoParser, registers: [12]u64) !void { const info = &self.cores[self.core_no]; info.* = .{}; - // CPU part - info.part = mem.readIntLittle(u16, data.cp_4000[0..2]) >> 4; - self.have_fields += 1; - - // CPU implementer - info.implementer = data.cp_4000[3]; - self.have_fields += 1; - - var tokens = mem.tokenize(u8, data.identifier, " "); - while (tokens.next()) |token| { - if (mem.eql(u8, "Family", token)) { - // CPU architecture - const family = tokens.next() orelse continue; - info.architecture = try std.fmt.parseInt(u8, family, 10); - self.have_fields += 1; - break; - } - } else return; + for (registers) |register| { + std.log.warn("{x}", .{register}); + } + + // // CPU part + // info.part = mem.readIntLittle(u16, data.cp_4000[0..2]) >> 4; + // self.have_fields += 1; + + // // CPU implementer + // info.implementer = data.cp_4000[3]; + // self.have_fields += 1; - self.addOne(); + // self.addOne(); } - fn addOne(self: *ArmCpuInfoImpl) void { + fn addOne(self: *ArmCpuInfoParser) void { if (self.have_fields == 3 and self.core_no < self.cores.len) { if (self.core_no > 0) { // Deduplicate the core info. @@ -249,7 +240,7 @@ const ArmCpuInfoImpl = struct { } } - fn finalize(self: ArmCpuInfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu { + fn finalize(self: ArmCpuInfoParser, arch: Target.Cpu.Arch) ?Target.Cpu { if (self.core_no == 0) return null; const is_64bit = switch (arch) { @@ -271,36 +262,49 @@ const ArmCpuInfoImpl = struct { .features = model.features, }; } -}; - -const ArmCpuInfoParser = CpuInfoParser(ArmCpuInfoImpl); - -fn CpuInfoParser(comptime impl: anytype) type { - return struct { - fn parse(arch: Target.Cpu.Arch) !?Target.Cpu { - var obj: impl = .{}; - var out_buf: [2][max_value_len]u8 = undefined; - var i: usize = 0; - while (i < getCpuCount()) : (i += 1) { - try getCpuInfoFromRegistry(i, 2, .{ - .{ .key = "CP 4000", .value = REG.QWORD }, - .{ .key = "Identifier", .value = REG.SZ }, - }, &out_buf); - - const cp_4000 = out_buf[0][0..8]; - const identifier = mem.sliceTo(out_buf[1][0..], 0); - - try obj.parseDataHook(.{ - .cp_4000 = cp_4000, - .identifier = identifier, - }); - } - - return obj.finalize(arch); + fn parse(arch: Target.Cpu.Arch) !?Target.Cpu { + var obj: ArmCpuInfoParser = .{}; + + // Backing datastore + var registers: [12]u64 = undefined; + + var i: usize = 0; + while (i < getCpuCount()) : (i += 1) { + // Registry key to system ID register mapping + // CP 4000 -> MIDR_EL1 + // CP 4020 -> ID_AA64PFR0_EL1 + // CP 4021 -> ID_AA64PFR1_EL1 + // CP 4028 -> ID_AA64DFR0_EL1 + // CP 4029 -> ID_AA64DFR1_EL1 + // CP 402C -> ID_AA64AFR0_EL1 + // CP 402D -> ID_AA64AFR1_EL1 + // CP 4030 -> ID_AA64ISAR0_EL1 + // CP 4031 -> ID_AA64ISAR1_EL1 + // CP 4038 -> ID_AA64MMFR0_EL1 + // CP 4039 -> ID_AA64MMFR1_EL1 + // CP 403A -> ID_AA64MMFR2_EL1 + try getCpuInfoFromRegistry(i, .{ + .{ .key = "CP 4000", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[0]) }, + .{ .key = "CP 4020", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[1]) }, + .{ .key = "CP 4021", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[2]) }, + .{ .key = "CP 4028", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[3]) }, + .{ .key = "CP 4029", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[4]) }, + .{ .key = "CP 402C", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[5]) }, + .{ .key = "CP 402D", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[6]) }, + .{ .key = "CP 4030", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[7]) }, + .{ .key = "CP 4031", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[8]) }, + .{ .key = "CP 4038", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[9]) }, + .{ .key = "CP 4039", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[10]) }, + .{ .key = "CP 403A", .value_type = REG.QWORD, .value_buf = @ptrCast(*[8]u8, ®isters[11]) }, + }); + + try obj.parseFeaturesFromRegisters(registers); } - }; -} + + return obj.finalize(arch); + } +}; /// If the fine-grained detection of CPU features via Win registry fails, /// we fallback to a generic CPU model but we override the feature set @@ -333,10 +337,9 @@ fn genericCpuAndNativeFeatures(arch: Target.Cpu.Arch) Target.Cpu { pub fn detectNativeCpuAndFeatures() ?Target.Cpu { const current_arch = builtin.cpu.arch; - switch (current_arch) { - .aarch64, .aarch64_be, .aarch64_32 => { - return ArmCpuInfoParser.parse(current_arch) catch genericCpuAndNativeFeatures(current_arch); - }, - else => return null, - } + const cpu: ?Target.Cpu = switch (current_arch) { + .aarch64, .aarch64_be, .aarch64_32 => ArmCpuInfoParser.parse(current_arch) catch null, + else => null, + }; + return cpu orelse genericCpuAndNativeFeatures(current_arch); } |
