/* * (C) 2001-2011 Dave Jones. * * Licensed under the terms of the GNU GPL License version 2. */ #include #include #include #include #include "x86info.h" #include "mptable.h" #include "Intel/Intel.h" unsigned int user_is_root = 0; unsigned int nrCPUs=1; static unsigned int nrSMPCPUs; struct cpudata *firstcpu; static void separator(void) { int j; for (j = 0; j < 74; j++) printf("-"); printf("\n"); } static void display_detailed_info(struct cpudata *cpu) { bind_cpu(cpu); /* FIXME: Eventually remove once 'gather' has all the per-cpu stuff */ show_info(cpu); if (show_cpuid) { dump_raw_cpuid(cpu->number, 0, cpu->cpuid_level); if (cpu->maxei >=0x80000000) dump_raw_cpuid(cpu->number, 0x80000000, cpu->maxei); if (cpu->maxei2 >=0xC0000000) dump_raw_cpuid(cpu->number, 0xC0000000, cpu->maxei2); } if (show_cacheinfo) { switch (cpu->vendor) { case VENDOR_INTEL: decode_Intel_caches(cpu, 1); break; case VENDOR_AMD: decode_AMD_cacheinfo(cpu); break; default: break; } } if (show_feature_flags) display_feature_flags(cpu); if (show_connector) decode_connector(cpu->connector); if (show_urls) { if (cpu->info_url != NULL) printf("Info URL: %s\n", cpu->info_url); if (cpu->datasheet_url != NULL) printf("Datasheet: %s\n", cpu->datasheet_url); if (cpu->errata_url != NULL) printf("Errata: %s\n", cpu->errata_url); } /* Info that requires root access (eg, reading MSRs etc) */ if (user_is_root) { if (show_mtrr) dump_mtrrs(cpu); if (show_apic) dump_apics(cpu); } if (show_addr_sizes) printf("Address sizes : %u bits physical, %u bits virtual\n", cpu->phyaddr_bits, cpu->viraddr_bits); if (show_MHz) { display_MHz(cpu); printf(" processor (estimate).\n\n"); } if (show_bench) show_benchmarks(cpu); } /* * check to see if all CPUs are the same. * returns 1 if all cpus are the same, 0 if something is different */ static int check_cpu_similarity() { struct cpudata *cpu; unsigned int i; /* force to display all cpus if the user requested it. */ if (all_cpus) return 0; if (nrCPUs == 1) return 1; cpu = firstcpu; for (i = 0; i < nrCPUs; i++) { cpu = cpu->next; if (!cpu) return 1; if (cpu->efamily != firstcpu->efamily) return 0; if (cpu->emodel != firstcpu->emodel) return 0; if (cpu->family != firstcpu->family) return 0; if (model(cpu) != model(firstcpu)) return 0; if (cpu->stepping != firstcpu->stepping) return 0; } return 1; } static struct cpudata *alloc_cpu() { struct cpudata *newcpu; newcpu = malloc (sizeof (struct cpudata)); if (!newcpu) { printf("Out of memory\n"); exit(EXIT_FAILURE); } memset(newcpu, 0, sizeof(struct cpudata)); return newcpu; } static void fill_in_cpu_info(struct cpudata *cpu) { bind_cpu(cpu); estimate_MHz(cpu); get_cpu_info_basics(cpu); /* get vendor,family,model,stepping */ get_feature_flags(cpu); identify(cpu); get_topology(cpu); } int main (int argc, char **argv) { struct cpudata *cpu=NULL, *tmp; unsigned int i; unsigned int display_one_cpu = 1; if (getuid() == 0) user_is_root = 1; parse_command_line(argc, argv); printf("x86info v" __stringify(VERSION) " Dave Jones 2001-2011\n"); printf("Feedback to .\n\n"); if ((HaveCPUID()) == 0) { printf("No CPUID instruction available.\n"); printf("No further information available for this CPU.\n"); exit(EXIT_SUCCESS); } if (need_root && !user_is_root) { printf("Need to be root to use specified options.\n"); exit(EXIT_FAILURE); } nrCPUs = sysconf(_SC_NPROCESSORS_ONLN); /* * can't have less than 1 CPU, or more than * 65535 (some arbitrary large number) */ if ((nrCPUs < 1) || (nrCPUs > 65535)) { printf("CPU count is bogus: defaulting to 1 CPU.\n"); nrCPUs = 1; } /* Allocate a cpu for boot cpu. */ cpu = firstcpu = alloc_cpu(); fill_in_cpu_info(cpu); /* Allocate structs for non-boot CPUs if present */ if (nrCPUs > 1) { for (i = 1; i < nrCPUs; i++) { cpu->next = alloc_cpu(); cpu = cpu->next; cpu->number = i; fill_in_cpu_info(cpu); } } display_one_cpu = check_cpu_similarity(); if (show_mptable && user_is_root) display_mptable(); /* Now we display the info we gathered */ cpu = firstcpu; if (display_one_cpu) { if (nrCPUs >= 2) printf("Found %d identical CPUs", nrCPUs); /* Check mptable if present. This way we get number of CPUs on SMP systems that have booted UP kernels. */ if (user_is_root) { nrSMPCPUs = enumerate_cpus(); if (nrSMPCPUs > nrCPUs) printf(" (but found %ud CPUs in MPTable!)", nrSMPCPUs); } if (nrCPUs >= 2) printf("\n"); display_detailed_info(cpu); } else { printf("Found %d CPUs.\n", nrCPUs); for (i = 0; i < nrCPUs; i++) { printf("CPU #%u:\n", i+1); display_detailed_info(cpu); if (nrCPUs > 1) separator(); cpu = cpu->next; } } display_topology(firstcpu); printf(" running at an estimated "); display_MHz(firstcpu); printf("\n"); /* Tear down the linked list. */ cpu = firstcpu; for (i = 0; i < nrCPUs; i++) { if (cpu->info_url) free(cpu->info_url); if (cpu->datasheet_url) free(cpu->datasheet_url); if (cpu->errata_url) free(cpu->errata_url); tmp = cpu->next; free(cpu); cpu = tmp; } exit(EXIT_SUCCESS); }