@@ -18,18 +18,22 @@ static CPUInfo::CpuGeneration currentGeneration = CPUInfo::CpuGeneration::Unknow
1818static uint32_t currentFamily = 0 ;
1919static uint32_t currentModel = 0 ;
2020static uint32_t currentStepping = 0 ;
21+ static uint32_t currentMaxLevel = 0 ;
22+ static uint32_t currentMaxLevelExt = 0x80000000 ;
2123
2224void CPUInfo::loadCpuInformation () {
2325 // Start with detecting CPU vendor
2426 uint32_t b = 0 , c = 0 , d = 0 ;
25- getCpuid (0 , 0 , nullptr , &b, &c, &d);
27+ getCpuid (0 , 0 , ¤tMaxLevel , &b, &c, &d);
2628 if (b == signature_INTEL_ebx && c == signature_INTEL_ecx && d == signature_INTEL_edx)
2729 currentVendor = CpuVendor::Intel;
2830 else if (b == signature_AMD_ebx && c == signature_AMD_ecx && d == signature_AMD_edx)
2931 currentVendor = CpuVendor::AMD;
3032
31- // Only do extended model checking on Intel
32- if (currentVendor != CpuVendor::Intel)
33+ getCpuid (0x80000000 , 0 , ¤tMaxLevelExt);
34+
35+ // Only do extended model checking on Intel or when unsupported.
36+ if (currentVendor != CpuVendor::Intel || currentMaxLevel < 1 )
3337 return ;
3438
3539 // Detect CPU family and model
@@ -174,6 +178,7 @@ bool CPUInfo::getCpuTopology(CpuTopology &topology) {
174178 topology.logicalCount [topology.packageCount ]++;
175179 lcpu = lcpu->next_in_core ;
176180 }
181+ core = core->next_in_pkg ;
177182 }
178183
179184 topology.packageCount ++;
@@ -183,16 +188,24 @@ bool CPUInfo::getCpuTopology(CpuTopology &topology) {
183188 return true ;
184189}
185190
186- void CPUInfo::getCpuid (uint32_t no, uint32_t count, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) {
191+ bool CPUInfo::getCpuid (uint32_t no, uint32_t count, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) {
187192 uint32_t eax = 0 , ebx = 0 , ecx = 0 , edx = 0 ;
188- asm (" xchgq %%rbx, %q1\n "
189- " cpuid\n "
190- " xchgq %%rbx, %q1"
191- : " =a" (eax), " =b" (ebx), " =c" (ecx), " =d" (edx)
192- : " 0" (no), " 2" (count));
193+
194+ bool supported = (no & 0x80000000 ) ? currentMaxLevelExt >= no : currentMaxLevel >= no;
195+
196+ // At least pass zeroes on failure
197+ if (supported) {
198+ asm (" xchgq %%rbx, %q1\n "
199+ " cpuid\n "
200+ " xchgq %%rbx, %q1"
201+ : " =a" (eax), " =b" (ebx), " =c" (ecx), " =d" (edx)
202+ : " 0" (no), " 2" (count));
203+ }
193204
194205 if (a) *a = eax;
195206 if (b) *b = ebx;
196207 if (c) *c = ecx;
197208 if (d) *d = edx;
209+
210+ return supported;
198211}
0 commit comments