| #include <stdio.h> |
| #include <stdint.h> |
| #include <inttypes.h> |
| #include <string.h> |
| |
| #include <x86/cpuid.h> |
| |
| static void print_cpuid(struct cpuid_regs regs, uint32_t eax) { |
| printf("CPUID %08"PRIX32": %08"PRIX32"-%08"PRIX32"-%08"PRIX32"-%08"PRIX32"\n", |
| eax, regs.eax, regs.ebx, regs.ecx, regs.edx); |
| } |
| |
| static void print_cpuidex(struct cpuid_regs regs, uint32_t eax, uint32_t ecx) { |
| printf("CPUID %08"PRIX32": %08"PRIX32"-%08"PRIX32"-%08"PRIX32"-%08"PRIX32" [SL %02"PRIX32"]\n", |
| eax, regs.eax, regs.ebx, regs.ecx, regs.edx, ecx); |
| } |
| |
| static void print_cpuid_vendor(struct cpuid_regs regs, uint32_t eax) { |
| if (regs.ebx | regs.ecx | regs.edx) { |
| char vendor_id[12]; |
| memcpy(&vendor_id[0], ®s.ebx, sizeof(regs.ebx)); |
| memcpy(&vendor_id[4], ®s.edx, sizeof(regs.edx)); |
| memcpy(&vendor_id[8], ®s.ecx, sizeof(regs.ecx)); |
| printf("CPUID %08"PRIX32": %08"PRIX32"-%08"PRIX32"-%08"PRIX32"-%08"PRIX32" [%.12s]\n", |
| eax, regs.eax, regs.ebx, regs.ecx, regs.edx, vendor_id); |
| } else { |
| print_cpuid(regs, eax); |
| } |
| } |
| |
| static void print_cpuid_brand_string(struct cpuid_regs regs, uint32_t eax) { |
| char brand_string[16]; |
| memcpy(&brand_string[0], ®s.eax, sizeof(regs.eax)); |
| memcpy(&brand_string[4], ®s.ebx, sizeof(regs.ebx)); |
| memcpy(&brand_string[8], ®s.ecx, sizeof(regs.ecx)); |
| memcpy(&brand_string[12], ®s.edx, sizeof(regs.edx)); |
| printf("CPUID %08"PRIX32": %08"PRIX32"-%08"PRIX32"-%08"PRIX32"-%08"PRIX32" [%.16s]\n", |
| eax, regs.eax, regs.ebx, regs.ecx, regs.edx, brand_string); |
| } |
| |
| int main(int argc, char** argv) { |
| const uint32_t max_base_index = cpuid(0).eax; |
| uint32_t max_structured_index = 0, max_trace_index = 0, max_socid_index = 0; |
| bool has_sgx = false; |
| for (uint32_t eax = 0; eax <= max_base_index; eax++) { |
| switch (eax) { |
| case UINT32_C(0x00000000): |
| print_cpuid_vendor(cpuid(eax), eax); |
| break; |
| case UINT32_C(0x00000004): |
| for (uint32_t ecx = 0; ; ecx++) { |
| const struct cpuid_regs regs = cpuidex(eax, ecx); |
| if ((regs.eax & UINT32_C(0x1F)) == 0) { |
| break; |
| } |
| print_cpuidex(regs, eax, ecx); |
| } |
| break; |
| case UINT32_C(0x00000007): |
| for (uint32_t ecx = 0; ecx <= max_structured_index; ecx++) { |
| const struct cpuid_regs regs = cpuidex(eax, ecx); |
| if (ecx == 0) { |
| max_structured_index = regs.eax; |
| has_sgx = !!(regs.ebx & UINT32_C(0x00000004)); |
| } |
| print_cpuidex(regs, eax, ecx); |
| } |
| break; |
| case UINT32_C(0x0000000B): |
| for (uint32_t ecx = 0; ; ecx++) { |
| const struct cpuid_regs regs = cpuidex(eax, ecx); |
| if ((regs.ecx & UINT32_C(0x0000FF00)) == 0) { |
| break; |
| } |
| print_cpuidex(regs, eax, ecx); |
| } |
| break; |
| case UINT32_C(0x00000012): |
| if (has_sgx) { |
| for (uint32_t ecx = 0; ; ecx++) { |
| const struct cpuid_regs regs = cpuidex(eax, ecx); |
| if (ecx >= 2 && (regs.eax & UINT32_C(0x0000000F)) == 0) { |
| break; |
| } |
| print_cpuidex(regs, eax, ecx); |
| } |
| } |
| break; |
| case UINT32_C(0x00000014): |
| for (uint32_t ecx = 0; ecx <= max_trace_index; ecx++) { |
| const struct cpuid_regs regs = cpuidex(eax, ecx); |
| if (ecx == 0) { |
| max_trace_index = regs.eax; |
| } |
| print_cpuidex(regs, eax, ecx); |
| } |
| break; |
| case UINT32_C(0x00000017): |
| for (uint32_t ecx = 0; ecx <= max_socid_index; ecx++) { |
| const struct cpuid_regs regs = cpuidex(eax, ecx); |
| if (ecx == 0) { |
| max_socid_index = regs.eax; |
| } |
| print_cpuidex(regs, eax, ecx); |
| } |
| break; |
| default: |
| print_cpuid(cpuidex(eax, 0), eax); |
| break; |
| } |
| } |
| |
| const uint32_t max_extended_index = cpuid(UINT32_C(0x80000000)).eax; |
| for (uint32_t eax = UINT32_C(0x80000000); eax <= max_extended_index; eax++) { |
| switch (eax) { |
| case UINT32_C(0x80000000): |
| print_cpuid_vendor(cpuid(eax), eax); |
| break; |
| case UINT32_C(0x80000002): |
| case UINT32_C(0x80000003): |
| case UINT32_C(0x80000004): |
| print_cpuid_brand_string(cpuid(eax), eax); |
| break; |
| default: |
| print_cpuid(cpuidex(eax, 0), eax); |
| } |
| } |
| } |