aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r--arch/x86/kernel/apic/apic.c95
1 files changed, 78 insertions, 17 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index f3e9b2df4b16..46bb29958509 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -64,6 +64,8 @@ unsigned disabled_cpus;
64unsigned int boot_cpu_physical_apicid = -1U; 64unsigned int boot_cpu_physical_apicid = -1U;
65EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid); 65EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid);
66 66
67u8 boot_cpu_apic_version;
68
67/* 69/*
68 * The highest APIC ID seen during enumeration. 70 * The highest APIC ID seen during enumeration.
69 */ 71 */
@@ -1374,7 +1376,6 @@ void setup_local_APIC(void)
1374 * Actually disabling the focus CPU check just makes the hang less 1376 * Actually disabling the focus CPU check just makes the hang less
1375 * frequent as it makes the interrupt distributon model be more 1377 * frequent as it makes the interrupt distributon model be more
1376 * like LRU than MRU (the short-term load is more even across CPUs). 1378 * like LRU than MRU (the short-term load is more even across CPUs).
1377 * See also the comment in end_level_ioapic_irq(). --macro
1378 */ 1379 */
1379 1380
1380 /* 1381 /*
@@ -1816,8 +1817,7 @@ void __init init_apic_mappings(void)
1816 * since smp_sanity_check is prepared for such a case 1817 * since smp_sanity_check is prepared for such a case
1817 * and disable smp mode 1818 * and disable smp mode
1818 */ 1819 */
1819 apic_version[new_apicid] = 1820 boot_cpu_apic_version = GET_APIC_VERSION(apic_read(APIC_LVR));
1820 GET_APIC_VERSION(apic_read(APIC_LVR));
1821 } 1821 }
1822} 1822}
1823 1823
@@ -1828,17 +1828,14 @@ void __init register_lapic_address(unsigned long address)
1828 if (!x2apic_mode) { 1828 if (!x2apic_mode) {
1829 set_fixmap_nocache(FIX_APIC_BASE, address); 1829 set_fixmap_nocache(FIX_APIC_BASE, address);
1830 apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", 1830 apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
1831 APIC_BASE, mp_lapic_addr); 1831 APIC_BASE, address);
1832 } 1832 }
1833 if (boot_cpu_physical_apicid == -1U) { 1833 if (boot_cpu_physical_apicid == -1U) {
1834 boot_cpu_physical_apicid = read_apic_id(); 1834 boot_cpu_physical_apicid = read_apic_id();
1835 apic_version[boot_cpu_physical_apicid] = 1835 boot_cpu_apic_version = GET_APIC_VERSION(apic_read(APIC_LVR));
1836 GET_APIC_VERSION(apic_read(APIC_LVR));
1837 } 1836 }
1838} 1837}
1839 1838
1840int apic_version[MAX_LOCAL_APIC];
1841
1842/* 1839/*
1843 * Local APIC interrupts 1840 * Local APIC interrupts
1844 */ 1841 */
@@ -2027,7 +2024,53 @@ void disconnect_bsp_APIC(int virt_wire_setup)
2027 apic_write(APIC_LVT1, value); 2024 apic_write(APIC_LVT1, value);
2028} 2025}
2029 2026
2030int generic_processor_info(int apicid, int version) 2027/*
2028 * The number of allocated logical CPU IDs. Since logical CPU IDs are allocated
2029 * contiguously, it equals to current allocated max logical CPU ID plus 1.
2030 * All allocated CPU ID should be in [0, nr_logical_cpuidi), so the maximum of
2031 * nr_logical_cpuids is nr_cpu_ids.
2032 *
2033 * NOTE: Reserve 0 for BSP.
2034 */
2035static int nr_logical_cpuids = 1;
2036
2037/*
2038 * Used to store mapping between logical CPU IDs and APIC IDs.
2039 */
2040static int cpuid_to_apicid[] = {
2041 [0 ... NR_CPUS - 1] = -1,
2042};
2043
2044/*
2045 * Should use this API to allocate logical CPU IDs to keep nr_logical_cpuids
2046 * and cpuid_to_apicid[] synchronized.
2047 */
2048static int allocate_logical_cpuid(int apicid)
2049{
2050 int i;
2051
2052 /*
2053 * cpuid <-> apicid mapping is persistent, so when a cpu is up,
2054 * check if the kernel has allocated a cpuid for it.
2055 */
2056 for (i = 0; i < nr_logical_cpuids; i++) {
2057 if (cpuid_to_apicid[i] == apicid)
2058 return i;
2059 }
2060
2061 /* Allocate a new cpuid. */
2062 if (nr_logical_cpuids >= nr_cpu_ids) {
2063 WARN_ONCE(1, "Only %d processors supported."
2064 "Processor %d/0x%x and the rest are ignored.\n",
2065 nr_cpu_ids - 1, nr_logical_cpuids, apicid);
2066 return -1;
2067 }
2068
2069 cpuid_to_apicid[nr_logical_cpuids] = apicid;
2070 return nr_logical_cpuids++;
2071}
2072
2073int __generic_processor_info(int apicid, int version, bool enabled)
2031{ 2074{
2032 int cpu, max = nr_cpu_ids; 2075 int cpu, max = nr_cpu_ids;
2033 bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid, 2076 bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
@@ -2102,8 +2145,16 @@ int generic_processor_info(int apicid, int version)
2102 * for BSP. 2145 * for BSP.
2103 */ 2146 */
2104 cpu = 0; 2147 cpu = 0;
2105 } else 2148
2106 cpu = cpumask_next_zero(-1, cpu_present_mask); 2149 /* Logical cpuid 0 is reserved for BSP. */
2150 cpuid_to_apicid[0] = apicid;
2151 } else {
2152 cpu = allocate_logical_cpuid(apicid);
2153 if (cpu < 0) {
2154 disabled_cpus++;
2155 return -EINVAL;
2156 }
2157 }
2107 2158
2108 /* 2159 /*
2109 * This can happen on physical hotplug. The sanity check at boot time 2160 * This can happen on physical hotplug. The sanity check at boot time
@@ -2130,14 +2181,12 @@ int generic_processor_info(int apicid, int version)
2130 cpu, apicid); 2181 cpu, apicid);
2131 version = 0x10; 2182 version = 0x10;
2132 } 2183 }
2133 apic_version[apicid] = version;
2134 2184
2135 if (version != apic_version[boot_cpu_physical_apicid]) { 2185 if (version != boot_cpu_apic_version) {
2136 pr_warning("BIOS bug: APIC version mismatch, boot CPU: %x, CPU %d: version %x\n", 2186 pr_warning("BIOS bug: APIC version mismatch, boot CPU: %x, CPU %d: version %x\n",
2137 apic_version[boot_cpu_physical_apicid], cpu, version); 2187 boot_cpu_apic_version, cpu, version);
2138 } 2188 }
2139 2189
2140 physid_set(apicid, phys_cpu_present_map);
2141 if (apicid > max_physical_apicid) 2190 if (apicid > max_physical_apicid)
2142 max_physical_apicid = apicid; 2191 max_physical_apicid = apicid;
2143 2192
@@ -2150,11 +2199,23 @@ int generic_processor_info(int apicid, int version)
2150 apic->x86_32_early_logical_apicid(cpu); 2199 apic->x86_32_early_logical_apicid(cpu);
2151#endif 2200#endif
2152 set_cpu_possible(cpu, true); 2201 set_cpu_possible(cpu, true);
2153 set_cpu_present(cpu, true); 2202
2203 if (enabled) {
2204 num_processors++;
2205 physid_set(apicid, phys_cpu_present_map);
2206 set_cpu_present(cpu, true);
2207 } else {
2208 disabled_cpus++;
2209 }
2154 2210
2155 return cpu; 2211 return cpu;
2156} 2212}
2157 2213
2214int generic_processor_info(int apicid, int version)
2215{
2216 return __generic_processor_info(apicid, version, true);
2217}
2218
2158int hard_smp_processor_id(void) 2219int hard_smp_processor_id(void)
2159{ 2220{
2160 return read_apic_id(); 2221 return read_apic_id();
@@ -2277,7 +2338,7 @@ int __init APIC_init_uniprocessor(void)
2277 * Complain if the BIOS pretends there is one. 2338 * Complain if the BIOS pretends there is one.
2278 */ 2339 */
2279 if (!boot_cpu_has(X86_FEATURE_APIC) && 2340 if (!boot_cpu_has(X86_FEATURE_APIC) &&
2280 APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { 2341 APIC_INTEGRATED(boot_cpu_apic_version)) {
2281 pr_err("BIOS bug, local APIC 0x%x not detected!...\n", 2342 pr_err("BIOS bug, local APIC 0x%x not detected!...\n",
2282 boot_cpu_physical_apicid); 2343 boot_cpu_physical_apicid);
2283 return -1; 2344 return -1;