static void cpuid_or_from_dump(unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx, struct cpuiddump *src_cpuiddump) { if (src_cpuiddump) { cpuiddump_find_by_input(eax, ebx, ecx, edx, src_cpuiddump); } else { hwloc_x86_cpuid(eax, ebx, ecx, edx); } }
static void dump_one_cpuid(FILE *output, unsigned *regs, unsigned inregmask) { unsigned i; /* clear unused inputs */ for(i=0; i<4; i++) if (!(inregmask & (1<<i))) regs[i] = 0; fprintf(output, "%x %x %x %x %x", inregmask, regs[0], regs[1], regs[2], regs[3]); hwloc_x86_cpuid(®s[0], ®s[1], ®s[2], ®s[3]); fprintf(output, " => %x %x %x %x\n", regs[0], regs[1], regs[2], regs[3]); }
static int dump_one_proc(hwloc_topology_t topo, hwloc_obj_t pu, const char *path) { unsigned regs[4]; unsigned highest_cpuid, highest_ext_cpuid; unsigned i; int has_intel_x2apic = 0; int has_intel_sgx = 0; int has_amd_topoext = 0; FILE *output; int err; err = hwloc_set_cpubind(topo, pu->cpuset, HWLOC_CPUBIND_PROCESS); if (err < 0) { err = hwloc_set_cpubind(topo, pu->cpuset, HWLOC_CPUBIND_THREAD); if (err < 0) { fprintf(stderr, "Cannot bind to PU P#%u\n", pu->os_index); return -1; } } if (path) { output = fopen(path, "w"); if (!output) { fprintf(stderr, "Cannot open file '%s' for writing: %s\n", path, strerror(errno)); return -1; } if (verbose) printf("Gathering CPUID of PU P#%u in path %s ...\n", pu->os_index, path); } else { output = stdout; if (verbose) printf("Gathering CPUID of PU P#%u on stdout ...\n", pu->os_index); } fprintf(output, "# mask e[abcd]x => e[abcd]x\n"); regs[0] = 0; hwloc_x86_cpuid(®s[0], ®s[1], ®s[2], ®s[3]); highest_cpuid = regs[0]; regs[0] = 0x80000000; hwloc_x86_cpuid(®s[0], ®s[1], ®s[2], ®s[3]); highest_ext_cpuid = regs[0]; /* 0x0 = Highest cpuid + Vendor string */ regs[0] = 0x0; dump_one_cpuid(output, regs, 0x1); /* 0x1 = Family, Model, Stepping, Topology, Features */ if (highest_cpuid >= 0x1) { regs[0] = 0x1; dump_one_cpuid(output, regs, 0x1); if (regs[2] & (1 << 21)) has_intel_x2apic = 1; } /* 0x2 = Cache + TLB on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x2) { regs[0] = 0x2; dump_one_cpuid(output, regs, 0x1); } /* 0x3 = Processor serial number on Intel P3, reserved otherwise ; Reserved on AMD */ if (highest_cpuid >= 0x3) { regs[0] = 0x3; dump_one_cpuid(output, regs, 0x1); } /* 0x4 = Caches on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x4) { for(i=0; ; i++) { regs[0] = 0x4; regs[2] = i; dump_one_cpuid(output, regs, 0x5); if (!(regs[0] & 0x1f)) /* invalid, no more caches */ break; } } /* 0x5 = Monitor/mwait */ if (highest_cpuid >= 0x5) { regs[0] = 0x5; dump_one_cpuid(output, regs, 0x1); } /* 0x6 = Thermal and Power management */ if (highest_cpuid >= 0x6) { regs[0] = 0x6; dump_one_cpuid(output, regs, 0x1); } /* 0x7 = Extended features */ if (highest_cpuid >= 0x7) { unsigned max; regs[0] = 0x7; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); if (regs[1] & (1<<2)) has_intel_sgx = 1; max = regs[0]; for(i=1; i<=max; i++) { regs[0] = 0x7; regs[2] = i; dump_one_cpuid(output, regs, 0x5); } } /* 0x9 = DCA on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x9) { regs[0] = 0x9; dump_one_cpuid(output, regs, 0x1); } /* 0xa = Perf monitoring on Intel ; Reserved on AMD */ if (highest_cpuid >= 0xa) { regs[0] = 0xa; dump_one_cpuid(output, regs, 0x1); } /* 0xb = Extended topology on Intel ; Reserved on AMD */ if (has_intel_x2apic && highest_cpuid >= 0xb) { for(i=0; ; i++) { regs[0] = 0xb; regs[2] = i; dump_one_cpuid(output, regs, 0x5); if (!(regs[2] & 0xff00)) /* invalid, no more levels */ break; } } /* 0xd = Extended state enumeration */ if (highest_cpuid >= 0xd) { unsigned xcr0_l, xcr0_h, ia32xss_l, ia32xss_h; regs[0] = 0xd; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); xcr0_l = regs[0]; xcr0_h = regs[3]; regs[0] = 0xd; regs[2] = 1; dump_one_cpuid(output, regs, 0x5); ia32xss_l = regs[2]; ia32xss_h = regs[3]; for(i=2; i<32; i++) { if ((xcr0_l | ia32xss_l) & (1<<i)) { regs[0] = 0xd; regs[2] = i; dump_one_cpuid(output, regs, 0x5); } } for(i=0; i<32; i++) { if ((xcr0_h | ia32xss_h) & (1<<i)) { regs[0] = 0xd; regs[2] = i+32; dump_one_cpuid(output, regs, 0x5); } } } /* 0xf = Platform/L3 QoS enumeration on Intel and AMD */ if (highest_cpuid >= 0xf) { regs[0] = 0xf; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); regs[0] = 0xf; regs[2] = 1; dump_one_cpuid(output, regs, 0x5); } /* 0x10 = Platform/L3 QoS enforcement enumeration on Intel and AMD */ if (highest_cpuid >= 0x10) { /* Intel Resource Director Technology (Intel RDT) Allocation */ regs[0] = 0x10; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); /* L3 Cache Allocation Technology */ regs[0] = 0x10; regs[2] = 1; dump_one_cpuid(output, regs, 0x5); /* L2 Cache Allocation Technology */ regs[0] = 0x10; regs[2] = 2; dump_one_cpuid(output, regs, 0x5); /* Memory Bandwidth Allocation */ regs[0] = 0x10; regs[2] = 3; dump_one_cpuid(output, regs, 0x5); } /* 0x12 = SGX Attributes Enumeration on Intel ; Reserved on AMD */ if (has_intel_sgx && highest_cpuid >= 0x12) { regs[0] = 0x12; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); regs[0] = 0x12; regs[2] = 1; dump_one_cpuid(output, regs, 0x5); for(i=2; ; i++) { regs[0] = 0x12; regs[2] = i; dump_one_cpuid(output, regs, 0x5); if (!(regs[0] & 0xf)) /* invalid, no more subleaves */ break; } } /* 0x14 = Processor trace enumeration on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x14) { regs[0] = 0x14; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); regs[0] = 0x14; regs[2] = 1; dump_one_cpuid(output, regs, 0x5); } /* 0x15 = Timestamp counter/core crystal clock on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x15) { regs[0] = 0x15; dump_one_cpuid(output, regs, 0x1); } /* 0x16 = Processor frequency on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x16) { regs[0] = 0x16; dump_one_cpuid(output, regs, 0x1); } /* 0x17 = System-On-Chip Vendor Attribute on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x17) { unsigned maxsocid; regs[0] = 0x17; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); maxsocid = regs[0]; if (maxsocid >= 3) { for(i=1; i<=maxsocid; i++) { regs[0] = 0x17; regs[2] = i; dump_one_cpuid(output, regs, 0x5); } } } /* 0x18 = Deterministic Address Translation Parameters on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x18) { unsigned max; regs[0] = 0x18; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); max = regs[0]; for(i=1; i<=max; i++) { regs[0] = 0x18; regs[2] = i; regs[3] = 0; /* mark as invalid in case the cpuid call doesn't do anything */ dump_one_cpuid(output, regs, 0x5); if (!(regs[3] & 0x1f)) /* invalid, but it doesn't mean the next subleaf will be invalid */ continue; } } /* 0x1b = (Removed) PCONFIG Information on Intel ; Reserved on AMD */ /* 0x1f = V2 Extended Topology Enumeration on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x1f) { for(i=0; ; i++) { regs[0] = 0x1f; regs[2] = i; dump_one_cpuid(output, regs, 0x5); if (!(regs[2] & 0xff00)) /* invalid, no more levels */ break; } } if (highest_cpuid > 0x1f) { static int reported = 0; if (!reported) fprintf(stderr, "WARNING: Processor supports new CPUID leaves upto 0x%x\n", highest_cpuid); reported = 1; } /* 0x80000000 = Largest extended cpuid */ regs[0] = 0x80000000; dump_one_cpuid(output, regs, 0x1); /* 0x80000001 = Extended processor signature and features */ if (highest_ext_cpuid >= 0x80000001) { regs[0] = 0x80000001; dump_one_cpuid(output, regs, 0x1); if (regs[2] & (1 << 22)) has_amd_topoext = 1; } /* 0x80000002-4 = Processor name string */ if (highest_ext_cpuid >= 0x80000002) { regs[0] = 0x80000002; dump_one_cpuid(output, regs, 0x1); } if (highest_ext_cpuid >= 0x80000003) { regs[0] = 0x80000003; dump_one_cpuid(output, regs, 0x1); } if (highest_ext_cpuid >= 0x80000004) { regs[0] = 0x80000004; dump_one_cpuid(output, regs, 0x1); } /* 0x80000005 = L1 and TLB on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x80000005) { regs[0] = 0x80000005; dump_one_cpuid(output, regs, 0x1); } /* 0x80000006 = L2, L3 and TLB on AMD ; L2 and reserved on Intel */ if (highest_ext_cpuid >= 0x80000006) { regs[0] = 0x80000006; dump_one_cpuid(output, regs, 0x1); } /* 0x80000007 = Advanced power management on AMD ; Almost reserved on Intel */ if (highest_ext_cpuid >= 0x80000007) { regs[0] = 0x80000007; dump_one_cpuid(output, regs, 0x1); } /* 0x80000008 = Long mode and topology on AMD ; Long mode on Intel */ if (highest_ext_cpuid >= 0x80000008) { regs[0] = 0x80000008; dump_one_cpuid(output, regs, 0x1); } /* 0x8000000a = SVM on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x8000000a) { regs[0] = 0x8000000a; dump_one_cpuid(output, regs, 0x1); } /* 0x80000019 = TLB1G + Perf optim identifiers on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x80000019) { regs[0] = 0x80000019; dump_one_cpuid(output, regs, 0x1); } /* 0x8000001b = IBS on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x8000001b) { regs[0] = 0x8000001b; dump_one_cpuid(output, regs, 0x1); } /* 0x8000001c = Profiling on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x8000001c) { regs[0] = 0x8000001c; dump_one_cpuid(output, regs, 0x1); } /* 0x8000001d = Cache properties on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x8000001d) { for(i=0; ; i++) { regs[0] = 0x8000001d; regs[2] = i; dump_one_cpuid(output, regs, 0x5); if (!(regs[0] & 0x1f)) /* no such cache, no more cache */ break; } } /* 0x8000001e = Topoext on AMD ; Reserved on Intel */ if (has_amd_topoext && highest_ext_cpuid >= 0x8000001e) { regs[0] = 0x8000001e; dump_one_cpuid(output, regs, 0x1); } /* 0x8000001f = Encrypted Memory Capabilities ; Reserved on Intel */ if (highest_ext_cpuid >= 0x8000001f) { regs[0] = 0x8000001f; dump_one_cpuid(output, regs, 0x1); } /* 0x80000020 = Platform QoS Enforcement for Memory Bandwidth */ if (highest_ext_cpuid >= 0x80000020) { regs[0] = 0x80000020; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); regs[0] = 0x80000020; regs[2] = 1; dump_one_cpuid(output, regs, 0x5); } if (highest_ext_cpuid > 0x8000001f) { static int reported = 0; if (!reported) fprintf(stderr, "WARNING: Processor supports new extended CPUID leaves upto 0x%x\n", highest_ext_cpuid); reported = 1; } if (path) fclose(output); return 0; }
static int dump_one_proc(hwloc_topology_t topo, hwloc_obj_t pu, const char *path) { unsigned regs[4]; unsigned highest_cpuid, highest_ext_cpuid; unsigned i; FILE *output; int err; err = hwloc_set_cpubind(topo, pu->cpuset, HWLOC_CPUBIND_PROCESS); if (err < 0) { err = hwloc_set_cpubind(topo, pu->cpuset, HWLOC_CPUBIND_THREAD); if (err < 0) { fprintf(stderr, "Cannot bind to PU P#%u\n", pu->os_index); return -1; } } if (path) { output = fopen(path, "w"); if (!output) { fprintf(stderr, "Cannot open file '%s' for writing: %s\n", path, strerror(errno)); return -1; } printf("Gathering CPUID of PU P#%u in path %s ...\n", pu->os_index, path); } else { output = stdout; printf("Gathering CPUID of PU P#%u on stdout ...\n", pu->os_index); } fprintf(output, "# mask e[abcd]x => e[abcd]x\n"); regs[0] = 0; hwloc_x86_cpuid(®s[0], ®s[1], ®s[2], ®s[3]); highest_cpuid = regs[0]; regs[0] = 0x80000000; hwloc_x86_cpuid(®s[0], ®s[1], ®s[2], ®s[3]); highest_ext_cpuid = regs[0]; /* 0x0 = Highest cpuid + Vendor string */ regs[0] = 0x0; dump_one_cpuid(output, regs, 0x1); /* 0x1 = Family, Model, Stepping, Topology, Features */ if (highest_cpuid >= 0x1) { regs[0] = 0x1; dump_one_cpuid(output, regs, 0x1); } /* 0x2 = Cache + TLB on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x2) { regs[0] = 0x2; dump_one_cpuid(output, regs, 0x1); } /* 0x3 = Processor serial number on Intel P3, reserved otherwise ; Reserved on AMD */ if (highest_cpuid >= 0x3) { regs[0] = 0x3; dump_one_cpuid(output, regs, 0x1); } /* 0x4 = Caches on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x4) { for(i=0; ; i++) { regs[0] = 0x4; regs[2] = i; dump_one_cpuid(output, regs, 0x5); if (!(regs[0] & 0x1f)) break; } } /* 0x5 = Monitor/mwait */ if (highest_cpuid >= 0x5) { regs[0] = 0x5; dump_one_cpuid(output, regs, 0x1); } /* 0x6 = Thermal and Power management */ if (highest_cpuid >= 0x6) { regs[0] = 0x6; dump_one_cpuid(output, regs, 0x1); } /* 0x7 = Extended features */ if (highest_cpuid >= 0x7) { unsigned max; regs[0] = 0x7; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); max = regs[0]; for(i=1; i<=max; i++) { regs[0] = 0x7; regs[2] = i; dump_one_cpuid(output, regs, 0x5); } } /* 0x9 = DCA on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x9) { regs[0] = 0x9; dump_one_cpuid(output, regs, 0x1); } /* 0xa = Perf monitoring on Intel ; Reserved on AMD */ if (highest_cpuid >= 0xa) { regs[0] = 0xa; dump_one_cpuid(output, regs, 0x1); } /* 0xb = Extended topology on Intel ; Reserved on AMD */ if (highest_cpuid >= 0xb) { for(i=0; ; i++) { regs[0] = 0xb; regs[2] = i; dump_one_cpuid(output, regs, 0x5); if (!regs[0] && !regs[1]) break; } } /* 0xd = Extended state enumeration */ if (highest_cpuid >= 0xd) { unsigned xcr0_l, xcr0_h, ia32xss_l, ia32xss_h; regs[0] = 0xd; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); xcr0_l = regs[0]; xcr0_h = regs[3]; regs[0] = 0xd; regs[2] = 1; dump_one_cpuid(output, regs, 0x5); ia32xss_l = regs[2]; ia32xss_h = regs[3]; for(i=2; i<32; i++) { if ((xcr0_l | ia32xss_l) & (1<<i)) { regs[0] = 0xd; regs[2] = i; dump_one_cpuid(output, regs, 0x5); } } for(i=0; i<32; i++) { if ((xcr0_h | ia32xss_h) & (1<<i)) { regs[0] = 0xd; regs[2] = i+32; dump_one_cpuid(output, regs, 0x5); } } } /* 0xf = Platform/L3 QoS enumeration on Intel ; Reserved on AMD */ if (highest_cpuid >= 0xf) { regs[0] = 0xf; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); regs[0] = 0xf; regs[2] = 1; dump_one_cpuid(output, regs, 0x5); } /* 0x10 = Platform/L3 QoS enforcement enumeration on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x10) { regs[0] = 0x10; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); regs[0] = 0x10; regs[2] = 1; dump_one_cpuid(output, regs, 0x5); } /* 0x14 = Processor trace enumeration on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x14) { regs[0] = 0x14; regs[2] = 0; dump_one_cpuid(output, regs, 0x5); } /* 0x15 = Timestamp counter/core crystal clock on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x15) { regs[0] = 0x15; dump_one_cpuid(output, regs, 0x1); } /* 0x16 = Processor frequency on Intel ; Reserved on AMD */ if (highest_cpuid >= 0x16) { regs[0] = 0x16; dump_one_cpuid(output, regs, 0x1); } if (highest_cpuid > 0x16) { static int reported = 0; if (!reported) fprintf(stderr, "WARNING: Processor supports new CPUID leaves upto 0x%x\n", highest_cpuid); reported = 1; } /* 0x80000000 = Largest extended cpuid */ regs[0] = 0x80000000; dump_one_cpuid(output, regs, 0x1); /* 0x80000001 = Extended processor signature and features */ if (highest_ext_cpuid >= 0x80000001) { regs[0] = 0x80000001; dump_one_cpuid(output, regs, 0x1); } /* 0x80000002-4 = Processor name string */ if (highest_ext_cpuid >= 0x80000002) { regs[0] = 0x80000002; dump_one_cpuid(output, regs, 0x1); } if (highest_ext_cpuid >= 0x80000003) { regs[0] = 0x80000003; dump_one_cpuid(output, regs, 0x1); } if (highest_ext_cpuid >= 0x80000004) { regs[0] = 0x80000004; dump_one_cpuid(output, regs, 0x1); } /* 0x80000005 = L1 and TLB on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x80000005) { regs[0] = 0x80000005; dump_one_cpuid(output, regs, 0x1); } /* 0x80000006 = L2, L3 and TLB on AMD ; L2 and reserved on Intel */ if (highest_ext_cpuid >= 0x80000006) { regs[0] = 0x80000006; dump_one_cpuid(output, regs, 0x1); } /* 0x80000007 = Advanced power management on AMD ; Almost reserved on Intel */ if (highest_ext_cpuid >= 0x80000007) { regs[0] = 0x80000007; dump_one_cpuid(output, regs, 0x1); } /* 0x80000008 = Long mode and topology on AMD ; Long mode on Intel */ if (highest_ext_cpuid >= 0x80000008) { regs[0] = 0x80000008; dump_one_cpuid(output, regs, 0x1); } /* 0x8000000a = SVM on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x8000000a) { regs[0] = 0x8000000a; dump_one_cpuid(output, regs, 0x1); } /* 0x80000019 = TLB1G + Perf optim identifiers on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x80000019) { regs[0] = 0x80000019; dump_one_cpuid(output, regs, 0x1); } /* 0x8000001b = IBS on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x8000001b) { regs[0] = 0x8000001b; dump_one_cpuid(output, regs, 0x1); } /* 0x8000001c = Profiling on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x8000001c) { regs[0] = 0x8000001c; dump_one_cpuid(output, regs, 0x1); } /* 0x8000001d = Cache properties on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x8000001d) { for(i=0; ; i++) { regs[0] = 0x8000001d; regs[2] = i; dump_one_cpuid(output, regs, 0x5); if (!(regs[0] & 0x1f)) break; } } /* 0x8000001e = Topoext on AMD ; Reserved on Intel */ if (highest_ext_cpuid >= 0x8000001e) { regs[0] = 0x8000001e; dump_one_cpuid(output, regs, 0x1); } if (highest_ext_cpuid > 0x8000001e) { static int reported = 0; if (!reported) fprintf(stderr, "WARNING: Processor supports new extended CPUID leaves upto 0x%x\n", highest_ext_cpuid); reported = 1; } if (path) fclose(output); return 0; }