/* Initialize PMU properties of the current CPU */ static void init_pmu_props_cpu(void* dummy) { int this_cpu=smp_processor_id(); int i=0; pmu_props_t* props=&pmu_props_cpu[this_cpu]; #if defined(CONFIG_PMC_CORE_2_DUO) || defined(CONFIG_PMC_CORE_I7) cpuid_regs_t rv; int nr_gp_pmcs; unsigned int model=0; rv.eax=0x0A; rv.ebx=rv.edx=rv.ecx=0x0; run_cpuid(rv); nr_gp_pmcs=(rv.eax&0xFF00)>>8; props->processor_model=rv.eax&0xFF; #ifdef DEBUG if (this_cpu==0) { printk("*** PMU Info ***\n"); printk("Version Id:: 0x%x\n", rv.eax&0xFF); printk("GP Counter per Logical Processor:: %d\n",nr_gp_pmcs); printk("Bit width of the PMC:: %d\n", (rv.eax&0xFF0000)>>16); if ((rv.eax&0xFF) > 1) { printk("Number of fixed func. counters:: %d\n", rv.edx&0x1F); printk("Bit width of fixed func. counters:: %d\n", (rv.edx&0x1FE0)>>5); }
/* * Obtain model information from the current processor * and figure out if it supports RAPL or not */ static int processor_is_supported(int* processor_model) { int i=0; cpuid_regs_t rv; unsigned int this_model=0; if (boot_cpu_data.x86_vendor!=X86_VENDOR_INTEL) return 0; /* Figure out CPU */ rv.eax=0x1; rv.ebx=rv.edx=rv.ecx=0x0; run_cpuid(rv); this_model= (rv.eax & 0xF0) >> 4; this_model += ((rv.eax >> 16) & 0xf) << 4; while(supported_models[i].model!=0 && supported_models[i].model!=this_model) i++; /* Not found in table */ if (supported_models[i].model==0) return 0; (*processor_model)=this_model; return 1; }
/// @todo Document void init_cpuinfo(cpuinfo::impl& info) { // Note: We need to capture these 4 registers, otherwise we get // a segmentation fault on 32-bit Linux uint32_t output[4]; // The register information per input can be extracted from here: // http://en.wikipedia.org/wiki/CPUID // Set registers for basic flag extraction run_cpuid(1, 0, output); extract_x86_flags(info, output[2], output[3]); // Set registers for extended flags extraction run_cpuid(7, 0, output); extract_x86_extended_flags(info, output[1]); }
int main(int argc, char **argv) { const char *file = NULL; struct cpuid_state_t state; int c, ret = 0; int cpu_start = -2, cpu_end = -2; INIT_CPUID_STATE(&state); while (TRUE) { static struct option long_options[] = { {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {"sanity", no_argument, &do_sanity, 1}, {"dump", no_argument, &do_dump, 1}, {"cpu", required_argument, 0, 'c'}, {"kernel", no_argument, &do_kernel, 'k'}, {"ignore-vendor", no_argument, &ignore_vendor, 1}, {"vendor", required_argument, 0, 'V'}, {"parse", required_argument, 0, 'f'}, {"format", required_argument, 0, 'o'}, {"scan-to", required_argument, 0, 2}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long(argc, argv, "c:hdvV:o:f:", long_options, &option_index); if (c == -1) break; switch (c) { case 0: break; case 2: assert(optarg); if (sscanf(optarg, "0x%x", &scan_to) != 1) if (sscanf(optarg, "%u", &scan_to) != 1) if (sscanf(optarg, "%x", &scan_to) != 1) scan_to = 0; break; case 'c': assert(optarg); if (sscanf(optarg, "%d", &cpu_start) != 1) { printf("Option --cpu= requires an integer parameter.\n"); exit(1); } if (cpu_start < -1) { printf("Option --cpu= requires a value >= -1.\n"); exit(1); } break; case 'd': do_dump = 1; if (cpu_start == -2 && cpu_end == -2) cpu_start = -1; break; case 'f': file = optarg; break; case 'o': assert(optarg); for (c = 0; formats[c].name != NULL; c++) { if (0 == strcmp(optarg, formats[c].name)) { do_dump = 1; dump_format = formats[c].value; break; } } if (!formats[c].name) { printf("Unrecognized format: '%s'\n", optarg); exit(1); } break; case 'V': assert(optarg); state.vendor = vendor_id(optarg); break; case 'v': version(); /* falls through */ case 'h': case '?': default: usage(argv[0]); } } if (cpu_start == -2) cpu_start = cpu_end = 0; if (do_sanity && !file) { state.thread_bind(&state, 0); ret = sanity_run(&state); goto leave; } switch(dump_format) { case DUMP_FORMAT_DEFAULT: state.cpuid_print = cpuid_dump_normal; break; case DUMP_FORMAT_VMWARE: cpu_start = 0; state.cpuid_print = cpuid_dump_vmware; break; case DUMP_FORMAT_XEN: cpu_start = 0; state.cpuid_print = cpuid_dump_xen; printf("cpuid = [\n"); break; case DUMP_FORMAT_XEN_SXP: cpu_start = 0; state.cpuid_print = cpuid_dump_xen_sxp; printf("(\n"); break; case DUMP_FORMAT_ETALLEN: state.cpuid_print = cpuid_dump_etallen; break; } if (file) { cpuid_load_from_file(file, &state); state.cpuid_call = cpuid_stub; state.thread_init = thread_init_stub; state.thread_bind = thread_bind_stub; state.thread_count = thread_count_stub; #ifdef __linux__ } else if (do_kernel) { state.cpuid_call = cpuid_kernel; #endif } state.thread_init(); if (cpu_start == -1) { cpu_start = 0; cpu_end = state.thread_count(&state) - 1; #ifdef TARGET_OS_MACOSX /* Because thread_bind() doesn't work on Mac. Stupidest * operating system design ever. */ if (!file) { cpu_start = 0; cpu_end = 0; } #endif } else { cpu_end = cpu_start; } if ((uint32_t)cpu_start >= state.thread_count(&state)) { printf("CPU %d doesn't seem to exist.\n", cpu_start); exit(1); } for (c = cpu_start; c <= cpu_end; c++) { state.thread_bind(&state, c); switch(dump_format) { case DUMP_FORMAT_DEFAULT: case DUMP_FORMAT_ETALLEN: printf("CPU %d:\n", c); break; } run_cpuid(&state, do_dump); } switch (dump_format) { case DUMP_FORMAT_XEN: printf("]\n"); break; case DUMP_FORMAT_XEN_SXP: printf(")\n"); break; } leave: FREE_CPUID_STATE(&state); return ret; }