diff options
Diffstat (limited to 'arch/x86/kernel/apic.c')
-rw-r--r-- | arch/x86/kernel/apic.c | 177 |
1 files changed, 114 insertions, 63 deletions
diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index abfa0b641aea..c9aed4510585 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Local APIC handling, local APIC timers | 2 | * Local APIC handling, local APIC timers |
3 | * | 3 | * |
4 | * (c) 1999, 2000 Ingo Molnar <mingo@redhat.com> | 4 | * (c) 1999, 2000, 2009 Ingo Molnar <mingo@redhat.com> |
5 | * | 5 | * |
6 | * Fixes | 6 | * Fixes |
7 | * Maciej W. Rozycki : Bits for genuine 82489DX APICs; | 7 | * Maciej W. Rozycki : Bits for genuine 82489DX APICs; |
@@ -14,52 +14,72 @@ | |||
14 | * Mikael Pettersson : PM converted to driver model. | 14 | * Mikael Pettersson : PM converted to driver model. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <linux/mm.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/bootmem.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/mc146818rtc.h> | ||
24 | #include <linux/kernel_stat.h> | 17 | #include <linux/kernel_stat.h> |
25 | #include <linux/sysdev.h> | 18 | #include <linux/mc146818rtc.h> |
26 | #include <linux/ioport.h> | ||
27 | #include <linux/cpu.h> | ||
28 | #include <linux/clockchips.h> | ||
29 | #include <linux/acpi_pmtmr.h> | 19 | #include <linux/acpi_pmtmr.h> |
20 | #include <linux/clockchips.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/bootmem.h> | ||
23 | #include <linux/ftrace.h> | ||
24 | #include <linux/ioport.h> | ||
30 | #include <linux/module.h> | 25 | #include <linux/module.h> |
31 | #include <linux/dmi.h> | 26 | #include <linux/sysdev.h> |
27 | #include <linux/delay.h> | ||
28 | #include <linux/timex.h> | ||
32 | #include <linux/dmar.h> | 29 | #include <linux/dmar.h> |
33 | #include <linux/ftrace.h> | 30 | #include <linux/init.h> |
34 | #include <linux/smp.h> | 31 | #include <linux/cpu.h> |
32 | #include <linux/dmi.h> | ||
35 | #include <linux/nmi.h> | 33 | #include <linux/nmi.h> |
36 | #include <linux/timex.h> | 34 | #include <linux/smp.h> |
35 | #include <linux/mm.h> | ||
37 | 36 | ||
38 | #include <asm/perf_counter.h> | 37 | #include <asm/perf_counter.h> |
39 | #include <asm/atomic.h> | ||
40 | #include <asm/mtrr.h> | ||
41 | #include <asm/mpspec.h> | ||
42 | #include <asm/desc.h> | ||
43 | #include <asm/arch_hooks.h> | 38 | #include <asm/arch_hooks.h> |
44 | #include <asm/hpet.h> | ||
45 | #include <asm/pgalloc.h> | 39 | #include <asm/pgalloc.h> |
40 | #include <asm/genapic.h> | ||
41 | #include <asm/atomic.h> | ||
42 | #include <asm/mpspec.h> | ||
46 | #include <asm/i8253.h> | 43 | #include <asm/i8253.h> |
47 | #include <asm/idle.h> | 44 | #include <asm/i8259.h> |
48 | #include <asm/proto.h> | 45 | #include <asm/proto.h> |
49 | #include <asm/apic.h> | 46 | #include <asm/apic.h> |
50 | #include <asm/i8259.h> | 47 | #include <asm/desc.h> |
48 | #include <asm/hpet.h> | ||
49 | #include <asm/idle.h> | ||
50 | #include <asm/mtrr.h> | ||
51 | #include <asm/smp.h> | 51 | #include <asm/smp.h> |
52 | 52 | ||
53 | #include <mach_apic.h> | 53 | unsigned int num_processors; |
54 | #include <mach_apicdef.h> | 54 | |
55 | #include <mach_ipi.h> | 55 | unsigned disabled_cpus __cpuinitdata; |
56 | |||
57 | /* Processor that is doing the boot up */ | ||
58 | unsigned int boot_cpu_physical_apicid = -1U; | ||
56 | 59 | ||
57 | /* | 60 | /* |
58 | * Sanity check | 61 | * The highest APIC ID seen during enumeration. |
62 | * | ||
63 | * This determines the messaging protocol we can use: if all APIC IDs | ||
64 | * are in the 0 ... 7 range, then we can use logical addressing which | ||
65 | * has some performance advantages (better broadcasting). | ||
66 | * | ||
67 | * If there's an APIC ID above 8, we use physical addressing. | ||
59 | */ | 68 | */ |
60 | #if ((SPURIOUS_APIC_VECTOR & 0x0F) != 0x0F) | 69 | unsigned int max_physical_apicid; |
61 | # error SPURIOUS_APIC_VECTOR definition error | 70 | |
62 | #endif | 71 | /* |
72 | * Bitmask of physically existing CPUs: | ||
73 | */ | ||
74 | physid_mask_t phys_cpu_present_map; | ||
75 | |||
76 | /* | ||
77 | * Map cpu index to physical APIC ID | ||
78 | */ | ||
79 | DEFINE_EARLY_PER_CPU(u16, x86_cpu_to_apicid, BAD_APICID); | ||
80 | DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID); | ||
81 | EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid); | ||
82 | EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid); | ||
63 | 83 | ||
64 | #ifdef CONFIG_X86_32 | 84 | #ifdef CONFIG_X86_32 |
65 | /* | 85 | /* |
@@ -458,7 +478,7 @@ static void lapic_timer_setup(enum clock_event_mode mode, | |||
458 | static void lapic_timer_broadcast(const struct cpumask *mask) | 478 | static void lapic_timer_broadcast(const struct cpumask *mask) |
459 | { | 479 | { |
460 | #ifdef CONFIG_SMP | 480 | #ifdef CONFIG_SMP |
461 | send_IPI_mask(mask, LOCAL_TIMER_VECTOR); | 481 | apic->send_IPI_mask(mask, LOCAL_TIMER_VECTOR); |
462 | #endif | 482 | #endif |
463 | } | 483 | } |
464 | 484 | ||
@@ -536,7 +556,8 @@ static void __init lapic_cal_handler(struct clock_event_device *dev) | |||
536 | } | 556 | } |
537 | } | 557 | } |
538 | 558 | ||
539 | static int __init calibrate_by_pmtimer(long deltapm, long *delta) | 559 | static int __init |
560 | calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc) | ||
540 | { | 561 | { |
541 | const long pm_100ms = PMTMR_TICKS_PER_SEC / 10; | 562 | const long pm_100ms = PMTMR_TICKS_PER_SEC / 10; |
542 | const long pm_thresh = pm_100ms / 100; | 563 | const long pm_thresh = pm_100ms / 100; |
@@ -547,7 +568,7 @@ static int __init calibrate_by_pmtimer(long deltapm, long *delta) | |||
547 | return -1; | 568 | return -1; |
548 | #endif | 569 | #endif |
549 | 570 | ||
550 | apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm); | 571 | apic_printk(APIC_VERBOSE, "... PM-Timer delta = %ld\n", deltapm); |
551 | 572 | ||
552 | /* Check, if the PM timer is available */ | 573 | /* Check, if the PM timer is available */ |
553 | if (!deltapm) | 574 | if (!deltapm) |
@@ -557,19 +578,30 @@ static int __init calibrate_by_pmtimer(long deltapm, long *delta) | |||
557 | 578 | ||
558 | if (deltapm > (pm_100ms - pm_thresh) && | 579 | if (deltapm > (pm_100ms - pm_thresh) && |
559 | deltapm < (pm_100ms + pm_thresh)) { | 580 | deltapm < (pm_100ms + pm_thresh)) { |
560 | apic_printk(APIC_VERBOSE, "... PM timer result ok\n"); | 581 | apic_printk(APIC_VERBOSE, "... PM-Timer result ok\n"); |
561 | } else { | 582 | return 0; |
562 | res = (((u64)deltapm) * mult) >> 22; | 583 | } |
563 | do_div(res, 1000000); | 584 | |
564 | pr_warning("APIC calibration not consistent " | 585 | res = (((u64)deltapm) * mult) >> 22; |
565 | "with PM Timer: %ldms instead of 100ms\n", | 586 | do_div(res, 1000000); |
566 | (long)res); | 587 | pr_warning("APIC calibration not consistent " |
567 | /* Correct the lapic counter value */ | 588 | "with PM-Timer: %ldms instead of 100ms\n",(long)res); |
568 | res = (((u64)(*delta)) * pm_100ms); | 589 | |
590 | /* Correct the lapic counter value */ | ||
591 | res = (((u64)(*delta)) * pm_100ms); | ||
592 | do_div(res, deltapm); | ||
593 | pr_info("APIC delta adjusted to PM-Timer: " | ||
594 | "%lu (%ld)\n", (unsigned long)res, *delta); | ||
595 | *delta = (long)res; | ||
596 | |||
597 | /* Correct the tsc counter value */ | ||
598 | if (cpu_has_tsc) { | ||
599 | res = (((u64)(*deltatsc)) * pm_100ms); | ||
569 | do_div(res, deltapm); | 600 | do_div(res, deltapm); |
570 | pr_info("APIC delta adjusted to PM-Timer: " | 601 | apic_printk(APIC_VERBOSE, "TSC delta adjusted to " |
571 | "%lu (%ld)\n", (unsigned long)res, *delta); | 602 | "PM-Timer: %lu (%ld) \n", |
572 | *delta = (long)res; | 603 | (unsigned long)res, *deltatsc); |
604 | *deltatsc = (long)res; | ||
573 | } | 605 | } |
574 | 606 | ||
575 | return 0; | 607 | return 0; |
@@ -580,7 +612,7 @@ static int __init calibrate_APIC_clock(void) | |||
580 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); | 612 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); |
581 | void (*real_handler)(struct clock_event_device *dev); | 613 | void (*real_handler)(struct clock_event_device *dev); |
582 | unsigned long deltaj; | 614 | unsigned long deltaj; |
583 | long delta; | 615 | long delta, deltatsc; |
584 | int pm_referenced = 0; | 616 | int pm_referenced = 0; |
585 | 617 | ||
586 | local_irq_disable(); | 618 | local_irq_disable(); |
@@ -610,9 +642,11 @@ static int __init calibrate_APIC_clock(void) | |||
610 | delta = lapic_cal_t1 - lapic_cal_t2; | 642 | delta = lapic_cal_t1 - lapic_cal_t2; |
611 | apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta); | 643 | apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta); |
612 | 644 | ||
645 | deltatsc = (long)(lapic_cal_tsc2 - lapic_cal_tsc1); | ||
646 | |||
613 | /* we trust the PM based calibration if possible */ | 647 | /* we trust the PM based calibration if possible */ |
614 | pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1, | 648 | pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1, |
615 | &delta); | 649 | &delta, &deltatsc); |
616 | 650 | ||
617 | /* Calculate the scaled math multiplication factor */ | 651 | /* Calculate the scaled math multiplication factor */ |
618 | lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, | 652 | lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, |
@@ -630,11 +664,10 @@ static int __init calibrate_APIC_clock(void) | |||
630 | calibration_result); | 664 | calibration_result); |
631 | 665 | ||
632 | if (cpu_has_tsc) { | 666 | if (cpu_has_tsc) { |
633 | delta = (long)(lapic_cal_tsc2 - lapic_cal_tsc1); | ||
634 | apic_printk(APIC_VERBOSE, "..... CPU clock speed is " | 667 | apic_printk(APIC_VERBOSE, "..... CPU clock speed is " |
635 | "%ld.%04ld MHz.\n", | 668 | "%ld.%04ld MHz.\n", |
636 | (delta / LAPIC_CAL_LOOPS) / (1000000 / HZ), | 669 | (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ), |
637 | (delta / LAPIC_CAL_LOOPS) % (1000000 / HZ)); | 670 | (deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ)); |
638 | } | 671 | } |
639 | 672 | ||
640 | apic_printk(APIC_VERBOSE, "..... host bus clock speed is " | 673 | apic_printk(APIC_VERBOSE, "..... host bus clock speed is " |
@@ -994,11 +1027,11 @@ int __init verify_local_APIC(void) | |||
994 | */ | 1027 | */ |
995 | reg0 = apic_read(APIC_ID); | 1028 | reg0 = apic_read(APIC_ID); |
996 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); | 1029 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); |
997 | apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); | 1030 | apic_write(APIC_ID, reg0 ^ apic->apic_id_mask); |
998 | reg1 = apic_read(APIC_ID); | 1031 | reg1 = apic_read(APIC_ID); |
999 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); | 1032 | apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); |
1000 | apic_write(APIC_ID, reg0); | 1033 | apic_write(APIC_ID, reg0); |
1001 | if (reg1 != (reg0 ^ APIC_ID_MASK)) | 1034 | if (reg1 != (reg0 ^ apic->apic_id_mask)) |
1002 | return 0; | 1035 | return 0; |
1003 | 1036 | ||
1004 | /* | 1037 | /* |
@@ -1092,7 +1125,7 @@ static void __cpuinit lapic_setup_esr(void) | |||
1092 | return; | 1125 | return; |
1093 | } | 1126 | } |
1094 | 1127 | ||
1095 | if (esr_disable) { | 1128 | if (apic->disable_esr) { |
1096 | /* | 1129 | /* |
1097 | * Something untraceable is creating bad interrupts on | 1130 | * Something untraceable is creating bad interrupts on |
1098 | * secondary quads ... for the moment, just leave the | 1131 | * secondary quads ... for the moment, just leave the |
@@ -1134,15 +1167,13 @@ void __cpuinit setup_local_APIC(void) | |||
1134 | int i, j; | 1167 | int i, j; |
1135 | 1168 | ||
1136 | if (disable_apic) { | 1169 | if (disable_apic) { |
1137 | #ifdef CONFIG_X86_IO_APIC | 1170 | arch_disable_smp_support(); |
1138 | disable_ioapic_setup(); | ||
1139 | #endif | ||
1140 | return; | 1171 | return; |
1141 | } | 1172 | } |
1142 | 1173 | ||
1143 | #ifdef CONFIG_X86_32 | 1174 | #ifdef CONFIG_X86_32 |
1144 | /* Pound the ESR really hard over the head with a big hammer - mbligh */ | 1175 | /* Pound the ESR really hard over the head with a big hammer - mbligh */ |
1145 | if (lapic_is_integrated() && esr_disable) { | 1176 | if (lapic_is_integrated() && apic->disable_esr) { |
1146 | apic_write(APIC_ESR, 0); | 1177 | apic_write(APIC_ESR, 0); |
1147 | apic_write(APIC_ESR, 0); | 1178 | apic_write(APIC_ESR, 0); |
1148 | apic_write(APIC_ESR, 0); | 1179 | apic_write(APIC_ESR, 0); |
@@ -1157,7 +1188,7 @@ void __cpuinit setup_local_APIC(void) | |||
1157 | * Double-check whether this APIC is really registered. | 1188 | * Double-check whether this APIC is really registered. |
1158 | * This is meaningless in clustered apic mode, so we skip it. | 1189 | * This is meaningless in clustered apic mode, so we skip it. |
1159 | */ | 1190 | */ |
1160 | if (!apic_id_registered()) | 1191 | if (!apic->apic_id_registered()) |
1161 | BUG(); | 1192 | BUG(); |
1162 | 1193 | ||
1163 | /* | 1194 | /* |
@@ -1165,7 +1196,7 @@ void __cpuinit setup_local_APIC(void) | |||
1165 | * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel | 1196 | * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel |
1166 | * document number 292116). So here it goes... | 1197 | * document number 292116). So here it goes... |
1167 | */ | 1198 | */ |
1168 | init_apic_ldr(); | 1199 | apic->init_apic_ldr(); |
1169 | 1200 | ||
1170 | /* | 1201 | /* |
1171 | * Set Task Priority to 'accept all'. We never change this | 1202 | * Set Task Priority to 'accept all'. We never change this |
@@ -1611,7 +1642,7 @@ int __init APIC_init_uniprocessor(void) | |||
1611 | enable_IR_x2apic(); | 1642 | enable_IR_x2apic(); |
1612 | #endif | 1643 | #endif |
1613 | #ifdef CONFIG_X86_64 | 1644 | #ifdef CONFIG_X86_64 |
1614 | setup_apic_routing(); | 1645 | default_setup_apic_routing(); |
1615 | #endif | 1646 | #endif |
1616 | 1647 | ||
1617 | verify_local_APIC(); | 1648 | verify_local_APIC(); |
@@ -1749,7 +1780,8 @@ void __init connect_bsp_APIC(void) | |||
1749 | outb(0x01, 0x23); | 1780 | outb(0x01, 0x23); |
1750 | } | 1781 | } |
1751 | #endif | 1782 | #endif |
1752 | enable_apic_mode(); | 1783 | if (apic->enable_apic_mode) |
1784 | apic->enable_apic_mode(); | ||
1753 | } | 1785 | } |
1754 | 1786 | ||
1755 | /** | 1787 | /** |
@@ -1887,7 +1919,7 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1887 | } | 1919 | } |
1888 | #endif | 1920 | #endif |
1889 | 1921 | ||
1890 | #if defined(CONFIG_X86_SMP) || defined(CONFIG_X86_64) | 1922 | #if defined(CONFIG_SMP) || defined(CONFIG_X86_64) |
1891 | early_per_cpu(x86_cpu_to_apicid, cpu) = apicid; | 1923 | early_per_cpu(x86_cpu_to_apicid, cpu) = apicid; |
1892 | early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid; | 1924 | early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid; |
1893 | #endif | 1925 | #endif |
@@ -1896,11 +1928,30 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1896 | set_cpu_present(cpu, true); | 1928 | set_cpu_present(cpu, true); |
1897 | } | 1929 | } |
1898 | 1930 | ||
1899 | #ifdef CONFIG_X86_64 | ||
1900 | int hard_smp_processor_id(void) | 1931 | int hard_smp_processor_id(void) |
1901 | { | 1932 | { |
1902 | return read_apic_id(); | 1933 | return read_apic_id(); |
1903 | } | 1934 | } |
1935 | |||
1936 | void default_init_apic_ldr(void) | ||
1937 | { | ||
1938 | unsigned long val; | ||
1939 | |||
1940 | apic_write(APIC_DFR, APIC_DFR_VALUE); | ||
1941 | val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; | ||
1942 | val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); | ||
1943 | apic_write(APIC_LDR, val); | ||
1944 | } | ||
1945 | |||
1946 | #ifdef CONFIG_X86_32 | ||
1947 | int default_apicid_to_node(int logical_apicid) | ||
1948 | { | ||
1949 | #ifdef CONFIG_SMP | ||
1950 | return apicid_2_node[hard_smp_processor_id()]; | ||
1951 | #else | ||
1952 | return 0; | ||
1953 | #endif | ||
1954 | } | ||
1904 | #endif | 1955 | #endif |
1905 | 1956 | ||
1906 | /* | 1957 | /* |