/*- * Copyright (c) 2005-2009 Jung-uk Kim * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #if !defined(__amd64__) && !defined(__i386__) #error "Unsupported architecture" #endif #include #include #include static struct { char *vendor; u_int vendor_id; } cpu_vendors[] = { { INTEL_VENDOR_ID, CPU_VENDOR_INTEL }, /* GenuineIntel */ { AMD_VENDOR_ID, CPU_VENDOR_AMD }, /* AuthenticAMD */ { CENTAUR_VENDOR_ID, CPU_VENDOR_CENTAUR }, /* CentaurHauls */ #if defined(__i386__) { NSC_VENDOR_ID, CPU_VENDOR_NSC }, /* Geode by NSC */ { CYRIX_VENDOR_ID, CPU_VENDOR_CYRIX }, /* CyrixInstead */ { TRANSMETA_VENDOR_ID, CPU_VENDOR_TRANSMETA }, /* GenuineTMx86 */ { SIS_VENDOR_ID, CPU_VENDOR_SIS }, /* SiS SiS SiS */ { UMC_VENDOR_ID, CPU_VENDOR_UMC }, /* UMC UMC UMC */ { NEXGEN_VENDOR_ID, CPU_VENDOR_NEXGEN }, /* NexGenDriven */ { RISE_VENDOR_ID, CPU_VENDOR_RISE }, /* RiseRiseRise */ #if 0 /* XXX CPUID 8000_0000h and 8086_0000h, not 0000_0000h */ { "TransmetaCPU", CPU_VENDOR_TRANSMETA }, #endif #endif }; static u_int find_cpu_vendor_id(char *cpu_vendor) { int i; for (i = 0; i < sizeof(cpu_vendors) / sizeof(cpu_vendors[0]); i++) if (strcmp(cpu_vendor, cpu_vendors[i].vendor) == 0) return (cpu_vendors[i].vendor_id); return (0); } static void proc_bind(int cpu) { cpuset_t mask; CPU_ZERO(&mask); CPU_SET(cpu, &mask); if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(mask), &mask) < 0) err(1, "cpuset_setaffinity()"); } static void print_cpuid(void) { char vendor[13]; u_int i, j, cpuhigh, exthigh, regs[4], vendorid; do_cpuid(0, regs); cpuhigh = regs[0]; memcpy(vendor, ®s[1], 4); memcpy(vendor + 4, ®s[3], 4); memcpy(vendor + 8, ®s[2], 4); vendor[12] = '\0'; vendorid = find_cpu_vendor_id(vendor); printf("CPUID function %%eax %%ebx %%ecx %%edx\n"); printf("--------------------------------------------------\n"); for (i = 0; i <= cpuhigh; i++) { switch (vendorid) { case CPU_VENDOR_INTEL: switch (i) { case 4: /* Deterministic Cache Parameters Leaf */ for (j = 0; j < 32; j++) { cpuid_count(i, j, regs); if ((regs[0] & 0x1f) == 0) break; printf( " %8xh[%02x] %08x %08x %08x %08x\n", i & 0xffff, j, regs[0], regs[1], regs[2], regs[3]); } continue; case 11: /* x2APIC Features / Processor Topology Leaf */ for (j = 0; j < 32; j++) { cpuid_count(i, j, regs); if ((regs[0] & 0xffff) == 0 && (regs[1] & 0xffff) == 0) break; printf( " %8xh[%02x] %08x %08x %08x %08x\n", i & 0xffff, j, regs[0], regs[1], regs[2], regs[3]); } continue; } /* FALLTHROUGH */ default: do_cpuid(i, regs); printf(" %8xh %08x %08x %08x %08x\n", i & 0xffff, regs[0], regs[1], regs[2], regs[3]); } } exthigh = 0; do_cpuid(0x80000000, regs); if (regs[0] >= 0x80000000) exthigh = regs[0]; for (i = 0x80000000; i <= exthigh; i++) { do_cpuid(i, regs); printf("%04x_%04xh %08x %08x %08x %08x\n", (i >> 16) & 0xffff, i & 0xffff, regs[0], regs[1], regs[2], regs[3]); } } int main(void) { cpuset_t mask; int i; if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(mask), &mask) < 0) err(1, "cpuset_getaffinity()"); for (i = 0; i < CPU_SETSIZE; i++) { if (!CPU_ISSET(i, &mask)) continue; if (i > 0) printf("\n"); printf("-------------------- CPU #%02d ---------------------\n", i); proc_bind(i); print_cpuid(); } return (0); }