├── .circleci └── config.yml ├── .gitignore ├── .gitmodules ├── .travis.yml ├── README.md ├── appveyor.yml ├── dub.sdl ├── index.d ├── meson.build ├── report.d ├── source └── cpuid │ ├── amd.d │ ├── common.d │ ├── intel.d │ ├── unified.d │ └── x86_any.d └── subprojects └── mir-core.wrap /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | mirci: libmir/upload_docs@0.3.0 5 | 6 | workflows: 7 | version: 2 8 | build-deploy: 9 | jobs: 10 | - mirci/test_and_build_docs: 11 | filters: 12 | tags: 13 | only: /^v(\d)+(\.(\d)+)+$/ 14 | - mirci/upload_docs: 15 | to: mir-cpuid.libmir.org 16 | requires: 17 | - mirci/test_and_build_docs 18 | filters: 19 | branches: 20 | ignore: /.*/ 21 | tags: 22 | only: /^v(\d)+(\.(\d)+)+$/ 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .dub 2 | docs.json 3 | __dummy.html 4 | *.o 5 | *.obj 6 | 7 | __test__library__ 8 | 9 | dub.selections.json 10 | 11 | *.sublime-project 12 | .generated 13 | web 14 | index.html 15 | 16 | *.a 17 | build/* 18 | 19 | __.SYMDEF 20 | 21 | __.SYMDEF SORTED 22 | 23 | *.s 24 | docs 25 | cpuid-report 26 | 27 | *.sublime-workspace 28 | 29 | mir-cpuid-test-library 30 | cpuid-report.exe 31 | mir-cpuid-test-library.exe 32 | mir-cpuid.lib 33 | subprojects/*/ 34 | builddir 35 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "doc/dlang.org"] 2 | path = doc/dlang.org 3 | url = https://github.com/dlang/dlang.org 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | os: 4 | - linux 5 | - osx 6 | 7 | language: d 8 | 9 | d: 10 | - dmd 11 | - ldc 12 | 13 | env: 14 | - ARCH="x86_64" 15 | 16 | matrix: 17 | include: 18 | # - {os: linux, d: dmd-2.071.2, env: ARCH="x86", addons: {apt: {packages: [[gcc-multilib]]}}} 19 | - {os: linux, d: ldc, env: ARCH="x86", addons: {apt: {packages: [[gcc-multilib]]}}} 20 | - {os: linux, d: gdc, env: ARCH="x86_64"} 21 | allow_failures: 22 | - {d: dmd-nightly} 23 | - {d: ldc-beta} 24 | - {d: gdc} 25 | 26 | branches: 27 | only: 28 | - master 29 | - stable 30 | 31 | packages: 32 | - pkg-config 33 | 34 | script: 35 | - echo "$ARCH" 36 | - dub build --arch "$ARCH" 37 | - dub --arch "$ARCH" --single report.d 38 | 39 | after_success: 40 | - bash <(curl -s https://codecov.io/bash) 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Gitter](https://img.shields.io/gitter/room/libmir/public.svg)](https://gitter.im/libmir/public) 2 | 3 | [![Build Status](https://travis-ci.org/libmir/mir-cpuid.svg?branch=master)](https://travis-ci.org/libmir/mir-cpuid) 4 | [![Build Status](https://ci.appveyor.com/api/projects/status/github/libmir/mir-cpuid?svg=true)](https://ci.appveyor.com/project/9il/mir-cpuid/branch/master) 5 | 6 | [![Dub version](https://img.shields.io/dub/v/mir-cpuid.svg)](http://code.dlang.org/packages/mir-cpuid) 7 | [![Dub downloads](https://img.shields.io/dub/dt/mir-cpuid.svg)](http://code.dlang.org/packages/mir-cpuid) 8 | [![License](https://img.shields.io/dub/l/mir-cpuid.svg)](http://code.dlang.org/packages/mir-cpuid) 9 | 10 | # CPU Information 11 | 12 | ```d 13 | void main() 14 | { 15 | import std.stdio; 16 | import cpuid.unified; 17 | 18 | enum fmt = "%14s: %s"; 19 | 20 | fmt.writefln("cores", cores); 21 | fmt.writefln("threads", threads); 22 | 23 | fmt.writefln("data caches", dCache.length); 24 | fmt.writefln("code caches", iCache.length); 25 | fmt.writefln("unified caches", uCache.length); 26 | 27 | fmt.writefln("data TLBs", dTlb.length); 28 | fmt.writefln("code TLBs", iTlb.length); 29 | fmt.writefln("unified TLBs", uTlb.length); 30 | } 31 | ``` 32 | 33 | This package also can be used as workaround for [core.cpuid Issue 16028](https://issues.dlang.org/show_bug.cgi?id=16028). 34 | 35 | ## Documentation 36 | 37 | http://mir-cpuid.libmir.org 38 | 39 | ## Testing 40 | 41 | See [all reports](https://github.com/libmir/mir-cpuid/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3AReports%20). 42 | 43 | Run the following command from the project's directory to receive a report about your CPU 44 | 45 | ``` 46 | dub --single report.d 47 | ``` 48 | 49 | Please report dub log in a new GitHub issue! 50 | 51 | See also [output example](https://gist.github.com/9il/66d2f824ca52e1293358b86604e7fb21). 52 | 53 | ## Building a betterC library 54 | 55 | BetterC mode works when compiled with LDC only. 56 | 57 | ``` 58 | dub build --compiler=ldmd2 --build-mode=singleFile --parallel 59 | ``` 60 | 61 | ## API Features 62 | 63 | - API was split to _unified_, _target_ specified, and _vendor_ specified parts. 64 | - Complex cache topology (number of cores per cache) is supported. This feature is required by ARM CPUs. 65 | - Translation lookaside buffers are supported. They are used in server and math software, for example cache optimized BLAS requires TLB information. 66 | - Caches and TLBs are split into three types: 67 | - Data 68 | - Instruction (code) 69 | - Unified (data and code) 70 | - `_cpuid` function is available for x86/x86-64 targets. 71 | 72 | ## Implementation Features 73 | 74 | - The library was written completely from scratch. 75 | - Code is clean and simple. 76 | - Unions and `mir.bitmanip.bitfields` are used instead of bit operations. 77 | - Slim betterC library with `extern(C)` insterface. 78 | 79 | ## TODO 80 | 81 | - [x] Add information about recent features like AVX2, AVX512F. 82 | - [ ] Add information about ARM target and ARM vendors. 83 | - [x] Test a lot of different CPUs. 84 | - [ ] Extend testing infrastructure. 85 | - [ ] CPU(package) count identification. 86 | - [ ] Per CPU(package) CPUID information. 87 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | platform: x64 2 | environment: 3 | matrix: 4 | - DC: dmd 5 | DVersion: 2.085.0 6 | arch: x64 7 | - DC: dmd 8 | DVersion: 2.085.0 9 | arch: x86 10 | - DC: ldc 11 | DVersion: '1.15.0' 12 | arch: x64 13 | 14 | matrix: 15 | allow_failures: 16 | - {DC: dmd, arch: x86} 17 | 18 | skip_tags: true 19 | branches: 20 | only: 21 | - master 22 | - stable 23 | 24 | install: 25 | - ps: function SetUpDCompiler 26 | { 27 | if($env:DC -eq "dmd"){ 28 | if($env:arch -eq "x86"){ 29 | $env:DConf = "m32"; 30 | } 31 | elseif($env:arch -eq "x64"){ 32 | $env:DConf = "m64"; 33 | } 34 | echo "downloading ..."; 35 | $env:toolchain = "msvc"; 36 | $version = $env:DVersion; 37 | Invoke-WebRequest "http://downloads.dlang.org/releases/2.x/$($version)/dmd.$($version).windows.7z" -OutFile "c:\dmd.7z"; 38 | echo "finished."; 39 | pushd c:\\; 40 | 7z x dmd.7z > $null; 41 | popd; 42 | } 43 | elseif($env:DC -eq "ldc"){ 44 | echo "downloading ..."; 45 | if($env:arch -eq "x86"){ 46 | $env:DConf = "m32"; 47 | } 48 | elseif($env:arch -eq "x64"){ 49 | $env:DConf = "m64"; 50 | } 51 | $env:toolchain = "msvc"; 52 | $version = $env:DVersion; 53 | Invoke-WebRequest "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-windows-x64.7z" -OutFile "c:\ldc.7z"; 54 | echo "finished."; 55 | pushd c:\\; 56 | 7z x ldc.7z > $null; 57 | popd; 58 | } 59 | } 60 | - ps: SetUpDCompiler 61 | - powershell -Command Invoke-WebRequest https://code.dlang.org/files/dub-1.9.0-windows-x86.zip -OutFile dub.zip 62 | - 7z x dub.zip -odub > nul 63 | - set PATH=%CD%\%binpath%;%CD%\dub;%PATH% 64 | - dub --version 65 | 66 | before_build: 67 | - ps: if($env:arch -eq "x86"){ 68 | $env:compilersetupargs = "x86"; 69 | $env:Darch = "x86"; 70 | } 71 | elseif($env:arch -eq "x64"){ 72 | $env:compilersetupargs = "amd64"; 73 | $env:Darch = "x86_64"; 74 | } 75 | - ps : if($env:DC -eq "dmd"){ 76 | $env:PATH += ";C:\dmd2\windows\bin;"; 77 | } 78 | elseif($env:DC -eq "ldc"){ 79 | $version = $env:DVersion; 80 | $env:PATH += ";C:\ldc2-$($version)-windows-x64\bin"; 81 | $env:DC = "ldc2"; 82 | } 83 | - ps: $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall"; 84 | - '"%compilersetup%" %compilersetupargs%' 85 | 86 | build_script: 87 | - echo dummy build script - dont remove me 88 | 89 | test_script: 90 | - echo %PLATFORM% 91 | - echo %Darch% 92 | - echo %DC% 93 | - echo %PATH% 94 | - '%DC% --version' 95 | - dub --arch=%Darch% --compiler=%DC% --single report.d 96 | 97 | notifications: 98 | - provider: Webhook 99 | url: https://webhooks.gitter.im/e/56aae174f8cc81f4eda4 100 | - provider: Email 101 | to: 102 | - devteam@mir.rocks 103 | on_build_success: false 104 | on_build_failure: true 105 | on_build_status_changed: true 106 | -------------------------------------------------------------------------------- /dub.sdl: -------------------------------------------------------------------------------- 1 | name "mir-cpuid" 2 | authors "Ilia Ki" 3 | dependency "mir-core" version=">=1.0.0" 4 | description "CPU Characteristics Identification" 5 | copyright "Ilia Ki" 6 | license "BSL-1.0" 7 | -------------------------------------------------------------------------------- /index.d: -------------------------------------------------------------------------------- 1 | Ddoc 2 | 3 | $(H1 CPU Identification) 4 | 5 | $(P The following table is a quick reference guide for which cpuid modules to 6 | use for a given category of functionality.) 7 | 8 | $(BOOKTABLE , 9 | $(TR 10 | $(TH Modules) 11 | $(TH Description) 12 | ) 13 | $(LEADINGROW High Level API) 14 | $(TR 15 | $(TDNW $(LINK2 cpuid_unified.html, cpuid.unified)) 16 | $(TD High level abstraction on top of all architectures) 17 | ) 18 | $(TR 19 | $(TDNW $(LINK2 cpuid_x86_any.html, cpuid.x86_any)) 20 | $(TD Common information for all x86 and x86_64 vendors) 21 | ) 22 | $(LEADINGROW Low Level API) 23 | $(TR 24 | $(TDNW $(LINK2 cpuid_intel.html, cpuid.intel)) 25 | $(TD Intel 64 and IA-32 CPUID information) 26 | ) 27 | $(TR 28 | $(TDNW $(LINK2 cpuid_amd.html, cpuid.amd)) 29 | $(TD AMD CPUID information) 30 | ) 31 | $(LEADINGROW Auxiliary) 32 | $(TR 33 | $(TDNW $(LINK2 cpuid_common.html, cpuid.common)) 34 | $(TD Auxiliary data types and functions) 35 | ) 36 | ) 37 | 38 | Macros: 39 | TITLE=CPUID 40 | DDOC_BLANKLINE= 41 | _= 42 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('mir-cpuid', 'd', version: '1.2.3', license: 'BSL-1.0') 2 | 3 | description = 'Mir CPUID - CPU Information' 4 | 5 | subprojects = ['mir-core'] 6 | 7 | has_cpp_headers = false 8 | 9 | sources_list = [ 10 | 'cpuid/amd', 11 | 'cpuid/common', 12 | 'cpuid/intel', 13 | 'cpuid/unified', 14 | 'cpuid/x86_any', 15 | ] 16 | 17 | sources = [] 18 | foreach s : sources_list 19 | sources += 'source/' + s + '.d' 20 | endforeach 21 | 22 | add_project_arguments([ 23 | '-preview=dip1008', 24 | '-lowmem', 25 | ], language: 'd') 26 | 27 | required_deps = [] 28 | 29 | foreach p : subprojects 30 | required_deps += dependency(p, fallback : [p, 'this_dep']) 31 | endforeach 32 | 33 | directories = ['source'] 34 | 35 | if has_cpp_headers 36 | directories += 'include' 37 | endif 38 | 39 | directories = include_directories(directories) 40 | 41 | this_lib = library(meson.project_name(), 42 | sources, 43 | include_directories: directories, 44 | install: true, 45 | version: meson.project_version(), 46 | dependencies: required_deps, 47 | ) 48 | 49 | this_dep = declare_dependency( 50 | link_with: [this_lib], 51 | include_directories: directories, 52 | dependencies: required_deps, 53 | ) 54 | 55 | test_versions = [] 56 | 57 | if has_cpp_headers 58 | install_subdir('include/', 59 | strip_directory :true, 60 | install_dir: 'include/', 61 | ) 62 | endif 63 | 64 | install_subdir('source/', 65 | strip_directory : true, 66 | install_dir: 'include/d/' + meson.project_name(), 67 | ) 68 | 69 | import('pkgconfig').generate(this_lib, 70 | description: description, 71 | subdirs: 'd/' + meson.project_name(), 72 | ) 73 | 74 | mir_cpuid_dep = this_dep 75 | mir_cpuid_lib = this_lib 76 | 77 | test_subdirs = [] 78 | -------------------------------------------------------------------------------- /report.d: -------------------------------------------------------------------------------- 1 | /+ dub.json: 2 | { 3 | "name": "cpuid-report", 4 | "dependencies": {"mir-cpuid": {"path": "./"}}, 5 | } 6 | +/ 7 | /++ 8 | Text information generators. 9 | 10 | License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 11 | 12 | Authors: Ilia Ki 13 | +/ 14 | module cpuid.report; 15 | 16 | void main() 17 | { 18 | import cpuid.unified; 19 | import cpuid.report; 20 | 21 | import std.stdio; 22 | cpuid.report.unified.writeln; 23 | version(X86) 24 | cpuid.report.x86_any.writeln; 25 | version(X86_64) 26 | cpuid.report.x86_any.writeln; 27 | } 28 | 29 | /// Returns report for `cpuid.unified`. 30 | string unified()() 31 | { 32 | import std.traits; 33 | import std.array; 34 | import std.format; 35 | 36 | import cpuid.unified; 37 | 38 | auto app = appender!string; 39 | 40 | void putAssociative(T)(T v) 41 | { 42 | switch(v) 43 | { 44 | case 1: 45 | app.formattedWrite("\t\tAssociativity: direct mapped\n"); 46 | break; 47 | case T.max: 48 | app.formattedWrite("\t\tAssociativity: Fully associative\n"); 49 | break; 50 | default: 51 | app.formattedWrite("\t\tAssociativity: %s-way associative\n", v); 52 | } 53 | } 54 | 55 | void putCache(Cache cache) 56 | { 57 | app.formattedWrite("\t\tCache size = %s KB\n", cache.size); 58 | app.formattedWrite("\t\tLine = %s bytes\n", cache.line); 59 | app.formattedWrite("\t\tCores per cache = %s\n", cache.cores); 60 | app.formattedWrite("\t\tInclusive: %s\n", cache.inclusive); 61 | putAssociative(cache.associative); 62 | } 63 | 64 | void putTlb(Tlb tlb) 65 | { 66 | app.formattedWrite("\t\tPage size = %s KB\n", tlb.page); 67 | app.formattedWrite("\t\tPages count = %s\n", tlb.entries); 68 | putAssociative(tlb.associative); 69 | } 70 | 71 | app.formattedWrite("################ Unified Information ################\n"); 72 | app.formattedWrite("Cores per CPU: %s\n", cores); 73 | app.formattedWrite("Threads per CPU: %s\n", threads); 74 | 75 | 76 | app.formattedWrite("------------------ TLB Information ------------------\n"); 77 | 78 | app.formattedWrite("Instruction TLB:\n"); 79 | foreach(i, tlb; iTlb) 80 | { 81 | app.formattedWrite("- - - - - ITLB%s: - - - - - - - - - - - - - - - - - -\n", i + 1); 82 | putTlb(tlb); 83 | } 84 | 85 | app.formattedWrite("Data TLB:\n"); 86 | foreach(i, tlb; dTlb) 87 | { 88 | app.formattedWrite("- - - - - DTLB%s: - - - - - - - - - - - - - - - - - -\n", i + 1); 89 | putTlb(tlb); 90 | } 91 | 92 | app.formattedWrite("Unified TLB:\n"); 93 | foreach(i, tlb; uTlb) 94 | { 95 | app.formattedWrite("- - - - - UTLB%s: - - - - - - - - - - - - - - - - - -\n", i + 1); 96 | putTlb(tlb); 97 | } 98 | 99 | app.formattedWrite("----------------- Cache Information -----------------\n"); 100 | 101 | app.formattedWrite("Instruction Cache:\n"); 102 | foreach(i, cache; iCache) 103 | { 104 | app.formattedWrite("- - - - - ICache%s: - - - - - - - - - - - - - - - - -\n", i + 1); 105 | putCache(cache); 106 | } 107 | 108 | app.formattedWrite("Data Cache:\n"); 109 | foreach(i, cache; dCache) 110 | { 111 | app.formattedWrite("- - - - - DCache%s: - - - - - - - - - - - - - - - - -\n", i + 1); 112 | putCache(cache); 113 | } 114 | 115 | app.formattedWrite("Unified Cache:\n"); 116 | foreach(i, cache; uCache) 117 | { 118 | app.formattedWrite("- - - - - UCache%s: - - - - - - - - - - - - - - - - -\n", i + 1); 119 | putCache(cache); 120 | } 121 | 122 | return app.data; 123 | } 124 | 125 | private alias AliasSeq(T...) = T; 126 | 127 | /// Returns report for `cpuid.x86_any`. 128 | string x86_any()() 129 | { 130 | 131 | import std.traits; 132 | import std.array; 133 | import std.format; 134 | 135 | import cpuid.x86_any; 136 | 137 | auto app = appender!string; 138 | 139 | app.formattedWrite("################## x86 Information ##################\n"); 140 | 141 | //app.formattedWrite("CPU count = %s\n", cpus); 142 | char[48] brandName = void; 143 | auto len = brand(brandName); 144 | app.formattedWrite("%20s: %s\n", "brand", brandName[0 .. len]); 145 | 146 | foreach(i, name; AliasSeq!( 147 | "vendor", 148 | "virtualVendor", 149 | "virtual", 150 | "vendorIndex", 151 | "virtualVendorIndex", 152 | "brandIndex", 153 | "maxBasicLeaf", 154 | "maxExtendedLeaf", 155 | "max7SubLeafs", 156 | "acpi", 157 | "adx", 158 | "aes", 159 | "apic", 160 | "avx", 161 | "avx2", 162 | "avx512bitalg", 163 | "avx512bw", 164 | "avx512cd", 165 | "avx512dq", 166 | "avx512er", 167 | "avx512f", 168 | "avx512ifma", 169 | "avx512pf", 170 | "avx512vbmi", 171 | "avx512vbmi2", 172 | "avx512vl", 173 | "avx512vnni", 174 | "avx512vpopcntdq", 175 | "bmi1", 176 | "bmi2", 177 | "cet_ss", 178 | "cldemote", 179 | "clflushLineSize", 180 | "clflushopt", 181 | "clfsh", 182 | "clwb", 183 | "cmov", 184 | "cmpxchg16b", 185 | "cnxt_id", 186 | "cx8", 187 | "dca", 188 | "de", 189 | "deprecates", 190 | "ds_cpl", 191 | "ds", 192 | "dtes64", 193 | "eist", 194 | "extendedFamily", 195 | "extendedModel", 196 | "f16c", 197 | "family", 198 | "fdp_excptn_only", 199 | "fma", 200 | "fpu", 201 | "fsgsbase", 202 | "fxsr", 203 | "gfni", 204 | "hle", 205 | "htt", 206 | "ia32_tsc_adjust", 207 | "initialAPIC", 208 | "intel_pt", 209 | "invpcid", 210 | "mawau", 211 | "max7SubLeafs", 212 | "maxLogicalProcessors", 213 | "mca", 214 | "mce", 215 | "mmx", 216 | "model", 217 | "monitor", 218 | "movbe", 219 | "movdir64b", 220 | "movdiri", 221 | "mpx", 222 | "msr", 223 | "mtrr", 224 | "ospke", 225 | "osxsave", 226 | "pae", 227 | "pat", 228 | "pbe", 229 | "pcid", 230 | "pclmulqdq", 231 | "pcommit", 232 | "pdcm", 233 | "pge", 234 | "pku", 235 | "popcnt", 236 | "prefetchwt1", 237 | "pse", 238 | "pse36", 239 | "psn", 240 | "rdrand", 241 | "rdseed", 242 | "rdt_a", 243 | "rdt_m", 244 | "rtm", 245 | "sdbg", 246 | "self_snoop", 247 | "sep", 248 | "sgx_lc", 249 | "sgx", 250 | "sha", 251 | "smap", 252 | "smep", 253 | "smx", 254 | "sse", 255 | "sse2", 256 | "sse3", 257 | "sse41", 258 | "sse42", 259 | "ssse3", 260 | "stepping", 261 | "supports", 262 | "therm_monitor", 263 | "therm_monitor2", 264 | "tsc_deadline", 265 | "tsc", 266 | "type", 267 | "umip", 268 | "vaes", 269 | "vme", 270 | "vmx", 271 | "vpclmulqdq", 272 | "waitpkg", 273 | "x2apic", 274 | "xsave", 275 | "xtpr", 276 | )) 277 | static if(mixin(`isIntegral!(typeof(` ~ name ~ `))`)) 278 | mixin(`app.formattedWrite("%20s: 0x%X\n", "` ~ name ~ `", ` ~ name ~ `);`); 279 | else 280 | mixin(`app.formattedWrite("%20s: %s\n", "` ~ name ~ `", ` ~ name ~ `);`); 281 | 282 | return app.data; 283 | } 284 | -------------------------------------------------------------------------------- /source/cpuid/amd.d: -------------------------------------------------------------------------------- 1 | /++ 2 | $(H2 AMD CPUID Information) 3 | 4 | $(GREEN This module is compatible with betterC compilation mode.) 5 | 6 | References: 7 | AMD CPUID Specification. Publication # 25481 / Revision: 2.34 / Issue Date: September 2010 8 | 9 | License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 10 | 11 | Authors: Ilia Ki 12 | +/ 13 | module cpuid.amd; 14 | 15 | version(X86) 16 | version = X86_Any; 17 | else 18 | version(X86_64) 19 | version = X86_Any; 20 | 21 | version(X86_Any): 22 | 23 | public import cpuid.x86_any; 24 | 25 | /++ 26 | L1 Cache and TLB Identifiers. 27 | 28 | The associativity fields are encoded as follows: 29 | 30 | Specification: AMD 31 | +/ 32 | union LeafExt5Information 33 | { 34 | version(BigEndian) static assert(0, "Leaf2Information is not implemented for BigEndian architecture."); 35 | 36 | /// 37 | CpuInfo info; 38 | 39 | /// 40 | struct 41 | { 42 | /// Instruction TLB number of entries for 2 MB and 4 MB pages. 43 | ubyte L1ITlb2and4MSize; 44 | /// Instruction TLB associativity for 2 MB and 4 MB pages. 45 | ubyte L1ITlb2and4MAssoc; 46 | /// Data TLB number of entries for 2 MB and 4 MB pages. 47 | ubyte L1DTlb2and4MSize; 48 | /// Data TLB associativity for 2 MB and 4 MB pages. 49 | ubyte L1DTlb2and4MAssoc; 50 | 51 | /// Instruction TLB number of entries for 4 KB pages. 52 | ubyte L1ITlb4KSize; 53 | /// Instruction TLB associativity for 4 KB pages. 54 | /// See_also: CPUID Fn8000_0005_EDX[L1IcAssoc]. 55 | ubyte L1ITlb4KAssoc; 56 | /// Data TLB number of entries for 4 KB pages. 57 | ubyte L1DTlb4KSize; 58 | /// Data TLB associativity for 4 KB pages. 59 | /// See_also: CPUID Fn8000_0005_EDX[L1IcAssoc]. 60 | ubyte L1DTlb4KAssoc; 61 | 62 | /// L1 data cache line size in bytes. 63 | ubyte L1DcLineSize; 64 | /// L1 data cache lines per tag. 65 | ubyte L1DcLinesPerTag; 66 | /// L1 data cache associativity. 67 | /// See_also: CPUID Fn8000_0005_EDX[L1IcAssoc]. 68 | ubyte L1DcAssoc; 69 | /// L1 data cache size in KB. 70 | ubyte L1DcSize; 71 | 72 | /// L1 instruction cache line size in bytes. 73 | ubyte L1IcLineSize; 74 | /// L1 instruction cache lines per tag. 75 | ubyte L1IcLinesPerTag; 76 | /// L1 instruction cache associativity. 77 | ubyte L1IcAssoc; 78 | /// L1 instruction cache size KB. 79 | ubyte L1IcSize; 80 | } 81 | } 82 | 83 | /++ 84 | L2/L3 Cache and TLB Identifiers. 85 | 86 | This function contains the processor’s second level cache and TLB characteristics for each core. 87 | The EDX register contains the processor’s third level cache characteristics that are shared by all cores of the processor. 88 | 89 | Note: 90 | Use $(MREF decodeL2orL3Assoc) to get final result for any `*Assoc` field. 91 | 92 | Specification: AMD 93 | +/ 94 | union LeafExt6Information 95 | { 96 | /// CPUID payload 97 | CpuInfo info; 98 | 99 | /// 100 | struct 101 | { 102 | import mir.bitmanip: bitfields; 103 | 104 | version(D_Ddoc) 105 | { 106 | const @trusted @property pure nothrow @nogc: 107 | /// L2 instruction TLB number of entries for 4 KB pages. 108 | uint L2ITlb4KSize(); 109 | /// L2 instruction TLB associativity for 4 KB pages. 110 | uint L2ITlb4KAssoc(); 111 | /// L2 data TLB number of entries for 4 KB pages. 112 | uint L2DTlb4KSize(); 113 | /// L2 data TLB associativity for 4 KB pages. 114 | uint L2DTlb4KAssoc(); 115 | /// L2 instruction TLB number of entries for 2 MB and 4 MB pages. 116 | /// The value returned is for the number of entries available for the 2 MB page size; 4 MB pages require two 2 MB entries, so the number of entries available for the 4 MB page size is one-half the returned value. 117 | uint L2ITlb2and4MSize(); 118 | /// L2 instruction TLB associativity for 2 MB and 4 MB pages. 119 | uint L2ITlb2and4MAssoc(); 120 | /// L2 data TLB number of entries for 2 MB and 4 MB pages. 121 | /// The value returned is for the number of entries available for the 2 MB page size; 4 MB pages require two 2 MB entries, so the number of entries available for the 4 MB page size is one-half the returned value. 122 | uint L2DTlb2and4MSize(); 123 | /// L2 data TLB associativity for 2 MB and 4 MB pages. 124 | uint L2DTlb2and4MAssoc(); 125 | /// L2 cache line size in bytes. 126 | uint L2LineSize(); 127 | /// L2 cache lines per tag. 128 | uint L2LinesPerTag(); 129 | /// L2 cache associativity. 130 | uint L2Assoc(); 131 | /// L2 cache size in KB. 132 | uint L2Size(); 133 | /// L3 cache line size in bytes. 134 | uint L3LineSize(); 135 | /// L3 cache lines per tag. 136 | uint L3LinesPerTag(); 137 | /// L3 cache associativity. L3 cache associativity. 138 | uint L3Assoc(); 139 | /// L3 cache size. Specifies the L3 cache size is within the following range: `(L3Size * 512KB) <= L3 cache size < ((L3Size+1) * 512KB)`. 140 | uint L3Size(); 141 | } 142 | else 143 | { 144 | @trusted @property pure nothrow @nogc: 145 | 146 | /// EAX 147 | mixin(bitfields!( 148 | uint, "L2ITlb4KSize", 11 - 0 + 1, 149 | uint, "L2ITlb4KAssoc", 15 - 12 + 1, 150 | uint, "L2DTlb4KSize", 27 - 16 + 1, 151 | uint, "L2DTlb4KAssoc", 31 - 28 + 1, 152 | )); 153 | 154 | /// EBX 155 | mixin(bitfields!( 156 | uint, "L2ITlb2and4MSize", 11 - 0 + 1, 157 | uint, "L2ITlb2and4MAssoc", 15 - 12 + 1, 158 | uint, "L2DTlb2and4MSize", 27 - 16 + 1, 159 | uint, "L2DTlb2and4MAssoc", 31 - 28 + 1, 160 | )); 161 | 162 | /// ECX 163 | mixin(bitfields!( 164 | uint, "L2LineSize", 7 - 0 + 1, 165 | uint, "L2LinesPerTag", 11 - 8 + 1, 166 | uint, "L2Assoc", 15 - 12 + 1, 167 | uint, "L2Size", 31 - 16 + 1, 168 | )); 169 | 170 | /// EDX 171 | mixin(bitfields!( 172 | uint, "L3LineSize", 7 - 0 + 1, 173 | uint, "L3LinesPerTag", 11 - 8 + 1, 174 | uint, "L3Assoc", 15 - 12 + 1, 175 | uint, "", 17 - 16 + 1, 176 | uint, "L3Size", 31 - 18 + 1, 177 | )); 178 | } 179 | } 180 | } 181 | 182 | /++ 183 | Long Mode Address Size Identifiers. 184 | 185 | Extended Feature Extensions ID EBX. 186 | 187 | Size Identifiers. 188 | 189 | Specification: AMD 190 | +/ 191 | union LeafExt8Information 192 | { 193 | /// CPUID payload 194 | CpuInfo info; 195 | 196 | /// 197 | struct 198 | { 199 | import mir.bitmanip: bitfields; 200 | 201 | version(D_Ddoc) 202 | { 203 | const @trusted @property pure nothrow @nogc: 204 | /// Maximum physical byte address size in bits 205 | uint L2ITlb4KSize(); 206 | /// Maximum linear byte address size in bits 207 | uint PhysAddrSize(); 208 | /// Maximum guest physical byte address size in bits 209 | uint GuestPhysAddrSize(); 210 | /// Clear Zero Instruction 211 | uint CLZERO(); 212 | /// Instructions retired count support 213 | uint IRPerf(); 214 | /// 215 | uint XSaveErPtr(); 216 | /// Number of threads in the package - 1 217 | uint NC(); 218 | /// The number of bits in the initial value that indicate thread ID within a package. 219 | uint ApicIdCoreIdSize(); 220 | /// performance time-stamp counter size 221 | uint PerfTscSize(); 222 | } 223 | else 224 | { 225 | @trusted @property pure nothrow @nogc: 226 | 227 | /// EAX 228 | mixin(bitfields!( 229 | uint, "L2ITlb4KSize", 7 - 0 + 1, 230 | uint, "PhysAddrSize", 15 - 8 + 1, 231 | uint, "GuestPhysAddrSize", 23 - 16 + 1, 232 | uint, "", 31 - 24 + 1, 233 | )); 234 | 235 | /// EBX 236 | mixin(bitfields!( 237 | bool, "CLZERO", 1, 238 | bool, "IRPerf", 1, 239 | bool, "XSaveErPtr", 1, 240 | uint, "", 31 - 3 + 1, 241 | )); 242 | 243 | /// ECX 244 | mixin(bitfields!( 245 | uint, "NC", 7 - 0 + 1, 246 | uint, "", 11 - 8 + 1, 247 | uint, "ApicIdCoreIdSize", 15 - 12 + 1, 248 | uint, "PerfTscSize", 17 - 16 + 1, 249 | uint, "", 31 - 18 + 1, 250 | )); 251 | } 252 | } 253 | } 254 | 255 | /++ 256 | Extended APIC ID. 257 | 258 | Core Identifiers. 259 | 260 | Node Identifiers. 261 | 262 | Specification: AMD 263 | +/ 264 | union LeafExt1EInformation 265 | { 266 | /// CPUID payload 267 | CpuInfo info; 268 | 269 | /// 270 | struct 271 | { 272 | import mir.bitmanip: bitfields; 273 | // EAX 274 | /// Extended APIC ID 275 | uint ExtendedApicId; 276 | // EBX 277 | /// Core ID 278 | ubyte CoreId; 279 | /// The number of threads per core is ThreadsPerCore+1. 280 | ubyte ThreadsPerCore; 281 | ushort __reserved__EBX; 282 | version(D_Ddoc) 283 | { 284 | const @trusted @property pure nothrow @nogc: 285 | /// Node per processor. 286 | uint NodesPerProcessor(); 287 | /// Node ID 288 | uint NodeId(); 289 | } 290 | else 291 | { 292 | @trusted @property pure nothrow @nogc: 293 | 294 | /// ECX 295 | mixin(bitfields!( 296 | uint, "", 31 - 11 + 1, 297 | uint, "NodesPerProcessor", 10 - 8 + 1, 298 | uint, "NodeId", 7 - 0 + 1, 299 | )); 300 | } 301 | } 302 | } 303 | 304 | /++ 305 | Decodes Associativity Fields for L2/L3 Cache or TLB. 306 | `T.max` is used to represent full-associative Cache/TLB. 307 | +/ 308 | @safe pure nothrow @nogc 309 | T decodeL2or3Assoc(T = uint)(uint assoc) 310 | { 311 | switch(assoc) 312 | { 313 | case 0x1: return 1; 314 | case 0x2: return 2; 315 | case 0x4: return 4; 316 | case 0x6: return 8; 317 | case 0x8: return 16; 318 | case 0xA: return 32; 319 | case 0xB: return 48; 320 | case 0xC: return 64; 321 | case 0xD: return 96; 322 | case 0xE: return 128; 323 | case 0xF: return T.max; 324 | default: return 0; 325 | } 326 | } 327 | -------------------------------------------------------------------------------- /source/cpuid/common.d: -------------------------------------------------------------------------------- 1 | /++ 2 | $(H2 Auxiliary data types and functions.) 3 | 4 | $(GREEN This module is is compatible with betterC compilation mode.) 5 | 6 | License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 7 | 8 | Authors: Ilia Ki 9 | +/ 10 | module cpuid.common; 11 | 12 | /// Cache Information 13 | struct Cache 14 | { 15 | /// Cache size in KBs 16 | uint size; 17 | /// Ways of associativity. Equals `associative.max` if cache is fully associative. 18 | ushort associative; 19 | /// Cache line in bytes 20 | ushort line; 21 | /// CPU cores per cache 22 | ubyte cores; 23 | /// `true` if cache is inclusive of lower cache levels. 24 | bool inclusive; 25 | 26 | const @property @safe pure nothrow @nogc: 27 | 28 | /// Code: `associative == associative.max` 29 | bool isFullyAssociative()() 30 | { 31 | static if (__VERSION__ >= 2068) 32 | pragma(inline, true); 33 | return associative == associative.max; 34 | } 35 | } 36 | 37 | /// Translation Lookaside Buffer Information 38 | struct Tlb 39 | { 40 | /// Page size in KBs 41 | uint page; 42 | /// Amount of pages TLB 43 | uint entries; 44 | /// Ways of associativity. Equals `associative.max` if TLB is fully associative. 45 | ushort associative; 46 | 47 | const @property @safe pure nothrow @nogc: 48 | 49 | /** Computes size in KBs. 50 | Code: `entries * page` 51 | */ 52 | uint size()() 53 | { 54 | static if (__VERSION__ >= 2068) 55 | pragma(inline, true); 56 | return entries * page; 57 | } 58 | /// Code: `associative == associative.max` 59 | bool isFullyAssociative()() 60 | { 61 | static if (__VERSION__ >= 2068) 62 | pragma(inline, true); 63 | return associative == associative.max; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /source/cpuid/intel.d: -------------------------------------------------------------------------------- 1 | /++ 2 | $(H2 Intel 64 and IA-32 CPUID Information) 3 | 4 | $(GREEN This module is available for betterC compilation mode.) 5 | 6 | References: 7 | Intel® 64 and IA-32 Architectures Software Developer’s Manual 8 | 9 | License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 10 | 11 | Authors: Ilia Ki 12 | +/ 13 | module cpuid.intel; 14 | 15 | version(X86) 16 | version = X86_Any; 17 | else 18 | version(X86_64) 19 | version = X86_Any; 20 | 21 | version(X86_Any): 22 | 23 | public import cpuid.x86_any; 24 | 25 | /++ 26 | TLB and Cache information. 27 | 28 | For convinient Cache information see also $(MREF Leaf4Information). 29 | 30 | Specification: Intel 31 | +/ 32 | struct Leaf2Information 33 | { 34 | /// Level-1 instuciton cache 35 | Cache il1; 36 | /// Level-2 data cache 37 | Cache l1; 38 | /// Level-2 unified cache 39 | Cache l2; 40 | /// Level-2 unified cache 41 | Cache l3; 42 | /// Intruction TLB 43 | Tlb itlb; 44 | /// Intruction TLB, huge pages 45 | Tlb hitlb; 46 | /// Data TLB 47 | Tlb dtlb; 48 | /// Data TLB, huge pages 49 | Tlb hdtlb; 50 | /// Data TLB, giant pages 51 | Tlb gdtlb; 52 | /// Data TLB1 53 | Tlb dtlb1; 54 | /// Data TLB1, huge pages 55 | Tlb hdtlb1; 56 | /// Second-level unified TLB 57 | Tlb utlb; 58 | /// Second-level unified TLB, huge pages 59 | Tlb hutlb; 60 | /// Second-level unified TLB, giant pages 61 | Tlb gutlb; 62 | /// prefetch line size 63 | int prefetch; 64 | /// Cache trace 65 | int trace; 66 | /// `true` if CPUID leaf 2 does not report cache descriptor information. use CPUID leaf 4 to query cache parameters. 67 | bool noCacheInfo; 68 | // No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache 69 | bool noL2Or3; 70 | 71 | /+ 72 | Dencoding of CPUID Leaf 2 Descriptors. 73 | 74 | Note: 75 | 76 | Specification: Intel 77 | +/ 78 | nothrow @nogc pure 79 | this()(CpuInfo info) 80 | { 81 | version(BigEndian) static assert(0, "Leaf2Information is not implemented for BigEndian."); 82 | 83 | foreach(i, b; (*(cast(ubyte[16]*)&info))[1..$]) 84 | switch(b) 85 | { 86 | default: 87 | break; 88 | case 0x00: 89 | // General Null descriptor, this byte contains no information 90 | break; 91 | case 0x01: 92 | itlb.page = 4; 93 | itlb.associative = 4; 94 | itlb.entries = 32; 95 | break; 96 | case 0x02: 97 | hitlb.page = 4 * 1024; 98 | hitlb.associative = hitlb.associative.max; 99 | hitlb.entries = 2; 100 | break; 101 | case 0x03: 102 | dtlb.page = 4; 103 | dtlb.associative = 4; 104 | dtlb.entries = 64; 105 | break; 106 | case 0x04: 107 | hdtlb.page = 4 * 1024; 108 | hdtlb.associative = 4; 109 | hdtlb.entries = 8; 110 | break; 111 | case 0x05: 112 | hdtlb1.page = 4 * 1024; 113 | hdtlb1.associative = 4; 114 | hdtlb1.entries = 32; 115 | break; 116 | case 0x06: 117 | il1.size = 8; 118 | il1.associative = 4; 119 | il1.line = 32; 120 | break; 121 | case 0x08: 122 | il1.size = 16; 123 | il1.associative = 4; 124 | il1.line = 32; 125 | break; 126 | case 0x09: 127 | il1.size = 32; 128 | il1.associative = 4; 129 | il1.line = 64; 130 | break; 131 | case 0x0A: 132 | l1.size = 8; 133 | l1.associative = 2; 134 | l1.line = 32; 135 | break; 136 | case 0x0B: 137 | hitlb.page = 4 * 1024; 138 | hitlb.associative = 4; 139 | hitlb.entries = 4; 140 | break; 141 | case 0x0C: 142 | l1.size = 16; 143 | l1.associative = 4; 144 | l1.line = 32; 145 | break; 146 | case 0x0D: 147 | l1.size = 16; 148 | l1.associative = 4; 149 | l1.line = 64; 150 | break; 151 | case 0x0E: 152 | l1.size = 24; 153 | l1.associative = 6; 154 | l1.line = 64; 155 | break; 156 | case 0x1D: 157 | l2.size = 128; 158 | l2.associative = 2; 159 | l2.line = 64; 160 | break; 161 | case 0x21: 162 | l2.size = 256; 163 | l2.associative = 8; 164 | l2.line = 64; 165 | break; 166 | case 0x22: 167 | l3.size = 512; 168 | l3.associative = 4; 169 | l3.line = 64; 170 | break; 171 | case 0x23: 172 | l3.size = 1 * 1024; 173 | l3.associative = 8; 174 | l3.line = 64; 175 | break; 176 | case 0x24: 177 | l2.size = 1 * 1024; 178 | l2.associative = 16; 179 | l2.line = 64; 180 | break; 181 | case 0x25: 182 | l3.size = 2 * 1024; 183 | l3.associative = 8; 184 | l3.line = 64; 185 | break; 186 | case 0x29: 187 | l3.size = 4 * 1024; 188 | l3.associative = 8; 189 | l3.line = 64; 190 | break; 191 | case 0x2C: 192 | l1.size = 32; 193 | l1.associative = 8; 194 | l1.line = 64; 195 | break; 196 | case 0x30: 197 | il1.size = 32; 198 | il1.associative = 8; 199 | il1.line = 64; 200 | break; 201 | case 0x40: 202 | noL2Or3 = true; 203 | break; 204 | case 0x41: 205 | l2.size = 128; 206 | l2.associative = 4; 207 | l2.line = 32; 208 | break; 209 | case 0x42: 210 | l2.size = 256; 211 | l2.associative = 4; 212 | l2.line = 32; 213 | break; 214 | case 0x43: 215 | l2.size = 512; 216 | l2.associative = 4; 217 | l2.line = 32; 218 | break; 219 | case 0x44: 220 | l2.size = 1 * 1024; 221 | l2.associative = 4; 222 | l2.line = 32; 223 | break; 224 | case 0x45: 225 | l2.size = 2 * 1024; 226 | l2.associative = 4; 227 | l2.line = 32; 228 | break; 229 | case 0x46: 230 | l3.size = 4 * 1024; 231 | l3.associative = 4; 232 | l3.line = 64; 233 | break; 234 | case 0x47: 235 | l3.size = 8 * 1024; 236 | l3.associative = 8; 237 | l3.line = 64; 238 | break; 239 | case 0x48: 240 | l2.size = 3 * 1024; 241 | l2.associative = 12; 242 | l2.line = 64; 243 | break; 244 | case 0x49: 245 | if(family == 0x0F && model == 0x06) 246 | { 247 | l3.size = 4 * 1024; 248 | l3.associative = 16; 249 | l3.line = 64; 250 | break; 251 | } 252 | l2.size = 4 * 1024; 253 | l2.associative = 16; 254 | l2.line = 64; 255 | break; 256 | case 0x4A: 257 | l3.size = 6 * 1024; 258 | l3.associative = 12; 259 | l3.line = 64; 260 | break; 261 | case 0x4B: 262 | l3.size = 8 * 1024; 263 | l3.associative = 16; 264 | l3.line = 64; 265 | break; 266 | case 0x4C: 267 | l3.size = 12 * 1024; 268 | l3.associative = 12; 269 | l3.line = 64; 270 | break; 271 | case 0x4D: 272 | l3.size = 16 * 1024; 273 | l3.associative = 16; 274 | l3.line = 64; 275 | break; 276 | case 0x4E: 277 | l2.size = 6 * 1024; 278 | l2.associative = 24; 279 | l2.line = 64; 280 | break; 281 | case 0x4F: 282 | itlb.page = 4; 283 | itlb.associative = 1; 284 | itlb.entries = 32; 285 | break; 286 | case 0x50: 287 | itlb.page = 4; 288 | itlb.associative = 1; 289 | itlb.entries = 64; 290 | hitlb.page = 2 * 1024; 291 | hitlb.associative = 1; 292 | hitlb.entries = 64; 293 | break; 294 | case 0x51: 295 | itlb.page = 4; 296 | itlb.associative = 1; 297 | itlb.entries = 128; 298 | hitlb.page = 2 * 1024; 299 | hitlb.associative = 1; 300 | hitlb.entries = 128; 301 | break; 302 | case 0x52: 303 | itlb.page = 4; 304 | itlb.associative = 1; 305 | itlb.entries = 256; 306 | hitlb.page = 2 * 1024; 307 | hitlb.associative = 1; 308 | hitlb.entries = 256; 309 | break; 310 | case 0x55: 311 | itlb.page = 2 * 1024; 312 | itlb.associative = itlb.associative.max; 313 | itlb.entries = 7; 314 | break; 315 | case 0x56: 316 | hdtlb.page = 4 * 1024; 317 | hdtlb.associative = 4; 318 | hdtlb.entries = 16; 319 | break; 320 | case 0x57: 321 | dtlb.page = 4; 322 | dtlb.associative = 4; 323 | dtlb.entries = 16; 324 | break; 325 | case 0x59: 326 | dtlb.page = 4; 327 | dtlb.associative = dtlb.associative.max; 328 | dtlb.entries = 16; 329 | break; 330 | case 0x5A: 331 | hdtlb.page = 2 * 1024; 332 | hdtlb.associative = 4; 333 | hdtlb.entries = 32; 334 | break; 335 | case 0x5B: 336 | dtlb.page = 4; 337 | dtlb.associative = 1; 338 | dtlb.entries = 64; 339 | hdtlb.page = 4 * 1024; 340 | hdtlb.associative = 1; 341 | hdtlb.entries = 64; 342 | break; 343 | case 0x5C: 344 | dtlb.page = 4; 345 | dtlb.associative = 1; 346 | dtlb.entries = 128; 347 | hdtlb.page = 4 * 1024; 348 | hdtlb.associative = 1; 349 | hdtlb.entries = 128; 350 | break; 351 | case 0x5D: 352 | dtlb.page = 4; 353 | dtlb.associative = 1; 354 | dtlb.entries = 256; 355 | hdtlb.page = 4 * 1024; 356 | hdtlb.associative = 1; 357 | hdtlb.entries = 256; 358 | break; 359 | case 0x60: 360 | l1.size = 16; 361 | l1.associative = 8; 362 | l1.line = 64; 363 | break; 364 | case 0x61: 365 | itlb.page = 4; 366 | itlb.associative = itlb.associative.max; 367 | itlb.entries = 48; 368 | break; 369 | case 0x63: 370 | hdtlb.page = 2 * 1024; 371 | hdtlb.associative = 4; 372 | hdtlb.entries = 32; 373 | gdtlb.page = 1024 * 1024; 374 | gdtlb.associative = 4; 375 | gdtlb.entries = 4; 376 | break; 377 | case 0x64: 378 | dtlb.page = 4; 379 | dtlb.associative = 4; 380 | dtlb.entries = 512; 381 | break; 382 | case 0x66: 383 | l1.size = 8; 384 | l1.associative = 4; 385 | l1.line = 64; 386 | break; 387 | case 0x67: 388 | l1.size = 16; 389 | l1.associative = 4; 390 | l1.line = 64; 391 | break; 392 | case 0x68: 393 | l1.size = 32; 394 | l1.associative = 4; 395 | l1.line = 64; 396 | break; 397 | case 0x6A: 398 | dtlb.page = 4; 399 | dtlb.associative = 8; 400 | dtlb.entries = 64; 401 | break; 402 | case 0x6B: 403 | dtlb.page = 4; 404 | dtlb.associative = 8; 405 | dtlb.entries = 256; 406 | break; 407 | case 0x6C: 408 | hdtlb.page = 2 * 1024; 409 | hdtlb.associative = 8; 410 | hdtlb.entries = 128; 411 | break; 412 | case 0x6D: 413 | gdtlb.page = 1024 * 1024; 414 | gdtlb.associative = gdtlb.associative.max; 415 | gdtlb.entries = 16; 416 | break; 417 | case 0x70: 418 | trace = 12; 419 | break; 420 | case 0x71: 421 | trace = 16; 422 | break; 423 | case 0x72: 424 | trace = 32; 425 | break; 426 | case 0x76: 427 | itlb.page = 2 * 1024; 428 | itlb.associative = itlb.associative.max; 429 | itlb.entries = 8; 430 | break; 431 | case 0x78: 432 | l2.size = 1 * 1024; 433 | l2.associative = 4; 434 | l2.line = 6; 435 | break; 436 | case 0x79: 437 | l2.size = 128; 438 | l2.associative = 8; 439 | l2.line = 64; 440 | break; 441 | case 0x7A: 442 | l2.size = 256; 443 | l2.associative = 8; 444 | l2.line = 64; 445 | break; 446 | case 0x7B: 447 | l2.size = 512; 448 | l2.associative = 8; 449 | l2.line = 64; 450 | break; 451 | case 0x7C: 452 | l2.size = 1 * 1024; 453 | l2.associative = 8; 454 | l2.line = 64; 455 | break; 456 | case 0x7D: 457 | l2.size = 2 * 1024; 458 | l2.associative = 8; 459 | l2.line = 6; 460 | break; 461 | case 0x7F: 462 | l2.size = 512; 463 | l2.associative = 2; 464 | l2.line = 64; 465 | break; 466 | case 0x80: 467 | l2.size = 512; 468 | l2.associative = 8; 469 | l2.line = 64; 470 | break; 471 | case 0x82: 472 | l2.size = 256; 473 | l2.associative = 8; 474 | l2.line = 32; 475 | break; 476 | case 0x83: 477 | l2.size = 512; 478 | l2.associative = 8; 479 | l2.line = 32; 480 | break; 481 | case 0x84: 482 | l2.size = 1 * 1024; 483 | l2.associative = 8; 484 | l2.line = 32; 485 | break; 486 | case 0x85: 487 | l2.size = 2 * 1024; 488 | l2.associative = 8; 489 | l2.line = 32; 490 | break; 491 | case 0x86: 492 | l2.size = 512; 493 | l2.associative = 4; 494 | l2.line = 64; 495 | break; 496 | case 0x87: 497 | l2.size = 1 * 1024; 498 | l2.associative = 8; 499 | l2.line = 64; 500 | break; 501 | case 0xA0: 502 | dtlb.page = 4; 503 | dtlb.associative = dtlb.associative.max; 504 | dtlb.entries = 32; 505 | break; 506 | case 0xB0: 507 | itlb.page = 4; 508 | itlb.associative = 4; 509 | itlb.entries = 128; 510 | break; 511 | case 0xB1: 512 | itlb.page = 2 * 1024; 513 | itlb.associative = 4; 514 | itlb.entries = 8; 515 | break; 516 | case 0xB2: 517 | itlb.page = 4; 518 | itlb.associative = 4; 519 | itlb.entries = 64; 520 | break; 521 | case 0xB3: 522 | dtlb.page = 4; 523 | dtlb.associative = 4; 524 | dtlb.entries = 128; 525 | break; 526 | case 0xB4: 527 | dtlb1.page = 4; 528 | dtlb1.associative = 4; 529 | dtlb1.entries = 256; 530 | break; 531 | case 0xB5: 532 | itlb.page = 4; 533 | itlb.associative = 8; 534 | itlb.entries = 64; 535 | break; 536 | case 0xB6: 537 | itlb.page = 4; 538 | itlb.associative = 8; 539 | itlb.entries = 128; 540 | break; 541 | case 0xBA: 542 | dtlb1.page = 4; 543 | dtlb1.associative = 4; 544 | dtlb1.entries = 64; 545 | break; 546 | case 0xC0: 547 | dtlb.page = 4; 548 | dtlb.associative = 4; 549 | dtlb.entries = 8; 550 | hdtlb.page = 4 * 1024; 551 | hdtlb.associative = 4; 552 | hdtlb.entries = 8; 553 | break; 554 | case 0xC1: 555 | utlb.page = 4; 556 | utlb.associative = 8; 557 | utlb.entries = 1024; 558 | hutlb.page = 2 * 1024; 559 | hutlb.associative = 8; 560 | hutlb.entries = 1024; 561 | break; 562 | case 0xC2: 563 | dtlb.page = 4; 564 | dtlb.associative = 4; 565 | dtlb.entries = 16; 566 | hdtlb.page = 2 * 1024; 567 | hdtlb.associative = 4; 568 | hdtlb.entries = 16; 569 | break; 570 | case 0xC3: 571 | utlb.page = 4; 572 | utlb.associative = 6; 573 | utlb.entries = 1536; 574 | hutlb.page = 2 * 1024; 575 | hutlb.associative = 6; 576 | hutlb.entries = 1536; 577 | gutlb.page = 1024 * 1024; 578 | gutlb.associative = 4; 579 | gutlb.entries = 16; 580 | break; 581 | case 0xC4: 582 | hdtlb.page = 2 * 1024; 583 | hdtlb.associative = 4; 584 | hdtlb.entries = 32; 585 | break; 586 | case 0xCA: 587 | utlb.page = 4; 588 | utlb.associative = 4; 589 | utlb.entries = 512; 590 | break; 591 | case 0xD0: 592 | l3.size = 512; 593 | l3.associative = 4; 594 | l3.line = 64; 595 | break; 596 | case 0xD1: 597 | l3.size = 1 * 1024; 598 | l3.associative = 4; 599 | l3.line = 64; 600 | break; 601 | case 0xD2: 602 | l3.size = 2 * 1024; 603 | l3.associative = 4; 604 | l3.line = 64; 605 | break; 606 | case 0xD6: 607 | l3.size = 1 * 1024; 608 | l3.associative = 8; 609 | l3.line = 64; 610 | break; 611 | case 0xD7: 612 | l3.size = 2 * 1024; 613 | l3.associative = 8; 614 | l3.line = 64; 615 | break; 616 | case 0xD8: 617 | l3.size = 4 * 1024; 618 | l3.associative = 8; 619 | l3.line = 64; 620 | break; 621 | case 0xDC: 622 | l3.size = 1536; 623 | l3.associative = 12; 624 | l3.line = 64; 625 | break; 626 | case 0xDD: 627 | l3.size = 3 * 1024; 628 | l3.associative = 12; 629 | l3.line = 64; 630 | break; 631 | case 0xDE: 632 | l3.size = 6 * 1024; 633 | l3.associative = 12; 634 | l3.line = 64; 635 | break; 636 | case 0xE2: 637 | l3.size = 2 * 1024; 638 | l3.associative = 16; 639 | l3.line = 64; 640 | break; 641 | case 0xE3: 642 | l3.size = 4 * 1024; 643 | l3.associative = 16; 644 | l3.line = 64; 645 | break; 646 | case 0xE4: 647 | l3.size = 8 * 1024; 648 | l3.associative = 16; 649 | l3.line = 64; 650 | break; 651 | case 0xEA: 652 | l3.size = 12 * 1024; 653 | l3.associative = 24; 654 | l3.line = 64; 655 | break; 656 | case 0xEB: 657 | l3.size = 18 * 1024; 658 | l3.associative = 24; 659 | l3.line = 64; 660 | break; 661 | case 0xEC: 662 | l3.size = 24 * 1024; 663 | l3.associative = 24; 664 | l3.line = 64; 665 | break; 666 | case 0xF0: 667 | // Prefetch 64-B prefetching 668 | prefetch = 64; 669 | break; 670 | case 0xF1: 671 | // Prefetch 128-B prefetching 672 | prefetch = 128; 673 | break; 674 | case 0xFF: 675 | // General CPUID leaf 2 does not report cache descriptor information, use CPUID leaf 4 to query cache parameters 676 | noCacheInfo = true; 677 | break; 678 | } 679 | } 680 | } 681 | 682 | 683 | ///// 684 | unittest 685 | { 686 | auto leaf2 = Leaf2Information(_cpuid(2)); 687 | } 688 | 689 | /++ 690 | Deterministic Cache Parameters for Each Level. 691 | 692 | ** - Add one to the return value to get the result. 693 | 694 | Specification: Intel 695 | +/ 696 | union Leaf4Information 697 | { 698 | import mir.bitmanip: bitfields; 699 | 700 | /// CPUID payload 701 | CpuInfo info; 702 | 703 | /// 704 | struct 705 | { 706 | /// 707 | enum Type 708 | { 709 | /// 710 | noMoreCaches, 711 | /// 712 | data, 713 | /// 714 | instruction, 715 | /// 716 | unified, 717 | } 718 | 719 | version(D_Ddoc) 720 | { 721 | @trusted @property pure nothrow @nogc const: 722 | /// Cache Type Field. 723 | Type type(); 724 | /// Cache Level (starts at 1). 725 | uint level(); 726 | /// Self Initializing cache level (does not need SW initialization). 727 | bool selfInitializing(); 728 | /// Fully Associative cache. 729 | bool fullyAssociative(); 730 | /// Maximum number of addressable IDs for logical processors sharing this cache. ** 731 | uint maxThreadsPerCache(); 732 | /// Maximum number of addressable IDs for processor cores in the physical package ** 733 | uint maxCorePerCPU(); 734 | /// System Coherency Line Size **. 735 | uint l(); 736 | /// Physical Line partitions **. 737 | uint p(); 738 | /// Ways of associativity **. 739 | uint w(); 740 | /// Number of Sets **. 741 | uint s; 742 | /// Write-Back Invalidate/Invalidate. 743 | /// `false` if WBINVD/INVD from threads sharing this cache acts upon lower level caches for threads sharing this cache. 744 | /// `true` if WBINVD/INVD is not guaranteed to act upon lower level caches of non-originating threads sharing this cache. 745 | bool invalidate(); 746 | /// `true` - Cache is not inclusive of lower cache levels. `false` - Cache is inclusive of lower cache levels. 747 | bool inclusive(); 748 | /// `false` - Direct mapped cache. `true` A complex function is used to index the cache, potentially using all address bits. 749 | bool complex(); 750 | } 751 | else 752 | { 753 | @trusted @property pure nothrow @nogc: 754 | /// EAX 755 | mixin(bitfields!( 756 | Type, "type", 5, 757 | uint, "level", 3, 758 | bool, "selfInitializing", 1, 759 | bool, "fullyAssociative", 1, 760 | uint, "", 4, 761 | uint, "maxThreadsPerCache", 12, 762 | uint, "maxCorePerCPU", 6, 763 | )); 764 | 765 | /// EBX 766 | mixin(bitfields!( 767 | uint, "l", 12, 768 | uint, "p", 10, 769 | uint, "w", 10, 770 | )); 771 | 772 | /// Number of Sets**. 773 | uint s; 774 | 775 | /// EDX 776 | mixin(bitfields!( 777 | bool, "invalidate", 1, 778 | bool, "inclusive", 1, 779 | bool, "complex", 1, 780 | uint, "", 29, 781 | )); 782 | } 783 | 784 | /// Compute cache size in KBs. 785 | pure nothrow @nogc 786 | uint size()() @property 787 | { 788 | return cast(uint) ( 789 | size_t(l + 1) * 790 | size_t(p + 1) * 791 | size_t(w + 1) * 792 | size_t(s + 1) >> 10); 793 | } 794 | 795 | /// 796 | pure nothrow @nogc 797 | void fill()(ref Cache cache) @property 798 | { 799 | cache.size = size; 800 | cache.line = cast(typeof(cache.line))(l + 1); 801 | cache.inclusive = inclusive; 802 | cache.associative = cast(typeof(cache.associative)) (w + 1); 803 | if(fullyAssociative) 804 | cache.associative = cache.associative.max; 805 | } 806 | } 807 | } 808 | 809 | /// 810 | unittest 811 | { 812 | if(maxBasicLeaf >= 4 && vendorIndex == VendorIndex.intel) 813 | { 814 | Cache cache = void; 815 | Leaf4Information leaf4 = void; 816 | foreach(ecx; 0..12) 817 | { 818 | leaf4.info = _cpuid(4, ecx); 819 | if(!leaf4.type) 820 | break; 821 | leaf4.fill(cache); 822 | debug(cpuid) import std.stdio; 823 | debug(cpuid) writefln("Cache #%s has type '%s' and %s KB size", ecx, leaf4.type, leaf4.size); 824 | } 825 | } 826 | } 827 | -------------------------------------------------------------------------------- /source/cpuid/unified.d: -------------------------------------------------------------------------------- 1 | /++ 2 | $(H2 High level abstraction on top of all architectures.) 3 | 4 | $(GREEN This module is compatible with betterC compilation mode.) 5 | 6 | 7 | License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 8 | 9 | Authors: Ilia Ki 10 | +/ 11 | module cpuid.unified; 12 | 13 | /// 14 | unittest 15 | { 16 | void smallReport() 17 | { 18 | import cpuid.unified; 19 | 20 | import std.stdio: writefln; 21 | enum fmt = "%14s: %s"; 22 | 23 | fmt.writefln("cores", cores); 24 | fmt.writefln("threads", threads); 25 | 26 | fmt.writefln("data caches", dCache.length); 27 | fmt.writefln("code caches", iCache.length); 28 | fmt.writefln("unified caches", uCache.length); 29 | 30 | fmt.writefln("data TLBs", dTlb.length); 31 | fmt.writefln("code TLBs", iTlb.length); 32 | fmt.writefln("unified TLBs", uTlb.length); 33 | } 34 | } 35 | 36 | public import cpuid.common; 37 | 38 | version(X86) 39 | version = X86_Any; 40 | version(X86_64) 41 | version = X86_Any; 42 | 43 | version(all) 44 | { 45 | enum uint _dCache_max_length = 1; 46 | enum uint _iCache_max_length = 1; 47 | enum uint _uCache_max_length = 3; 48 | 49 | enum uint _dTlb_max_length = 2; 50 | enum uint _iTlb_max_length = 2; 51 | enum uint _uTlb_max_length = 1; 52 | } 53 | else 54 | static assert(0); 55 | 56 | private __gshared 57 | { 58 | immutable uint _cpus; 59 | immutable uint _cores; 60 | immutable uint _threads; 61 | immutable uint _iCache_length; immutable Cache[_iCache_max_length] _iCache; 62 | immutable uint _dCache_length; immutable Cache[_dCache_max_length] _dCache; 63 | immutable uint _uCache_length; immutable Cache[_uCache_max_length] _uCache; 64 | immutable uint _iTlb_length; immutable Tlb[_iTlb_max_length] _iTlb; 65 | immutable uint _dTlb_length; immutable Tlb[_dTlb_max_length] _dTlb; 66 | immutable uint _uTlb_length; immutable Tlb[_uTlb_max_length] _uTlb; 67 | } 68 | 69 | private T2 assocCopy(T2, T1)(T1 from) 70 | { 71 | import std.traits: Unqual; 72 | Unqual!T2 to = cast(T2) from; 73 | static if(!is(Unqual!T1 == Unqual!T2)) 74 | { 75 | if(from == T1.max) 76 | { 77 | to = T2.max; 78 | } 79 | } 80 | return to; 81 | } 82 | 83 | package ref T _mut(T)(return ref immutable T value) 84 | { 85 | return *cast(T*)&value; 86 | } 87 | 88 | export 89 | nothrow @nogc 90 | extern(C): 91 | 92 | /++ 93 | Initialize basic CPU information including basic architecture. 94 | It is safe to call this function multiple times. 95 | It calls appropriate basic initialization for each module (`cpuid_x86_any_init` for X86 machines). 96 | +/ 97 | version(X86_Any) 98 | pragma(crt_constructor) 99 | void mir_cpuid_init() 100 | { 101 | static if (__VERSION__ >= 2068) 102 | pragma(inline, false); 103 | 104 | if (_cpus) 105 | return; // already initialized 106 | 107 | import cpuid.x86_any; 108 | 109 | mir_cpuid_x86_any_init(); 110 | 111 | static import cpuid.intel; 112 | static import cpuid.amd; 113 | 114 | /// for old CPUs 115 | if(htt) 116 | { 117 | _threads._mut = _cores._mut = maxLogicalProcessors; 118 | _cores._mut /= 2; 119 | } 120 | 121 | if (vendorIndex == VendorIndex.amd || 122 | vendorIndex == VendorIndex.amd_old || 123 | vendorIndex == VendorIndex.centaur || 124 | vendorIndex == VendorIndex.hygon) 125 | { 126 | // Caches and TLB 127 | if(maxExtendedLeaf >= 0x8000_0005) 128 | { 129 | // Level 1 130 | auto leafExt5 = cpuid.amd.LeafExt5Information(_cpuid(0x8000_0005)); 131 | 132 | alias CacheAssoc = typeof(Cache.associative); 133 | alias TlbAssoc = typeof(Tlb.associative); 134 | 135 | if(leafExt5.L1DTlb4KSize) 136 | { 137 | _dTlb._mut[0].page = 4; 138 | _dTlb._mut[0].entries = leafExt5.L1DTlb4KSize; 139 | _dTlb._mut[0].associative = leafExt5.L1DTlb4KAssoc.assocCopy!TlbAssoc; 140 | _dTlb_length._mut = 1; 141 | } 142 | if(leafExt5.L1ITlb4KSize) 143 | { 144 | _iTlb._mut[0].page = 4; 145 | _iTlb._mut[0].entries = leafExt5.L1ITlb4KSize; 146 | _iTlb._mut[0].associative = leafExt5.L1ITlb4KAssoc.assocCopy!TlbAssoc; 147 | _iTlb_length._mut = 1; 148 | } 149 | if(leafExt5.L1DcSize) 150 | { 151 | _dCache_length._mut = 1; 152 | _dCache._mut[0].size = leafExt5.L1DcSize; 153 | _dCache._mut[0].line = leafExt5.L1DcLineSize; 154 | _dCache._mut[0].associative = leafExt5.L1DcAssoc.assocCopy!CacheAssoc; 155 | } 156 | if(leafExt5.L1IcSize) 157 | { 158 | _iCache_length._mut = 1; 159 | _iCache._mut[0].size = leafExt5.L1IcSize; 160 | _iCache._mut[0].line = leafExt5.L1IcLineSize; 161 | _iCache._mut[0].associative = leafExt5.L1IcAssoc.assocCopy!CacheAssoc; 162 | } 163 | 164 | // Levels 2 and 3 165 | if(maxExtendedLeaf >= 0x8000_0006) 166 | { 167 | import cpuid.amd: decodeL2or3Assoc; 168 | auto leafExt6 = cpuid.amd.LeafExt6Information(_cpuid(0x8000_0006)); 169 | 170 | if(leafExt6.L2DTlb4KSize) 171 | { 172 | _dTlb._mut[_dTlb_length].page = 4; 173 | _dTlb._mut[_dTlb_length].entries = leafExt6.L2DTlb4KSize; 174 | _dTlb._mut[_dTlb_length].associative = leafExt6.L2DTlb4KAssoc.decodeL2or3Assoc!TlbAssoc; 175 | _dTlb_length._mut++; 176 | } 177 | if(leafExt6.L2ITlb4KSize) 178 | { 179 | _iTlb._mut[_iTlb_length].page = 4; 180 | _iTlb._mut[_iTlb_length].entries = leafExt6.L2ITlb4KSize; 181 | _iTlb._mut[_iTlb_length].associative = leafExt6.L2ITlb4KAssoc.decodeL2or3Assoc!TlbAssoc; 182 | _iTlb_length._mut++; 183 | } 184 | if(leafExt6.L2Size) 185 | { 186 | _uCache._mut[_uCache_length].size = leafExt6.L2Size; 187 | _uCache._mut[_uCache_length].line = cast(typeof(Cache.line)) leafExt6.L2LineSize; 188 | _uCache._mut[_uCache_length].associative = leafExt6.L2Assoc.decodeL2or3Assoc!CacheAssoc; 189 | _uCache_length._mut++; 190 | } 191 | if(leafExt6.L3Size) 192 | { 193 | _uCache._mut[_uCache_length].size = leafExt6.L3Size * 512; 194 | _uCache._mut[_uCache_length].line = cast(typeof(Cache.line)) leafExt6.L3LineSize; 195 | _uCache._mut[_uCache_length].associative = leafExt6.L3Assoc.decodeL2or3Assoc!CacheAssoc; 196 | _uCache_length._mut++; 197 | } 198 | 199 | if(maxExtendedLeaf >= 0x8000_0008) 200 | { 201 | auto leafExt8 = cpuid.amd.LeafExt8Information(_cpuid(0x8000_0008)); 202 | _threads._mut = leafExt8.NC + 1; 203 | 204 | if (maxExtendedLeaf >= 0x8000_001E) 205 | { 206 | auto leafExt1E = cpuid.amd.LeafExt1EInformation(_cpuid(0x8000_001E)); 207 | _cores._mut = _threads / (leafExt1E.ThreadsPerCore + 1); 208 | } 209 | } 210 | } 211 | } 212 | } 213 | else 214 | { 215 | /// Other vendors 216 | if(maxBasicLeaf >= 0x2) 217 | { 218 | /// Get TLB and Cache info 219 | auto leaf2 = cpuid.intel.Leaf2Information(_cpuid(2)); 220 | 221 | /// Fill cache info 222 | if(leaf2.dtlb.size) 223 | { 224 | _dTlb._mut[0] = leaf2.dtlb; 225 | _dTlb_length._mut = 1; 226 | } 227 | if(leaf2.dtlb1.size) 228 | { 229 | _dTlb._mut[_dTlb_length] = leaf2.dtlb1; 230 | _dTlb_length._mut++; 231 | } 232 | if(leaf2.itlb.size) 233 | { 234 | _iTlb._mut[0] = leaf2.itlb; 235 | _iTlb_length._mut = 1; 236 | } 237 | if(leaf2.utlb.size) 238 | { 239 | _uTlb._mut[0] = leaf2.utlb; 240 | _uTlb_length._mut = 1; 241 | } 242 | 243 | if(maxBasicLeaf >= 0x4) 244 | { 245 | /// Fill cache info from leaf 4 246 | cpuid.intel.Leaf4Information leaf4 = void; 247 | Cache cache; 248 | Leaf4Loop: foreach(uint ecx; 0 .. 12) 249 | { 250 | leaf4.info = _cpuid(4, ecx); 251 | leaf4.fill(cache); 252 | 253 | with(cpuid.intel.Leaf4Information.Type) 254 | switch(leaf4.type) 255 | { 256 | case data: 257 | if(_dCache_length < _dCache.length) 258 | _dCache._mut[_dCache_length._mut++] = cache; 259 | break; 260 | case instruction: 261 | if(_iCache_length < _iCache.length) 262 | _iCache._mut[_iCache_length._mut++] = cache; 263 | break; 264 | case unified: 265 | if(_uCache_length < _uCache.length) 266 | _uCache._mut[_uCache_length._mut++] = cache; 267 | break; 268 | default: break Leaf4Loop; 269 | } 270 | /// Fill core number for old CPUs 271 | _cores._mut = leaf4.maxCorePerCPU; 272 | } 273 | if(maxBasicLeaf >= 0xB) 274 | { 275 | auto th = cast(ushort) _cpuid(0xB, 1).b; 276 | if(th > 0) 277 | _threads._mut = th; 278 | auto threadsPerCore = cast(ushort) _cpuid(0xB, 0).b; 279 | if(threadsPerCore) 280 | { 281 | _cores._mut = _threads / threadsPerCore; 282 | } 283 | } 284 | } 285 | else 286 | { 287 | /// Fill cache info from leaf 2 288 | if(leaf2.l1.size) 289 | { 290 | _dCache._mut[0] = leaf2.l1; 291 | _dCache_length._mut = 1; 292 | } 293 | if(leaf2.il1.size) 294 | { 295 | _iCache._mut[0] = leaf2.il1; 296 | _iCache_length._mut = 1; 297 | } 298 | if(leaf2.l2.size) 299 | { 300 | _uCache._mut[0] = leaf2.l2; 301 | _uCache_length._mut = 1; 302 | } 303 | if(leaf2.l3.size) 304 | { 305 | _uCache._mut[_uCache_length] = leaf2.l3; 306 | _uCache_length._mut++; 307 | } 308 | } 309 | } 310 | } 311 | 312 | if(!_cpus) _cpus._mut = 1; 313 | if(!_cores) _cores._mut = 1; 314 | if(!_threads) _threads._mut = 1; 315 | if(_threads < _cores) _threads._mut = _cores; 316 | 317 | if(_iCache_length) _iCache._mut[0].cores = 1; 318 | if(_dCache_length) _dCache._mut[0].cores = 1; 319 | switch(_uCache_length) 320 | { 321 | case 0: 322 | break; 323 | case 1: 324 | _uCache._mut[0].cores = cast(typeof(Cache.cores)) _cores; 325 | break; 326 | default: 327 | _uCache._mut[0].cores = 1; 328 | foreach(i; 1.._uCache_length) 329 | _uCache._mut[i].cores = cast(typeof(Cache.cores)) _cores; 330 | } 331 | } 332 | else 333 | pragma(crt_constructor) 334 | void mir_cpuid_init() 335 | { 336 | _cpus._mut = 1; 337 | _cores._mut = 1; 338 | _threads._mut = 1; 339 | } 340 | /// ditto 341 | 342 | alias cpuid_init = mir_cpuid_init; 343 | 344 | unittest // make sure a 2nd invocation after the implicit CRT constructor doesn't throw 345 | { 346 | mir_cpuid_init(); 347 | } 348 | 349 | pure @trusted: 350 | 351 | /++ 352 | Total number of CPU packages. 353 | Note: not implemented 354 | +/ 355 | uint mir_cpuid_cpus() { return _cpus; } 356 | /// ditto 357 | alias cpus = mir_cpuid_cpus; 358 | 359 | /++ 360 | Total number of cores per CPU. 361 | +/ 362 | uint mir_cpuid_cores() { return _cores; } 363 | /// ditto 364 | alias cores = mir_cpuid_cores; 365 | 366 | /++ 367 | Total number of threads per CPU. 368 | +/ 369 | uint mir_cpuid_threads() { return _threads; } 370 | /// ditto 371 | alias threads = mir_cpuid_threads; 372 | 373 | /++ 374 | Data Caches 375 | 376 | Returns: 377 | Array composed of detected data caches. Array is sorted in ascending order. 378 | +/ 379 | immutable(Cache)[] mir_cpuid_dCache() { return _dCache[0 .. _dCache_length]; } 380 | /// ditto 381 | alias dCache = mir_cpuid_dCache; 382 | 383 | /++ 384 | Instruction Caches 385 | 386 | Returns: 387 | Array composed of detected instruction caches. Array is sorted in ascending order. 388 | +/ 389 | immutable(Cache)[] mir_cpuid_iCache() { return _iCache[0 .. _iCache_length]; } 390 | /// ditto 391 | alias iCache = mir_cpuid_iCache; 392 | 393 | /++ 394 | Unified Caches 395 | 396 | Returns: 397 | Array composed of detected unified caches. Array is sorted in ascending order. 398 | +/ 399 | immutable(Cache)[] mir_cpuid_uCache() { return _uCache[0 .. _uCache_length]; } 400 | /// ditto 401 | alias uCache = mir_cpuid_uCache; 402 | 403 | /++ 404 | Data Translation Lookaside Buffers 405 | 406 | Returns: 407 | Array composed of detected data translation lookaside buffers. Array is sorted in ascending order. 408 | +/ 409 | immutable(Tlb)[] mir_cpuid_dTlb() { return _dTlb[0 .. _dTlb_length]; } 410 | /// ditto 411 | alias dTlb = mir_cpuid_dTlb; 412 | 413 | /++ 414 | Instruction Translation Lookaside Buffers 415 | 416 | Returns: 417 | Array composed of detected instruction translation lookaside buffers. Array is sorted in ascending order. 418 | +/ 419 | immutable(Tlb)[] mir_cpuid_iTlb() { return _iTlb[0 .. _iTlb_length]; } 420 | /// ditto 421 | alias iTlb = mir_cpuid_iTlb; 422 | 423 | /++ 424 | Unified Translation Lookaside Buffers 425 | 426 | Returns: 427 | Array composed of detected unified translation lookaside buffers. Array is sorted in ascending order. 428 | +/ 429 | immutable(Tlb)[] mir_cpuid_uTlb() { return _uTlb[0 .. _uTlb_length]; } 430 | /// ditto 431 | alias uTlb = mir_cpuid_uTlb; 432 | -------------------------------------------------------------------------------- /source/cpuid/x86_any.d: -------------------------------------------------------------------------------- 1 | /++ 2 | $(H2 Common information for all x86 and x86_64 vendors.) 3 | 4 | $(GREEN This module is compatible with betterC compilation mode.) 5 | 6 | Note: 7 | `T.max` value value is used to represent fully-associative Cache/TLB. 8 | 9 | References: 10 | $(LINK2 https://en.wikipedia.org/wiki/CPUID, wikipedia:CPUID) 11 | 12 | License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 13 | 14 | Authors: Ilia Ki 15 | +/ 16 | module cpuid.x86_any; 17 | 18 | version(LDC) 19 | { 20 | import ldc.llvmasm; 21 | // @@@FIXME@@@ 22 | // https://github.com/ldc-developers/druntime/pull/80 23 | pragma(LDC_inline_asm) 24 | { 25 | template __asmtuple(T...) 26 | { 27 | __asmtuple_t!(T) __asmtuple(const(char)[] asmcode, const(char)[] constraints, ...) pure nothrow @nogc; 28 | } 29 | } 30 | } 31 | 32 | version(X86) 33 | version = X86_Any; 34 | else 35 | version(X86_64) 36 | version = X86_Any; 37 | 38 | version(X86_Any): 39 | 40 | version(D_InlineAsm_X86) 41 | version = InlineAsm_X86_Any; 42 | else 43 | version(D_InlineAsm_X86_64) 44 | version = InlineAsm_X86_Any; 45 | 46 | public import cpuid.common; 47 | 48 | /// Leaf0 49 | private immutable uint _maxBasicLeaf; 50 | 51 | /// Leaf1 52 | private immutable Leaf1Information leaf1Information; 53 | /// Leaf7 54 | private immutable Leaf7Information leaf7Information; 55 | 56 | /// ExtLeaf0 57 | private immutable uint _maxExtendedLeaf; 58 | 59 | /// Other 60 | private immutable VendorIndex _vendorId; 61 | private immutable VendorIndex _virtualVendorId; 62 | 63 | /++ 64 | Initialize basic x86 CPU information. 65 | It is safe to call this function multiple times. 66 | +/ 67 | export extern(C) 68 | nothrow @nogc 69 | void mir_cpuid_x86_any_init() 70 | { 71 | import cpuid.unified: _mut; 72 | static if (__VERSION__ >= 2068) 73 | pragma(inline, false); 74 | CpuInfo info = void; 75 | 76 | info = _cpuid(0); 77 | _maxBasicLeaf._mut = info.a; 78 | 79 | { 80 | uint[3] n = void; 81 | n[0] = info.b; 82 | n[1] = info.d; 83 | n[2] = info.c; 84 | _vendorId._mut = VendorIndex.undefined; 85 | auto vs = vendors[0 .. $ - 1]; 86 | foreach(i, ref name; (cast(uint[3]*)(vs.ptr))[0 .. vs.length]) 87 | { 88 | if (n[0] == name[0] && n[1] == name[1] && n[2] == name[2]) 89 | { 90 | _vendorId._mut = cast(VendorIndex) i; 91 | break; 92 | } 93 | } 94 | } 95 | _virtualVendorId._mut = _vendorId; 96 | leaf1Information._mut.info = _cpuid(1); 97 | if(_maxBasicLeaf >= 7) 98 | leaf7Information._mut.info = _cpuid(0x07); 99 | if(leaf1Information.virtual) 100 | { 101 | auto infov = _cpuid(0x4000_0000); 102 | uint[3] n = void; 103 | n[0] = infov.b; 104 | n[1] = infov.c; 105 | n[2] = infov.d; 106 | _virtualVendorId._mut = VendorIndex.undefinedvm; 107 | auto vs = vendors[VendorIndex.undefined + 1 .. $ - 1]; 108 | foreach(i, ref name; (cast(uint[3]*)(vs.ptr))[0 .. vs.length]) 109 | { 110 | if (n[0] == name[0] && n[1] == name[1] && n[2] == name[2]) 111 | { 112 | _virtualVendorId._mut = cast(VendorIndex) (i + VendorIndex.undefined + 1); 113 | break; 114 | } 115 | } 116 | } 117 | _maxExtendedLeaf._mut = _cpuid(0x8000_0000).a; 118 | } 119 | 120 | /// Basic information about CPU. 121 | union Leaf1Information 122 | { 123 | import mir.bitmanip: bitfields; 124 | /// CPUID payload 125 | CpuInfo info; 126 | struct 127 | { 128 | @trusted @property pure nothrow @nogc: 129 | version(D_Ddoc) 130 | { 131 | const: 132 | /// Stepping ID 133 | uint stepping(); 134 | /// Model 135 | uint model(); 136 | /// Family ID 137 | uint family(); 138 | /// Processor Type, Specification: Intel 139 | uint type(); 140 | /// Extended Model ID 141 | uint extendedModel(); 142 | /// Extended Family ID 143 | uint extendedFamily(); 144 | 145 | 146 | /// Brand Index 147 | ubyte brandIndex; 148 | /// `clflush` line size 149 | ubyte clflushLineSize; 150 | /// maximal number of logical processors 151 | ubyte maxLogicalProcessors; 152 | /// initial APIC 153 | ubyte initialAPIC; 154 | 155 | /// SSE3 Extensions 156 | bool sse3(); 157 | /// Carryless Multiplication 158 | bool pclmulqdq(); 159 | /// 64-bit DS Area 160 | bool dtes64(); 161 | /// MONITOR/MWAIT 162 | bool monitor(); 163 | ///(); /// CPL Qualified Debug Store 164 | bool ds_cpl(); 165 | /// Virtual Machine Extensions 166 | bool vmx(); 167 | /// Safer Mode Extensions 168 | bool smx(); 169 | /// Enhanced Intel SpeedStep® Technology 170 | bool eist(); 171 | /// Thermal Monitor 2 172 | bool therm_monitor2(); 173 | /// SSSE3 Extensions 174 | bool ssse3(); 175 | /// L1 Context ID 176 | bool cnxt_id(); 177 | /// 178 | bool sdbg(); 179 | /// Fused Multiply Add 180 | bool fma(); 181 | /// 182 | bool cmpxchg16b(); 183 | /// TPR Update Control 184 | bool xtpr(); 185 | /// Perf/Debug Capability MSR xTPR Update Control 186 | bool pdcm(); 187 | /// Process-context Identifiers 188 | bool pcid(); 189 | /// Direct Cache Access 190 | bool dca(); 191 | /// SSE4.1 192 | bool sse41(); 193 | /// SSE4.2 194 | bool sse42(); 195 | /// 196 | bool x2apic(); 197 | /// 198 | bool movbe(); 199 | /// 200 | bool popcnt(); 201 | /// 202 | bool tsc_deadline(); 203 | /// 204 | bool aes(); 205 | /// 206 | bool xsave(); 207 | /// 208 | bool osxsave(); 209 | /// 210 | bool avx(); 211 | /// 212 | bool f16c(); 213 | /// 214 | bool rdrand(); 215 | /// 216 | bool virtual(); 217 | /// x87 FPU on Chip 218 | bool fpu(); 219 | /// Virtual-8086 Mode Enhancement 220 | bool vme(); 221 | /// Debugging Extensions 222 | bool de(); 223 | /// Page Size Extensions 224 | bool pse(); 225 | /// Time Stamp Counter 226 | bool tsc(); 227 | /// RDMSR and WRMSR Support 228 | bool msr(); 229 | /// Physical Address Extensions 230 | bool pae(); 231 | /// Machine Check Exception 232 | bool mce(); 233 | /// CMPXCHG8B Inst. 234 | bool cx8(); 235 | /// APIC on Chip 236 | bool apic(); 237 | /// SYSENTER and SYSEXIT 238 | bool sep(); 239 | /// Memory Type Range Registers 240 | bool mtrr(); 241 | /// PTE Global Bit 242 | bool pge(); 243 | /// Machine Check Architecture 244 | bool mca(); 245 | /// Conditional Move/Compare Instruction 246 | bool cmov(); 247 | /// Page Attribute Table 248 | bool pat(); 249 | /// Page Size Extension 250 | bool pse36(); 251 | /// Processor Serial Number 252 | bool psn(); 253 | /// CLFLUSH instruction 254 | bool clfsh(); 255 | /// Debug Store 256 | bool ds(); 257 | /// Thermal Monitor and Clock Ctrl 258 | bool acpi(); 259 | /// MMX Technology 260 | bool mmx(); 261 | /// FXSAVE/FXRSTOR 262 | bool fxsr(); 263 | /// SSE Extensions 264 | bool sse(); 265 | /// SSE2 Extensions 266 | bool sse2(); 267 | /// Self Snoop 268 | bool self_snoop(); 269 | /// Multi-threading 270 | bool htt(); 271 | /// Therm. Monitor 272 | bool therm_monitor(); 273 | /// Pend. Brk. EN. 274 | bool pbe(); 275 | } 276 | else 277 | { 278 | /// EAX 279 | mixin(bitfields!( 280 | uint, "stepping", 3 - 0 + 1, /// Stepping ID 281 | uint, "model", 7 - 4 + 1, /// Model 282 | uint, "family", 11 - 8 + 1, /// Family ID 283 | uint, "type", 13 - 12 + 1, /// Processor Type, Specification: Intel 284 | uint, "", 15 - 14 + 1, 285 | uint, "extendedModel", 19 - 16 + 1, /// Extended Model ID 286 | uint, "extendedFamily", 27 - 20 + 1, /// Extended Family ID 287 | uint, "", 31 - 28 + 1, 288 | )); 289 | 290 | /// EBX 291 | ubyte brandIndex; 292 | ubyte clflushLineSize; 293 | ubyte maxLogicalProcessors; 294 | ubyte initialAPIC; 295 | 296 | /// ECX 297 | mixin(bitfields!( 298 | bool, "sse3", 1, /// SSE3 Extensions 299 | bool, "pclmulqdq", 1, /// Carryless Multiplication 300 | bool, "dtes64", 1, /// 64-bit DS Area 301 | bool, "monitor", 1, /// MONITOR/MWAIT 302 | bool, "ds_cpl", 1, /// CPL Qualified Debug Store 303 | bool, "vmx", 1, /// Virtual Machine Extensions 304 | bool, "smx", 1, /// Safer Mode Extensions 305 | bool, "eist", 1, /// Enhanced Intel SpeedStep® Technology 306 | bool, "therm_monitor2", 1, /// Thermal Monitor 2 307 | bool, "ssse3", 1, /// SSSE3 Extensions 308 | bool, "cnxt_id", 1, /// L1 Context ID 309 | bool, "sdbg", 1, 310 | bool, "fma", 1, /// Fused Multiply Add 311 | bool, "cmpxchg16b", 1, 312 | bool, "xtpr", 1, /// TPR Update Control 313 | bool, "pdcm", 1, /// Perf/Debug Capability MSR xTPR Update Control 314 | bool, "", 1, 315 | bool, "pcid", 1, /// Process-context Identifiers 316 | bool, "dca", 1, /// Direct Cache Access 317 | bool, "sse41", 1, /// SSE4.1 318 | bool, "sse42", 1, /// SSE4.2 319 | bool, "x2apic", 1, 320 | bool, "movbe", 1, 321 | bool, "popcnt", 1, 322 | bool, "tsc_deadline", 1, 323 | bool, "aes", 1, 324 | bool, "xsave", 1, 325 | bool, "osxsave", 1, 326 | bool, "avx", 1, 327 | bool, "f16c", 1, 328 | bool, "rdrand", 1, 329 | bool, "virtual", 1, 330 | )); 331 | 332 | /// EDX 333 | mixin(bitfields!( 334 | bool, "fpu", 1, /// x87 FPU on Chip 335 | bool, "vme", 1, /// Virtual-8086 Mode Enhancement 336 | bool, "de", 1, /// Debugging Extensions 337 | bool, "pse", 1, /// Page Size Extensions 338 | bool, "tsc", 1, /// Time Stamp Counter 339 | bool, "msr", 1, /// RDMSR and WRMSR Support 340 | bool, "pae", 1, /// Physical Address Extensions 341 | bool, "mce", 1, /// Machine Check Exception 342 | bool, "cx8", 1, /// CMPXCHG8B Inst. 343 | bool, "apic", 1, /// APIC on Chip 344 | bool, "", 1, 345 | bool, "sep", 1, /// SYSENTER and SYSEXIT 346 | bool, "mtrr", 1, /// Memory Type Range Registers 347 | bool, "pge", 1, /// PTE Global Bit 348 | bool, "mca", 1, /// Machine Check Architecture 349 | bool, "cmov", 1, /// Conditional Move/Compare Instruction 350 | bool, "pat", 1, /// Page Attribute Table 351 | bool, "pse36", 1, /// Page Size Extension 352 | bool, "psn", 1, /// Processor Serial Number 353 | bool, "clfsh", 1, /// CLFLUSH instruction 354 | bool, "", 1, 355 | bool, "ds", 1, /// Debug Store 356 | bool, "acpi", 1, /// Thermal Monitor and Clock Ctrl 357 | bool, "mmx", 1, /// MMX Technology 358 | bool, "fxsr", 1, /// FXSAVE/FXRSTOR 359 | bool, "sse", 1, /// SSE Extensions 360 | bool, "sse2", 1, /// SSE2 Extensions 361 | bool, "self_snoop", 1, /// Self Snoop 362 | bool, "htt", 1, /// Multi-threading 363 | bool, "therm_monitor", 1, /// Therm. Monitor 364 | bool, "", 1, 365 | bool, "pbe", 1, /// Pend. Brk. EN. 366 | )); 367 | } 368 | } 369 | } 370 | 371 | /// ditto 372 | alias cpuid_x86_any_init = mir_cpuid_x86_any_init; 373 | 374 | /// Extended information about CPU. 375 | union Leaf7Information 376 | { 377 | import mir.bitmanip: bitfields; 378 | /// CPUID payload 379 | CpuInfo info; 380 | struct 381 | { 382 | /// Reports the maximum input value for supported leaf 7 sub-leaves 383 | uint max7SubLeafs; 384 | @trusted @property pure nothrow @nogc: 385 | version(D_Ddoc) 386 | { 387 | const: 388 | /// Supports RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE if 1. 389 | bool fsgsbase(); 390 | ///MSR is supported if 1. 391 | bool ia32_tsc_adjust(); 392 | /// Supports Intel® Software Guard Extensions (Intel® SGX Extensions) if 1. 393 | bool sgx(); 394 | /// Bit Manipulation Instruction Set 1 395 | bool bmi1(); 396 | /// Transactional Synchronization Extensions 397 | bool hle(); 398 | /// Advanced Vector Extensions 2 399 | bool avx2(); 400 | /// x87 FPU Data Pointer updated only on x87 exceptions if 1. 401 | bool fdp_excptn_only(); 402 | /// Supports Supervisor-Mode Execution Prevention if 1. 403 | bool smep(); 404 | /// Bit Manipulation Instruction Set 2 405 | bool bmi2(); 406 | /// Enhanced REP MOVSB/STOSB if 1. 407 | bool supports(); 408 | /// If 1, supports INVPCID instruction for system software that manages process-context identifiers. 409 | bool invpcid(); 410 | /// Transactional Synchronization Extensions 411 | bool rtm(); 412 | /// Supports Intel® Resource Director Technology (Intel® RDT) Monitoring capability if 1. 413 | bool rdt_m(); 414 | ///FPU CS and FPU DS values if 1. 415 | bool deprecates(); 416 | /// Supports Intel® Memory Protection Extensions if 1. 417 | bool mpx(); 418 | /// Supports Intel® Resource Director Technology (Intel® RDT) Allocation capability if 1. 419 | bool rdt_a(); 420 | /// AVX-512 Foundation 421 | bool avx512f(); 422 | /// AVX-512 Doubleword and Quadword Instructions 423 | bool avx512dq(); 424 | /// RDSEED instruction 425 | bool rdseed(); 426 | /// Intel ADX (Multi-Precision Add-Carry Instruction Extensions) 427 | bool adx(); 428 | /// Supports Supervisor-Mode Access Prevention (and the CLAC/STAC instructions) if 1. 429 | bool smap(); 430 | /// AVX-512 Integer Fused Multiply-Add Instructions 431 | bool avx512ifma(); 432 | /// PCOMMIT instruction 433 | bool pcommit(); 434 | /// CLFLUSHOPT instruction 435 | bool clflushopt(); 436 | /// CLWB instruction 437 | bool clwb(); 438 | /// Intel Processor Trace. 439 | bool intel_pt(); 440 | /// AVX-512 Prefetch Instructions 441 | bool avx512pf(); 442 | /// AVX-512 Exponential and Reciprocal Instructions 443 | bool avx512er(); 444 | /// AVX-512 Conflict Detection Instructions 445 | bool avx512cd(); 446 | /// supports Intel® Secure Hash Algorithm Extens 447 | bool sha(); 448 | /// AVX-512 Byte and Word Instructions 449 | bool avx512bw(); 450 | /// AVX-512 Vector Length Extensions 451 | bool avx512vl(); 452 | /// PREFETCHWT1 instruction 453 | bool prefetchwt1(); 454 | /// AVX-512 Vector Bit Manipulation Instructions 455 | bool avx512vbmi(); 456 | /// Supports user-mode instruction prevention if 1 457 | bool umip(); 458 | /// Memory Protection Keys for User-mode pages 459 | bool pku(); 460 | /// If 1, OS has set CR4.PKE to enable protection keys (and the RDPKRU/WRPKRU instructions). 461 | bool ospke(); 462 | /// 463 | bool waitpkg(); 464 | /// 465 | bool avx512vbmi2(); 466 | /// Supports CET shadow stack features if 1. 467 | bool cet_ss(); 468 | /// 469 | bool gfni(); 470 | /// 471 | bool vaes(); 472 | /// 473 | bool vpclmulqdq(); 474 | /// 475 | bool avx512vnni(); 476 | /// 477 | bool avx512bitalg(); 478 | /// 479 | bool avx512vpopcntdq(); 480 | /// The value of MAWAU used by the BNDLDX and BNDSTX instructions in 64-bit mode. 481 | uint mawau(); 482 | /// RDPID and IA32_TSC_AUX are available if 1. 483 | bool rdpid(); 484 | /// Supports cache line demote if 1. 485 | bool cldemote(); 486 | /// Supports MOVDIRI if 1. 487 | bool movdiri(); 488 | /// Supports MOVDIR64B if 1. 489 | bool movdir64b(); 490 | /// Supports SGX Launch Configuration if 1. 491 | bool sgx_lc(); 492 | } 493 | else 494 | { 495 | mixin(bitfields!( 496 | bool, "fsgsbase", 1, /// Supports RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE if 1. 497 | bool, "ia32_tsc_adjust", 1, ///MSR is supported if 1. 498 | bool, "sgx", 1, /// Supports Intel® Software Guard Extensions (Intel® SGX Extensions) if 1. 499 | bool, "bmi1", 1, /// Bit Manipulation Instruction Set 1 500 | bool, "hle", 1, /// Transactional Synchronization Extensions 501 | bool, "avx2", 1, /// Advanced Vector Extensions 2 502 | bool, "fdp_excptn_only", 1, /// x87 FPU Data Pointer updated only on x87 exceptions if 1. 503 | bool, "smep", 1, /// Supports Supervisor-Mode Execution Prevention if 1. 504 | bool, "bmi2", 1, /// Bit Manipulation Instruction Set 2 505 | bool, "supports", 1, /// Enhanced REP MOVSB/STOSB if 1. 506 | bool, "invpcid", 1, /// If 1, supports INVPCID instruction for system software that manages process-context identifiers. 507 | bool, "rtm", 1, /// Transactional Synchronization Extensions 508 | bool, "rdt_m", 1, /// Supports Intel® Resource Director Technology (Intel® RDT) Monitoring capability if 1. 509 | bool, "deprecates", 1, ///FPU CS and FPU DS values if 1. 510 | bool, "mpx", 1, /// Supports Intel® Memory Protection Extensions if 1. 511 | bool, "rdt_a", 1, /// Supports Intel® Resource Director Technology (Intel® RDT) Allocation capability if 1. 512 | bool, "avx512f", 1, /// AVX-512 Foundation 513 | bool, "avx512dq", 1, /// AVX-512 Doubleword and Quadword Instructions 514 | bool, "rdseed", 1, /// RDSEED instruction 515 | bool, "adx", 1, /// Intel ADX (Multi-Precision Add-Carry Instruction Extensions) 516 | bool, "smap", 1, /// Supports Supervisor-Mode Access Prevention (and the CLAC/STAC instructions) if 1. 517 | bool, "avx512ifma", 1, /// AVX-512 Integer Fused Multiply-Add Instructions 518 | bool, "pcommit", 1, /// PCOMMIT instruction 519 | bool, "clflushopt", 1, /// CLFLUSHOPT instruction 520 | bool, "clwb", 1, /// CLWB instruction 521 | bool, "intel_pt", 1, /// Intel Processor Trace. 522 | bool, "avx512pf", 1, /// AVX-512 Prefetch Instructions 523 | bool, "avx512er", 1, /// AVX-512 Exponential and Reciprocal Instructions 524 | bool, "avx512cd", 1, /// AVX-512 Conflict Detection Instructions 525 | bool, "sha", 1, /// supports Intel® Secure Hash Algorithm Extens 526 | bool, "avx512bw", 1, /// AVX-512 Byte and Word Instructions 527 | bool, "avx512vl", 1, /// AVX-512 Vector Length Extensions 528 | )); 529 | mixin(bitfields!( 530 | bool, "prefetchwt1", 1, /// PREFETCHWT1 instruction 531 | bool, "avx512vbmi", 1, /// AVX-512 Vector Bit Manipulation Instructions 532 | bool, "umip", 1, /// Supports user-mode instruction prevention if 1 533 | bool, "pku", 1, /// Memory Protection Keys for User-mode pages 534 | bool, "ospke", 1, // If 1, OS has set CR4.PKE to enable protection keys (and the RDPKRU/WRPKRU instructions). 535 | bool, "waitpkg", 1, /// 536 | bool, "avx512vbmi2", 1, /// 537 | bool, "cet_ss", 1, /// Supports CET shadow stack features if 1. 538 | bool, "gfni", 1, /// 539 | bool, "vaes", 1, /// 540 | bool, "vpclmulqdq", 1, /// 541 | bool, "avx512vnni", 1, /// 542 | bool, "avx512bitalg", 1, /// 543 | bool, "", 1, 544 | bool, "avx512vpopcntdq", 1, /// 545 | uint, "", 16 - 15 + 1, 546 | uint, "mawau", 21 - 17 + 1, /// The value of MAWAU used by the BNDLDX and BNDSTX instructions in 64-bit mode. 547 | bool, "rdpid", 1, /// RDPID and IA32_TSC_AUX are available if 1. 548 | uint, "", 24 - 23 + 1, 549 | bool, "cldemote", 1, /// Supports cache line demote if 1. 550 | bool, "", 1, 551 | bool, "movdiri", 1, /// Supports MOVDIRI if 1. 552 | bool, "movdir64b", 1, /// Supports MOVDIR64B if 1. 553 | bool, "", 1, 554 | bool, "sgx_lc", 1, /// Supports SGX Launch Configuration if 1. 555 | bool, "", 1, 556 | )); 557 | } 558 | } 559 | } 560 | 561 | 562 | 563 | /// x86 CPU information 564 | struct CpuInfo 565 | { 566 | /// EAX 567 | uint a; 568 | /// EBX 569 | uint b; 570 | /// ECX 571 | uint c; 572 | /// EDX 573 | uint d; 574 | } 575 | 576 | /++ 577 | Params: 578 | eax = function id 579 | ecx = sub-function id 580 | +/ 581 | pure nothrow @nogc @trusted 582 | CpuInfo _cpuid()(uint eax, uint ecx = 0) 583 | { 584 | uint a = void; 585 | uint b = void; 586 | uint c = void; 587 | uint d = void; 588 | version(LDC) 589 | { 590 | pragma(inline, true); 591 | auto asmt = __asmtuple! 592 | (uint, uint, uint, uint) ( 593 | "cpuid", 594 | "={eax},={ebx},={ecx},={edx},{eax},{ecx}", 595 | eax, ecx); 596 | a = asmt.v[0]; 597 | b = asmt.v[1]; 598 | c = asmt.v[2]; 599 | d = asmt.v[3]; 600 | } 601 | else 602 | version(GNU) 603 | asm pure nothrow @nogc 604 | { 605 | "cpuid" : 606 | "=a" a, 607 | "=b" b, 608 | "=c" c, 609 | "=d" d, 610 | : "a" eax, "c" ecx; 611 | } 612 | else 613 | version(InlineAsm_X86_Any) 614 | asm pure nothrow @nogc 615 | { 616 | mov EAX, eax; 617 | mov ECX, ecx; 618 | cpuid; 619 | mov a, EAX; 620 | mov b, EBX; 621 | mov c, ECX; 622 | mov d, EDX; 623 | } 624 | else static assert(0); 625 | return CpuInfo(a, b, c, d); 626 | } 627 | 628 | nothrow @nogc @property: 629 | 630 | align(4) 631 | private __gshared immutable char[12][22] _vendors = 632 | [ 633 | "GenuineIntel", 634 | "AuthenticAMD", 635 | 636 | " SiS SiS SiS", 637 | " UMC UMC UMC", 638 | " VIA VIA VIA", 639 | "AMDisbetter!", 640 | "CentaurHauls", 641 | "CyrixInstead", 642 | "HygonGenuine", 643 | "GenuineTMx86", 644 | "Geode by NSC", 645 | "NexGenDriven", 646 | "RiseRiseRise", 647 | "TransmetaCPU", 648 | "Vortex86 SoC", 649 | " undefined", 650 | 651 | " KVM KVM KVM", 652 | " lrpepyh vr", 653 | "Microsoft Hv", 654 | "VMwareVMware", 655 | "XenVMMXenVMM", 656 | "undefined vm", 657 | ]; 658 | 659 | /// VendorIndex name 660 | immutable(char)[12][] vendors()() 661 | { 662 | return _vendors; 663 | } 664 | 665 | /// 666 | unittest 667 | { 668 | assert(vendors[VendorIndex.intel] == "GenuineIntel"); 669 | } 670 | 671 | /// VendorIndex encoded value. 672 | VendorIndex vendorIndex()() 673 | { 674 | return _vendorId; 675 | } 676 | 677 | /// VendorIndex encoded value for virtual machine. 678 | VendorIndex virtualVendorIndex()() 679 | { 680 | return _virtualVendorId; 681 | } 682 | 683 | /// Maximum Input Value for Basic CPUID Information 684 | uint maxBasicLeaf()() 685 | { 686 | return _maxBasicLeaf; 687 | } 688 | 689 | /// Maximum Input Value for Extended CPUID Information 690 | uint maxExtendedLeaf()() 691 | { 692 | return _maxExtendedLeaf; 693 | } 694 | 695 | /// Reports the maximum input value for supported leaf 7 sub-leaves. 696 | uint max7SubLeafs()() 697 | { 698 | return leaf7Information.max7SubLeafs; 699 | } 700 | 701 | /// Encoded vendors 702 | enum VendorIndex 703 | { 704 | /// Intel 705 | intel, 706 | /// AMD 707 | amd, 708 | 709 | /// SiS 710 | sis, 711 | /// UMC 712 | umc, 713 | /// VIA 714 | via, 715 | /// early engineering samples of AMD K5 processor 716 | amd_old, 717 | /// Centaur (Including some VIA CPU) 718 | centaur, 719 | /// Cyrix 720 | cyrix, 721 | /// Hygon CPU (AMD like) 722 | hygon, 723 | /// Transmeta 724 | transmeta, 725 | /// National Semiconductor 726 | nsc, 727 | /// NexGen 728 | nexgen, 729 | /// Rise 730 | rise, 731 | /// Transmeta 732 | transmeta_old, 733 | /// Vortex 734 | vortex, 735 | 736 | /// undefined 737 | undefined, 738 | 739 | 740 | /// KVM 741 | kvm, 742 | /// Parallels 743 | parallels, 744 | /// Microsoft Hyper-V or Windows Virtual PC 745 | microsoft, 746 | /// VMware 747 | vmware, 748 | /// Xen HVM 749 | xen, 750 | 751 | /// undefined virtual machine 752 | undefinedvm, 753 | } 754 | 755 | /++ 756 | Brand, e.g. `Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz`. 757 | Returns: brand length 758 | Params: brand = fixed length string to initiate 759 | +/ 760 | size_t brand()(ref char[48] brand) 761 | { 762 | static if (__VERSION__ >= 2068) 763 | pragma(inline, false); 764 | CpuInfo info = void; 765 | info = _cpuid(0 + 2 ^ 0x8000_0000); 766 | (cast(uint[12])brand)[0 * 4 + 0] = info.a; 767 | (cast(uint[12])brand)[0 * 4 + 1] = info.b; 768 | (cast(uint[12])brand)[0 * 4 + 2] = info.c; 769 | (cast(uint[12])brand)[0 * 4 + 3] = info.d; 770 | info = _cpuid(1 + 2 ^ 0x8000_0000); 771 | (cast(uint[12])brand)[1 * 4 + 0] = info.a; 772 | (cast(uint[12])brand)[1 * 4 + 1] = info.b; 773 | (cast(uint[12])brand)[1 * 4 + 2] = info.c; 774 | (cast(uint[12])brand)[1 * 4 + 3] = info.d; 775 | info = _cpuid(2 + 2 ^ 0x8000_0000); 776 | (cast(uint[12])brand)[2 * 4 + 0] = info.a; 777 | (cast(uint[12])brand)[2 * 4 + 1] = info.b; 778 | (cast(uint[12])brand)[2 * 4 + 2] = info.c; 779 | (cast(uint[12])brand)[2 * 4 + 3] = info.d; 780 | 781 | size_t i = brand.length; 782 | while(brand[i - 1] == '\0') 783 | { 784 | --i; 785 | if(i == 0) 786 | break; 787 | } 788 | return i; 789 | } 790 | 791 | /++ 792 | Vendor, e.g. `GenuineIntel`. 793 | +/ 794 | string vendor()() 795 | { 796 | return vendors[_vendorId]; 797 | } 798 | 799 | /++ 800 | Virtual vendor, e.g. `GenuineIntel` or `VMwareVMware`. 801 | +/ 802 | string virtualVendor()() 803 | { 804 | return vendors[_virtualVendorId]; 805 | } 806 | 807 | /++ 808 | Brand Index 809 | +/ 810 | ubyte brandIndex()() { return leaf1Information.brandIndex; } 811 | /++ 812 | CLFLUSH line size 813 | Note: Value ∗ 8 = cache line size in bytes; used also by CLFLUSHOPT. 814 | +/ 815 | ubyte clflushLineSize()() { return leaf1Information.clflushLineSize; } 816 | /++ 817 | Maximum number of addressable IDs for logical processors in this physical package. 818 | +/ 819 | ubyte maxLogicalProcessors()() { return leaf1Information.maxLogicalProcessors; } 820 | /++ 821 | Initial APIC ID 822 | +/ 823 | ubyte initialAPIC()() { return leaf1Information.initialAPIC; } 824 | /// Stepping ID 825 | uint stepping()() { return leaf1Information.stepping; } 826 | /// Model 827 | uint model()() { return leaf1Information.model; } 828 | /// Family ID 829 | uint family()() { return leaf1Information.family; } 830 | /// Processor Type, Specification: Intel 831 | uint type()() { return leaf1Information.type; } 832 | /// Extended Model ID 833 | uint extendedModel()() { return leaf1Information.extendedModel; } 834 | /// Extended Family ID 835 | uint extendedFamily()() { return leaf1Information.extendedFamily; } 836 | /// SSE3 Extensions 837 | bool sse3()() { return leaf1Information.sse3; } 838 | /// Carryless Multiplication 839 | bool pclmulqdq()() { return leaf1Information.pclmulqdq; } 840 | /// 64-bit DS Area 841 | bool dtes64()() { return leaf1Information.dtes64; } 842 | /// MONITOR/MWAIT 843 | bool monitor()() { return leaf1Information.monitor; } 844 | /// CPL Qualified Debug Store 845 | bool ds_cpl()() { return leaf1Information.ds_cpl; } 846 | /// Virtual Machine Extensions 847 | bool vmx()() { return leaf1Information.vmx; } 848 | /// Safer Mode Extensions 849 | bool smx()() { return leaf1Information.smx; } 850 | /// Enhanced Intel SpeedStep® Technology 851 | bool eist()() { return leaf1Information.eist; } 852 | /// Thermal Monitor 2 853 | bool therm_monitor2()() { return leaf1Information.therm_monitor2; } 854 | /// SSSE3 Extensions 855 | bool ssse3()() { return leaf1Information.ssse3; } 856 | /// L1 Context ID 857 | bool cnxt_id()() { return leaf1Information.cnxt_id; } 858 | /// 859 | bool sdbg()() { return leaf1Information.sdbg; } 860 | /// Fused Multiply Add 861 | bool fma()() { return leaf1Information.fma; } 862 | /// 863 | bool cmpxchg16b()() { return leaf1Information.cmpxchg16b; } 864 | /// TPR Update Control 865 | bool xtpr()() { return leaf1Information.xtpr; } 866 | /// Perf/Debug Capability MSR xTPR Update Control 867 | bool pdcm()() { return leaf1Information.pdcm; } 868 | /// Process-context Identifiers 869 | bool pcid()() { return leaf1Information.pcid; } 870 | /// Direct Cache Access 871 | bool dca()() { return leaf1Information.dca; } 872 | /// SSE4.1 873 | bool sse41()() { return leaf1Information.sse41; } 874 | /// SSE4.2 875 | bool sse42()() { return leaf1Information.sse42; } 876 | /// 877 | bool x2apic()() { return leaf1Information.x2apic; } 878 | /// 879 | bool movbe()() { return leaf1Information.movbe; } 880 | /// 881 | bool popcnt()() { return leaf1Information.popcnt; } 882 | /// 883 | bool tsc_deadline()() { return leaf1Information.tsc_deadline; } 884 | /// 885 | bool aes()() { return leaf1Information.aes; } 886 | /// 887 | bool xsave()() { return leaf1Information.xsave; } 888 | /// 889 | bool osxsave()() { return leaf1Information.osxsave; } 890 | /// 891 | bool avx()() { return leaf1Information.avx; } 892 | /// 893 | bool f16c()() { return leaf1Information.f16c; } 894 | /// 895 | bool rdrand()() { return leaf1Information.rdrand; } 896 | /// Virtual machine 897 | bool virtual()() { return leaf1Information.virtual; } 898 | /// x87 FPU on Chip 899 | bool fpu()() { return leaf1Information.fpu; } 900 | /// Virtual-8086 Mode Enhancement 901 | bool vme()() { return leaf1Information.vme; } 902 | /// Debugging Extensions 903 | bool de()() { return leaf1Information.de; } 904 | /// Page Size Extensions 905 | bool pse()() { return leaf1Information.pse; } 906 | /// Time Stamp Counter 907 | bool tsc()() { return leaf1Information.tsc; } 908 | /// RDMSR and WRMSR Support 909 | bool msr()() { return leaf1Information.msr; } 910 | /// Physical Address Extensions 911 | bool pae()() { return leaf1Information.pae; } 912 | /// Machine Check Exception 913 | bool mce()() { return leaf1Information.mce; } 914 | /// CMPXCHG8B Inst. 915 | bool cx8()() { return leaf1Information.cx8; } 916 | /// APIC on Chip 917 | bool apic()() { return leaf1Information.apic; } 918 | /// SYSENTER and SYSEXIT 919 | bool sep()() { return leaf1Information.sep; } 920 | /// Memory Type Range Registers 921 | bool mtrr()() { return leaf1Information.mtrr; } 922 | /// PTE Global Bit 923 | bool pge()() { return leaf1Information.pge; } 924 | /// Machine Check Architecture 925 | bool mca()() { return leaf1Information.mca; } 926 | /// Conditional Move/Compare Instruction 927 | bool cmov()() { return leaf1Information.cmov; } 928 | /// Page Attribute Table 929 | bool pat()() { return leaf1Information.pat; } 930 | /// Page Size Extension 931 | bool pse36()() { return leaf1Information.pse36; } 932 | /// Processor Serial Number 933 | bool psn()() { return leaf1Information.psn; } 934 | /// CLFLUSH instruction 935 | bool clfsh()() { return leaf1Information.clfsh; } 936 | /// Debug Store 937 | bool ds()() { return leaf1Information.ds; } 938 | /// Thermal Monitor and Clock Ctrl 939 | bool acpi()() { return leaf1Information.acpi; } 940 | /// MMX Technology 941 | bool mmx()() { return leaf1Information.mmx; } 942 | /// FXSAVE/FXRSTOR 943 | bool fxsr()() { return leaf1Information.fxsr; } 944 | /// SSE Extensions 945 | bool sse()() { return leaf1Information.sse; } 946 | /// SSE2 Extensions 947 | bool sse2()() { return leaf1Information.sse2; } 948 | /// Self Snoop 949 | bool self_snoop()() { return leaf1Information.self_snoop; } 950 | /// Multi-threading 951 | bool htt()() { return leaf1Information.htt; } 952 | /// Therm. Monitor 953 | bool therm_monitor()() { return leaf1Information.therm_monitor; } 954 | /// Pend. Brk. EN. 955 | bool pbe()() { return leaf1Information.pbe; } 956 | 957 | // EXTENDED 7 958 | 959 | /// Supports RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE if 1. 960 | bool fsgsbase()() { return leaf7Information.fsgsbase; } 961 | ///MSR is supported if 1. 962 | bool ia32_tsc_adjust()() { return leaf7Information.ia32_tsc_adjust; } 963 | /// Supports Intel® Software Guard Extensions (Intel® SGX Extensions) if 1. 964 | bool sgx()() { return leaf7Information.sgx; } 965 | /// Bit Manipulation Instruction Set 1 966 | bool bmi1()() { return leaf7Information.bmi1; } 967 | /// Transactional Synchronization Extensions 968 | bool hle()() { return leaf7Information.hle; } 969 | /// Advanced Vector Extensions 2 970 | bool avx2()() { return leaf7Information.avx2; } 971 | /// x87 FPU Data Pointer updated only on x87 exceptions if 1. 972 | bool fdp_excptn_only()() { return leaf7Information.fdp_excptn_only; } 973 | /// Supports Supervisor-Mode Execution Prevention if 1. 974 | bool smep()() { return leaf7Information.smep; } 975 | /// Bit Manipulation Instruction Set 2 976 | bool bmi2()() { return leaf7Information.bmi2; } 977 | /// Enhanced REP MOVSB/STOSB if 1. 978 | bool supports()() { return leaf7Information.supports; } 979 | /// If 1, supports INVPCID instruction for system software that manages process-context identifiers. 980 | bool invpcid()() { return leaf7Information.invpcid; } 981 | /// Transactional Synchronization Extensions 982 | bool rtm()() { return leaf7Information.rtm; } 983 | /// Supports Intel® Resource Director Technology (Intel® RDT) Monitoring capability if 1. 984 | bool rdt_m()() { return leaf7Information.rdt_m; } 985 | ///FPU CS and FPU DS values if 1. 986 | bool deprecates()() { return leaf7Information.deprecates; } 987 | /// Supports Intel® Memory Protection Extensions if 1. 988 | bool mpx()() { return leaf7Information.mpx; } 989 | /// Supports Intel® Resource Director Technology (Intel® RDT) Allocation capability if 1. 990 | bool rdt_a()() { return leaf7Information.rdt_a; } 991 | /// AVX-512 Foundation 992 | bool avx512f()() { return leaf7Information.avx512f; } 993 | /// AVX-512 Doubleword and Quadword Instructions 994 | bool avx512dq()() { return leaf7Information.avx512dq; } 995 | /// RDSEED instruction 996 | bool rdseed()() { return leaf7Information.rdseed; } 997 | /// Intel ADX (Multi-Precision Add-Carry Instruction Extensions) 998 | bool adx()() { return leaf7Information.adx; } 999 | /// Supports Supervisor-Mode Access Prevention (and the CLAC/STAC instructions) if 1. 1000 | bool smap()() { return leaf7Information.smap; } 1001 | /// AVX-512 Integer Fused Multiply-Add Instructions 1002 | bool avx512ifma()() { return leaf7Information.avx512ifma; } 1003 | /// PCOMMIT instruction 1004 | bool pcommit()() { return leaf7Information.pcommit; } 1005 | /// CLFLUSHOPT instruction 1006 | bool clflushopt()() { return leaf7Information.clflushopt; } 1007 | /// CLWB instruction 1008 | bool clwb()() { return leaf7Information.clwb; } 1009 | /// Intel Processor Trace. 1010 | bool intel_pt()() { return leaf7Information.intel_pt; } 1011 | /// AVX-512 Prefetch Instructions 1012 | bool avx512pf()() { return leaf7Information.avx512pf; } 1013 | /// AVX-512 Exponential and Reciprocal Instructions 1014 | bool avx512er()() { return leaf7Information.avx512er; } 1015 | /// AVX-512 Conflict Detection Instructions 1016 | bool avx512cd()() { return leaf7Information.avx512cd; } 1017 | /// supports Intel® Secure Hash Algorithm Extens 1018 | bool sha()() { return leaf7Information.sha; } 1019 | /// AVX-512 Byte and Word Instructions 1020 | bool avx512bw()() { return leaf7Information.avx512bw; } 1021 | /// AVX-512 Vector Length Extensions 1022 | bool avx512vl()() { return leaf7Information.avx512vl; } 1023 | /// PREFETCHWT1 instruction 1024 | bool prefetchwt1()() { return leaf7Information.prefetchwt1; } 1025 | /// AVX-512 Vector Bit Manipulation Instructions 1026 | bool avx512vbmi()() { return leaf7Information.avx512vbmi; } 1027 | /// Supports user-mode instruction prevention if 1 1028 | bool umip()() { return leaf7Information.umip; } 1029 | /// Memory Protection Keys for User-mode pages 1030 | bool pku()() { return leaf7Information.pku; } 1031 | /// If 1, OS has set CR4.PKE to enable protection keys (and the RDPKRU/WRPKRU instructions). 1032 | bool ospke()() { return leaf7Information.ospke; } 1033 | /// 1034 | bool waitpkg()() { return leaf7Information.waitpkg; } 1035 | /// 1036 | bool avx512vbmi2()() { return leaf7Information.avx512vbmi2; } 1037 | /// Supports CET shadow stack features if 1. 1038 | bool cet_ss()() { return leaf7Information.cet_ss; } 1039 | /// 1040 | bool gfni()() { return leaf7Information.gfni; } 1041 | /// 1042 | bool vaes()() { return leaf7Information.vaes; } 1043 | /// 1044 | bool vpclmulqdq()() { return leaf7Information.vpclmulqdq; } 1045 | /// 1046 | bool avx512vnni()() { return leaf7Information.avx512vnni; } 1047 | /// 1048 | bool avx512bitalg()() { return leaf7Information.avx512bitalg; } 1049 | /// 1050 | bool avx512vpopcntdq()() { return leaf7Information.avx512vpopcntdq; } 1051 | /// The value of MAWAU used by the BNDLDX and BNDSTX instructions in 64-bit mode. 1052 | uint mawau()() { return leaf7Information.mawau; } 1053 | /// RDPID and IA32_TSC_AUX are available if 1. 1054 | bool rdpid(); 1055 | /// Supports cache line demote if 1. 1056 | bool cldemote()() { return leaf7Information.cldemote; } 1057 | /// Supports MOVDIRI if 1. 1058 | bool movdiri()() { return leaf7Information.movdiri; } 1059 | /// Supports MOVDIR64B if 1. 1060 | bool movdir64b()() { return leaf7Information.movdir64b; } 1061 | /// Supports SGX Launch Configuration if 1. 1062 | bool sgx_lc()() { return leaf7Information.sgx_lc; } 1063 | -------------------------------------------------------------------------------- /subprojects/mir-core.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory=mir-core 3 | url=https://github.com/libmir/mir-core.git 4 | revision=head 5 | --------------------------------------------------------------------------------