#include #include #include #include #include #include #include #include #if !CONFIG_SERIAL_CPU_INIT #error Intel hyper-threading requires serialized cpu init #endif static int first_time = 1; static int disable_siblings = !CONFIG_LOGICAL_CPUS; /* Return true if running thread does not have the smallest lapic ID * within a CPU core. */ int intel_ht_sibling(void) { unsigned int core_ids, apic_ids, threads; apic_ids = 1; if (cpuid_eax(0) >= 1) apic_ids = (cpuid_ebx(1) >> 16) & 0xff; if (apic_ids < 1) apic_ids = 1; core_ids = 1; if (cpuid_eax(0) >= 4) core_ids += (cpuid_eax(4) >> 26) & 0x3f; threads = (apic_ids / core_ids); return !!(lapicid() & (threads-1)); } void intel_sibling_init(device_t cpu) { unsigned i, siblings; struct cpuid_result result; /* On the bootstrap processor see if I want sibling cpus enabled */ if (first_time) { first_time = 0; get_option(&disable_siblings, "hyper_threading"); } result = cpuid(1); /* Is hyperthreading supported */ if (!(result.edx & (1 << 28))) { return; } /* See how many sibling cpus we have */ siblings = (result.ebx >> 16) & 0xff; if (siblings < 1) { siblings = 1; } printk(BIOS_DEBUG, "CPU: %u %d siblings\n", cpu->path.apic.apic_id, siblings); /* See if I am a sibling cpu */ if (cpu->path.apic.apic_id & (siblings -1)) { if (disable_siblings) { cpu->enabled = 0; } return; } /* I am the primary cpu start up my siblings */ for(i = 1; i < siblings; i++) { struct device_path cpu_path; device_t new; /* Build the cpu device path */ cpu_path.type = DEVICE_PATH_APIC; cpu_path.apic.apic_id = cpu->path.apic.apic_id + i; /* Allocate new cpu device structure iff sibling CPU * was not in static device tree. */ new = alloc_find_dev(cpu->bus, &cpu_path); if (!new) { continue; } printk(BIOS_DEBUG, "CPU: %u has sibling %u\n", cpu->path.apic.apic_id, new->path.apic.apic_id); } }