2 * Copyright (c) 2013 Ahmed Samy <f.fallen45@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * This file has been written with some help from wikipedia:
23 * http://en.wikipedia.org/wiki/CPUID
31 CPU_PROC_BRAND_STRING_INTERNAL0 = 0x80000003,
32 CPU_PROC_BRAND_STRING_INTERNAL1 = 0x80000004
36 static void ___cpuid(cpuid_t info, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
39 "xchg %%ebx, %%edi\n\t" /* 32bit PIC: Don't clobber ebx. */
41 "xchg %%ebx, %%edi\n\t"
42 : "=a"(*eax), "=D"(*ebx), "=c"(*ecx), "=d"(*edx)
49 static void ___cpuid(cpuid_t info, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
51 uint32_t registers[4];
52 __cpuid(registers, info);
61 int highest_ext_func_supported(void)
69 : "a" (CPU_HIGHEST_EXTENDED_FUNCTION_SUPPORTED)
76 int cpuid_test_feature(cpuid_t feature)
78 if (feature > CPU_VIRT_PHYS_ADDR_SIZES || feature < CPU_EXTENDED_PROC_INFO_FEATURE_BITS)
81 return (feature <= highest_ext_func_supported());
84 int cpuid_has_feature(cpufeature_t feature)
86 uint32_t eax, ebx, ecx, edx;
88 ___cpuid(CPU_PROCINFO_AND_FEATUREBITS, &eax, &ebx, &ecx, &edx);
93 return (edx & ((int)feature)) != 0;
100 return (ecx & ((int)feature)) != 0;
106 int cpuid_has_ext_feature(cpuextfeature_t extfeature)
108 uint32_t eax, ebx, ecx, edx;
109 if (!cpuid_test_feature(CPU_EXTENDED_PROC_INFO_FEATURE_BITS))
112 ___cpuid(CPU_EXTENDED_PROC_INFO_FEATURE_BITS, &eax, &ebx, &ecx, &edx);
113 switch (extfeature) {
115 return (edx & ((int)extfeature)) != 0;
119 return (ecx & ((int)extfeature)) != 0;
125 static const char *cpuids[] = {
144 cputype_t get_cpu_type(void)
146 static cputype_t cputype;
147 if (cputype == CT_NONE) {
154 ___cpuid(CPU_VENDORID, &i, &u.bufu32[0], &u.bufu32[2], &u.bufu32[1]);
157 for (i = 0; i < sizeof(cpuids) / sizeof(cpuids[0]); ++i) {
158 if (strncmp(cpuids[i], u.buf, 12) == 0) {
159 cputype = (cputype_t)i;
168 const char *get_cpu_type_string(const cputype_t cputype)
170 return cpuids[(int)cputype];
173 void cpuid(cpuid_t info, void *buf)
175 /* Sanity checks, make sure we're not trying to do something
176 * invalid or we are trying to get information that isn't supported
178 if (info > CPU_VIRT_PHYS_ADDR_SIZES || (info > CPU_HIGHEST_EXTENDED_FUNCTION_SUPPORTED
179 && !cpuid_test_feature(info)))
182 uint32_t *ubuf = buf;
183 if (info == CPU_PROC_BRAND_STRING) {
184 ___cpuid(CPU_PROC_BRAND_STRING, &ubuf[0], &ubuf[1], &ubuf[2], &ubuf[3]);
185 ___cpuid(CPU_PROC_BRAND_STRING_INTERNAL0, &ubuf[4], &ubuf[5], &ubuf[6], &ubuf[7]);
186 ___cpuid(CPU_PROC_BRAND_STRING_INTERNAL1, &ubuf[8], &ubuf[9], &ubuf[10], &ubuf[11]);
188 } else if (info == CPU_HIGHEST_EXTENDED_FUNCTION_SUPPORTED) {
189 *ubuf = highest_ext_func_supported();
193 uint32_t eax, ebx, ecx, edx;
194 ___cpuid(info, &eax, &ebx, &ecx, &edx);
202 case CPU_PROCINFO_AND_FEATUREBITS:
203 ubuf[0] = eax; /* The so called "signature" of the CPU. */
204 ubuf[1] = edx; /* Feature flags #1. */
205 ubuf[2] = ecx; /* Feature flags #2. */
206 ubuf[3] = ebx; /* Additional feature information. */
208 case CPU_CACHE_AND_TLBD_INFO:
214 case CPU_EXTENDED_PROC_INFO_FEATURE_BITS:
218 case CPU_L1_CACHE_AND_TLB_IDS:
220 case CPU_EXTENDED_L2_CACHE_FEATURES:
223 case CPU_ADV_POWER_MGT_INFO:
226 case CPU_VIRT_PHYS_ADDR_SIZES: