| author | |
| committer | |
| log | 1f61a00a419e814c619ccdc5a93177752a4f6ddd |
| tree | b2b72726299cf91124eb199703481c811b7d1cd1 |
| parent | 3357425b8786a0fcde44bd52675200999efe4eb3 |
windows: add native CPU and features detection for Armv8 chips7 files changed, 931 insertions(+), 125 deletions(-)
lib/std/os/windows.zig+440-1| ... | @@ -2089,6 +2089,7 @@ pub const LPWSTR = [*:0]WCHAR; | ... | @@ -2089,6 +2089,7 @@ pub const LPWSTR = [*:0]WCHAR; |
| 2089 | pub const LPCWSTR = [*:0]const WCHAR; | 2089 | pub const LPCWSTR = [*:0]const WCHAR; |
| 2090 | pub const PVOID = *anyopaque; | 2090 | pub const PVOID = *anyopaque; |
| 2091 | pub const PWSTR = [*:0]WCHAR; | 2091 | pub const PWSTR = [*:0]WCHAR; |
| 2092 | pub const PCWSTR = [*:0]const WCHAR; | ||
| 2092 | pub const SIZE_T = usize; | 2093 | pub const SIZE_T = usize; |
| 2093 | pub const UINT = c_uint; | 2094 | pub const UINT = c_uint; |
| 2094 | pub const ULONG_PTR = usize; | 2095 | pub const ULONG_PTR = usize; |
| ... | @@ -2104,6 +2105,7 @@ pub const USHORT = u16; | ... | @@ -2104,6 +2105,7 @@ pub const USHORT = u16; |
| 2104 | pub const SHORT = i16; | 2105 | pub const SHORT = i16; |
| 2105 | pub const ULONG = u32; | 2106 | pub const ULONG = u32; |
| 2106 | pub const LONG = i32; | 2107 | pub const LONG = i32; |
| 2108 | pub const ULONG64 = u64; | ||
| 2107 | pub const ULONGLONG = u64; | 2109 | pub const ULONGLONG = u64; |
| 2108 | pub const LONGLONG = i64; | 2110 | pub const LONGLONG = i64; |
| 2109 | pub const HLOCAL = HANDLE; | 2111 | pub const HLOCAL = HANDLE; |
| ... | @@ -2504,6 +2506,7 @@ pub const STANDARD_RIGHTS_READ = READ_CONTROL; | ... | @@ -2504,6 +2506,7 @@ pub const STANDARD_RIGHTS_READ = READ_CONTROL; |
| 2504 | pub const STANDARD_RIGHTS_WRITE = READ_CONTROL; | 2506 | pub const STANDARD_RIGHTS_WRITE = READ_CONTROL; |
| 2505 | pub const STANDARD_RIGHTS_EXECUTE = READ_CONTROL; | 2507 | pub const STANDARD_RIGHTS_EXECUTE = READ_CONTROL; |
| 2506 | pub const STANDARD_RIGHTS_REQUIRED = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER; | 2508 | pub const STANDARD_RIGHTS_REQUIRED = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER; |
| 2509 | pub const MAXIMUM_ALLOWED = 0x02000000; | ||
| 2507 | 2510 | ||
| 2508 | // disposition for NtCreateFile | 2511 | // disposition for NtCreateFile |
| 2509 | pub const FILE_SUPERSEDE = 0; | 2512 | pub const FILE_SUPERSEDE = 0; |
| ... | @@ -2872,9 +2875,143 @@ pub const PROV_RSA_FULL = 1; | ... | @@ -2872,9 +2875,143 @@ pub const PROV_RSA_FULL = 1; |
| 2872 | 2875 | ||
| 2873 | pub const REGSAM = ACCESS_MASK; | 2876 | pub const REGSAM = ACCESS_MASK; |
| 2874 | pub const ACCESS_MASK = DWORD; | 2877 | pub const ACCESS_MASK = DWORD; |
| 2875 | pub const HKEY = *opaque {}; | ||
| 2876 | pub const LSTATUS = LONG; | 2878 | pub const LSTATUS = LONG; |
| 2877 | 2879 | ||
| 2880 | pub const HKEY = *opaque {}; | ||
| 2881 | |||
| 2882 | pub const HKEY_LOCAL_MACHINE: HKEY = @intToPtr(HKEY, 0x80000002); | ||
| 2883 | |||
| 2884 | /// Combines the STANDARD_RIGHTS_REQUIRED, KEY_QUERY_VALUE, KEY_SET_VALUE, KEY_CREATE_SUB_KEY, | ||
| 2885 | /// KEY_ENUMERATE_SUB_KEYS, KEY_NOTIFY, and KEY_CREATE_LINK access rights. | ||
| 2886 | pub const KEY_ALL_ACCESS = 0xF003F; | ||
| 2887 | /// Reserved for system use. | ||
| 2888 | pub const KEY_CREATE_LINK = 0x0020; | ||
| 2889 | /// Required to create a subkey of a registry key. | ||
| 2890 | pub const KEY_CREATE_SUB_KEY = 0x0004; | ||
| 2891 | /// Required to enumerate the subkeys of a registry key. | ||
| 2892 | pub const KEY_ENUMERATE_SUB_KEYS = 0x0008; | ||
| 2893 | /// Equivalent to KEY_READ. | ||
| 2894 | pub const KEY_EXECUTE = 0x20019; | ||
| 2895 | /// Required to request change notifications for a registry key or for subkeys of a registry key. | ||
| 2896 | pub const KEY_NOTIFY = 0x0010; | ||
| 2897 | /// Required to query the values of a registry key. | ||
| 2898 | pub const KEY_QUERY_VALUE = 0x0001; | ||
| 2899 | /// Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY values. | ||
| 2900 | pub const KEY_READ = 0x20019; | ||
| 2901 | /// Required to create, delete, or set a registry value. | ||
| 2902 | pub const KEY_SET_VALUE = 0x0002; | ||
| 2903 | /// Indicates that an application on 64-bit Windows should operate on the 32-bit registry view. | ||
| 2904 | /// This flag is ignored by 32-bit Windows. | ||
| 2905 | pub const KEY_WOW64_32KEY = 0x0200; | ||
| 2906 | /// Indicates that an application on 64-bit Windows should operate on the 64-bit registry view. | ||
| 2907 | /// This flag is ignored by 32-bit Windows. | ||
| 2908 | pub const KEY_WOW64_64KEY = 0x0100; | ||
| 2909 | /// Combines the STANDARD_RIGHTS_WRITE, KEY_SET_VALUE, and KEY_CREATE_SUB_KEY access rights. | ||
| 2910 | pub const KEY_WRITE = 0x20006; | ||
| 2911 | |||
| 2912 | /// Open symbolic link. | ||
| 2913 | pub const REG_OPTION_OPEN_LINK: DWORD = 0x8; | ||
| 2914 | |||
| 2915 | pub const RTL_QUERY_REGISTRY_TABLE = extern struct { | ||
| 2916 | QueryRoutine: RTL_QUERY_REGISTRY_ROUTINE, | ||
| 2917 | Flags: ULONG, | ||
| 2918 | Name: ?PWSTR, | ||
| 2919 | EntryContext: ?*anyopaque, | ||
| 2920 | DefaultType: ULONG, | ||
| 2921 | DefaultData: ?*anyopaque, | ||
| 2922 | DefaultLength: ULONG, | ||
| 2923 | }; | ||
| 2924 | |||
| 2925 | pub const RTL_QUERY_REGISTRY_ROUTINE = ?std.meta.FnPtr(fn ( | ||
| 2926 | PWSTR, | ||
| 2927 | ULONG, | ||
| 2928 | ?*anyopaque, | ||
| 2929 | ULONG, | ||
| 2930 | ?*anyopaque, | ||
| 2931 | ?*anyopaque, | ||
| 2932 | ) callconv(WINAPI) NTSTATUS); | ||
| 2933 | |||
| 2934 | /// Path is a full path | ||
| 2935 | pub const RTL_REGISTRY_ABSOLUTE = 0; | ||
| 2936 | /// \Registry\Machine\System\CurrentControlSet\Services | ||
| 2937 | pub const RTL_REGISTRY_SERVICES = 1; | ||
| 2938 | /// \Registry\Machine\System\CurrentControlSet\Control | ||
| 2939 | pub const RTL_REGISTRY_CONTROL = 2; | ||
| 2940 | /// \Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion | ||
| 2941 | pub const RTL_REGISTRY_WINDOWS_NT = 3; | ||
| 2942 | /// \Registry\Machine\Hardware\DeviceMap | ||
| 2943 | pub const RTL_REGISTRY_DEVICEMAP = 4; | ||
| 2944 | /// \Registry\User\CurrentUser | ||
| 2945 | pub const RTL_REGISTRY_USER = 5; | ||
| 2946 | pub const RTL_REGISTRY_MAXIMUM = 6; | ||
| 2947 | |||
| 2948 | /// Low order bits are registry handle | ||
| 2949 | pub const RTL_REGISTRY_HANDLE = 0x40000000; | ||
| 2950 | /// Indicates the key node is optional | ||
| 2951 | pub const RTL_REGISTRY_OPTIONAL = 0x80000000; | ||
| 2952 | |||
| 2953 | /// Name is a subkey and remainder of table or until next subkey are value | ||
| 2954 | /// names for that subkey to look at. | ||
| 2955 | pub const RTL_QUERY_REGISTRY_SUBKEY = 0x00000001; | ||
| 2956 | |||
| 2957 | /// Reset current key to original key for this and all following table entries. | ||
| 2958 | pub const RTL_QUERY_REGISTRY_TOPKEY = 0x00000002; | ||
| 2959 | |||
| 2960 | /// Fail if no match found for this table entry. | ||
| 2961 | pub const RTL_QUERY_REGISTRY_REQUIRED = 0x00000004; | ||
| 2962 | |||
| 2963 | /// Used to mark a table entry that has no value name, just wants a call out, not | ||
| 2964 | /// an enumeration of all values. | ||
| 2965 | pub const RTL_QUERY_REGISTRY_NOVALUE = 0x00000008; | ||
| 2966 | |||
| 2967 | /// Used to suppress the expansion of REG_MULTI_SZ into multiple callouts or | ||
| 2968 | /// to prevent the expansion of environment variable values in REG_EXPAND_SZ. | ||
| 2969 | pub const RTL_QUERY_REGISTRY_NOEXPAND = 0x00000010; | ||
| 2970 | |||
| 2971 | /// QueryRoutine field ignored. EntryContext field points to location to store value. | ||
| 2972 | /// For null terminated strings, EntryContext points to UNICODE_STRING structure that | ||
| 2973 | /// that describes maximum size of buffer. If .Buffer field is NULL then a buffer is | ||
| 2974 | /// allocated. | ||
| 2975 | pub const RTL_QUERY_REGISTRY_DIRECT = 0x00000020; | ||
| 2976 | |||
| 2977 | /// Used to delete value keys after they are queried. | ||
| 2978 | pub const RTL_QUERY_REGISTRY_DELETE = 0x00000040; | ||
| 2979 | |||
| 2980 | /// Use this flag with the RTL_QUERY_REGISTRY_DIRECT flag to verify that the REG_XXX type | ||
| 2981 | /// of the stored registry value matches the type expected by the caller. | ||
| 2982 | /// If the types do not match, the call fails. | ||
| 2983 | pub const RTL_QUERY_REGISTRY_TYPECHECK = 0x00000100; | ||
| 2984 | |||
| 2985 | pub const REG = struct { | ||
| 2986 | /// No value type | ||
| 2987 | pub const NONE: ULONG = 0; | ||
| 2988 | /// Unicode nul terminated string | ||
| 2989 | pub const SZ: ULONG = 1; | ||
| 2990 | /// Unicode nul terminated string (with environment variable references) | ||
| 2991 | pub const EXPAND_SZ: ULONG = 2; | ||
| 2992 | /// Free form binary | ||
| 2993 | pub const BINARY: ULONG = 3; | ||
| 2994 | /// 32-bit number | ||
| 2995 | pub const DWORD: ULONG = 4; | ||
| 2996 | /// 32-bit number (same as REG_DWORD) | ||
| 2997 | pub const DWORD_LITTLE_ENDIAN: ULONG = 4; | ||
| 2998 | /// 32-bit number | ||
| 2999 | pub const DWORD_BIG_ENDIAN: ULONG = 5; | ||
| 3000 | /// Symbolic Link (unicode) | ||
| 3001 | pub const LINK: ULONG = 6; | ||
| 3002 | /// Multiple Unicode strings | ||
| 3003 | pub const MULTI_SZ: ULONG = 7; | ||
| 3004 | /// Resource list in the resource map | ||
| 3005 | pub const RESOURCE_LIST: ULONG = 8; | ||
| 3006 | /// Resource list in the hardware description | ||
| 3007 | pub const FULL_RESOURCE_DESCRIPTOR: ULONG = 9; | ||
| 3008 | pub const RESOURCE_REQUIREMENTS_LIST: ULONG = 10; | ||
| 3009 | /// 64-bit number | ||
| 3010 | pub const QWORD: ULONG = 11; | ||
| 3011 | /// 64-bit number (same as REG_QWORD) | ||
| 3012 | pub const QWORD_LITTLE_ENDIAN: ULONG = 11; | ||
| 3013 | }; | ||
| 3014 | |||
| 2878 | pub const FILE_NOTIFY_INFORMATION = extern struct { | 3015 | pub const FILE_NOTIFY_INFORMATION = extern struct { |
| 2879 | NextEntryOffset: DWORD, | 3016 | NextEntryOffset: DWORD, |
| 2880 | Action: DWORD, | 3017 | Action: DWORD, |
| ... | @@ -3715,3 +3852,305 @@ pub const CTRL_LOGOFF_EVENT: DWORD = 5; | ... | @@ -3715,3 +3852,305 @@ pub const CTRL_LOGOFF_EVENT: DWORD = 5; |
| 3715 | pub const CTRL_SHUTDOWN_EVENT: DWORD = 6; | 3852 | pub const CTRL_SHUTDOWN_EVENT: DWORD = 6; |
| 3716 | 3853 | ||
| 3717 | pub const HANDLER_ROUTINE = std.meta.FnPtr(fn (dwCtrlType: DWORD) callconv(WINAPI) BOOL); | 3854 | pub const HANDLER_ROUTINE = std.meta.FnPtr(fn (dwCtrlType: DWORD) callconv(WINAPI) BOOL); |
| 3855 | |||
| 3856 | /// Processor feature enumeration. | ||
| 3857 | pub const PF = enum(DWORD) { | ||
| 3858 | /// On a Pentium, a floating-point precision error can occur in rare circumstances. | ||
| 3859 | FLOATING_POINT_PRECISION_ERRATA = 0, | ||
| 3860 | |||
| 3861 | /// Floating-point operations are emulated using software emulator. | ||
| 3862 | /// This function returns a nonzero value if floating-point operations are emulated; otherwise, it returns zero. | ||
| 3863 | FLOATING_POINT_EMULATED = 1, | ||
| 3864 | |||
| 3865 | /// The atomic compare and exchange operation (cmpxchg) is available. | ||
| 3866 | COMPARE_EXCHANGE_DOUBLE = 2, | ||
| 3867 | |||
| 3868 | /// The MMX instruction set is available. | ||
| 3869 | MMX_INSTRUCTIONS_AVAILABLE = 3, | ||
| 3870 | |||
| 3871 | PPC_MOVEMEM_64BIT_OK = 4, | ||
| 3872 | ALPHA_BYTE_INSTRUCTIONS = 5, | ||
| 3873 | |||
| 3874 | /// The SSE instruction set is available. | ||
| 3875 | XMMI_INSTRUCTIONS_AVAILABLE = 6, | ||
| 3876 | |||
| 3877 | /// The 3D-Now instruction is available. | ||
| 3878 | @"3DNOW_INSTRUCTIONS_AVAILABLE" = 7, | ||
| 3879 | |||
| 3880 | /// The RDTSC instruction is available. | ||
| 3881 | RDTSC_INSTRUCTION_AVAILABLE = 8, | ||
| 3882 | |||
| 3883 | /// The processor is PAE-enabled. | ||
| 3884 | PAE_ENABLED = 9, | ||
| 3885 | |||
| 3886 | /// The SSE2 instruction set is available. | ||
| 3887 | XMMI64_INSTRUCTIONS_AVAILABLE = 10, | ||
| 3888 | |||
| 3889 | SSE_DAZ_MODE_AVAILABLE = 11, | ||
| 3890 | |||
| 3891 | /// Data execution prevention is enabled. | ||
| 3892 | NX_ENABLED = 12, | ||
| 3893 | |||
| 3894 | /// The SSE3 instruction set is available. | ||
| 3895 | SSE3_INSTRUCTIONS_AVAILABLE = 13, | ||
| 3896 | |||
| 3897 | /// The atomic compare and exchange 128-bit operation (cmpxchg16b) is available. | ||
| 3898 | COMPARE_EXCHANGE128 = 14, | ||
| 3899 | |||
| 3900 | /// The atomic compare 64 and exchange 128-bit operation (cmp8xchg16) is available. | ||
| 3901 | COMPARE64_EXCHANGE128 = 15, | ||
| 3902 | |||
| 3903 | /// The processor channels are enabled. | ||
| 3904 | CHANNELS_ENABLED = 16, | ||
| 3905 | |||
| 3906 | /// The processor implements the XSAVI and XRSTOR instructions. | ||
| 3907 | XSAVE_ENABLED = 17, | ||
| 3908 | |||
| 3909 | /// The VFP/Neon: 32 x 64bit register bank is present. | ||
| 3910 | /// This flag has the same meaning as PF_ARM_VFP_EXTENDED_REGISTERS. | ||
| 3911 | ARM_VFP_32_REGISTERS_AVAILABLE = 18, | ||
| 3912 | |||
| 3913 | /// This ARM processor implements the ARM v8 NEON instruction set. | ||
| 3914 | ARM_NEON_INSTRUCTIONS_AVAILABLE = 19, | ||
| 3915 | |||
| 3916 | /// Second Level Address Translation is supported by the hardware. | ||
| 3917 | SECOND_LEVEL_ADDRESS_TRANSLATION = 20, | ||
| 3918 | |||
| 3919 | /// Virtualization is enabled in the firmware and made available by the operating system. | ||
| 3920 | VIRT_FIRMWARE_ENABLED = 21, | ||
| 3921 | |||
| 3922 | /// RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE instructions are available. | ||
| 3923 | RDWRFSGBASE_AVAILABLE = 22, | ||
| 3924 | |||
| 3925 | /// _fastfail() is available. | ||
| 3926 | FASTFAIL_AVAILABLE = 23, | ||
| 3927 | |||
| 3928 | /// The divide instruction_available. | ||
| 3929 | ARM_DIVIDE_INSTRUCTION_AVAILABLE = 24, | ||
| 3930 | |||
| 3931 | /// The 64-bit load/store atomic instructions are available. | ||
| 3932 | ARM_64BIT_LOADSTORE_ATOMIC = 25, | ||
| 3933 | |||
| 3934 | /// The external cache is available. | ||
| 3935 | ARM_EXTERNAL_CACHE_AVAILABLE = 26, | ||
| 3936 | |||
| 3937 | /// The floating-point multiply-accumulate instruction is available. | ||
| 3938 | ARM_FMAC_INSTRUCTIONS_AVAILABLE = 27, | ||
| 3939 | |||
| 3940 | RDRAND_INSTRUCTION_AVAILABLE = 28, | ||
| 3941 | |||
| 3942 | /// This ARM processor implements the ARM v8 instructions set. | ||
| 3943 | ARM_V8_INSTRUCTIONS_AVAILABLE = 29, | ||
| 3944 | |||
| 3945 | /// This ARM processor implements the ARM v8 extra cryptographic instructions (i.e., AES, SHA1 and SHA2). | ||
| 3946 | ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE = 30, | ||
| 3947 | |||
| 3948 | /// This ARM processor implements the ARM v8 extra CRC32 instructions. | ||
| 3949 | ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE = 31, | ||
| 3950 | |||
| 3951 | RDTSCP_INSTRUCTION_AVAILABLE = 32, | ||
| 3952 | RDPID_INSTRUCTION_AVAILABLE = 33, | ||
| 3953 | |||
| 3954 | /// This ARM processor implements the ARM v8.1 atomic instructions (e.g., CAS, SWP). | ||
| 3955 | ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE = 34, | ||
| 3956 | |||
| 3957 | MONITORX_INSTRUCTION_AVAILABLE = 35, | ||
| 3958 | |||
| 3959 | /// The SSSE3 instruction set is available. | ||
| 3960 | SSSE3_INSTRUCTIONS_AVAILABLE = 36, | ||
| 3961 | |||
| 3962 | /// The SSE4_1 instruction set is available. | ||
| 3963 | SSE4_1_INSTRUCTIONS_AVAILABLE = 37, | ||
| 3964 | |||
| 3965 | /// The SSE4_2 instruction set is available. | ||
| 3966 | SSE4_2_INSTRUCTIONS_AVAILABLE = 38, | ||
| 3967 | |||
| 3968 | /// The AVX instruction set is available. | ||
| 3969 | AVX_INSTRUCTIONS_AVAILABLE = 39, | ||
| 3970 | |||
| 3971 | /// The AVX2 instruction set is available. | ||
| 3972 | AVX2_INSTRUCTIONS_AVAILABLE = 40, | ||
| 3973 | |||
| 3974 | /// The AVX512F instruction set is available. | ||
| 3975 | AVX512F_INSTRUCTIONS_AVAILABLE = 41, | ||
| 3976 | |||
| 3977 | ERMS_AVAILABLE = 42, | ||
| 3978 | |||
| 3979 | /// This ARM processor implements the ARM v8.2 Dot Product (DP) instructions. | ||
| 3980 | ARM_V82_DP_INSTRUCTIONS_AVAILABLE = 43, | ||
| 3981 | |||
| 3982 | /// This ARM processor implements the ARM v8.3 JavaScript conversion (JSCVT) instructions. | ||
| 3983 | ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE = 44, | ||
| 3984 | }; | ||
| 3985 | |||
| 3986 | pub const MAX_WOW64_SHARED_ENTRIES = 16; | ||
| 3987 | pub const PROCESSOR_FEATURE_MAX = 64; | ||
| 3988 | pub const MAXIMUM_XSTATE_FEATURES = 64; | ||
| 3989 | |||
| 3990 | pub const KSYSTEM_TIME = extern struct { | ||
| 3991 | LowPart: ULONG, | ||
| 3992 | High1Time: LONG, | ||
| 3993 | High2Time: LONG, | ||
| 3994 | }; | ||
| 3995 | |||
| 3996 | pub const NT_PRODUCT_TYPE = enum(INT) { | ||
| 3997 | NtProductWinNt = 1, | ||
| 3998 | NtProductLanManNt, | ||
| 3999 | NtProductServer, | ||
| 4000 | }; | ||
| 4001 | |||
| 4002 | pub const ALTERNATIVE_ARCHITECTURE_TYPE = enum(INT) { | ||
| 4003 | StandardDesign, | ||
| 4004 | NEC98x86, | ||
| 4005 | EndAlternatives, | ||
| 4006 | }; | ||
| 4007 | |||
| 4008 | pub const XSTATE_FEATURE = extern struct { | ||
| 4009 | Offset: ULONG, | ||
| 4010 | Size: ULONG, | ||
| 4011 | }; | ||
| 4012 | |||
| 4013 | pub const XSTATE_CONFIGURATION = extern struct { | ||
| 4014 | EnabledFeatures: ULONG64, | ||
| 4015 | Size: ULONG, | ||
| 4016 | OptimizedSave: ULONG, | ||
| 4017 | Features: [MAXIMUM_XSTATE_FEATURES]XSTATE_FEATURE, | ||
| 4018 | }; | ||
| 4019 | |||
| 4020 | /// Shared Kernel User Data | ||
| 4021 | pub const KUSER_SHARED_DATA = extern struct { | ||
| 4022 | TickCountLowDeprecated: ULONG, | ||
| 4023 | TickCountMultiplier: ULONG, | ||
| 4024 | InterruptTime: KSYSTEM_TIME, | ||
| 4025 | SystemTime: KSYSTEM_TIME, | ||
| 4026 | TimeZoneBias: KSYSTEM_TIME, | ||
| 4027 | ImageNumberLow: USHORT, | ||
| 4028 | ImageNumberHigh: USHORT, | ||
| 4029 | NtSystemRoot: [260]WCHAR, | ||
| 4030 | MaxStackTraceDepth: ULONG, | ||
| 4031 | CryptoExponent: ULONG, | ||
| 4032 | TimeZoneId: ULONG, | ||
| 4033 | LargePageMinimum: ULONG, | ||
| 4034 | AitSamplingValue: ULONG, | ||
| 4035 | AppCompatFlag: ULONG, | ||
| 4036 | RNGSeedVersion: ULONGLONG, | ||
| 4037 | GlobalValidationRunlevel: ULONG, | ||
| 4038 | TimeZoneBiasStamp: LONG, | ||
| 4039 | NtBuildNumber: ULONG, | ||
| 4040 | NtProductType: NT_PRODUCT_TYPE, | ||
| 4041 | ProductTypeIsValid: BOOLEAN, | ||
| 4042 | Reserved0: [1]BOOLEAN, | ||
| 4043 | NativeProcessorArchitecture: USHORT, | ||
| 4044 | NtMajorVersion: ULONG, | ||
| 4045 | NtMinorVersion: ULONG, | ||
| 4046 | ProcessorFeatures: [PROCESSOR_FEATURE_MAX]BOOLEAN, | ||
| 4047 | Reserved1: ULONG, | ||
| 4048 | Reserved3: ULONG, | ||
| 4049 | TimeSlip: ULONG, | ||
| 4050 | AlternativeArchitecture: ALTERNATIVE_ARCHITECTURE_TYPE, | ||
| 4051 | BootId: ULONG, | ||
| 4052 | SystemExpirationDate: LARGE_INTEGER, | ||
| 4053 | SuiteMaskY: ULONG, | ||
| 4054 | KdDebuggerEnabled: BOOLEAN, | ||
| 4055 | DummyUnion1: extern union { | ||
| 4056 | MitigationPolicies: UCHAR, | ||
| 4057 | Alt: packed struct { | ||
| 4058 | NXSupportPolicy: u2, | ||
| 4059 | SEHValidationPolicy: u2, | ||
| 4060 | CurDirDevicesSkippedForDlls: u2, | ||
| 4061 | Reserved: u2, | ||
| 4062 | }, | ||
| 4063 | }, | ||
| 4064 | CyclesPerYield: USHORT, | ||
| 4065 | ActiveConsoleId: ULONG, | ||
| 4066 | DismountCount: ULONG, | ||
| 4067 | ComPlusPackage: ULONG, | ||
| 4068 | LastSystemRITEventTickCount: ULONG, | ||
| 4069 | NumberOfPhysicalPages: ULONG, | ||
| 4070 | SafeBootMode: BOOLEAN, | ||
| 4071 | DummyUnion2: extern union { | ||
| 4072 | VirtualizationFlags: UCHAR, | ||
| 4073 | Alt: packed struct { | ||
| 4074 | ArchStartedInEl2: u1, | ||
| 4075 | QcSlIsSupported: u1, | ||
| 4076 | SpareBits: u6, | ||
| 4077 | }, | ||
| 4078 | }, | ||
| 4079 | Reserved12: [2]UCHAR, | ||
| 4080 | DummyUnion3: extern union { | ||
| 4081 | SharedDataFlags: ULONG, | ||
| 4082 | Alt: packed struct { | ||
| 4083 | DbgErrorPortPresent: u1, | ||
| 4084 | DbgElevationEnabled: u1, | ||
| 4085 | DbgVirtEnabled: u1, | ||
| 4086 | DbgInstallerDetectEnabled: u1, | ||
| 4087 | DbgLkgEnabled: u1, | ||
| 4088 | DbgDynProcessorEnabled: u1, | ||
| 4089 | DbgConsoleBrokerEnabled: u1, | ||
| 4090 | DbgSecureBootEnabled: u1, | ||
| 4091 | DbgMultiSessionSku: u1, | ||
| 4092 | DbgMultiUsersInSessionSku: u1, | ||
| 4093 | DbgStateSeparationEnabled: u1, | ||
| 4094 | SpareBits: u21, | ||
| 4095 | }, | ||
| 4096 | }, | ||
| 4097 | DataFlagsPad: [1]ULONG, | ||
| 4098 | TestRetInstruction: ULONGLONG, | ||
| 4099 | QpcFrequency: LONGLONG, | ||
| 4100 | SystemCall: ULONG, | ||
| 4101 | Reserved2: ULONG, | ||
| 4102 | SystemCallPad: [2]ULONGLONG, | ||
| 4103 | DummyUnion4: extern union { | ||
| 4104 | TickCount: KSYSTEM_TIME, | ||
| 4105 | TickCountQuad: ULONG64, | ||
| 4106 | Alt: extern struct { | ||
| 4107 | ReservedTickCountOverlay: [3]ULONG, | ||
| 4108 | TickCountPad: [1]ULONG, | ||
| 4109 | }, | ||
| 4110 | }, | ||
| 4111 | Cookie: ULONG, | ||
| 4112 | CookiePad: [1]ULONG, | ||
| 4113 | ConsoleSessionForegroundProcessId: LONGLONG, | ||
| 4114 | TimeUpdateLock: ULONGLONG, | ||
| 4115 | BaselineSystemTimeQpc: ULONGLONG, | ||
| 4116 | BaselineInterruptTimeQpc: ULONGLONG, | ||
| 4117 | QpcSystemTimeIncrement: ULONGLONG, | ||
| 4118 | QpcInterruptTimeIncrement: ULONGLONG, | ||
| 4119 | QpcSystemTimeIncrementShift: UCHAR, | ||
| 4120 | QpcInterruptTimeIncrementShift: UCHAR, | ||
| 4121 | UnparkedProcessorCount: USHORT, | ||
| 4122 | EnclaveFeatureMask: [4]ULONG, | ||
| 4123 | TelemetryCoverageRound: ULONG, | ||
| 4124 | UserModeGlobalLogger: [16]USHORT, | ||
| 4125 | ImageFileExecutionOptions: ULONG, | ||
| 4126 | LangGenerationCount: ULONG, | ||
| 4127 | Reserved4: ULONGLONG, | ||
| 4128 | InterruptTimeBias: ULONGLONG, | ||
| 4129 | QpcBias: ULONGLONG, | ||
| 4130 | ActiveProcessorCount: ULONG, | ||
| 4131 | ActiveGroupCount: UCHAR, | ||
| 4132 | Reserved9: UCHAR, | ||
| 4133 | DummyUnion5: extern union { | ||
| 4134 | QpcData: USHORT, | ||
| 4135 | Alt: extern struct { | ||
| 4136 | QpcBypassEnabled: UCHAR, | ||
| 4137 | QpcShift: UCHAR, | ||
| 4138 | }, | ||
| 4139 | }, | ||
| 4140 | TimeZoneBiasEffectiveStart: LARGE_INTEGER, | ||
| 4141 | TimeZoneBiasEffectiveEnd: LARGE_INTEGER, | ||
| 4142 | XState: XSTATE_CONFIGURATION, | ||
| 4143 | FeatureConfigurationChangeStamp: KSYSTEM_TIME, | ||
| 4144 | Spare: ULONG, | ||
| 4145 | UserPointerAuthMask: ULONG64, | ||
| 4146 | }; | ||
| 4147 | |||
| 4148 | /// Read-only user-mode address for the shared data. | ||
| 4149 | /// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm | ||
| 4150 | /// https://msrc-blog.microsoft.com/2022/04/05/randomizing-the-kuser_shared_data-structure-on-windows/ | ||
| 4151 | pub const SharedUserData: *const KUSER_SHARED_DATA = @intToPtr(*const KUSER_SHARED_DATA, 0x7FFE0000); | ||
| 4152 | |||
| 4153 | pub fn IsProcessorFeaturePresent(feature: PF) bool { | ||
| 4154 | if (@enumToInt(feature) >= PROCESSOR_FEATURE_MAX) return false; | ||
| 4155 | return SharedUserData.ProcessorFeatures[@enumToInt(feature)] == 1; | ||
| 4156 | } |
lib/std/os/windows/kernel32.zig+12| ... | @@ -10,6 +10,7 @@ const DWORD = windows.DWORD; | ... | @@ -10,6 +10,7 @@ const DWORD = windows.DWORD; |
| 10 | const FILE_INFO_BY_HANDLE_CLASS = windows.FILE_INFO_BY_HANDLE_CLASS; | 10 | const FILE_INFO_BY_HANDLE_CLASS = windows.FILE_INFO_BY_HANDLE_CLASS; |
| 11 | const HANDLE = windows.HANDLE; | 11 | const HANDLE = windows.HANDLE; |
| 12 | const HMODULE = windows.HMODULE; | 12 | const HMODULE = windows.HMODULE; |
| 13 | const HKEY = windows.HKEY; | ||
| 13 | const HRESULT = windows.HRESULT; | 14 | const HRESULT = windows.HRESULT; |
| 14 | const LARGE_INTEGER = windows.LARGE_INTEGER; | 15 | const LARGE_INTEGER = windows.LARGE_INTEGER; |
| 15 | const LPCWSTR = windows.LPCWSTR; | 16 | const LPCWSTR = windows.LPCWSTR; |
| ... | @@ -57,6 +58,8 @@ const UCHAR = windows.UCHAR; | ... | @@ -57,6 +58,8 @@ const UCHAR = windows.UCHAR; |
| 57 | const FARPROC = windows.FARPROC; | 58 | const FARPROC = windows.FARPROC; |
| 58 | const INIT_ONCE_FN = windows.INIT_ONCE_FN; | 59 | const INIT_ONCE_FN = windows.INIT_ONCE_FN; |
| 59 | const PMEMORY_BASIC_INFORMATION = windows.PMEMORY_BASIC_INFORMATION; | 60 | const PMEMORY_BASIC_INFORMATION = windows.PMEMORY_BASIC_INFORMATION; |
| 61 | const REGSAM = windows.REGSAM; | ||
| 62 | const LSTATUS = windows.LSTATUS; | ||
| 60 | 63 | ||
| 61 | pub extern "kernel32" fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) callconv(WINAPI) ?*anyopaque; | 64 | pub extern "kernel32" fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) callconv(WINAPI) ?*anyopaque; |
| 62 | pub extern "kernel32" fn RemoveVectoredExceptionHandler(Handle: HANDLE) callconv(WINAPI) c_ulong; | 65 | pub extern "kernel32" fn RemoveVectoredExceptionHandler(Handle: HANDLE) callconv(WINAPI) c_ulong; |
| ... | @@ -231,6 +234,7 @@ pub extern "kernel32" fn GetQueuedCompletionStatusEx( | ... | @@ -231,6 +234,7 @@ pub extern "kernel32" fn GetQueuedCompletionStatusEx( |
| 231 | 234 | ||
| 232 | pub extern "kernel32" fn GetSystemInfo(lpSystemInfo: *SYSTEM_INFO) callconv(WINAPI) void; | 235 | pub extern "kernel32" fn GetSystemInfo(lpSystemInfo: *SYSTEM_INFO) callconv(WINAPI) void; |
| 233 | pub extern "kernel32" fn GetSystemTimeAsFileTime(*FILETIME) callconv(WINAPI) void; | 236 | pub extern "kernel32" fn GetSystemTimeAsFileTime(*FILETIME) callconv(WINAPI) void; |
| 237 | pub extern "kernel32" fn IsProcessorFeaturePresent(ProcessorFeature: DWORD) BOOL; | ||
| 234 | 238 | ||
| 235 | pub extern "kernel32" fn HeapCreate(flOptions: DWORD, dwInitialSize: SIZE_T, dwMaximumSize: SIZE_T) callconv(WINAPI) ?HANDLE; | 239 | pub extern "kernel32" fn HeapCreate(flOptions: DWORD, dwInitialSize: SIZE_T, dwMaximumSize: SIZE_T) callconv(WINAPI) ?HANDLE; |
| 236 | pub extern "kernel32" fn HeapDestroy(hHeap: HANDLE) callconv(WINAPI) BOOL; | 240 | pub extern "kernel32" fn HeapDestroy(hHeap: HANDLE) callconv(WINAPI) BOOL; |
| ... | @@ -411,3 +415,11 @@ pub extern "kernel32" fn SleepConditionVariableSRW( | ... | @@ -411,3 +415,11 @@ pub extern "kernel32" fn SleepConditionVariableSRW( |
| 411 | pub extern "kernel32" fn TryAcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) BOOLEAN; | 415 | pub extern "kernel32" fn TryAcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) BOOLEAN; |
| 412 | pub extern "kernel32" fn AcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void; | 416 | pub extern "kernel32" fn AcquireSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void; |
| 413 | pub extern "kernel32" fn ReleaseSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void; | 417 | pub extern "kernel32" fn ReleaseSRWLockExclusive(s: *SRWLOCK) callconv(WINAPI) void; |
| 418 | |||
| 419 | pub extern "kernel32" fn RegOpenKeyExW( | ||
| 420 | hkey: HKEY, | ||
| 421 | lpSubKey: LPCWSTR, | ||
| 422 | ulOptions: DWORD, | ||
| 423 | samDesired: REGSAM, | ||
| 424 | phkResult: *HKEY, | ||
| 425 | ) callconv(WINAPI) LSTATUS; |
lib/std/os/windows/ntdll.zig+16| ... | @@ -22,6 +22,8 @@ const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW; | ... | @@ -22,6 +22,8 @@ const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW; |
| 22 | const FILE_BASIC_INFORMATION = windows.FILE_BASIC_INFORMATION; | 22 | const FILE_BASIC_INFORMATION = windows.FILE_BASIC_INFORMATION; |
| 23 | const SIZE_T = windows.SIZE_T; | 23 | const SIZE_T = windows.SIZE_T; |
| 24 | const CURDIR = windows.CURDIR; | 24 | const CURDIR = windows.CURDIR; |
| 25 | const PCWSTR = windows.PCWSTR; | ||
| 26 | const RTL_QUERY_REGISTRY_TABLE = windows.RTL_QUERY_REGISTRY_TABLE; | ||
| 25 | 27 | ||
| 26 | pub const THREADINFOCLASS = enum(c_int) { | 28 | pub const THREADINFOCLASS = enum(c_int) { |
| 27 | ThreadBasicInformation, | 29 | ThreadBasicInformation, |
| ... | @@ -253,3 +255,17 @@ pub extern "ntdll" fn NtUnlockFile( | ... | @@ -253,3 +255,17 @@ pub extern "ntdll" fn NtUnlockFile( |
| 253 | Length: *const LARGE_INTEGER, | 255 | Length: *const LARGE_INTEGER, |
| 254 | Key: ?*ULONG, | 256 | Key: ?*ULONG, |
| 255 | ) callconv(WINAPI) NTSTATUS; | 257 | ) callconv(WINAPI) NTSTATUS; |
| 258 | |||
| 259 | pub extern "ntdll" fn NtOpenKey( | ||
| 260 | KeyHandle: *HANDLE, | ||
| 261 | DesiredAccess: ACCESS_MASK, | ||
| 262 | ObjectAttributes: OBJECT_ATTRIBUTES, | ||
| 263 | ) callconv(WINAPI) NTSTATUS; | ||
| 264 | |||
| 265 | pub extern "ntdll" fn RtlQueryRegistryValues( | ||
| 266 | RelativeTo: ULONG, | ||
| 267 | Path: PCWSTR, | ||
| 268 | QueryTable: [*]RTL_QUERY_REGISTRY_TABLE, | ||
| 269 | Context: ?*anyopaque, | ||
| 270 | Environment: ?*anyopaque, | ||
| 271 | ) callconv(WINAPI) NTSTATUS; |
lib/std/zig/system/NativeTargetInfo.zig+1| ... | @@ -978,6 +978,7 @@ fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, cross_ta | ... | @@ -978,6 +978,7 @@ fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, cross_ta |
| 978 | switch (builtin.os.tag) { | 978 | switch (builtin.os.tag) { |
| 979 | .linux => return linux.detectNativeCpuAndFeatures(), | 979 | .linux => return linux.detectNativeCpuAndFeatures(), |
| 980 | .macos => return darwin.macos.detectNativeCpuAndFeatures(), | 980 | .macos => return darwin.macos.detectNativeCpuAndFeatures(), |
| 981 | .windows => return windows.detectNativeCpuAndFeatures(), | ||
| 981 | else => {}, | 982 | else => {}, |
| 982 | } | 983 | } |
| 983 | 984 |
lib/std/zig/system/arm.zig created+134| ... | @@ -0,0 +1,134 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub const CoreInfo = struct { | ||
| 4 | architecture: u8 = 0, | ||
| 5 | implementer: u8 = 0, | ||
| 6 | variant: u8 = 0, | ||
| 7 | part: u16 = 0, | ||
| 8 | }; | ||
| 9 | |||
| 10 | pub const cpu_models = struct { | ||
| 11 | // Shorthands to simplify the tables below. | ||
| 12 | const A32 = std.Target.arm.cpu; | ||
| 13 | const A64 = std.Target.aarch64.cpu; | ||
| 14 | |||
| 15 | const E = struct { | ||
| 16 | part: u16, | ||
| 17 | variant: ?u8 = null, // null if matches any variant | ||
| 18 | m32: ?*const std.Target.Cpu.Model = null, | ||
| 19 | m64: ?*const std.Target.Cpu.Model = null, | ||
| 20 | }; | ||
| 21 | |||
| 22 | // implementer = 0x41 | ||
| 23 | const ARM = [_]E{ | ||
| 24 | E{ .part = 0x926, .m32 = &A32.arm926ej_s, .m64 = null }, | ||
| 25 | E{ .part = 0xb02, .m32 = &A32.mpcore, .m64 = null }, | ||
| 26 | E{ .part = 0xb36, .m32 = &A32.arm1136j_s, .m64 = null }, | ||
| 27 | E{ .part = 0xb56, .m32 = &A32.arm1156t2_s, .m64 = null }, | ||
| 28 | E{ .part = 0xb76, .m32 = &A32.arm1176jz_s, .m64 = null }, | ||
| 29 | E{ .part = 0xc05, .m32 = &A32.cortex_a5, .m64 = null }, | ||
| 30 | E{ .part = 0xc07, .m32 = &A32.cortex_a7, .m64 = null }, | ||
| 31 | E{ .part = 0xc08, .m32 = &A32.cortex_a8, .m64 = null }, | ||
| 32 | E{ .part = 0xc09, .m32 = &A32.cortex_a9, .m64 = null }, | ||
| 33 | E{ .part = 0xc0d, .m32 = &A32.cortex_a17, .m64 = null }, | ||
| 34 | E{ .part = 0xc0f, .m32 = &A32.cortex_a15, .m64 = null }, | ||
| 35 | E{ .part = 0xc0e, .m32 = &A32.cortex_a17, .m64 = null }, | ||
| 36 | E{ .part = 0xc14, .m32 = &A32.cortex_r4, .m64 = null }, | ||
| 37 | E{ .part = 0xc15, .m32 = &A32.cortex_r5, .m64 = null }, | ||
| 38 | E{ .part = 0xc17, .m32 = &A32.cortex_r7, .m64 = null }, | ||
| 39 | E{ .part = 0xc18, .m32 = &A32.cortex_r8, .m64 = null }, | ||
| 40 | E{ .part = 0xc20, .m32 = &A32.cortex_m0, .m64 = null }, | ||
| 41 | E{ .part = 0xc21, .m32 = &A32.cortex_m1, .m64 = null }, | ||
| 42 | E{ .part = 0xc23, .m32 = &A32.cortex_m3, .m64 = null }, | ||
| 43 | E{ .part = 0xc24, .m32 = &A32.cortex_m4, .m64 = null }, | ||
| 44 | E{ .part = 0xc27, .m32 = &A32.cortex_m7, .m64 = null }, | ||
| 45 | E{ .part = 0xc60, .m32 = &A32.cortex_m0plus, .m64 = null }, | ||
| 46 | E{ .part = 0xd01, .m32 = &A32.cortex_a32, .m64 = null }, | ||
| 47 | E{ .part = 0xd03, .m32 = &A32.cortex_a53, .m64 = &A64.cortex_a53 }, | ||
| 48 | E{ .part = 0xd04, .m32 = &A32.cortex_a35, .m64 = &A64.cortex_a35 }, | ||
| 49 | E{ .part = 0xd05, .m32 = &A32.cortex_a55, .m64 = &A64.cortex_a55 }, | ||
| 50 | E{ .part = 0xd07, .m32 = &A32.cortex_a57, .m64 = &A64.cortex_a57 }, | ||
| 51 | E{ .part = 0xd08, .m32 = &A32.cortex_a72, .m64 = &A64.cortex_a72 }, | ||
| 52 | E{ .part = 0xd09, .m32 = &A32.cortex_a73, .m64 = &A64.cortex_a73 }, | ||
| 53 | E{ .part = 0xd0a, .m32 = &A32.cortex_a75, .m64 = &A64.cortex_a75 }, | ||
| 54 | E{ .part = 0xd0b, .m32 = &A32.cortex_a76, .m64 = &A64.cortex_a76 }, | ||
| 55 | E{ .part = 0xd0c, .m32 = &A32.neoverse_n1, .m64 = &A64.neoverse_n1 }, | ||
| 56 | E{ .part = 0xd0d, .m32 = &A32.cortex_a77, .m64 = &A64.cortex_a77 }, | ||
| 57 | E{ .part = 0xd13, .m32 = &A32.cortex_r52, .m64 = null }, | ||
| 58 | E{ .part = 0xd20, .m32 = &A32.cortex_m23, .m64 = null }, | ||
| 59 | E{ .part = 0xd21, .m32 = &A32.cortex_m33, .m64 = null }, | ||
| 60 | E{ .part = 0xd41, .m32 = &A32.cortex_a78, .m64 = &A64.cortex_a78 }, | ||
| 61 | E{ .part = 0xd4b, .m32 = &A32.cortex_a78c, .m64 = &A64.cortex_a78c }, | ||
| 62 | // This is a guess based on https://www.notebookcheck.net/Qualcomm-Snapdragon-8cx-Gen-3-Processor-Benchmarks-and-Specs.652916.0.html | ||
| 63 | E{ .part = 0xd4c, .m32 = &A32.cortex_x1c, .m64 = &A64.cortex_x1c }, | ||
| 64 | E{ .part = 0xd44, .m32 = &A32.cortex_x1, .m64 = &A64.cortex_x1 }, | ||
| 65 | E{ .part = 0xd02, .m64 = &A64.cortex_a34 }, | ||
| 66 | E{ .part = 0xd06, .m64 = &A64.cortex_a65 }, | ||
| 67 | E{ .part = 0xd43, .m64 = &A64.cortex_a65ae }, | ||
| 68 | }; | ||
| 69 | // implementer = 0x42 | ||
| 70 | const Broadcom = [_]E{ | ||
| 71 | E{ .part = 0x516, .m64 = &A64.thunderx2t99 }, | ||
| 72 | }; | ||
| 73 | // implementer = 0x43 | ||
| 74 | const Cavium = [_]E{ | ||
| 75 | E{ .part = 0x0a0, .m64 = &A64.thunderx }, | ||
| 76 | E{ .part = 0x0a2, .m64 = &A64.thunderxt81 }, | ||
| 77 | E{ .part = 0x0a3, .m64 = &A64.thunderxt83 }, | ||
| 78 | E{ .part = 0x0a1, .m64 = &A64.thunderxt88 }, | ||
| 79 | E{ .part = 0x0af, .m64 = &A64.thunderx2t99 }, | ||
| 80 | }; | ||
| 81 | // implementer = 0x46 | ||
| 82 | const Fujitsu = [_]E{ | ||
| 83 | E{ .part = 0x001, .m64 = &A64.a64fx }, | ||
| 84 | }; | ||
| 85 | // implementer = 0x48 | ||
| 86 | const HiSilicon = [_]E{ | ||
| 87 | E{ .part = 0xd01, .m64 = &A64.tsv110 }, | ||
| 88 | }; | ||
| 89 | // implementer = 0x4e | ||
| 90 | const Nvidia = [_]E{ | ||
| 91 | E{ .part = 0x004, .m64 = &A64.carmel }, | ||
| 92 | }; | ||
| 93 | // implementer = 0x50 | ||
| 94 | const Ampere = [_]E{ | ||
| 95 | E{ .part = 0x000, .variant = 3, .m64 = &A64.emag }, | ||
| 96 | E{ .part = 0x000, .m64 = &A64.xgene1 }, | ||
| 97 | }; | ||
| 98 | // implementer = 0x51 | ||
| 99 | const Qualcomm = [_]E{ | ||
| 100 | E{ .part = 0x06f, .m32 = &A32.krait }, | ||
| 101 | E{ .part = 0x201, .m64 = &A64.kryo, .m32 = &A64.kryo }, | ||
| 102 | E{ .part = 0x205, .m64 = &A64.kryo, .m32 = &A64.kryo }, | ||
| 103 | E{ .part = 0x211, .m64 = &A64.kryo, .m32 = &A64.kryo }, | ||
| 104 | E{ .part = 0x800, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 }, | ||
| 105 | E{ .part = 0x801, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 }, | ||
| 106 | E{ .part = 0x802, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 }, | ||
| 107 | E{ .part = 0x803, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 }, | ||
| 108 | E{ .part = 0x804, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 }, | ||
| 109 | E{ .part = 0x805, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 }, | ||
| 110 | E{ .part = 0xc00, .m64 = &A64.falkor }, | ||
| 111 | E{ .part = 0xc01, .m64 = &A64.saphira }, | ||
| 112 | }; | ||
| 113 | |||
| 114 | pub fn isKnown(core: CoreInfo, is_64bit: bool) ?*const std.Target.Cpu.Model { | ||
| 115 | const models = switch (core.implementer) { | ||
| 116 | 0x41 => &ARM, | ||
| 117 | 0x42 => &Broadcom, | ||
| 118 | 0x43 => &Cavium, | ||
| 119 | 0x46 => &Fujitsu, | ||
| 120 | 0x48 => &HiSilicon, | ||
| 121 | 0x50 => &Ampere, | ||
| 122 | 0x51 => &Qualcomm, | ||
| 123 | else => return null, | ||
| 124 | }; | ||
| 125 | |||
| 126 | for (models) |model| { | ||
| 127 | if (model.part == core.part and | ||
| 128 | (model.variant == null or model.variant.? == core.variant)) | ||
| 129 | return if (is_64bit) model.m64 else model.m32; | ||
| 130 | } | ||
| 131 | |||
| 132 | return null; | ||
| 133 | } | ||
| 134 | }; | ||
lib/std/zig/system/linux.zig+7-124| ... | @@ -159,129 +159,7 @@ const ArmCpuinfoImpl = struct { | ... | @@ -159,129 +159,7 @@ const ArmCpuinfoImpl = struct { |
| 159 | is_really_v6: bool = false, | 159 | is_really_v6: bool = false, |
| 160 | }; | 160 | }; |
| 161 | 161 | ||
| 162 | const cpu_models = struct { | 162 | const cpu_models = @import("arm.zig").cpu_models; |
| 163 | // Shorthands to simplify the tables below. | ||
| 164 | const A32 = Target.arm.cpu; | ||
| 165 | const A64 = Target.aarch64.cpu; | ||
| 166 | |||
| 167 | const E = struct { | ||
| 168 | part: u16, | ||
| 169 | variant: ?u8 = null, // null if matches any variant | ||
| 170 | m32: ?*const Target.Cpu.Model = null, | ||
| 171 | m64: ?*const Target.Cpu.Model = null, | ||
| 172 | }; | ||
| 173 | |||
| 174 | // implementer = 0x41 | ||
| 175 | const ARM = [_]E{ | ||
| 176 | E{ .part = 0x926, .m32 = &A32.arm926ej_s, .m64 = null }, | ||
| 177 | E{ .part = 0xb02, .m32 = &A32.mpcore, .m64 = null }, | ||
| 178 | E{ .part = 0xb36, .m32 = &A32.arm1136j_s, .m64 = null }, | ||
| 179 | E{ .part = 0xb56, .m32 = &A32.arm1156t2_s, .m64 = null }, | ||
| 180 | E{ .part = 0xb76, .m32 = &A32.arm1176jz_s, .m64 = null }, | ||
| 181 | E{ .part = 0xc05, .m32 = &A32.cortex_a5, .m64 = null }, | ||
| 182 | E{ .part = 0xc07, .m32 = &A32.cortex_a7, .m64 = null }, | ||
| 183 | E{ .part = 0xc08, .m32 = &A32.cortex_a8, .m64 = null }, | ||
| 184 | E{ .part = 0xc09, .m32 = &A32.cortex_a9, .m64 = null }, | ||
| 185 | E{ .part = 0xc0d, .m32 = &A32.cortex_a17, .m64 = null }, | ||
| 186 | E{ .part = 0xc0f, .m32 = &A32.cortex_a15, .m64 = null }, | ||
| 187 | E{ .part = 0xc0e, .m32 = &A32.cortex_a17, .m64 = null }, | ||
| 188 | E{ .part = 0xc14, .m32 = &A32.cortex_r4, .m64 = null }, | ||
| 189 | E{ .part = 0xc15, .m32 = &A32.cortex_r5, .m64 = null }, | ||
| 190 | E{ .part = 0xc17, .m32 = &A32.cortex_r7, .m64 = null }, | ||
| 191 | E{ .part = 0xc18, .m32 = &A32.cortex_r8, .m64 = null }, | ||
| 192 | E{ .part = 0xc20, .m32 = &A32.cortex_m0, .m64 = null }, | ||
| 193 | E{ .part = 0xc21, .m32 = &A32.cortex_m1, .m64 = null }, | ||
| 194 | E{ .part = 0xc23, .m32 = &A32.cortex_m3, .m64 = null }, | ||
| 195 | E{ .part = 0xc24, .m32 = &A32.cortex_m4, .m64 = null }, | ||
| 196 | E{ .part = 0xc27, .m32 = &A32.cortex_m7, .m64 = null }, | ||
| 197 | E{ .part = 0xc60, .m32 = &A32.cortex_m0plus, .m64 = null }, | ||
| 198 | E{ .part = 0xd01, .m32 = &A32.cortex_a32, .m64 = null }, | ||
| 199 | E{ .part = 0xd03, .m32 = &A32.cortex_a53, .m64 = &A64.cortex_a53 }, | ||
| 200 | E{ .part = 0xd04, .m32 = &A32.cortex_a35, .m64 = &A64.cortex_a35 }, | ||
| 201 | E{ .part = 0xd05, .m32 = &A32.cortex_a55, .m64 = &A64.cortex_a55 }, | ||
| 202 | E{ .part = 0xd07, .m32 = &A32.cortex_a57, .m64 = &A64.cortex_a57 }, | ||
| 203 | E{ .part = 0xd08, .m32 = &A32.cortex_a72, .m64 = &A64.cortex_a72 }, | ||
| 204 | E{ .part = 0xd09, .m32 = &A32.cortex_a73, .m64 = &A64.cortex_a73 }, | ||
| 205 | E{ .part = 0xd0a, .m32 = &A32.cortex_a75, .m64 = &A64.cortex_a75 }, | ||
| 206 | E{ .part = 0xd0b, .m32 = &A32.cortex_a76, .m64 = &A64.cortex_a76 }, | ||
| 207 | E{ .part = 0xd0c, .m32 = &A32.neoverse_n1, .m64 = &A64.neoverse_n1 }, | ||
| 208 | E{ .part = 0xd0d, .m32 = &A32.cortex_a77, .m64 = &A64.cortex_a77 }, | ||
| 209 | E{ .part = 0xd13, .m32 = &A32.cortex_r52, .m64 = null }, | ||
| 210 | E{ .part = 0xd20, .m32 = &A32.cortex_m23, .m64 = null }, | ||
| 211 | E{ .part = 0xd21, .m32 = &A32.cortex_m33, .m64 = null }, | ||
| 212 | E{ .part = 0xd41, .m32 = &A32.cortex_a78, .m64 = &A64.cortex_a78 }, | ||
| 213 | E{ .part = 0xd4b, .m32 = &A32.cortex_a78c, .m64 = &A64.cortex_a78c }, | ||
| 214 | E{ .part = 0xd44, .m32 = &A32.cortex_x1, .m64 = &A64.cortex_x1 }, | ||
| 215 | E{ .part = 0xd02, .m64 = &A64.cortex_a34 }, | ||
| 216 | E{ .part = 0xd06, .m64 = &A64.cortex_a65 }, | ||
| 217 | E{ .part = 0xd43, .m64 = &A64.cortex_a65ae }, | ||
| 218 | }; | ||
| 219 | // implementer = 0x42 | ||
| 220 | const Broadcom = [_]E{ | ||
| 221 | E{ .part = 0x516, .m64 = &A64.thunderx2t99 }, | ||
| 222 | }; | ||
| 223 | // implementer = 0x43 | ||
| 224 | const Cavium = [_]E{ | ||
| 225 | E{ .part = 0x0a0, .m64 = &A64.thunderx }, | ||
| 226 | E{ .part = 0x0a2, .m64 = &A64.thunderxt81 }, | ||
| 227 | E{ .part = 0x0a3, .m64 = &A64.thunderxt83 }, | ||
| 228 | E{ .part = 0x0a1, .m64 = &A64.thunderxt88 }, | ||
| 229 | E{ .part = 0x0af, .m64 = &A64.thunderx2t99 }, | ||
| 230 | }; | ||
| 231 | // implementer = 0x46 | ||
| 232 | const Fujitsu = [_]E{ | ||
| 233 | E{ .part = 0x001, .m64 = &A64.a64fx }, | ||
| 234 | }; | ||
| 235 | // implementer = 0x48 | ||
| 236 | const HiSilicon = [_]E{ | ||
| 237 | E{ .part = 0xd01, .m64 = &A64.tsv110 }, | ||
| 238 | }; | ||
| 239 | // implementer = 0x4e | ||
| 240 | const Nvidia = [_]E{ | ||
| 241 | E{ .part = 0x004, .m64 = &A64.carmel }, | ||
| 242 | }; | ||
| 243 | // implementer = 0x50 | ||
| 244 | const Ampere = [_]E{ | ||
| 245 | E{ .part = 0x000, .variant = 3, .m64 = &A64.emag }, | ||
| 246 | E{ .part = 0x000, .m64 = &A64.xgene1 }, | ||
| 247 | }; | ||
| 248 | // implementer = 0x51 | ||
| 249 | const Qualcomm = [_]E{ | ||
| 250 | E{ .part = 0x06f, .m32 = &A32.krait }, | ||
| 251 | E{ .part = 0x201, .m64 = &A64.kryo, .m32 = &A64.kryo }, | ||
| 252 | E{ .part = 0x205, .m64 = &A64.kryo, .m32 = &A64.kryo }, | ||
| 253 | E{ .part = 0x211, .m64 = &A64.kryo, .m32 = &A64.kryo }, | ||
| 254 | E{ .part = 0x800, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 }, | ||
| 255 | E{ .part = 0x801, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 }, | ||
| 256 | E{ .part = 0x802, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 }, | ||
| 257 | E{ .part = 0x803, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 }, | ||
| 258 | E{ .part = 0x804, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 }, | ||
| 259 | E{ .part = 0x805, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 }, | ||
| 260 | E{ .part = 0xc00, .m64 = &A64.falkor }, | ||
| 261 | E{ .part = 0xc01, .m64 = &A64.saphira }, | ||
| 262 | }; | ||
| 263 | |||
| 264 | fn isKnown(core: CoreInfo, is_64bit: bool) ?*const Target.Cpu.Model { | ||
| 265 | const models = switch (core.implementer) { | ||
| 266 | 0x41 => &ARM, | ||
| 267 | 0x42 => &Broadcom, | ||
| 268 | 0x43 => &Cavium, | ||
| 269 | 0x46 => &Fujitsu, | ||
| 270 | 0x48 => &HiSilicon, | ||
| 271 | 0x50 => &Ampere, | ||
| 272 | 0x51 => &Qualcomm, | ||
| 273 | else => return null, | ||
| 274 | }; | ||
| 275 | |||
| 276 | for (models) |model| { | ||
| 277 | if (model.part == core.part and | ||
| 278 | (model.variant == null or model.variant.? == core.variant)) | ||
| 279 | return if (is_64bit) model.m64 else model.m32; | ||
| 280 | } | ||
| 281 | |||
| 282 | return null; | ||
| 283 | } | ||
| 284 | }; | ||
| 285 | 163 | ||
| 286 | fn addOne(self: *ArmCpuinfoImpl) void { | 164 | fn addOne(self: *ArmCpuinfoImpl) void { |
| 287 | if (self.have_fields == 4 and self.core_no < self.cores.len) { | 165 | if (self.have_fields == 4 and self.core_no < self.cores.len) { |
| ... | @@ -346,7 +224,12 @@ const ArmCpuinfoImpl = struct { | ... | @@ -346,7 +224,12 @@ const ArmCpuinfoImpl = struct { |
| 346 | 224 | ||
| 347 | var known_models: [self.cores.len]?*const Target.Cpu.Model = undefined; | 225 | var known_models: [self.cores.len]?*const Target.Cpu.Model = undefined; |
| 348 | for (self.cores[0..self.core_no]) |core, i| { | 226 | for (self.cores[0..self.core_no]) |core, i| { |
| 349 | known_models[i] = cpu_models.isKnown(core, is_64bit); | 227 | known_models[i] = cpu_models.isKnown(.{ |
| 228 | .architecture = core.architecture, | ||
| 229 | .implementer = core.implementer, | ||
| 230 | .variant = core.variant, | ||
| 231 | .part = core.part, | ||
| 232 | }, is_64bit); | ||
| 350 | } | 233 | } |
| 351 | 234 | ||
| 352 | // XXX We pick the first core on big.LITTLE systems, hopefully the | 235 | // XXX We pick the first core on big.LITTLE systems, hopefully the |
lib/std/zig/system/windows.zig+321| ... | @@ -1,6 +1,12 @@ | ... | @@ -1,6 +1,12 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 3 | const mem = std.mem; | ||
| 4 | const Target = std.Target; | ||
| 2 | 5 | ||
| 3 | pub const WindowsVersion = std.Target.Os.WindowsVersion; | 6 | pub const WindowsVersion = std.Target.Os.WindowsVersion; |
| 7 | pub const PF = std.os.windows.PF; | ||
| 8 | pub const REG = std.os.windows.REG; | ||
| 9 | pub const IsProcessorFeaturePresent = std.os.windows.IsProcessorFeaturePresent; | ||
| 4 | 10 | ||
| 5 | /// Returns the highest known WindowsVersion deduced from reported runtime information. | 11 | /// Returns the highest known WindowsVersion deduced from reported runtime information. |
| 6 | /// Discards information about in-between versions we don't differentiate. | 12 | /// Discards information about in-between versions we don't differentiate. |
| ... | @@ -38,3 +44,318 @@ pub fn detectRuntimeVersion() WindowsVersion { | ... | @@ -38,3 +44,318 @@ pub fn detectRuntimeVersion() WindowsVersion { |
| 38 | 44 | ||
| 39 | return @intToEnum(WindowsVersion, version); | 45 | return @intToEnum(WindowsVersion, version); |
| 40 | } | 46 | } |
| 47 | |||
| 48 | // Technically, a registry value can be as long as 1MB. However, MS recommends storing | ||
| 49 | // values larger than 2048 bytes in a file rather than directly in the registry, and since we | ||
| 50 | // are only accessing a system hive \Registry\Machine, we stick to MS guidelines. | ||
| 51 | // https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-element-size-limits | ||
| 52 | const max_value_len = 2048; | ||
| 53 | |||
| 54 | const RegistryPair = struct { | ||
| 55 | key: []const u8, | ||
| 56 | value: std.os.windows.ULONG, | ||
| 57 | }; | ||
| 58 | |||
| 59 | fn getCpuInfoFromRegistry( | ||
| 60 | core: usize, | ||
| 61 | comptime pairs_num: comptime_int, | ||
| 62 | comptime pairs: [pairs_num]RegistryPair, | ||
| 63 | out_buf: *[pairs_num][max_value_len]u8, | ||
| 64 | ) !void { | ||
| 65 | // Originally, I wanted to issue a single call with a more complex table structure such that we | ||
| 66 | // would sequentially visit each CPU#d subkey in the registry and pull the value of interest into | ||
| 67 | // a buffer, however, NT seems to be expecting a single buffer per each table meaning we would | ||
| 68 | // end up pulling only the last CPU core info, overwriting everything else. | ||
| 69 | // If anyone can come up with a solution to this, please do! | ||
| 70 | const table_size = 1 + pairs.len; | ||
| 71 | var table: [table_size + 1]std.os.windows.RTL_QUERY_REGISTRY_TABLE = undefined; | ||
| 72 | |||
| 73 | const topkey = std.unicode.utf8ToUtf16LeStringLiteral("\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor"); | ||
| 74 | |||
| 75 | const max_cpu_buf = 4; | ||
| 76 | var next_cpu_buf: [max_cpu_buf]u8 = undefined; | ||
| 77 | const next_cpu = try std.fmt.bufPrint(&next_cpu_buf, "{d}", .{core}); | ||
| 78 | |||
| 79 | var subkey: [max_cpu_buf + 1]u16 = undefined; | ||
| 80 | const subkey_len = try std.unicode.utf8ToUtf16Le(&subkey, next_cpu); | ||
| 81 | subkey[subkey_len] = 0; | ||
| 82 | |||
| 83 | table[0] = .{ | ||
| 84 | .QueryRoutine = null, | ||
| 85 | .Flags = std.os.windows.RTL_QUERY_REGISTRY_SUBKEY | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED, | ||
| 86 | .Name = subkey[0..subkey_len :0], | ||
| 87 | .EntryContext = null, | ||
| 88 | .DefaultType = REG.NONE, | ||
| 89 | .DefaultData = null, | ||
| 90 | .DefaultLength = 0, | ||
| 91 | }; | ||
| 92 | |||
| 93 | inline for (pairs) |pair, i| { | ||
| 94 | const ctx: *anyopaque = blk: { | ||
| 95 | switch (pair.value) { | ||
| 96 | REG.SZ, | ||
| 97 | REG.EXPAND_SZ, | ||
| 98 | REG.MULTI_SZ, | ||
| 99 | => { | ||
| 100 | var buf: [max_value_len / 2]u16 = undefined; | ||
| 101 | var unicode = std.os.windows.UNICODE_STRING{ | ||
| 102 | .Length = 0, | ||
| 103 | .MaximumLength = max_value_len, | ||
| 104 | .Buffer = &buf, | ||
| 105 | }; | ||
| 106 | break :blk &unicode; | ||
| 107 | }, | ||
| 108 | |||
| 109 | REG.DWORD, | ||
| 110 | REG.DWORD_BIG_ENDIAN, | ||
| 111 | => { | ||
| 112 | var buf: [4]u8 = undefined; | ||
| 113 | break :blk &buf; | ||
| 114 | }, | ||
| 115 | |||
| 116 | REG.QWORD => { | ||
| 117 | var buf: [8]u8 = undefined; | ||
| 118 | break :blk &buf; | ||
| 119 | }, | ||
| 120 | |||
| 121 | else => unreachable, | ||
| 122 | } | ||
| 123 | }; | ||
| 124 | const key_namee = std.unicode.utf8ToUtf16LeStringLiteral(pair.key); | ||
| 125 | |||
| 126 | table[i + 1] = .{ | ||
| 127 | .QueryRoutine = null, | ||
| 128 | .Flags = std.os.windows.RTL_QUERY_REGISTRY_DIRECT | std.os.windows.RTL_QUERY_REGISTRY_REQUIRED, | ||
| 129 | .Name = @intToPtr([*:0]u16, @ptrToInt(key_namee)), | ||
| 130 | .EntryContext = ctx, | ||
| 131 | .DefaultType = REG.NONE, | ||
| 132 | .DefaultData = null, | ||
| 133 | .DefaultLength = 0, | ||
| 134 | }; | ||
| 135 | } | ||
| 136 | |||
| 137 | // Table sentinel | ||
| 138 | table[table_size] = .{ | ||
| 139 | .QueryRoutine = null, | ||
| 140 | .Flags = 0, | ||
| 141 | .Name = null, | ||
| 142 | .EntryContext = null, | ||
| 143 | .DefaultType = 0, | ||
| 144 | .DefaultData = null, | ||
| 145 | .DefaultLength = 0, | ||
| 146 | }; | ||
| 147 | |||
| 148 | const res = std.os.windows.ntdll.RtlQueryRegistryValues( | ||
| 149 | std.os.windows.RTL_REGISTRY_ABSOLUTE, | ||
| 150 | topkey, | ||
| 151 | &table, | ||
| 152 | null, | ||
| 153 | null, | ||
| 154 | ); | ||
| 155 | switch (res) { | ||
| 156 | .SUCCESS => { | ||
| 157 | inline for (pairs) |pair, i| switch (pair.value) { | ||
| 158 | REG.NONE => unreachable, | ||
| 159 | |||
| 160 | REG.SZ, | ||
| 161 | REG.EXPAND_SZ, | ||
| 162 | REG.MULTI_SZ, | ||
| 163 | => { | ||
| 164 | const entry = @ptrCast(*align(1) const std.os.windows.UNICODE_STRING, table[i + 1].EntryContext); | ||
| 165 | const len = try std.unicode.utf16leToUtf8(out_buf[i][0..], entry.Buffer[0 .. entry.Length / 2]); | ||
| 166 | out_buf[i][len] = 0; | ||
| 167 | }, | ||
| 168 | |||
| 169 | REG.DWORD, | ||
| 170 | REG.DWORD_BIG_ENDIAN, | ||
| 171 | REG.QWORD, | ||
| 172 | => { | ||
| 173 | const entry = @ptrCast([*]align(1) const u8, table[i + 1].EntryContext); | ||
| 174 | switch (pair.value) { | ||
| 175 | REG.DWORD, REG.DWORD_BIG_ENDIAN => { | ||
| 176 | mem.copy(u8, out_buf[i][0..4], entry[0..4]); | ||
| 177 | }, | ||
| 178 | REG.QWORD => { | ||
| 179 | mem.copy(u8, out_buf[i][0..8], entry[0..8]); | ||
| 180 | }, | ||
| 181 | else => unreachable, | ||
| 182 | } | ||
| 183 | }, | ||
| 184 | |||
| 185 | else => unreachable, | ||
| 186 | }; | ||
| 187 | }, | ||
| 188 | else => return error.Unexpected, | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | fn getCpuCount() usize { | ||
| 193 | return std.os.windows.peb().NumberOfProcessors; | ||
| 194 | } | ||
| 195 | |||
| 196 | const ArmCpuInfoImpl = struct { | ||
| 197 | cores: [4]CoreInfo = undefined, | ||
| 198 | core_no: usize = 0, | ||
| 199 | have_fields: usize = 0, | ||
| 200 | |||
| 201 | const CoreInfo = @import("arm.zig").CoreInfo; | ||
| 202 | const cpu_models = @import("arm.zig").cpu_models; | ||
| 203 | |||
| 204 | const Data = struct { | ||
| 205 | cp_4000: []const u8, | ||
| 206 | identifier: []const u8, | ||
| 207 | }; | ||
| 208 | |||
| 209 | fn parseDataHook(self: *ArmCpuInfoImpl, data: Data) !void { | ||
| 210 | const info = &self.cores[self.core_no]; | ||
| 211 | info.* = .{}; | ||
| 212 | |||
| 213 | // CPU part | ||
| 214 | info.part = mem.readIntLittle(u16, data.cp_4000[0..2]) >> 4; | ||
| 215 | self.have_fields += 1; | ||
| 216 | |||
| 217 | // CPU implementer | ||
| 218 | info.implementer = data.cp_4000[3]; | ||
| 219 | self.have_fields += 1; | ||
| 220 | |||
| 221 | var tokens = mem.tokenize(u8, data.identifier, " "); | ||
| 222 | while (tokens.next()) |token| { | ||
| 223 | if (mem.eql(u8, "Family", token)) { | ||
| 224 | // CPU architecture | ||
| 225 | const family = tokens.next() orelse continue; | ||
| 226 | info.architecture = try std.fmt.parseInt(u8, family, 10); | ||
| 227 | self.have_fields += 1; | ||
| 228 | break; | ||
| 229 | } | ||
| 230 | } else return; | ||
| 231 | |||
| 232 | self.addOne(); | ||
| 233 | } | ||
| 234 | |||
| 235 | fn addOne(self: *ArmCpuInfoImpl) void { | ||
| 236 | if (self.have_fields == 3 and self.core_no < self.cores.len) { | ||
| 237 | if (self.core_no > 0) { | ||
| 238 | // Deduplicate the core info. | ||
| 239 | for (self.cores[0..self.core_no]) |it| { | ||
| 240 | if (std.meta.eql(it, self.cores[self.core_no])) | ||
| 241 | return; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | self.core_no += 1; | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | fn finalize(self: ArmCpuInfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu { | ||
| 249 | if (self.core_no == 0) return null; | ||
| 250 | |||
| 251 | const is_64bit = switch (arch) { | ||
| 252 | .aarch64, .aarch64_be, .aarch64_32 => true, | ||
| 253 | else => false, | ||
| 254 | }; | ||
| 255 | |||
| 256 | var known_models: [self.cores.len]?*const Target.Cpu.Model = undefined; | ||
| 257 | for (self.cores[0..self.core_no]) |core, i| { | ||
| 258 | known_models[i] = cpu_models.isKnown(core, is_64bit); | ||
| 259 | } | ||
| 260 | |||
| 261 | // XXX We pick the first core on big.LITTLE systems, hopefully the | ||
| 262 | // LITTLE one. | ||
| 263 | const model = known_models[0] orelse return null; | ||
| 264 | return Target.Cpu{ | ||
| 265 | .arch = arch, | ||
| 266 | .model = model, | ||
| 267 | .features = model.features, | ||
| 268 | }; | ||
| 269 | } | ||
| 270 | }; | ||
| 271 | |||
| 272 | const ArmCpuInfoParser = CpuInfoParser(ArmCpuInfoImpl); | ||
| 273 | |||
| 274 | fn CpuInfoParser(comptime impl: anytype) type { | ||
| 275 | return struct { | ||
| 276 | fn parse(arch: Target.Cpu.Arch) !?Target.Cpu { | ||
| 277 | var obj: impl = .{}; | ||
| 278 | var out_buf: [2][max_value_len]u8 = undefined; | ||
| 279 | |||
| 280 | var i: usize = 0; | ||
| 281 | while (i < getCpuCount()) : (i += 1) { | ||
| 282 | try getCpuInfoFromRegistry(i, 2, .{ | ||
| 283 | .{ .key = "CP 4000", .value = REG.QWORD }, | ||
| 284 | .{ .key = "Identifier", .value = REG.SZ }, | ||
| 285 | }, &out_buf); | ||
| 286 | |||
| 287 | const cp_4000 = out_buf[0][0..8]; | ||
| 288 | const identifier = mem.sliceTo(out_buf[1][0..], 0); | ||
| 289 | |||
| 290 | try obj.parseDataHook(.{ | ||
| 291 | .cp_4000 = cp_4000, | ||
| 292 | .identifier = identifier, | ||
| 293 | }); | ||
| 294 | } | ||
| 295 | |||
| 296 | return obj.finalize(arch); | ||
| 297 | } | ||
| 298 | }; | ||
| 299 | } | ||
| 300 | |||
| 301 | fn genericCpu(comptime arch: Target.Cpu.Arch) Target.Cpu { | ||
| 302 | return .{ | ||
| 303 | .arch = arch, | ||
| 304 | .model = Target.Cpu.Model.generic(arch), | ||
| 305 | .features = Target.Cpu.Feature.Set.empty, | ||
| 306 | }; | ||
| 307 | } | ||
| 308 | |||
| 309 | pub fn detectNativeCpuAndFeatures() ?Target.Cpu { | ||
| 310 | const current_arch = builtin.cpu.arch; | ||
| 311 | switch (current_arch) { | ||
| 312 | .aarch64, .aarch64_be, .aarch64_32 => { | ||
| 313 | var cpu = cpu: { | ||
| 314 | var maybe_cpu = ArmCpuInfoParser.parse(current_arch) catch break :cpu genericCpu(current_arch); | ||
| 315 | break :cpu maybe_cpu orelse genericCpu(current_arch); | ||
| 316 | }; | ||
| 317 | |||
| 318 | const Feature = Target.aarch64.Feature; | ||
| 319 | |||
| 320 | // Override any features that are either present or absent | ||
| 321 | if (IsProcessorFeaturePresent(PF.ARM_NEON_INSTRUCTIONS_AVAILABLE)) { | ||
| 322 | cpu.features.addFeature(@enumToInt(Feature.neon)); | ||
| 323 | } else { | ||
| 324 | cpu.features.removeFeature(@enumToInt(Feature.neon)); | ||
| 325 | } | ||
| 326 | |||
| 327 | if (IsProcessorFeaturePresent(PF.ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)) { | ||
| 328 | cpu.features.addFeature(@enumToInt(Feature.crc)); | ||
| 329 | } else { | ||
| 330 | cpu.features.removeFeature(@enumToInt(Feature.crc)); | ||
| 331 | } | ||
| 332 | |||
| 333 | if (IsProcessorFeaturePresent(PF.ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) { | ||
| 334 | cpu.features.addFeature(@enumToInt(Feature.crypto)); | ||
| 335 | } else { | ||
| 336 | cpu.features.removeFeature(@enumToInt(Feature.crypto)); | ||
| 337 | } | ||
| 338 | |||
| 339 | if (IsProcessorFeaturePresent(PF.ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE)) { | ||
| 340 | cpu.features.addFeature(@enumToInt(Feature.lse)); | ||
| 341 | } else { | ||
| 342 | cpu.features.removeFeature(@enumToInt(Feature.lse)); | ||
| 343 | } | ||
| 344 | |||
| 345 | if (IsProcessorFeaturePresent(PF.ARM_V82_DP_INSTRUCTIONS_AVAILABLE)) { | ||
| 346 | cpu.features.addFeature(@enumToInt(Feature.dotprod)); | ||
| 347 | } else { | ||
| 348 | cpu.features.removeFeature(@enumToInt(Feature.dotprod)); | ||
| 349 | } | ||
| 350 | |||
| 351 | if (IsProcessorFeaturePresent(PF.ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE)) { | ||
| 352 | cpu.features.addFeature(@enumToInt(Feature.jsconv)); | ||
| 353 | } else { | ||
| 354 | cpu.features.removeFeature(@enumToInt(Feature.jsconv)); | ||
| 355 | } | ||
| 356 | |||
| 357 | return cpu; | ||
| 358 | }, | ||
| 359 | else => {}, | ||
| 360 | } | ||
| 361 | } |