Commit a3a255e744dfa672e741dc24306491139d0de2d8
Committed by
Linus Torvalds
1 parent
129f69465b
Exists in
master
and in
7 other branches
[PATCH] x86: cpu_khz type fix
x86_64's cpu_khz is unsigned int and there is no reason why x86 needs to use unsigned long. So make cpu_khz unsigned int on x86 as well. Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 7 changed files with 11 additions and 9 deletions Inline Diff
arch/i386/kernel/cpu/proc.c
1 | #include <linux/smp.h> | 1 | #include <linux/smp.h> |
2 | #include <linux/timex.h> | 2 | #include <linux/timex.h> |
3 | #include <linux/string.h> | 3 | #include <linux/string.h> |
4 | #include <asm/semaphore.h> | 4 | #include <asm/semaphore.h> |
5 | #include <linux/seq_file.h> | 5 | #include <linux/seq_file.h> |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Get CPU information for use by the procfs. | 8 | * Get CPU information for use by the procfs. |
9 | */ | 9 | */ |
10 | static int show_cpuinfo(struct seq_file *m, void *v) | 10 | static int show_cpuinfo(struct seq_file *m, void *v) |
11 | { | 11 | { |
12 | /* | 12 | /* |
13 | * These flag bits must match the definitions in <asm/cpufeature.h>. | 13 | * These flag bits must match the definitions in <asm/cpufeature.h>. |
14 | * NULL means this bit is undefined or reserved; either way it doesn't | 14 | * NULL means this bit is undefined or reserved; either way it doesn't |
15 | * have meaning as far as Linux is concerned. Note that it's important | 15 | * have meaning as far as Linux is concerned. Note that it's important |
16 | * to realize there is a difference between this table and CPUID -- if | 16 | * to realize there is a difference between this table and CPUID -- if |
17 | * applications want to get the raw CPUID data, they should access | 17 | * applications want to get the raw CPUID data, they should access |
18 | * /dev/cpu/<cpu_nr>/cpuid instead. | 18 | * /dev/cpu/<cpu_nr>/cpuid instead. |
19 | */ | 19 | */ |
20 | static char *x86_cap_flags[] = { | 20 | static char *x86_cap_flags[] = { |
21 | /* Intel-defined */ | 21 | /* Intel-defined */ |
22 | "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", | 22 | "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", |
23 | "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", | 23 | "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", |
24 | "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", | 24 | "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", |
25 | "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe", | 25 | "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe", |
26 | 26 | ||
27 | /* AMD-defined */ | 27 | /* AMD-defined */ |
28 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 28 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
29 | NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, | 29 | NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, |
30 | NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, | 30 | NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, |
31 | NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow", | 31 | NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow", |
32 | 32 | ||
33 | /* Transmeta-defined */ | 33 | /* Transmeta-defined */ |
34 | "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, | 34 | "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, |
35 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 35 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
36 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 36 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
37 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 37 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
38 | 38 | ||
39 | /* Other (Linux-defined) */ | 39 | /* Other (Linux-defined) */ |
40 | "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", | 40 | "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", |
41 | NULL, NULL, NULL, NULL, | 41 | NULL, NULL, NULL, NULL, |
42 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 42 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
43 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 43 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
44 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 44 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
45 | 45 | ||
46 | /* Intel-defined (#2) */ | 46 | /* Intel-defined (#2) */ |
47 | "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est", | 47 | "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est", |
48 | "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL, | 48 | "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL, |
49 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 49 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
50 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 50 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
51 | 51 | ||
52 | /* VIA/Cyrix/Centaur-defined */ | 52 | /* VIA/Cyrix/Centaur-defined */ |
53 | NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", | 53 | NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", |
54 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 54 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
55 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 55 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
56 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 56 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
57 | 57 | ||
58 | /* AMD-defined (#2) */ | 58 | /* AMD-defined (#2) */ |
59 | "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL, | 59 | "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL, |
60 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 60 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
61 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 61 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
62 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 62 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
63 | }; | 63 | }; |
64 | struct cpuinfo_x86 *c = v; | 64 | struct cpuinfo_x86 *c = v; |
65 | int i, n = c - cpu_data; | 65 | int i, n = c - cpu_data; |
66 | int fpu_exception; | 66 | int fpu_exception; |
67 | 67 | ||
68 | #ifdef CONFIG_SMP | 68 | #ifdef CONFIG_SMP |
69 | if (!cpu_online(n)) | 69 | if (!cpu_online(n)) |
70 | return 0; | 70 | return 0; |
71 | #endif | 71 | #endif |
72 | seq_printf(m, "processor\t: %d\n" | 72 | seq_printf(m, "processor\t: %d\n" |
73 | "vendor_id\t: %s\n" | 73 | "vendor_id\t: %s\n" |
74 | "cpu family\t: %d\n" | 74 | "cpu family\t: %d\n" |
75 | "model\t\t: %d\n" | 75 | "model\t\t: %d\n" |
76 | "model name\t: %s\n", | 76 | "model name\t: %s\n", |
77 | n, | 77 | n, |
78 | c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", | 78 | c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", |
79 | c->x86, | 79 | c->x86, |
80 | c->x86_model, | 80 | c->x86_model, |
81 | c->x86_model_id[0] ? c->x86_model_id : "unknown"); | 81 | c->x86_model_id[0] ? c->x86_model_id : "unknown"); |
82 | 82 | ||
83 | if (c->x86_mask || c->cpuid_level >= 0) | 83 | if (c->x86_mask || c->cpuid_level >= 0) |
84 | seq_printf(m, "stepping\t: %d\n", c->x86_mask); | 84 | seq_printf(m, "stepping\t: %d\n", c->x86_mask); |
85 | else | 85 | else |
86 | seq_printf(m, "stepping\t: unknown\n"); | 86 | seq_printf(m, "stepping\t: unknown\n"); |
87 | 87 | ||
88 | if ( cpu_has(c, X86_FEATURE_TSC) ) { | 88 | if ( cpu_has(c, X86_FEATURE_TSC) ) { |
89 | seq_printf(m, "cpu MHz\t\t: %lu.%03lu\n", | 89 | seq_printf(m, "cpu MHz\t\t: %u.%03u\n", |
90 | cpu_khz / 1000, (cpu_khz % 1000)); | 90 | cpu_khz / 1000, (cpu_khz % 1000)); |
91 | } | 91 | } |
92 | 92 | ||
93 | /* Cache size */ | 93 | /* Cache size */ |
94 | if (c->x86_cache_size >= 0) | 94 | if (c->x86_cache_size >= 0) |
95 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); | 95 | seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); |
96 | #ifdef CONFIG_X86_HT | 96 | #ifdef CONFIG_X86_HT |
97 | if (c->x86_num_cores * smp_num_siblings > 1) { | 97 | if (c->x86_num_cores * smp_num_siblings > 1) { |
98 | seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); | 98 | seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); |
99 | seq_printf(m, "siblings\t: %d\n", | 99 | seq_printf(m, "siblings\t: %d\n", |
100 | c->x86_num_cores * smp_num_siblings); | 100 | c->x86_num_cores * smp_num_siblings); |
101 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]); | 101 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]); |
102 | seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); | 102 | seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); |
103 | } | 103 | } |
104 | #endif | 104 | #endif |
105 | 105 | ||
106 | /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */ | 106 | /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */ |
107 | fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu); | 107 | fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu); |
108 | seq_printf(m, "fdiv_bug\t: %s\n" | 108 | seq_printf(m, "fdiv_bug\t: %s\n" |
109 | "hlt_bug\t\t: %s\n" | 109 | "hlt_bug\t\t: %s\n" |
110 | "f00f_bug\t: %s\n" | 110 | "f00f_bug\t: %s\n" |
111 | "coma_bug\t: %s\n" | 111 | "coma_bug\t: %s\n" |
112 | "fpu\t\t: %s\n" | 112 | "fpu\t\t: %s\n" |
113 | "fpu_exception\t: %s\n" | 113 | "fpu_exception\t: %s\n" |
114 | "cpuid level\t: %d\n" | 114 | "cpuid level\t: %d\n" |
115 | "wp\t\t: %s\n" | 115 | "wp\t\t: %s\n" |
116 | "flags\t\t:", | 116 | "flags\t\t:", |
117 | c->fdiv_bug ? "yes" : "no", | 117 | c->fdiv_bug ? "yes" : "no", |
118 | c->hlt_works_ok ? "no" : "yes", | 118 | c->hlt_works_ok ? "no" : "yes", |
119 | c->f00f_bug ? "yes" : "no", | 119 | c->f00f_bug ? "yes" : "no", |
120 | c->coma_bug ? "yes" : "no", | 120 | c->coma_bug ? "yes" : "no", |
121 | c->hard_math ? "yes" : "no", | 121 | c->hard_math ? "yes" : "no", |
122 | fpu_exception ? "yes" : "no", | 122 | fpu_exception ? "yes" : "no", |
123 | c->cpuid_level, | 123 | c->cpuid_level, |
124 | c->wp_works_ok ? "yes" : "no"); | 124 | c->wp_works_ok ? "yes" : "no"); |
125 | 125 | ||
126 | for ( i = 0 ; i < 32*NCAPINTS ; i++ ) | 126 | for ( i = 0 ; i < 32*NCAPINTS ; i++ ) |
127 | if ( test_bit(i, c->x86_capability) && | 127 | if ( test_bit(i, c->x86_capability) && |
128 | x86_cap_flags[i] != NULL ) | 128 | x86_cap_flags[i] != NULL ) |
129 | seq_printf(m, " %s", x86_cap_flags[i]); | 129 | seq_printf(m, " %s", x86_cap_flags[i]); |
130 | 130 | ||
131 | seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n", | 131 | seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n", |
132 | c->loops_per_jiffy/(500000/HZ), | 132 | c->loops_per_jiffy/(500000/HZ), |
133 | (c->loops_per_jiffy/(5000/HZ)) % 100); | 133 | (c->loops_per_jiffy/(5000/HZ)) % 100); |
134 | 134 | ||
135 | return 0; | 135 | return 0; |
136 | } | 136 | } |
137 | 137 | ||
138 | static void *c_start(struct seq_file *m, loff_t *pos) | 138 | static void *c_start(struct seq_file *m, loff_t *pos) |
139 | { | 139 | { |
140 | return *pos < NR_CPUS ? cpu_data + *pos : NULL; | 140 | return *pos < NR_CPUS ? cpu_data + *pos : NULL; |
141 | } | 141 | } |
142 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | 142 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) |
143 | { | 143 | { |
144 | ++*pos; | 144 | ++*pos; |
145 | return c_start(m, pos); | 145 | return c_start(m, pos); |
146 | } | 146 | } |
147 | static void c_stop(struct seq_file *m, void *v) | 147 | static void c_stop(struct seq_file *m, void *v) |
148 | { | 148 | { |
149 | } | 149 | } |
150 | struct seq_operations cpuinfo_op = { | 150 | struct seq_operations cpuinfo_op = { |
151 | .start = c_start, | 151 | .start = c_start, |
152 | .next = c_next, | 152 | .next = c_next, |
153 | .stop = c_stop, | 153 | .stop = c_stop, |
154 | .show = show_cpuinfo, | 154 | .show = show_cpuinfo, |
155 | }; | 155 | }; |
156 | 156 |
arch/i386/kernel/smpboot.c
1 | /* | 1 | /* |
2 | * x86 SMP booting functions | 2 | * x86 SMP booting functions |
3 | * | 3 | * |
4 | * (c) 1995 Alan Cox, Building #3 <alan@redhat.com> | 4 | * (c) 1995 Alan Cox, Building #3 <alan@redhat.com> |
5 | * (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com> | 5 | * (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com> |
6 | * | 6 | * |
7 | * Much of the core SMP work is based on previous work by Thomas Radke, to | 7 | * Much of the core SMP work is based on previous work by Thomas Radke, to |
8 | * whom a great many thanks are extended. | 8 | * whom a great many thanks are extended. |
9 | * | 9 | * |
10 | * Thanks to Intel for making available several different Pentium, | 10 | * Thanks to Intel for making available several different Pentium, |
11 | * Pentium Pro and Pentium-II/Xeon MP machines. | 11 | * Pentium Pro and Pentium-II/Xeon MP machines. |
12 | * Original development of Linux SMP code supported by Caldera. | 12 | * Original development of Linux SMP code supported by Caldera. |
13 | * | 13 | * |
14 | * This code is released under the GNU General Public License version 2 or | 14 | * This code is released under the GNU General Public License version 2 or |
15 | * later. | 15 | * later. |
16 | * | 16 | * |
17 | * Fixes | 17 | * Fixes |
18 | * Felix Koop : NR_CPUS used properly | 18 | * Felix Koop : NR_CPUS used properly |
19 | * Jose Renau : Handle single CPU case. | 19 | * Jose Renau : Handle single CPU case. |
20 | * Alan Cox : By repeated request 8) - Total BogoMIPS report. | 20 | * Alan Cox : By repeated request 8) - Total BogoMIPS report. |
21 | * Greg Wright : Fix for kernel stacks panic. | 21 | * Greg Wright : Fix for kernel stacks panic. |
22 | * Erich Boleyn : MP v1.4 and additional changes. | 22 | * Erich Boleyn : MP v1.4 and additional changes. |
23 | * Matthias Sattler : Changes for 2.1 kernel map. | 23 | * Matthias Sattler : Changes for 2.1 kernel map. |
24 | * Michel Lespinasse : Changes for 2.1 kernel map. | 24 | * Michel Lespinasse : Changes for 2.1 kernel map. |
25 | * Michael Chastain : Change trampoline.S to gnu as. | 25 | * Michael Chastain : Change trampoline.S to gnu as. |
26 | * Alan Cox : Dumb bug: 'B' step PPro's are fine | 26 | * Alan Cox : Dumb bug: 'B' step PPro's are fine |
27 | * Ingo Molnar : Added APIC timers, based on code | 27 | * Ingo Molnar : Added APIC timers, based on code |
28 | * from Jose Renau | 28 | * from Jose Renau |
29 | * Ingo Molnar : various cleanups and rewrites | 29 | * Ingo Molnar : various cleanups and rewrites |
30 | * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug. | 30 | * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug. |
31 | * Maciej W. Rozycki : Bits for genuine 82489DX APICs | 31 | * Maciej W. Rozycki : Bits for genuine 82489DX APICs |
32 | * Martin J. Bligh : Added support for multi-quad systems | 32 | * Martin J. Bligh : Added support for multi-quad systems |
33 | * Dave Jones : Report invalid combinations of Athlon CPUs. | 33 | * Dave Jones : Report invalid combinations of Athlon CPUs. |
34 | * Rusty Russell : Hacked into shape for new "hotplug" boot process. */ | 34 | * Rusty Russell : Hacked into shape for new "hotplug" boot process. */ |
35 | 35 | ||
36 | #include <linux/module.h> | 36 | #include <linux/module.h> |
37 | #include <linux/config.h> | 37 | #include <linux/config.h> |
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/kernel.h> | 39 | #include <linux/kernel.h> |
40 | 40 | ||
41 | #include <linux/mm.h> | 41 | #include <linux/mm.h> |
42 | #include <linux/sched.h> | 42 | #include <linux/sched.h> |
43 | #include <linux/kernel_stat.h> | 43 | #include <linux/kernel_stat.h> |
44 | #include <linux/smp_lock.h> | 44 | #include <linux/smp_lock.h> |
45 | #include <linux/irq.h> | 45 | #include <linux/irq.h> |
46 | #include <linux/bootmem.h> | 46 | #include <linux/bootmem.h> |
47 | 47 | ||
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/mc146818rtc.h> | 49 | #include <linux/mc146818rtc.h> |
50 | #include <asm/tlbflush.h> | 50 | #include <asm/tlbflush.h> |
51 | #include <asm/desc.h> | 51 | #include <asm/desc.h> |
52 | #include <asm/arch_hooks.h> | 52 | #include <asm/arch_hooks.h> |
53 | 53 | ||
54 | #include <mach_apic.h> | 54 | #include <mach_apic.h> |
55 | #include <mach_wakecpu.h> | 55 | #include <mach_wakecpu.h> |
56 | #include <smpboot_hooks.h> | 56 | #include <smpboot_hooks.h> |
57 | 57 | ||
58 | /* Set if we find a B stepping CPU */ | 58 | /* Set if we find a B stepping CPU */ |
59 | static int __initdata smp_b_stepping; | 59 | static int __initdata smp_b_stepping; |
60 | 60 | ||
61 | /* Number of siblings per CPU package */ | 61 | /* Number of siblings per CPU package */ |
62 | int smp_num_siblings = 1; | 62 | int smp_num_siblings = 1; |
63 | #ifdef CONFIG_X86_HT | 63 | #ifdef CONFIG_X86_HT |
64 | EXPORT_SYMBOL(smp_num_siblings); | 64 | EXPORT_SYMBOL(smp_num_siblings); |
65 | #endif | 65 | #endif |
66 | int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ | 66 | int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ |
67 | EXPORT_SYMBOL(phys_proc_id); | 67 | EXPORT_SYMBOL(phys_proc_id); |
68 | int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */ | 68 | int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */ |
69 | EXPORT_SYMBOL(cpu_core_id); | 69 | EXPORT_SYMBOL(cpu_core_id); |
70 | 70 | ||
71 | /* bitmap of online cpus */ | 71 | /* bitmap of online cpus */ |
72 | cpumask_t cpu_online_map; | 72 | cpumask_t cpu_online_map; |
73 | EXPORT_SYMBOL(cpu_online_map); | 73 | EXPORT_SYMBOL(cpu_online_map); |
74 | 74 | ||
75 | cpumask_t cpu_callin_map; | 75 | cpumask_t cpu_callin_map; |
76 | cpumask_t cpu_callout_map; | 76 | cpumask_t cpu_callout_map; |
77 | EXPORT_SYMBOL(cpu_callout_map); | 77 | EXPORT_SYMBOL(cpu_callout_map); |
78 | static cpumask_t smp_commenced_mask; | 78 | static cpumask_t smp_commenced_mask; |
79 | 79 | ||
80 | /* Per CPU bogomips and other parameters */ | 80 | /* Per CPU bogomips and other parameters */ |
81 | struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; | 81 | struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; |
82 | EXPORT_SYMBOL(cpu_data); | 82 | EXPORT_SYMBOL(cpu_data); |
83 | 83 | ||
84 | u8 x86_cpu_to_apicid[NR_CPUS] = | 84 | u8 x86_cpu_to_apicid[NR_CPUS] = |
85 | { [0 ... NR_CPUS-1] = 0xff }; | 85 | { [0 ... NR_CPUS-1] = 0xff }; |
86 | EXPORT_SYMBOL(x86_cpu_to_apicid); | 86 | EXPORT_SYMBOL(x86_cpu_to_apicid); |
87 | 87 | ||
88 | /* | 88 | /* |
89 | * Trampoline 80x86 program as an array. | 89 | * Trampoline 80x86 program as an array. |
90 | */ | 90 | */ |
91 | 91 | ||
92 | extern unsigned char trampoline_data []; | 92 | extern unsigned char trampoline_data []; |
93 | extern unsigned char trampoline_end []; | 93 | extern unsigned char trampoline_end []; |
94 | static unsigned char *trampoline_base; | 94 | static unsigned char *trampoline_base; |
95 | static int trampoline_exec; | 95 | static int trampoline_exec; |
96 | 96 | ||
97 | static void map_cpu_to_logical_apicid(void); | 97 | static void map_cpu_to_logical_apicid(void); |
98 | 98 | ||
99 | /* | 99 | /* |
100 | * Currently trivial. Write the real->protected mode | 100 | * Currently trivial. Write the real->protected mode |
101 | * bootstrap into the page concerned. The caller | 101 | * bootstrap into the page concerned. The caller |
102 | * has made sure it's suitably aligned. | 102 | * has made sure it's suitably aligned. |
103 | */ | 103 | */ |
104 | 104 | ||
105 | static unsigned long __init setup_trampoline(void) | 105 | static unsigned long __init setup_trampoline(void) |
106 | { | 106 | { |
107 | memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data); | 107 | memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data); |
108 | return virt_to_phys(trampoline_base); | 108 | return virt_to_phys(trampoline_base); |
109 | } | 109 | } |
110 | 110 | ||
111 | /* | 111 | /* |
112 | * We are called very early to get the low memory for the | 112 | * We are called very early to get the low memory for the |
113 | * SMP bootup trampoline page. | 113 | * SMP bootup trampoline page. |
114 | */ | 114 | */ |
115 | void __init smp_alloc_memory(void) | 115 | void __init smp_alloc_memory(void) |
116 | { | 116 | { |
117 | trampoline_base = (void *) alloc_bootmem_low_pages(PAGE_SIZE); | 117 | trampoline_base = (void *) alloc_bootmem_low_pages(PAGE_SIZE); |
118 | /* | 118 | /* |
119 | * Has to be in very low memory so we can execute | 119 | * Has to be in very low memory so we can execute |
120 | * real-mode AP code. | 120 | * real-mode AP code. |
121 | */ | 121 | */ |
122 | if (__pa(trampoline_base) >= 0x9F000) | 122 | if (__pa(trampoline_base) >= 0x9F000) |
123 | BUG(); | 123 | BUG(); |
124 | /* | 124 | /* |
125 | * Make the SMP trampoline executable: | 125 | * Make the SMP trampoline executable: |
126 | */ | 126 | */ |
127 | trampoline_exec = set_kernel_exec((unsigned long)trampoline_base, 1); | 127 | trampoline_exec = set_kernel_exec((unsigned long)trampoline_base, 1); |
128 | } | 128 | } |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * The bootstrap kernel entry code has set these up. Save them for | 131 | * The bootstrap kernel entry code has set these up. Save them for |
132 | * a given CPU | 132 | * a given CPU |
133 | */ | 133 | */ |
134 | 134 | ||
135 | static void __init smp_store_cpu_info(int id) | 135 | static void __init smp_store_cpu_info(int id) |
136 | { | 136 | { |
137 | struct cpuinfo_x86 *c = cpu_data + id; | 137 | struct cpuinfo_x86 *c = cpu_data + id; |
138 | 138 | ||
139 | *c = boot_cpu_data; | 139 | *c = boot_cpu_data; |
140 | if (id!=0) | 140 | if (id!=0) |
141 | identify_cpu(c); | 141 | identify_cpu(c); |
142 | /* | 142 | /* |
143 | * Mask B, Pentium, but not Pentium MMX | 143 | * Mask B, Pentium, but not Pentium MMX |
144 | */ | 144 | */ |
145 | if (c->x86_vendor == X86_VENDOR_INTEL && | 145 | if (c->x86_vendor == X86_VENDOR_INTEL && |
146 | c->x86 == 5 && | 146 | c->x86 == 5 && |
147 | c->x86_mask >= 1 && c->x86_mask <= 4 && | 147 | c->x86_mask >= 1 && c->x86_mask <= 4 && |
148 | c->x86_model <= 3) | 148 | c->x86_model <= 3) |
149 | /* | 149 | /* |
150 | * Remember we have B step Pentia with bugs | 150 | * Remember we have B step Pentia with bugs |
151 | */ | 151 | */ |
152 | smp_b_stepping = 1; | 152 | smp_b_stepping = 1; |
153 | 153 | ||
154 | /* | 154 | /* |
155 | * Certain Athlons might work (for various values of 'work') in SMP | 155 | * Certain Athlons might work (for various values of 'work') in SMP |
156 | * but they are not certified as MP capable. | 156 | * but they are not certified as MP capable. |
157 | */ | 157 | */ |
158 | if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) { | 158 | if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) { |
159 | 159 | ||
160 | /* Athlon 660/661 is valid. */ | 160 | /* Athlon 660/661 is valid. */ |
161 | if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1))) | 161 | if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1))) |
162 | goto valid_k7; | 162 | goto valid_k7; |
163 | 163 | ||
164 | /* Duron 670 is valid */ | 164 | /* Duron 670 is valid */ |
165 | if ((c->x86_model==7) && (c->x86_mask==0)) | 165 | if ((c->x86_model==7) && (c->x86_mask==0)) |
166 | goto valid_k7; | 166 | goto valid_k7; |
167 | 167 | ||
168 | /* | 168 | /* |
169 | * Athlon 662, Duron 671, and Athlon >model 7 have capability bit. | 169 | * Athlon 662, Duron 671, and Athlon >model 7 have capability bit. |
170 | * It's worth noting that the A5 stepping (662) of some Athlon XP's | 170 | * It's worth noting that the A5 stepping (662) of some Athlon XP's |
171 | * have the MP bit set. | 171 | * have the MP bit set. |
172 | * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for more. | 172 | * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for more. |
173 | */ | 173 | */ |
174 | if (((c->x86_model==6) && (c->x86_mask>=2)) || | 174 | if (((c->x86_model==6) && (c->x86_mask>=2)) || |
175 | ((c->x86_model==7) && (c->x86_mask>=1)) || | 175 | ((c->x86_model==7) && (c->x86_mask>=1)) || |
176 | (c->x86_model> 7)) | 176 | (c->x86_model> 7)) |
177 | if (cpu_has_mp) | 177 | if (cpu_has_mp) |
178 | goto valid_k7; | 178 | goto valid_k7; |
179 | 179 | ||
180 | /* If we get here, it's not a certified SMP capable AMD system. */ | 180 | /* If we get here, it's not a certified SMP capable AMD system. */ |
181 | tainted |= TAINT_UNSAFE_SMP; | 181 | tainted |= TAINT_UNSAFE_SMP; |
182 | } | 182 | } |
183 | 183 | ||
184 | valid_k7: | 184 | valid_k7: |
185 | ; | 185 | ; |
186 | } | 186 | } |
187 | 187 | ||
188 | /* | 188 | /* |
189 | * TSC synchronization. | 189 | * TSC synchronization. |
190 | * | 190 | * |
191 | * We first check whether all CPUs have their TSC's synchronized, | 191 | * We first check whether all CPUs have their TSC's synchronized, |
192 | * then we print a warning if not, and always resync. | 192 | * then we print a warning if not, and always resync. |
193 | */ | 193 | */ |
194 | 194 | ||
195 | static atomic_t tsc_start_flag = ATOMIC_INIT(0); | 195 | static atomic_t tsc_start_flag = ATOMIC_INIT(0); |
196 | static atomic_t tsc_count_start = ATOMIC_INIT(0); | 196 | static atomic_t tsc_count_start = ATOMIC_INIT(0); |
197 | static atomic_t tsc_count_stop = ATOMIC_INIT(0); | 197 | static atomic_t tsc_count_stop = ATOMIC_INIT(0); |
198 | static unsigned long long tsc_values[NR_CPUS]; | 198 | static unsigned long long tsc_values[NR_CPUS]; |
199 | 199 | ||
200 | #define NR_LOOPS 5 | 200 | #define NR_LOOPS 5 |
201 | 201 | ||
202 | static void __init synchronize_tsc_bp (void) | 202 | static void __init synchronize_tsc_bp (void) |
203 | { | 203 | { |
204 | int i; | 204 | int i; |
205 | unsigned long long t0; | 205 | unsigned long long t0; |
206 | unsigned long long sum, avg; | 206 | unsigned long long sum, avg; |
207 | long long delta; | 207 | long long delta; |
208 | unsigned long one_usec; | 208 | unsigned int one_usec; |
209 | int buggy = 0; | 209 | int buggy = 0; |
210 | 210 | ||
211 | printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus()); | 211 | printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus()); |
212 | 212 | ||
213 | /* convert from kcyc/sec to cyc/usec */ | 213 | /* convert from kcyc/sec to cyc/usec */ |
214 | one_usec = cpu_khz / 1000; | 214 | one_usec = cpu_khz / 1000; |
215 | 215 | ||
216 | atomic_set(&tsc_start_flag, 1); | 216 | atomic_set(&tsc_start_flag, 1); |
217 | wmb(); | 217 | wmb(); |
218 | 218 | ||
219 | /* | 219 | /* |
220 | * We loop a few times to get a primed instruction cache, | 220 | * We loop a few times to get a primed instruction cache, |
221 | * then the last pass is more or less synchronized and | 221 | * then the last pass is more or less synchronized and |
222 | * the BP and APs set their cycle counters to zero all at | 222 | * the BP and APs set their cycle counters to zero all at |
223 | * once. This reduces the chance of having random offsets | 223 | * once. This reduces the chance of having random offsets |
224 | * between the processors, and guarantees that the maximum | 224 | * between the processors, and guarantees that the maximum |
225 | * delay between the cycle counters is never bigger than | 225 | * delay between the cycle counters is never bigger than |
226 | * the latency of information-passing (cachelines) between | 226 | * the latency of information-passing (cachelines) between |
227 | * two CPUs. | 227 | * two CPUs. |
228 | */ | 228 | */ |
229 | for (i = 0; i < NR_LOOPS; i++) { | 229 | for (i = 0; i < NR_LOOPS; i++) { |
230 | /* | 230 | /* |
231 | * all APs synchronize but they loop on '== num_cpus' | 231 | * all APs synchronize but they loop on '== num_cpus' |
232 | */ | 232 | */ |
233 | while (atomic_read(&tsc_count_start) != num_booting_cpus()-1) | 233 | while (atomic_read(&tsc_count_start) != num_booting_cpus()-1) |
234 | mb(); | 234 | mb(); |
235 | atomic_set(&tsc_count_stop, 0); | 235 | atomic_set(&tsc_count_stop, 0); |
236 | wmb(); | 236 | wmb(); |
237 | /* | 237 | /* |
238 | * this lets the APs save their current TSC: | 238 | * this lets the APs save their current TSC: |
239 | */ | 239 | */ |
240 | atomic_inc(&tsc_count_start); | 240 | atomic_inc(&tsc_count_start); |
241 | 241 | ||
242 | rdtscll(tsc_values[smp_processor_id()]); | 242 | rdtscll(tsc_values[smp_processor_id()]); |
243 | /* | 243 | /* |
244 | * We clear the TSC in the last loop: | 244 | * We clear the TSC in the last loop: |
245 | */ | 245 | */ |
246 | if (i == NR_LOOPS-1) | 246 | if (i == NR_LOOPS-1) |
247 | write_tsc(0, 0); | 247 | write_tsc(0, 0); |
248 | 248 | ||
249 | /* | 249 | /* |
250 | * Wait for all APs to leave the synchronization point: | 250 | * Wait for all APs to leave the synchronization point: |
251 | */ | 251 | */ |
252 | while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1) | 252 | while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1) |
253 | mb(); | 253 | mb(); |
254 | atomic_set(&tsc_count_start, 0); | 254 | atomic_set(&tsc_count_start, 0); |
255 | wmb(); | 255 | wmb(); |
256 | atomic_inc(&tsc_count_stop); | 256 | atomic_inc(&tsc_count_stop); |
257 | } | 257 | } |
258 | 258 | ||
259 | sum = 0; | 259 | sum = 0; |
260 | for (i = 0; i < NR_CPUS; i++) { | 260 | for (i = 0; i < NR_CPUS; i++) { |
261 | if (cpu_isset(i, cpu_callout_map)) { | 261 | if (cpu_isset(i, cpu_callout_map)) { |
262 | t0 = tsc_values[i]; | 262 | t0 = tsc_values[i]; |
263 | sum += t0; | 263 | sum += t0; |
264 | } | 264 | } |
265 | } | 265 | } |
266 | avg = sum; | 266 | avg = sum; |
267 | do_div(avg, num_booting_cpus()); | 267 | do_div(avg, num_booting_cpus()); |
268 | 268 | ||
269 | sum = 0; | 269 | sum = 0; |
270 | for (i = 0; i < NR_CPUS; i++) { | 270 | for (i = 0; i < NR_CPUS; i++) { |
271 | if (!cpu_isset(i, cpu_callout_map)) | 271 | if (!cpu_isset(i, cpu_callout_map)) |
272 | continue; | 272 | continue; |
273 | delta = tsc_values[i] - avg; | 273 | delta = tsc_values[i] - avg; |
274 | if (delta < 0) | 274 | if (delta < 0) |
275 | delta = -delta; | 275 | delta = -delta; |
276 | /* | 276 | /* |
277 | * We report bigger than 2 microseconds clock differences. | 277 | * We report bigger than 2 microseconds clock differences. |
278 | */ | 278 | */ |
279 | if (delta > 2*one_usec) { | 279 | if (delta > 2*one_usec) { |
280 | long realdelta; | 280 | long realdelta; |
281 | if (!buggy) { | 281 | if (!buggy) { |
282 | buggy = 1; | 282 | buggy = 1; |
283 | printk("\n"); | 283 | printk("\n"); |
284 | } | 284 | } |
285 | realdelta = delta; | 285 | realdelta = delta; |
286 | do_div(realdelta, one_usec); | 286 | do_div(realdelta, one_usec); |
287 | if (tsc_values[i] < avg) | 287 | if (tsc_values[i] < avg) |
288 | realdelta = -realdelta; | 288 | realdelta = -realdelta; |
289 | 289 | ||
290 | printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta); | 290 | printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta); |
291 | } | 291 | } |
292 | 292 | ||
293 | sum += delta; | 293 | sum += delta; |
294 | } | 294 | } |
295 | if (!buggy) | 295 | if (!buggy) |
296 | printk("passed.\n"); | 296 | printk("passed.\n"); |
297 | } | 297 | } |
298 | 298 | ||
299 | static void __init synchronize_tsc_ap (void) | 299 | static void __init synchronize_tsc_ap (void) |
300 | { | 300 | { |
301 | int i; | 301 | int i; |
302 | 302 | ||
303 | /* | 303 | /* |
304 | * Not every cpu is online at the time | 304 | * Not every cpu is online at the time |
305 | * this gets called, so we first wait for the BP to | 305 | * this gets called, so we first wait for the BP to |
306 | * finish SMP initialization: | 306 | * finish SMP initialization: |
307 | */ | 307 | */ |
308 | while (!atomic_read(&tsc_start_flag)) mb(); | 308 | while (!atomic_read(&tsc_start_flag)) mb(); |
309 | 309 | ||
310 | for (i = 0; i < NR_LOOPS; i++) { | 310 | for (i = 0; i < NR_LOOPS; i++) { |
311 | atomic_inc(&tsc_count_start); | 311 | atomic_inc(&tsc_count_start); |
312 | while (atomic_read(&tsc_count_start) != num_booting_cpus()) | 312 | while (atomic_read(&tsc_count_start) != num_booting_cpus()) |
313 | mb(); | 313 | mb(); |
314 | 314 | ||
315 | rdtscll(tsc_values[smp_processor_id()]); | 315 | rdtscll(tsc_values[smp_processor_id()]); |
316 | if (i == NR_LOOPS-1) | 316 | if (i == NR_LOOPS-1) |
317 | write_tsc(0, 0); | 317 | write_tsc(0, 0); |
318 | 318 | ||
319 | atomic_inc(&tsc_count_stop); | 319 | atomic_inc(&tsc_count_stop); |
320 | while (atomic_read(&tsc_count_stop) != num_booting_cpus()) mb(); | 320 | while (atomic_read(&tsc_count_stop) != num_booting_cpus()) mb(); |
321 | } | 321 | } |
322 | } | 322 | } |
323 | #undef NR_LOOPS | 323 | #undef NR_LOOPS |
324 | 324 | ||
325 | extern void calibrate_delay(void); | 325 | extern void calibrate_delay(void); |
326 | 326 | ||
327 | static atomic_t init_deasserted; | 327 | static atomic_t init_deasserted; |
328 | 328 | ||
329 | static void __init smp_callin(void) | 329 | static void __init smp_callin(void) |
330 | { | 330 | { |
331 | int cpuid, phys_id; | 331 | int cpuid, phys_id; |
332 | unsigned long timeout; | 332 | unsigned long timeout; |
333 | 333 | ||
334 | /* | 334 | /* |
335 | * If waken up by an INIT in an 82489DX configuration | 335 | * If waken up by an INIT in an 82489DX configuration |
336 | * we may get here before an INIT-deassert IPI reaches | 336 | * we may get here before an INIT-deassert IPI reaches |
337 | * our local APIC. We have to wait for the IPI or we'll | 337 | * our local APIC. We have to wait for the IPI or we'll |
338 | * lock up on an APIC access. | 338 | * lock up on an APIC access. |
339 | */ | 339 | */ |
340 | wait_for_init_deassert(&init_deasserted); | 340 | wait_for_init_deassert(&init_deasserted); |
341 | 341 | ||
342 | /* | 342 | /* |
343 | * (This works even if the APIC is not enabled.) | 343 | * (This works even if the APIC is not enabled.) |
344 | */ | 344 | */ |
345 | phys_id = GET_APIC_ID(apic_read(APIC_ID)); | 345 | phys_id = GET_APIC_ID(apic_read(APIC_ID)); |
346 | cpuid = smp_processor_id(); | 346 | cpuid = smp_processor_id(); |
347 | if (cpu_isset(cpuid, cpu_callin_map)) { | 347 | if (cpu_isset(cpuid, cpu_callin_map)) { |
348 | printk("huh, phys CPU#%d, CPU#%d already present??\n", | 348 | printk("huh, phys CPU#%d, CPU#%d already present??\n", |
349 | phys_id, cpuid); | 349 | phys_id, cpuid); |
350 | BUG(); | 350 | BUG(); |
351 | } | 351 | } |
352 | Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id); | 352 | Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id); |
353 | 353 | ||
354 | /* | 354 | /* |
355 | * STARTUP IPIs are fragile beasts as they might sometimes | 355 | * STARTUP IPIs are fragile beasts as they might sometimes |
356 | * trigger some glue motherboard logic. Complete APIC bus | 356 | * trigger some glue motherboard logic. Complete APIC bus |
357 | * silence for 1 second, this overestimates the time the | 357 | * silence for 1 second, this overestimates the time the |
358 | * boot CPU is spending to send the up to 2 STARTUP IPIs | 358 | * boot CPU is spending to send the up to 2 STARTUP IPIs |
359 | * by a factor of two. This should be enough. | 359 | * by a factor of two. This should be enough. |
360 | */ | 360 | */ |
361 | 361 | ||
362 | /* | 362 | /* |
363 | * Waiting 2s total for startup (udelay is not yet working) | 363 | * Waiting 2s total for startup (udelay is not yet working) |
364 | */ | 364 | */ |
365 | timeout = jiffies + 2*HZ; | 365 | timeout = jiffies + 2*HZ; |
366 | while (time_before(jiffies, timeout)) { | 366 | while (time_before(jiffies, timeout)) { |
367 | /* | 367 | /* |
368 | * Has the boot CPU finished it's STARTUP sequence? | 368 | * Has the boot CPU finished it's STARTUP sequence? |
369 | */ | 369 | */ |
370 | if (cpu_isset(cpuid, cpu_callout_map)) | 370 | if (cpu_isset(cpuid, cpu_callout_map)) |
371 | break; | 371 | break; |
372 | rep_nop(); | 372 | rep_nop(); |
373 | } | 373 | } |
374 | 374 | ||
375 | if (!time_before(jiffies, timeout)) { | 375 | if (!time_before(jiffies, timeout)) { |
376 | printk("BUG: CPU%d started up but did not get a callout!\n", | 376 | printk("BUG: CPU%d started up but did not get a callout!\n", |
377 | cpuid); | 377 | cpuid); |
378 | BUG(); | 378 | BUG(); |
379 | } | 379 | } |
380 | 380 | ||
381 | /* | 381 | /* |
382 | * the boot CPU has finished the init stage and is spinning | 382 | * the boot CPU has finished the init stage and is spinning |
383 | * on callin_map until we finish. We are free to set up this | 383 | * on callin_map until we finish. We are free to set up this |
384 | * CPU, first the APIC. (this is probably redundant on most | 384 | * CPU, first the APIC. (this is probably redundant on most |
385 | * boards) | 385 | * boards) |
386 | */ | 386 | */ |
387 | 387 | ||
388 | Dprintk("CALLIN, before setup_local_APIC().\n"); | 388 | Dprintk("CALLIN, before setup_local_APIC().\n"); |
389 | smp_callin_clear_local_apic(); | 389 | smp_callin_clear_local_apic(); |
390 | setup_local_APIC(); | 390 | setup_local_APIC(); |
391 | map_cpu_to_logical_apicid(); | 391 | map_cpu_to_logical_apicid(); |
392 | 392 | ||
393 | /* | 393 | /* |
394 | * Get our bogomips. | 394 | * Get our bogomips. |
395 | */ | 395 | */ |
396 | calibrate_delay(); | 396 | calibrate_delay(); |
397 | Dprintk("Stack at about %p\n",&cpuid); | 397 | Dprintk("Stack at about %p\n",&cpuid); |
398 | 398 | ||
399 | /* | 399 | /* |
400 | * Save our processor parameters | 400 | * Save our processor parameters |
401 | */ | 401 | */ |
402 | smp_store_cpu_info(cpuid); | 402 | smp_store_cpu_info(cpuid); |
403 | 403 | ||
404 | disable_APIC_timer(); | 404 | disable_APIC_timer(); |
405 | 405 | ||
406 | /* | 406 | /* |
407 | * Allow the master to continue. | 407 | * Allow the master to continue. |
408 | */ | 408 | */ |
409 | cpu_set(cpuid, cpu_callin_map); | 409 | cpu_set(cpuid, cpu_callin_map); |
410 | 410 | ||
411 | /* | 411 | /* |
412 | * Synchronize the TSC with the BP | 412 | * Synchronize the TSC with the BP |
413 | */ | 413 | */ |
414 | if (cpu_has_tsc && cpu_khz) | 414 | if (cpu_has_tsc && cpu_khz) |
415 | synchronize_tsc_ap(); | 415 | synchronize_tsc_ap(); |
416 | } | 416 | } |
417 | 417 | ||
418 | static int cpucount; | 418 | static int cpucount; |
419 | 419 | ||
420 | /* | 420 | /* |
421 | * Activate a secondary processor. | 421 | * Activate a secondary processor. |
422 | */ | 422 | */ |
423 | static void __init start_secondary(void *unused) | 423 | static void __init start_secondary(void *unused) |
424 | { | 424 | { |
425 | /* | 425 | /* |
426 | * Dont put anything before smp_callin(), SMP | 426 | * Dont put anything before smp_callin(), SMP |
427 | * booting is too fragile that we want to limit the | 427 | * booting is too fragile that we want to limit the |
428 | * things done here to the most necessary things. | 428 | * things done here to the most necessary things. |
429 | */ | 429 | */ |
430 | cpu_init(); | 430 | cpu_init(); |
431 | smp_callin(); | 431 | smp_callin(); |
432 | while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) | 432 | while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) |
433 | rep_nop(); | 433 | rep_nop(); |
434 | setup_secondary_APIC_clock(); | 434 | setup_secondary_APIC_clock(); |
435 | if (nmi_watchdog == NMI_IO_APIC) { | 435 | if (nmi_watchdog == NMI_IO_APIC) { |
436 | disable_8259A_irq(0); | 436 | disable_8259A_irq(0); |
437 | enable_NMI_through_LVT0(NULL); | 437 | enable_NMI_through_LVT0(NULL); |
438 | enable_8259A_irq(0); | 438 | enable_8259A_irq(0); |
439 | } | 439 | } |
440 | enable_APIC_timer(); | 440 | enable_APIC_timer(); |
441 | /* | 441 | /* |
442 | * low-memory mappings have been cleared, flush them from | 442 | * low-memory mappings have been cleared, flush them from |
443 | * the local TLBs too. | 443 | * the local TLBs too. |
444 | */ | 444 | */ |
445 | local_flush_tlb(); | 445 | local_flush_tlb(); |
446 | cpu_set(smp_processor_id(), cpu_online_map); | 446 | cpu_set(smp_processor_id(), cpu_online_map); |
447 | 447 | ||
448 | /* We can take interrupts now: we're officially "up". */ | 448 | /* We can take interrupts now: we're officially "up". */ |
449 | local_irq_enable(); | 449 | local_irq_enable(); |
450 | 450 | ||
451 | wmb(); | 451 | wmb(); |
452 | cpu_idle(); | 452 | cpu_idle(); |
453 | } | 453 | } |
454 | 454 | ||
455 | /* | 455 | /* |
456 | * Everything has been set up for the secondary | 456 | * Everything has been set up for the secondary |
457 | * CPUs - they just need to reload everything | 457 | * CPUs - they just need to reload everything |
458 | * from the task structure | 458 | * from the task structure |
459 | * This function must not return. | 459 | * This function must not return. |
460 | */ | 460 | */ |
461 | void __init initialize_secondary(void) | 461 | void __init initialize_secondary(void) |
462 | { | 462 | { |
463 | /* | 463 | /* |
464 | * We don't actually need to load the full TSS, | 464 | * We don't actually need to load the full TSS, |
465 | * basically just the stack pointer and the eip. | 465 | * basically just the stack pointer and the eip. |
466 | */ | 466 | */ |
467 | 467 | ||
468 | asm volatile( | 468 | asm volatile( |
469 | "movl %0,%%esp\n\t" | 469 | "movl %0,%%esp\n\t" |
470 | "jmp *%1" | 470 | "jmp *%1" |
471 | : | 471 | : |
472 | :"r" (current->thread.esp),"r" (current->thread.eip)); | 472 | :"r" (current->thread.esp),"r" (current->thread.eip)); |
473 | } | 473 | } |
474 | 474 | ||
475 | extern struct { | 475 | extern struct { |
476 | void * esp; | 476 | void * esp; |
477 | unsigned short ss; | 477 | unsigned short ss; |
478 | } stack_start; | 478 | } stack_start; |
479 | 479 | ||
480 | #ifdef CONFIG_NUMA | 480 | #ifdef CONFIG_NUMA |
481 | 481 | ||
482 | /* which logical CPUs are on which nodes */ | 482 | /* which logical CPUs are on which nodes */ |
483 | cpumask_t node_2_cpu_mask[MAX_NUMNODES] = | 483 | cpumask_t node_2_cpu_mask[MAX_NUMNODES] = |
484 | { [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE }; | 484 | { [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE }; |
485 | /* which node each logical CPU is on */ | 485 | /* which node each logical CPU is on */ |
486 | int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 }; | 486 | int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 }; |
487 | EXPORT_SYMBOL(cpu_2_node); | 487 | EXPORT_SYMBOL(cpu_2_node); |
488 | 488 | ||
489 | /* set up a mapping between cpu and node. */ | 489 | /* set up a mapping between cpu and node. */ |
490 | static inline void map_cpu_to_node(int cpu, int node) | 490 | static inline void map_cpu_to_node(int cpu, int node) |
491 | { | 491 | { |
492 | printk("Mapping cpu %d to node %d\n", cpu, node); | 492 | printk("Mapping cpu %d to node %d\n", cpu, node); |
493 | cpu_set(cpu, node_2_cpu_mask[node]); | 493 | cpu_set(cpu, node_2_cpu_mask[node]); |
494 | cpu_2_node[cpu] = node; | 494 | cpu_2_node[cpu] = node; |
495 | } | 495 | } |
496 | 496 | ||
497 | /* undo a mapping between cpu and node. */ | 497 | /* undo a mapping between cpu and node. */ |
498 | static inline void unmap_cpu_to_node(int cpu) | 498 | static inline void unmap_cpu_to_node(int cpu) |
499 | { | 499 | { |
500 | int node; | 500 | int node; |
501 | 501 | ||
502 | printk("Unmapping cpu %d from all nodes\n", cpu); | 502 | printk("Unmapping cpu %d from all nodes\n", cpu); |
503 | for (node = 0; node < MAX_NUMNODES; node ++) | 503 | for (node = 0; node < MAX_NUMNODES; node ++) |
504 | cpu_clear(cpu, node_2_cpu_mask[node]); | 504 | cpu_clear(cpu, node_2_cpu_mask[node]); |
505 | cpu_2_node[cpu] = 0; | 505 | cpu_2_node[cpu] = 0; |
506 | } | 506 | } |
507 | #else /* !CONFIG_NUMA */ | 507 | #else /* !CONFIG_NUMA */ |
508 | 508 | ||
509 | #define map_cpu_to_node(cpu, node) ({}) | 509 | #define map_cpu_to_node(cpu, node) ({}) |
510 | #define unmap_cpu_to_node(cpu) ({}) | 510 | #define unmap_cpu_to_node(cpu) ({}) |
511 | 511 | ||
512 | #endif /* CONFIG_NUMA */ | 512 | #endif /* CONFIG_NUMA */ |
513 | 513 | ||
514 | u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; | 514 | u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; |
515 | 515 | ||
516 | static void map_cpu_to_logical_apicid(void) | 516 | static void map_cpu_to_logical_apicid(void) |
517 | { | 517 | { |
518 | int cpu = smp_processor_id(); | 518 | int cpu = smp_processor_id(); |
519 | int apicid = logical_smp_processor_id(); | 519 | int apicid = logical_smp_processor_id(); |
520 | 520 | ||
521 | cpu_2_logical_apicid[cpu] = apicid; | 521 | cpu_2_logical_apicid[cpu] = apicid; |
522 | map_cpu_to_node(cpu, apicid_to_node(apicid)); | 522 | map_cpu_to_node(cpu, apicid_to_node(apicid)); |
523 | } | 523 | } |
524 | 524 | ||
525 | static void unmap_cpu_to_logical_apicid(int cpu) | 525 | static void unmap_cpu_to_logical_apicid(int cpu) |
526 | { | 526 | { |
527 | cpu_2_logical_apicid[cpu] = BAD_APICID; | 527 | cpu_2_logical_apicid[cpu] = BAD_APICID; |
528 | unmap_cpu_to_node(cpu); | 528 | unmap_cpu_to_node(cpu); |
529 | } | 529 | } |
530 | 530 | ||
531 | #if APIC_DEBUG | 531 | #if APIC_DEBUG |
532 | static inline void __inquire_remote_apic(int apicid) | 532 | static inline void __inquire_remote_apic(int apicid) |
533 | { | 533 | { |
534 | int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; | 534 | int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; |
535 | char *names[] = { "ID", "VERSION", "SPIV" }; | 535 | char *names[] = { "ID", "VERSION", "SPIV" }; |
536 | int timeout, status; | 536 | int timeout, status; |
537 | 537 | ||
538 | printk("Inquiring remote APIC #%d...\n", apicid); | 538 | printk("Inquiring remote APIC #%d...\n", apicid); |
539 | 539 | ||
540 | for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) { | 540 | for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) { |
541 | printk("... APIC #%d %s: ", apicid, names[i]); | 541 | printk("... APIC #%d %s: ", apicid, names[i]); |
542 | 542 | ||
543 | /* | 543 | /* |
544 | * Wait for idle. | 544 | * Wait for idle. |
545 | */ | 545 | */ |
546 | apic_wait_icr_idle(); | 546 | apic_wait_icr_idle(); |
547 | 547 | ||
548 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); | 548 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); |
549 | apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]); | 549 | apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]); |
550 | 550 | ||
551 | timeout = 0; | 551 | timeout = 0; |
552 | do { | 552 | do { |
553 | udelay(100); | 553 | udelay(100); |
554 | status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK; | 554 | status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK; |
555 | } while (status == APIC_ICR_RR_INPROG && timeout++ < 1000); | 555 | } while (status == APIC_ICR_RR_INPROG && timeout++ < 1000); |
556 | 556 | ||
557 | switch (status) { | 557 | switch (status) { |
558 | case APIC_ICR_RR_VALID: | 558 | case APIC_ICR_RR_VALID: |
559 | status = apic_read(APIC_RRR); | 559 | status = apic_read(APIC_RRR); |
560 | printk("%08x\n", status); | 560 | printk("%08x\n", status); |
561 | break; | 561 | break; |
562 | default: | 562 | default: |
563 | printk("failed\n"); | 563 | printk("failed\n"); |
564 | } | 564 | } |
565 | } | 565 | } |
566 | } | 566 | } |
567 | #endif | 567 | #endif |
568 | 568 | ||
569 | #ifdef WAKE_SECONDARY_VIA_NMI | 569 | #ifdef WAKE_SECONDARY_VIA_NMI |
570 | /* | 570 | /* |
571 | * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal | 571 | * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal |
572 | * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this | 572 | * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this |
573 | * won't ... remember to clear down the APIC, etc later. | 573 | * won't ... remember to clear down the APIC, etc later. |
574 | */ | 574 | */ |
575 | static int __init | 575 | static int __init |
576 | wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) | 576 | wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) |
577 | { | 577 | { |
578 | unsigned long send_status = 0, accept_status = 0; | 578 | unsigned long send_status = 0, accept_status = 0; |
579 | int timeout, maxlvt; | 579 | int timeout, maxlvt; |
580 | 580 | ||
581 | /* Target chip */ | 581 | /* Target chip */ |
582 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid)); | 582 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid)); |
583 | 583 | ||
584 | /* Boot on the stack */ | 584 | /* Boot on the stack */ |
585 | /* Kick the second */ | 585 | /* Kick the second */ |
586 | apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL); | 586 | apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL); |
587 | 587 | ||
588 | Dprintk("Waiting for send to finish...\n"); | 588 | Dprintk("Waiting for send to finish...\n"); |
589 | timeout = 0; | 589 | timeout = 0; |
590 | do { | 590 | do { |
591 | Dprintk("+"); | 591 | Dprintk("+"); |
592 | udelay(100); | 592 | udelay(100); |
593 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; | 593 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; |
594 | } while (send_status && (timeout++ < 1000)); | 594 | } while (send_status && (timeout++ < 1000)); |
595 | 595 | ||
596 | /* | 596 | /* |
597 | * Give the other CPU some time to accept the IPI. | 597 | * Give the other CPU some time to accept the IPI. |
598 | */ | 598 | */ |
599 | udelay(200); | 599 | udelay(200); |
600 | /* | 600 | /* |
601 | * Due to the Pentium erratum 3AP. | 601 | * Due to the Pentium erratum 3AP. |
602 | */ | 602 | */ |
603 | maxlvt = get_maxlvt(); | 603 | maxlvt = get_maxlvt(); |
604 | if (maxlvt > 3) { | 604 | if (maxlvt > 3) { |
605 | apic_read_around(APIC_SPIV); | 605 | apic_read_around(APIC_SPIV); |
606 | apic_write(APIC_ESR, 0); | 606 | apic_write(APIC_ESR, 0); |
607 | } | 607 | } |
608 | accept_status = (apic_read(APIC_ESR) & 0xEF); | 608 | accept_status = (apic_read(APIC_ESR) & 0xEF); |
609 | Dprintk("NMI sent.\n"); | 609 | Dprintk("NMI sent.\n"); |
610 | 610 | ||
611 | if (send_status) | 611 | if (send_status) |
612 | printk("APIC never delivered???\n"); | 612 | printk("APIC never delivered???\n"); |
613 | if (accept_status) | 613 | if (accept_status) |
614 | printk("APIC delivery error (%lx).\n", accept_status); | 614 | printk("APIC delivery error (%lx).\n", accept_status); |
615 | 615 | ||
616 | return (send_status | accept_status); | 616 | return (send_status | accept_status); |
617 | } | 617 | } |
618 | #endif /* WAKE_SECONDARY_VIA_NMI */ | 618 | #endif /* WAKE_SECONDARY_VIA_NMI */ |
619 | 619 | ||
620 | #ifdef WAKE_SECONDARY_VIA_INIT | 620 | #ifdef WAKE_SECONDARY_VIA_INIT |
621 | static int __init | 621 | static int __init |
622 | wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) | 622 | wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) |
623 | { | 623 | { |
624 | unsigned long send_status = 0, accept_status = 0; | 624 | unsigned long send_status = 0, accept_status = 0; |
625 | int maxlvt, timeout, num_starts, j; | 625 | int maxlvt, timeout, num_starts, j; |
626 | 626 | ||
627 | /* | 627 | /* |
628 | * Be paranoid about clearing APIC errors. | 628 | * Be paranoid about clearing APIC errors. |
629 | */ | 629 | */ |
630 | if (APIC_INTEGRATED(apic_version[phys_apicid])) { | 630 | if (APIC_INTEGRATED(apic_version[phys_apicid])) { |
631 | apic_read_around(APIC_SPIV); | 631 | apic_read_around(APIC_SPIV); |
632 | apic_write(APIC_ESR, 0); | 632 | apic_write(APIC_ESR, 0); |
633 | apic_read(APIC_ESR); | 633 | apic_read(APIC_ESR); |
634 | } | 634 | } |
635 | 635 | ||
636 | Dprintk("Asserting INIT.\n"); | 636 | Dprintk("Asserting INIT.\n"); |
637 | 637 | ||
638 | /* | 638 | /* |
639 | * Turn INIT on target chip | 639 | * Turn INIT on target chip |
640 | */ | 640 | */ |
641 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); | 641 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); |
642 | 642 | ||
643 | /* | 643 | /* |
644 | * Send IPI | 644 | * Send IPI |
645 | */ | 645 | */ |
646 | apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | 646 | apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT |
647 | | APIC_DM_INIT); | 647 | | APIC_DM_INIT); |
648 | 648 | ||
649 | Dprintk("Waiting for send to finish...\n"); | 649 | Dprintk("Waiting for send to finish...\n"); |
650 | timeout = 0; | 650 | timeout = 0; |
651 | do { | 651 | do { |
652 | Dprintk("+"); | 652 | Dprintk("+"); |
653 | udelay(100); | 653 | udelay(100); |
654 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; | 654 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; |
655 | } while (send_status && (timeout++ < 1000)); | 655 | } while (send_status && (timeout++ < 1000)); |
656 | 656 | ||
657 | mdelay(10); | 657 | mdelay(10); |
658 | 658 | ||
659 | Dprintk("Deasserting INIT.\n"); | 659 | Dprintk("Deasserting INIT.\n"); |
660 | 660 | ||
661 | /* Target chip */ | 661 | /* Target chip */ |
662 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); | 662 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); |
663 | 663 | ||
664 | /* Send IPI */ | 664 | /* Send IPI */ |
665 | apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); | 665 | apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); |
666 | 666 | ||
667 | Dprintk("Waiting for send to finish...\n"); | 667 | Dprintk("Waiting for send to finish...\n"); |
668 | timeout = 0; | 668 | timeout = 0; |
669 | do { | 669 | do { |
670 | Dprintk("+"); | 670 | Dprintk("+"); |
671 | udelay(100); | 671 | udelay(100); |
672 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; | 672 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; |
673 | } while (send_status && (timeout++ < 1000)); | 673 | } while (send_status && (timeout++ < 1000)); |
674 | 674 | ||
675 | atomic_set(&init_deasserted, 1); | 675 | atomic_set(&init_deasserted, 1); |
676 | 676 | ||
677 | /* | 677 | /* |
678 | * Should we send STARTUP IPIs ? | 678 | * Should we send STARTUP IPIs ? |
679 | * | 679 | * |
680 | * Determine this based on the APIC version. | 680 | * Determine this based on the APIC version. |
681 | * If we don't have an integrated APIC, don't send the STARTUP IPIs. | 681 | * If we don't have an integrated APIC, don't send the STARTUP IPIs. |
682 | */ | 682 | */ |
683 | if (APIC_INTEGRATED(apic_version[phys_apicid])) | 683 | if (APIC_INTEGRATED(apic_version[phys_apicid])) |
684 | num_starts = 2; | 684 | num_starts = 2; |
685 | else | 685 | else |
686 | num_starts = 0; | 686 | num_starts = 0; |
687 | 687 | ||
688 | /* | 688 | /* |
689 | * Run STARTUP IPI loop. | 689 | * Run STARTUP IPI loop. |
690 | */ | 690 | */ |
691 | Dprintk("#startup loops: %d.\n", num_starts); | 691 | Dprintk("#startup loops: %d.\n", num_starts); |
692 | 692 | ||
693 | maxlvt = get_maxlvt(); | 693 | maxlvt = get_maxlvt(); |
694 | 694 | ||
695 | for (j = 1; j <= num_starts; j++) { | 695 | for (j = 1; j <= num_starts; j++) { |
696 | Dprintk("Sending STARTUP #%d.\n",j); | 696 | Dprintk("Sending STARTUP #%d.\n",j); |
697 | apic_read_around(APIC_SPIV); | 697 | apic_read_around(APIC_SPIV); |
698 | apic_write(APIC_ESR, 0); | 698 | apic_write(APIC_ESR, 0); |
699 | apic_read(APIC_ESR); | 699 | apic_read(APIC_ESR); |
700 | Dprintk("After apic_write.\n"); | 700 | Dprintk("After apic_write.\n"); |
701 | 701 | ||
702 | /* | 702 | /* |
703 | * STARTUP IPI | 703 | * STARTUP IPI |
704 | */ | 704 | */ |
705 | 705 | ||
706 | /* Target chip */ | 706 | /* Target chip */ |
707 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); | 707 | apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); |
708 | 708 | ||
709 | /* Boot on the stack */ | 709 | /* Boot on the stack */ |
710 | /* Kick the second */ | 710 | /* Kick the second */ |
711 | apic_write_around(APIC_ICR, APIC_DM_STARTUP | 711 | apic_write_around(APIC_ICR, APIC_DM_STARTUP |
712 | | (start_eip >> 12)); | 712 | | (start_eip >> 12)); |
713 | 713 | ||
714 | /* | 714 | /* |
715 | * Give the other CPU some time to accept the IPI. | 715 | * Give the other CPU some time to accept the IPI. |
716 | */ | 716 | */ |
717 | udelay(300); | 717 | udelay(300); |
718 | 718 | ||
719 | Dprintk("Startup point 1.\n"); | 719 | Dprintk("Startup point 1.\n"); |
720 | 720 | ||
721 | Dprintk("Waiting for send to finish...\n"); | 721 | Dprintk("Waiting for send to finish...\n"); |
722 | timeout = 0; | 722 | timeout = 0; |
723 | do { | 723 | do { |
724 | Dprintk("+"); | 724 | Dprintk("+"); |
725 | udelay(100); | 725 | udelay(100); |
726 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; | 726 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; |
727 | } while (send_status && (timeout++ < 1000)); | 727 | } while (send_status && (timeout++ < 1000)); |
728 | 728 | ||
729 | /* | 729 | /* |
730 | * Give the other CPU some time to accept the IPI. | 730 | * Give the other CPU some time to accept the IPI. |
731 | */ | 731 | */ |
732 | udelay(200); | 732 | udelay(200); |
733 | /* | 733 | /* |
734 | * Due to the Pentium erratum 3AP. | 734 | * Due to the Pentium erratum 3AP. |
735 | */ | 735 | */ |
736 | if (maxlvt > 3) { | 736 | if (maxlvt > 3) { |
737 | apic_read_around(APIC_SPIV); | 737 | apic_read_around(APIC_SPIV); |
738 | apic_write(APIC_ESR, 0); | 738 | apic_write(APIC_ESR, 0); |
739 | } | 739 | } |
740 | accept_status = (apic_read(APIC_ESR) & 0xEF); | 740 | accept_status = (apic_read(APIC_ESR) & 0xEF); |
741 | if (send_status || accept_status) | 741 | if (send_status || accept_status) |
742 | break; | 742 | break; |
743 | } | 743 | } |
744 | Dprintk("After Startup.\n"); | 744 | Dprintk("After Startup.\n"); |
745 | 745 | ||
746 | if (send_status) | 746 | if (send_status) |
747 | printk("APIC never delivered???\n"); | 747 | printk("APIC never delivered???\n"); |
748 | if (accept_status) | 748 | if (accept_status) |
749 | printk("APIC delivery error (%lx).\n", accept_status); | 749 | printk("APIC delivery error (%lx).\n", accept_status); |
750 | 750 | ||
751 | return (send_status | accept_status); | 751 | return (send_status | accept_status); |
752 | } | 752 | } |
753 | #endif /* WAKE_SECONDARY_VIA_INIT */ | 753 | #endif /* WAKE_SECONDARY_VIA_INIT */ |
754 | 754 | ||
755 | extern cpumask_t cpu_initialized; | 755 | extern cpumask_t cpu_initialized; |
756 | 756 | ||
757 | static int __init do_boot_cpu(int apicid) | 757 | static int __init do_boot_cpu(int apicid) |
758 | /* | 758 | /* |
759 | * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad | 759 | * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad |
760 | * (ie clustered apic addressing mode), this is a LOGICAL apic ID. | 760 | * (ie clustered apic addressing mode), this is a LOGICAL apic ID. |
761 | * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu. | 761 | * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu. |
762 | */ | 762 | */ |
763 | { | 763 | { |
764 | struct task_struct *idle; | 764 | struct task_struct *idle; |
765 | unsigned long boot_error; | 765 | unsigned long boot_error; |
766 | int timeout, cpu; | 766 | int timeout, cpu; |
767 | unsigned long start_eip; | 767 | unsigned long start_eip; |
768 | unsigned short nmi_high = 0, nmi_low = 0; | 768 | unsigned short nmi_high = 0, nmi_low = 0; |
769 | 769 | ||
770 | cpu = ++cpucount; | 770 | cpu = ++cpucount; |
771 | /* | 771 | /* |
772 | * We can't use kernel_thread since we must avoid to | 772 | * We can't use kernel_thread since we must avoid to |
773 | * reschedule the child. | 773 | * reschedule the child. |
774 | */ | 774 | */ |
775 | idle = fork_idle(cpu); | 775 | idle = fork_idle(cpu); |
776 | if (IS_ERR(idle)) | 776 | if (IS_ERR(idle)) |
777 | panic("failed fork for CPU %d", cpu); | 777 | panic("failed fork for CPU %d", cpu); |
778 | idle->thread.eip = (unsigned long) start_secondary; | 778 | idle->thread.eip = (unsigned long) start_secondary; |
779 | /* start_eip had better be page-aligned! */ | 779 | /* start_eip had better be page-aligned! */ |
780 | start_eip = setup_trampoline(); | 780 | start_eip = setup_trampoline(); |
781 | 781 | ||
782 | /* So we see what's up */ | 782 | /* So we see what's up */ |
783 | printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); | 783 | printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); |
784 | /* Stack for startup_32 can be just as for start_secondary onwards */ | 784 | /* Stack for startup_32 can be just as for start_secondary onwards */ |
785 | stack_start.esp = (void *) idle->thread.esp; | 785 | stack_start.esp = (void *) idle->thread.esp; |
786 | 786 | ||
787 | irq_ctx_init(cpu); | 787 | irq_ctx_init(cpu); |
788 | 788 | ||
789 | /* | 789 | /* |
790 | * This grunge runs the startup process for | 790 | * This grunge runs the startup process for |
791 | * the targeted processor. | 791 | * the targeted processor. |
792 | */ | 792 | */ |
793 | 793 | ||
794 | atomic_set(&init_deasserted, 0); | 794 | atomic_set(&init_deasserted, 0); |
795 | 795 | ||
796 | Dprintk("Setting warm reset code and vector.\n"); | 796 | Dprintk("Setting warm reset code and vector.\n"); |
797 | 797 | ||
798 | store_NMI_vector(&nmi_high, &nmi_low); | 798 | store_NMI_vector(&nmi_high, &nmi_low); |
799 | 799 | ||
800 | smpboot_setup_warm_reset_vector(start_eip); | 800 | smpboot_setup_warm_reset_vector(start_eip); |
801 | 801 | ||
802 | /* | 802 | /* |
803 | * Starting actual IPI sequence... | 803 | * Starting actual IPI sequence... |
804 | */ | 804 | */ |
805 | boot_error = wakeup_secondary_cpu(apicid, start_eip); | 805 | boot_error = wakeup_secondary_cpu(apicid, start_eip); |
806 | 806 | ||
807 | if (!boot_error) { | 807 | if (!boot_error) { |
808 | /* | 808 | /* |
809 | * allow APs to start initializing. | 809 | * allow APs to start initializing. |
810 | */ | 810 | */ |
811 | Dprintk("Before Callout %d.\n", cpu); | 811 | Dprintk("Before Callout %d.\n", cpu); |
812 | cpu_set(cpu, cpu_callout_map); | 812 | cpu_set(cpu, cpu_callout_map); |
813 | Dprintk("After Callout %d.\n", cpu); | 813 | Dprintk("After Callout %d.\n", cpu); |
814 | 814 | ||
815 | /* | 815 | /* |
816 | * Wait 5s total for a response | 816 | * Wait 5s total for a response |
817 | */ | 817 | */ |
818 | for (timeout = 0; timeout < 50000; timeout++) { | 818 | for (timeout = 0; timeout < 50000; timeout++) { |
819 | if (cpu_isset(cpu, cpu_callin_map)) | 819 | if (cpu_isset(cpu, cpu_callin_map)) |
820 | break; /* It has booted */ | 820 | break; /* It has booted */ |
821 | udelay(100); | 821 | udelay(100); |
822 | } | 822 | } |
823 | 823 | ||
824 | if (cpu_isset(cpu, cpu_callin_map)) { | 824 | if (cpu_isset(cpu, cpu_callin_map)) { |
825 | /* number CPUs logically, starting from 1 (BSP is 0) */ | 825 | /* number CPUs logically, starting from 1 (BSP is 0) */ |
826 | Dprintk("OK.\n"); | 826 | Dprintk("OK.\n"); |
827 | printk("CPU%d: ", cpu); | 827 | printk("CPU%d: ", cpu); |
828 | print_cpu_info(&cpu_data[cpu]); | 828 | print_cpu_info(&cpu_data[cpu]); |
829 | Dprintk("CPU has booted.\n"); | 829 | Dprintk("CPU has booted.\n"); |
830 | } else { | 830 | } else { |
831 | boot_error= 1; | 831 | boot_error= 1; |
832 | if (*((volatile unsigned char *)trampoline_base) | 832 | if (*((volatile unsigned char *)trampoline_base) |
833 | == 0xA5) | 833 | == 0xA5) |
834 | /* trampoline started but...? */ | 834 | /* trampoline started but...? */ |
835 | printk("Stuck ??\n"); | 835 | printk("Stuck ??\n"); |
836 | else | 836 | else |
837 | /* trampoline code not run */ | 837 | /* trampoline code not run */ |
838 | printk("Not responding.\n"); | 838 | printk("Not responding.\n"); |
839 | inquire_remote_apic(apicid); | 839 | inquire_remote_apic(apicid); |
840 | } | 840 | } |
841 | } | 841 | } |
842 | x86_cpu_to_apicid[cpu] = apicid; | 842 | x86_cpu_to_apicid[cpu] = apicid; |
843 | if (boot_error) { | 843 | if (boot_error) { |
844 | /* Try to put things back the way they were before ... */ | 844 | /* Try to put things back the way they were before ... */ |
845 | unmap_cpu_to_logical_apicid(cpu); | 845 | unmap_cpu_to_logical_apicid(cpu); |
846 | cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */ | 846 | cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */ |
847 | cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */ | 847 | cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */ |
848 | cpucount--; | 848 | cpucount--; |
849 | } | 849 | } |
850 | 850 | ||
851 | /* mark "stuck" area as not stuck */ | 851 | /* mark "stuck" area as not stuck */ |
852 | *((volatile unsigned long *)trampoline_base) = 0; | 852 | *((volatile unsigned long *)trampoline_base) = 0; |
853 | 853 | ||
854 | return boot_error; | 854 | return boot_error; |
855 | } | 855 | } |
856 | 856 | ||
857 | static void smp_tune_scheduling (void) | 857 | static void smp_tune_scheduling (void) |
858 | { | 858 | { |
859 | unsigned long cachesize; /* kB */ | 859 | unsigned long cachesize; /* kB */ |
860 | unsigned long bandwidth = 350; /* MB/s */ | 860 | unsigned long bandwidth = 350; /* MB/s */ |
861 | /* | 861 | /* |
862 | * Rough estimation for SMP scheduling, this is the number of | 862 | * Rough estimation for SMP scheduling, this is the number of |
863 | * cycles it takes for a fully memory-limited process to flush | 863 | * cycles it takes for a fully memory-limited process to flush |
864 | * the SMP-local cache. | 864 | * the SMP-local cache. |
865 | * | 865 | * |
866 | * (For a P5 this pretty much means we will choose another idle | 866 | * (For a P5 this pretty much means we will choose another idle |
867 | * CPU almost always at wakeup time (this is due to the small | 867 | * CPU almost always at wakeup time (this is due to the small |
868 | * L1 cache), on PIIs it's around 50-100 usecs, depending on | 868 | * L1 cache), on PIIs it's around 50-100 usecs, depending on |
869 | * the cache size) | 869 | * the cache size) |
870 | */ | 870 | */ |
871 | 871 | ||
872 | if (!cpu_khz) { | 872 | if (!cpu_khz) { |
873 | /* | 873 | /* |
874 | * this basically disables processor-affinity | 874 | * this basically disables processor-affinity |
875 | * scheduling on SMP without a TSC. | 875 | * scheduling on SMP without a TSC. |
876 | */ | 876 | */ |
877 | return; | 877 | return; |
878 | } else { | 878 | } else { |
879 | cachesize = boot_cpu_data.x86_cache_size; | 879 | cachesize = boot_cpu_data.x86_cache_size; |
880 | if (cachesize == -1) { | 880 | if (cachesize == -1) { |
881 | cachesize = 16; /* Pentiums, 2x8kB cache */ | 881 | cachesize = 16; /* Pentiums, 2x8kB cache */ |
882 | bandwidth = 100; | 882 | bandwidth = 100; |
883 | } | 883 | } |
884 | } | 884 | } |
885 | } | 885 | } |
886 | 886 | ||
887 | /* | 887 | /* |
888 | * Cycle through the processors sending APIC IPIs to boot each. | 888 | * Cycle through the processors sending APIC IPIs to boot each. |
889 | */ | 889 | */ |
890 | 890 | ||
891 | static int boot_cpu_logical_apicid; | 891 | static int boot_cpu_logical_apicid; |
892 | /* Where the IO area was mapped on multiquad, always 0 otherwise */ | 892 | /* Where the IO area was mapped on multiquad, always 0 otherwise */ |
893 | void *xquad_portio; | 893 | void *xquad_portio; |
894 | #ifdef CONFIG_X86_NUMAQ | 894 | #ifdef CONFIG_X86_NUMAQ |
895 | EXPORT_SYMBOL(xquad_portio); | 895 | EXPORT_SYMBOL(xquad_portio); |
896 | #endif | 896 | #endif |
897 | 897 | ||
898 | cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; | 898 | cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; |
899 | #ifdef CONFIG_X86_HT | 899 | #ifdef CONFIG_X86_HT |
900 | EXPORT_SYMBOL(cpu_sibling_map); | 900 | EXPORT_SYMBOL(cpu_sibling_map); |
901 | #endif | 901 | #endif |
902 | cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; | 902 | cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; |
903 | EXPORT_SYMBOL(cpu_core_map); | 903 | EXPORT_SYMBOL(cpu_core_map); |
904 | 904 | ||
905 | static void __init smp_boot_cpus(unsigned int max_cpus) | 905 | static void __init smp_boot_cpus(unsigned int max_cpus) |
906 | { | 906 | { |
907 | int apicid, cpu, bit, kicked; | 907 | int apicid, cpu, bit, kicked; |
908 | unsigned long bogosum = 0; | 908 | unsigned long bogosum = 0; |
909 | 909 | ||
910 | /* | 910 | /* |
911 | * Setup boot CPU information | 911 | * Setup boot CPU information |
912 | */ | 912 | */ |
913 | smp_store_cpu_info(0); /* Final full version of the data */ | 913 | smp_store_cpu_info(0); /* Final full version of the data */ |
914 | printk("CPU%d: ", 0); | 914 | printk("CPU%d: ", 0); |
915 | print_cpu_info(&cpu_data[0]); | 915 | print_cpu_info(&cpu_data[0]); |
916 | 916 | ||
917 | boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); | 917 | boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); |
918 | boot_cpu_logical_apicid = logical_smp_processor_id(); | 918 | boot_cpu_logical_apicid = logical_smp_processor_id(); |
919 | x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; | 919 | x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; |
920 | 920 | ||
921 | current_thread_info()->cpu = 0; | 921 | current_thread_info()->cpu = 0; |
922 | smp_tune_scheduling(); | 922 | smp_tune_scheduling(); |
923 | cpus_clear(cpu_sibling_map[0]); | 923 | cpus_clear(cpu_sibling_map[0]); |
924 | cpu_set(0, cpu_sibling_map[0]); | 924 | cpu_set(0, cpu_sibling_map[0]); |
925 | 925 | ||
926 | cpus_clear(cpu_core_map[0]); | 926 | cpus_clear(cpu_core_map[0]); |
927 | cpu_set(0, cpu_core_map[0]); | 927 | cpu_set(0, cpu_core_map[0]); |
928 | 928 | ||
929 | /* | 929 | /* |
930 | * If we couldn't find an SMP configuration at boot time, | 930 | * If we couldn't find an SMP configuration at boot time, |
931 | * get out of here now! | 931 | * get out of here now! |
932 | */ | 932 | */ |
933 | if (!smp_found_config && !acpi_lapic) { | 933 | if (!smp_found_config && !acpi_lapic) { |
934 | printk(KERN_NOTICE "SMP motherboard not detected.\n"); | 934 | printk(KERN_NOTICE "SMP motherboard not detected.\n"); |
935 | smpboot_clear_io_apic_irqs(); | 935 | smpboot_clear_io_apic_irqs(); |
936 | phys_cpu_present_map = physid_mask_of_physid(0); | 936 | phys_cpu_present_map = physid_mask_of_physid(0); |
937 | if (APIC_init_uniprocessor()) | 937 | if (APIC_init_uniprocessor()) |
938 | printk(KERN_NOTICE "Local APIC not detected." | 938 | printk(KERN_NOTICE "Local APIC not detected." |
939 | " Using dummy APIC emulation.\n"); | 939 | " Using dummy APIC emulation.\n"); |
940 | map_cpu_to_logical_apicid(); | 940 | map_cpu_to_logical_apicid(); |
941 | cpu_set(0, cpu_sibling_map[0]); | 941 | cpu_set(0, cpu_sibling_map[0]); |
942 | cpu_set(0, cpu_core_map[0]); | 942 | cpu_set(0, cpu_core_map[0]); |
943 | return; | 943 | return; |
944 | } | 944 | } |
945 | 945 | ||
946 | /* | 946 | /* |
947 | * Should not be necessary because the MP table should list the boot | 947 | * Should not be necessary because the MP table should list the boot |
948 | * CPU too, but we do it for the sake of robustness anyway. | 948 | * CPU too, but we do it for the sake of robustness anyway. |
949 | * Makes no sense to do this check in clustered apic mode, so skip it | 949 | * Makes no sense to do this check in clustered apic mode, so skip it |
950 | */ | 950 | */ |
951 | if (!check_phys_apicid_present(boot_cpu_physical_apicid)) { | 951 | if (!check_phys_apicid_present(boot_cpu_physical_apicid)) { |
952 | printk("weird, boot CPU (#%d) not listed by the BIOS.\n", | 952 | printk("weird, boot CPU (#%d) not listed by the BIOS.\n", |
953 | boot_cpu_physical_apicid); | 953 | boot_cpu_physical_apicid); |
954 | physid_set(hard_smp_processor_id(), phys_cpu_present_map); | 954 | physid_set(hard_smp_processor_id(), phys_cpu_present_map); |
955 | } | 955 | } |
956 | 956 | ||
957 | /* | 957 | /* |
958 | * If we couldn't find a local APIC, then get out of here now! | 958 | * If we couldn't find a local APIC, then get out of here now! |
959 | */ | 959 | */ |
960 | if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) { | 960 | if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) { |
961 | printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", | 961 | printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", |
962 | boot_cpu_physical_apicid); | 962 | boot_cpu_physical_apicid); |
963 | printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); | 963 | printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); |
964 | smpboot_clear_io_apic_irqs(); | 964 | smpboot_clear_io_apic_irqs(); |
965 | phys_cpu_present_map = physid_mask_of_physid(0); | 965 | phys_cpu_present_map = physid_mask_of_physid(0); |
966 | cpu_set(0, cpu_sibling_map[0]); | 966 | cpu_set(0, cpu_sibling_map[0]); |
967 | cpu_set(0, cpu_core_map[0]); | 967 | cpu_set(0, cpu_core_map[0]); |
968 | return; | 968 | return; |
969 | } | 969 | } |
970 | 970 | ||
971 | verify_local_APIC(); | 971 | verify_local_APIC(); |
972 | 972 | ||
973 | /* | 973 | /* |
974 | * If SMP should be disabled, then really disable it! | 974 | * If SMP should be disabled, then really disable it! |
975 | */ | 975 | */ |
976 | if (!max_cpus) { | 976 | if (!max_cpus) { |
977 | smp_found_config = 0; | 977 | smp_found_config = 0; |
978 | printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); | 978 | printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); |
979 | smpboot_clear_io_apic_irqs(); | 979 | smpboot_clear_io_apic_irqs(); |
980 | phys_cpu_present_map = physid_mask_of_physid(0); | 980 | phys_cpu_present_map = physid_mask_of_physid(0); |
981 | cpu_set(0, cpu_sibling_map[0]); | 981 | cpu_set(0, cpu_sibling_map[0]); |
982 | cpu_set(0, cpu_core_map[0]); | 982 | cpu_set(0, cpu_core_map[0]); |
983 | return; | 983 | return; |
984 | } | 984 | } |
985 | 985 | ||
986 | connect_bsp_APIC(); | 986 | connect_bsp_APIC(); |
987 | setup_local_APIC(); | 987 | setup_local_APIC(); |
988 | map_cpu_to_logical_apicid(); | 988 | map_cpu_to_logical_apicid(); |
989 | 989 | ||
990 | 990 | ||
991 | setup_portio_remap(); | 991 | setup_portio_remap(); |
992 | 992 | ||
993 | /* | 993 | /* |
994 | * Scan the CPU present map and fire up the other CPUs via do_boot_cpu | 994 | * Scan the CPU present map and fire up the other CPUs via do_boot_cpu |
995 | * | 995 | * |
996 | * In clustered apic mode, phys_cpu_present_map is a constructed thus: | 996 | * In clustered apic mode, phys_cpu_present_map is a constructed thus: |
997 | * bits 0-3 are quad0, 4-7 are quad1, etc. A perverse twist on the | 997 | * bits 0-3 are quad0, 4-7 are quad1, etc. A perverse twist on the |
998 | * clustered apic ID. | 998 | * clustered apic ID. |
999 | */ | 999 | */ |
1000 | Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map)); | 1000 | Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map)); |
1001 | 1001 | ||
1002 | kicked = 1; | 1002 | kicked = 1; |
1003 | for (bit = 0; kicked < NR_CPUS && bit < MAX_APICS; bit++) { | 1003 | for (bit = 0; kicked < NR_CPUS && bit < MAX_APICS; bit++) { |
1004 | apicid = cpu_present_to_apicid(bit); | 1004 | apicid = cpu_present_to_apicid(bit); |
1005 | /* | 1005 | /* |
1006 | * Don't even attempt to start the boot CPU! | 1006 | * Don't even attempt to start the boot CPU! |
1007 | */ | 1007 | */ |
1008 | if ((apicid == boot_cpu_apicid) || (apicid == BAD_APICID)) | 1008 | if ((apicid == boot_cpu_apicid) || (apicid == BAD_APICID)) |
1009 | continue; | 1009 | continue; |
1010 | 1010 | ||
1011 | if (!check_apicid_present(bit)) | 1011 | if (!check_apicid_present(bit)) |
1012 | continue; | 1012 | continue; |
1013 | if (max_cpus <= cpucount+1) | 1013 | if (max_cpus <= cpucount+1) |
1014 | continue; | 1014 | continue; |
1015 | 1015 | ||
1016 | if (do_boot_cpu(apicid)) | 1016 | if (do_boot_cpu(apicid)) |
1017 | printk("CPU #%d not responding - cannot use it.\n", | 1017 | printk("CPU #%d not responding - cannot use it.\n", |
1018 | apicid); | 1018 | apicid); |
1019 | else | 1019 | else |
1020 | ++kicked; | 1020 | ++kicked; |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | /* | 1023 | /* |
1024 | * Cleanup possible dangling ends... | 1024 | * Cleanup possible dangling ends... |
1025 | */ | 1025 | */ |
1026 | smpboot_restore_warm_reset_vector(); | 1026 | smpboot_restore_warm_reset_vector(); |
1027 | 1027 | ||
1028 | /* | 1028 | /* |
1029 | * Allow the user to impress friends. | 1029 | * Allow the user to impress friends. |
1030 | */ | 1030 | */ |
1031 | Dprintk("Before bogomips.\n"); | 1031 | Dprintk("Before bogomips.\n"); |
1032 | for (cpu = 0; cpu < NR_CPUS; cpu++) | 1032 | for (cpu = 0; cpu < NR_CPUS; cpu++) |
1033 | if (cpu_isset(cpu, cpu_callout_map)) | 1033 | if (cpu_isset(cpu, cpu_callout_map)) |
1034 | bogosum += cpu_data[cpu].loops_per_jiffy; | 1034 | bogosum += cpu_data[cpu].loops_per_jiffy; |
1035 | printk(KERN_INFO | 1035 | printk(KERN_INFO |
1036 | "Total of %d processors activated (%lu.%02lu BogoMIPS).\n", | 1036 | "Total of %d processors activated (%lu.%02lu BogoMIPS).\n", |
1037 | cpucount+1, | 1037 | cpucount+1, |
1038 | bogosum/(500000/HZ), | 1038 | bogosum/(500000/HZ), |
1039 | (bogosum/(5000/HZ))%100); | 1039 | (bogosum/(5000/HZ))%100); |
1040 | 1040 | ||
1041 | Dprintk("Before bogocount - setting activated=1.\n"); | 1041 | Dprintk("Before bogocount - setting activated=1.\n"); |
1042 | 1042 | ||
1043 | if (smp_b_stepping) | 1043 | if (smp_b_stepping) |
1044 | printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n"); | 1044 | printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n"); |
1045 | 1045 | ||
1046 | /* | 1046 | /* |
1047 | * Don't taint if we are running SMP kernel on a single non-MP | 1047 | * Don't taint if we are running SMP kernel on a single non-MP |
1048 | * approved Athlon | 1048 | * approved Athlon |
1049 | */ | 1049 | */ |
1050 | if (tainted & TAINT_UNSAFE_SMP) { | 1050 | if (tainted & TAINT_UNSAFE_SMP) { |
1051 | if (cpucount) | 1051 | if (cpucount) |
1052 | printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n"); | 1052 | printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n"); |
1053 | else | 1053 | else |
1054 | tainted &= ~TAINT_UNSAFE_SMP; | 1054 | tainted &= ~TAINT_UNSAFE_SMP; |
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | Dprintk("Boot done.\n"); | 1057 | Dprintk("Boot done.\n"); |
1058 | 1058 | ||
1059 | /* | 1059 | /* |
1060 | * construct cpu_sibling_map[], so that we can tell sibling CPUs | 1060 | * construct cpu_sibling_map[], so that we can tell sibling CPUs |
1061 | * efficiently. | 1061 | * efficiently. |
1062 | */ | 1062 | */ |
1063 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | 1063 | for (cpu = 0; cpu < NR_CPUS; cpu++) { |
1064 | cpus_clear(cpu_sibling_map[cpu]); | 1064 | cpus_clear(cpu_sibling_map[cpu]); |
1065 | cpus_clear(cpu_core_map[cpu]); | 1065 | cpus_clear(cpu_core_map[cpu]); |
1066 | } | 1066 | } |
1067 | 1067 | ||
1068 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | 1068 | for (cpu = 0; cpu < NR_CPUS; cpu++) { |
1069 | struct cpuinfo_x86 *c = cpu_data + cpu; | 1069 | struct cpuinfo_x86 *c = cpu_data + cpu; |
1070 | int siblings = 0; | 1070 | int siblings = 0; |
1071 | int i; | 1071 | int i; |
1072 | if (!cpu_isset(cpu, cpu_callout_map)) | 1072 | if (!cpu_isset(cpu, cpu_callout_map)) |
1073 | continue; | 1073 | continue; |
1074 | 1074 | ||
1075 | if (smp_num_siblings > 1) { | 1075 | if (smp_num_siblings > 1) { |
1076 | for (i = 0; i < NR_CPUS; i++) { | 1076 | for (i = 0; i < NR_CPUS; i++) { |
1077 | if (!cpu_isset(i, cpu_callout_map)) | 1077 | if (!cpu_isset(i, cpu_callout_map)) |
1078 | continue; | 1078 | continue; |
1079 | if (cpu_core_id[cpu] == cpu_core_id[i]) { | 1079 | if (cpu_core_id[cpu] == cpu_core_id[i]) { |
1080 | siblings++; | 1080 | siblings++; |
1081 | cpu_set(i, cpu_sibling_map[cpu]); | 1081 | cpu_set(i, cpu_sibling_map[cpu]); |
1082 | } | 1082 | } |
1083 | } | 1083 | } |
1084 | } else { | 1084 | } else { |
1085 | siblings++; | 1085 | siblings++; |
1086 | cpu_set(cpu, cpu_sibling_map[cpu]); | 1086 | cpu_set(cpu, cpu_sibling_map[cpu]); |
1087 | } | 1087 | } |
1088 | 1088 | ||
1089 | if (siblings != smp_num_siblings) { | 1089 | if (siblings != smp_num_siblings) { |
1090 | printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); | 1090 | printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); |
1091 | smp_num_siblings = siblings; | 1091 | smp_num_siblings = siblings; |
1092 | } | 1092 | } |
1093 | 1093 | ||
1094 | if (c->x86_num_cores > 1) { | 1094 | if (c->x86_num_cores > 1) { |
1095 | for (i = 0; i < NR_CPUS; i++) { | 1095 | for (i = 0; i < NR_CPUS; i++) { |
1096 | if (!cpu_isset(i, cpu_callout_map)) | 1096 | if (!cpu_isset(i, cpu_callout_map)) |
1097 | continue; | 1097 | continue; |
1098 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | 1098 | if (phys_proc_id[cpu] == phys_proc_id[i]) { |
1099 | cpu_set(i, cpu_core_map[cpu]); | 1099 | cpu_set(i, cpu_core_map[cpu]); |
1100 | } | 1100 | } |
1101 | } | 1101 | } |
1102 | } else { | 1102 | } else { |
1103 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | 1103 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; |
1104 | } | 1104 | } |
1105 | } | 1105 | } |
1106 | 1106 | ||
1107 | smpboot_setup_io_apic(); | 1107 | smpboot_setup_io_apic(); |
1108 | 1108 | ||
1109 | setup_boot_APIC_clock(); | 1109 | setup_boot_APIC_clock(); |
1110 | 1110 | ||
1111 | /* | 1111 | /* |
1112 | * Synchronize the TSC with the AP | 1112 | * Synchronize the TSC with the AP |
1113 | */ | 1113 | */ |
1114 | if (cpu_has_tsc && cpucount && cpu_khz) | 1114 | if (cpu_has_tsc && cpucount && cpu_khz) |
1115 | synchronize_tsc_bp(); | 1115 | synchronize_tsc_bp(); |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | /* These are wrappers to interface to the new boot process. Someone | 1118 | /* These are wrappers to interface to the new boot process. Someone |
1119 | who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ | 1119 | who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ |
1120 | void __init smp_prepare_cpus(unsigned int max_cpus) | 1120 | void __init smp_prepare_cpus(unsigned int max_cpus) |
1121 | { | 1121 | { |
1122 | smp_boot_cpus(max_cpus); | 1122 | smp_boot_cpus(max_cpus); |
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | void __devinit smp_prepare_boot_cpu(void) | 1125 | void __devinit smp_prepare_boot_cpu(void) |
1126 | { | 1126 | { |
1127 | cpu_set(smp_processor_id(), cpu_online_map); | 1127 | cpu_set(smp_processor_id(), cpu_online_map); |
1128 | cpu_set(smp_processor_id(), cpu_callout_map); | 1128 | cpu_set(smp_processor_id(), cpu_callout_map); |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | int __devinit __cpu_up(unsigned int cpu) | 1131 | int __devinit __cpu_up(unsigned int cpu) |
1132 | { | 1132 | { |
1133 | /* This only works at boot for x86. See "rewrite" above. */ | 1133 | /* This only works at boot for x86. See "rewrite" above. */ |
1134 | if (cpu_isset(cpu, smp_commenced_mask)) { | 1134 | if (cpu_isset(cpu, smp_commenced_mask)) { |
1135 | local_irq_enable(); | 1135 | local_irq_enable(); |
1136 | return -ENOSYS; | 1136 | return -ENOSYS; |
1137 | } | 1137 | } |
1138 | 1138 | ||
1139 | /* In case one didn't come up */ | 1139 | /* In case one didn't come up */ |
1140 | if (!cpu_isset(cpu, cpu_callin_map)) { | 1140 | if (!cpu_isset(cpu, cpu_callin_map)) { |
1141 | local_irq_enable(); | 1141 | local_irq_enable(); |
1142 | return -EIO; | 1142 | return -EIO; |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | local_irq_enable(); | 1145 | local_irq_enable(); |
1146 | /* Unleash the CPU! */ | 1146 | /* Unleash the CPU! */ |
1147 | cpu_set(cpu, smp_commenced_mask); | 1147 | cpu_set(cpu, smp_commenced_mask); |
1148 | while (!cpu_isset(cpu, cpu_online_map)) | 1148 | while (!cpu_isset(cpu, cpu_online_map)) |
1149 | mb(); | 1149 | mb(); |
1150 | return 0; | 1150 | return 0; |
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | void __init smp_cpus_done(unsigned int max_cpus) | 1153 | void __init smp_cpus_done(unsigned int max_cpus) |
1154 | { | 1154 | { |
1155 | #ifdef CONFIG_X86_IO_APIC | 1155 | #ifdef CONFIG_X86_IO_APIC |
1156 | setup_ioapic_dest(); | 1156 | setup_ioapic_dest(); |
1157 | #endif | 1157 | #endif |
1158 | zap_low_mappings(); | 1158 | zap_low_mappings(); |
1159 | /* | 1159 | /* |
1160 | * Disable executability of the SMP trampoline: | 1160 | * Disable executability of the SMP trampoline: |
1161 | */ | 1161 | */ |
1162 | set_kernel_exec((unsigned long)trampoline_base, trampoline_exec); | 1162 | set_kernel_exec((unsigned long)trampoline_base, trampoline_exec); |
1163 | } | 1163 | } |
1164 | 1164 | ||
1165 | void __init smp_intr_init(void) | 1165 | void __init smp_intr_init(void) |
1166 | { | 1166 | { |
1167 | /* | 1167 | /* |
1168 | * IRQ0 must be given a fixed assignment and initialized, | 1168 | * IRQ0 must be given a fixed assignment and initialized, |
1169 | * because it's used before the IO-APIC is set up. | 1169 | * because it's used before the IO-APIC is set up. |
1170 | */ | 1170 | */ |
1171 | set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]); | 1171 | set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]); |
1172 | 1172 | ||
1173 | /* | 1173 | /* |
1174 | * The reschedule interrupt is a CPU-to-CPU reschedule-helper | 1174 | * The reschedule interrupt is a CPU-to-CPU reschedule-helper |
1175 | * IPI, driven by wakeup. | 1175 | * IPI, driven by wakeup. |
1176 | */ | 1176 | */ |
1177 | set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); | 1177 | set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); |
1178 | 1178 | ||
1179 | /* IPI for invalidation */ | 1179 | /* IPI for invalidation */ |
1180 | set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); | 1180 | set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); |
1181 | 1181 | ||
1182 | /* IPI for generic function call */ | 1182 | /* IPI for generic function call */ |
1183 | set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); | 1183 | set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); |
1184 | } | 1184 | } |
1185 | 1185 |
arch/i386/kernel/time.c
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/time.c | 2 | * linux/arch/i386/kernel/time.c |
3 | * | 3 | * |
4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | 4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds |
5 | * | 5 | * |
6 | * This file contains the PC-specific time handling details: | 6 | * This file contains the PC-specific time handling details: |
7 | * reading the RTC at bootup, etc.. | 7 | * reading the RTC at bootup, etc.. |
8 | * 1994-07-02 Alan Modra | 8 | * 1994-07-02 Alan Modra |
9 | * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime | 9 | * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime |
10 | * 1995-03-26 Markus Kuhn | 10 | * 1995-03-26 Markus Kuhn |
11 | * fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887 | 11 | * fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887 |
12 | * precision CMOS clock update | 12 | * precision CMOS clock update |
13 | * 1996-05-03 Ingo Molnar | 13 | * 1996-05-03 Ingo Molnar |
14 | * fixed time warps in do_[slow|fast]_gettimeoffset() | 14 | * fixed time warps in do_[slow|fast]_gettimeoffset() |
15 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 | 15 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 |
16 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | 16 | * "A Kernel Model for Precision Timekeeping" by Dave Mills |
17 | * 1998-09-05 (Various) | 17 | * 1998-09-05 (Various) |
18 | * More robust do_fast_gettimeoffset() algorithm implemented | 18 | * More robust do_fast_gettimeoffset() algorithm implemented |
19 | * (works with APM, Cyrix 6x86MX and Centaur C6), | 19 | * (works with APM, Cyrix 6x86MX and Centaur C6), |
20 | * monotonic gettimeofday() with fast_get_timeoffset(), | 20 | * monotonic gettimeofday() with fast_get_timeoffset(), |
21 | * drift-proof precision TSC calibration on boot | 21 | * drift-proof precision TSC calibration on boot |
22 | * (C. Scott Ananian <cananian@alumni.princeton.edu>, Andrew D. | 22 | * (C. Scott Ananian <cananian@alumni.princeton.edu>, Andrew D. |
23 | * Balsa <andrebalsa@altern.org>, Philip Gladstone <philip@raptor.com>; | 23 | * Balsa <andrebalsa@altern.org>, Philip Gladstone <philip@raptor.com>; |
24 | * ported from 2.0.35 Jumbo-9 by Michael Krause <m.krause@tu-harburg.de>). | 24 | * ported from 2.0.35 Jumbo-9 by Michael Krause <m.krause@tu-harburg.de>). |
25 | * 1998-12-16 Andrea Arcangeli | 25 | * 1998-12-16 Andrea Arcangeli |
26 | * Fixed Jumbo-9 code in 2.1.131: do_gettimeofday was missing 1 jiffy | 26 | * Fixed Jumbo-9 code in 2.1.131: do_gettimeofday was missing 1 jiffy |
27 | * because was not accounting lost_ticks. | 27 | * because was not accounting lost_ticks. |
28 | * 1998-12-24 Copyright (C) 1998 Andrea Arcangeli | 28 | * 1998-12-24 Copyright (C) 1998 Andrea Arcangeli |
29 | * Fixed a xtime SMP race (we need the xtime_lock rw spinlock to | 29 | * Fixed a xtime SMP race (we need the xtime_lock rw spinlock to |
30 | * serialize accesses to xtime/lost_ticks). | 30 | * serialize accesses to xtime/lost_ticks). |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
34 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
35 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
36 | #include <linux/param.h> | 36 | #include <linux/param.h> |
37 | #include <linux/string.h> | 37 | #include <linux/string.h> |
38 | #include <linux/mm.h> | 38 | #include <linux/mm.h> |
39 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
40 | #include <linux/time.h> | 40 | #include <linux/time.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/init.h> | 42 | #include <linux/init.h> |
43 | #include <linux/smp.h> | 43 | #include <linux/smp.h> |
44 | #include <linux/module.h> | 44 | #include <linux/module.h> |
45 | #include <linux/sysdev.h> | 45 | #include <linux/sysdev.h> |
46 | #include <linux/bcd.h> | 46 | #include <linux/bcd.h> |
47 | #include <linux/efi.h> | 47 | #include <linux/efi.h> |
48 | #include <linux/mca.h> | 48 | #include <linux/mca.h> |
49 | 49 | ||
50 | #include <asm/io.h> | 50 | #include <asm/io.h> |
51 | #include <asm/smp.h> | 51 | #include <asm/smp.h> |
52 | #include <asm/irq.h> | 52 | #include <asm/irq.h> |
53 | #include <asm/msr.h> | 53 | #include <asm/msr.h> |
54 | #include <asm/delay.h> | 54 | #include <asm/delay.h> |
55 | #include <asm/mpspec.h> | 55 | #include <asm/mpspec.h> |
56 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
57 | #include <asm/processor.h> | 57 | #include <asm/processor.h> |
58 | #include <asm/timer.h> | 58 | #include <asm/timer.h> |
59 | 59 | ||
60 | #include "mach_time.h" | 60 | #include "mach_time.h" |
61 | 61 | ||
62 | #include <linux/timex.h> | 62 | #include <linux/timex.h> |
63 | #include <linux/config.h> | 63 | #include <linux/config.h> |
64 | 64 | ||
65 | #include <asm/hpet.h> | 65 | #include <asm/hpet.h> |
66 | 66 | ||
67 | #include <asm/arch_hooks.h> | 67 | #include <asm/arch_hooks.h> |
68 | 68 | ||
69 | #include "io_ports.h" | 69 | #include "io_ports.h" |
70 | 70 | ||
71 | extern spinlock_t i8259A_lock; | 71 | extern spinlock_t i8259A_lock; |
72 | int pit_latch_buggy; /* extern */ | 72 | int pit_latch_buggy; /* extern */ |
73 | 73 | ||
74 | #include "do_timer.h" | 74 | #include "do_timer.h" |
75 | 75 | ||
76 | u64 jiffies_64 = INITIAL_JIFFIES; | 76 | u64 jiffies_64 = INITIAL_JIFFIES; |
77 | 77 | ||
78 | EXPORT_SYMBOL(jiffies_64); | 78 | EXPORT_SYMBOL(jiffies_64); |
79 | 79 | ||
80 | unsigned long cpu_khz; /* Detected as we calibrate the TSC */ | 80 | unsigned int cpu_khz; /* Detected as we calibrate the TSC */ |
81 | EXPORT_SYMBOL(cpu_khz); | 81 | EXPORT_SYMBOL(cpu_khz); |
82 | 82 | ||
83 | extern unsigned long wall_jiffies; | 83 | extern unsigned long wall_jiffies; |
84 | 84 | ||
85 | DEFINE_SPINLOCK(rtc_lock); | 85 | DEFINE_SPINLOCK(rtc_lock); |
86 | EXPORT_SYMBOL(rtc_lock); | 86 | EXPORT_SYMBOL(rtc_lock); |
87 | 87 | ||
88 | DEFINE_SPINLOCK(i8253_lock); | 88 | DEFINE_SPINLOCK(i8253_lock); |
89 | EXPORT_SYMBOL(i8253_lock); | 89 | EXPORT_SYMBOL(i8253_lock); |
90 | 90 | ||
91 | struct timer_opts *cur_timer = &timer_none; | 91 | struct timer_opts *cur_timer = &timer_none; |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * This is a special lock that is owned by the CPU and holds the index | 94 | * This is a special lock that is owned by the CPU and holds the index |
95 | * register we are working with. It is required for NMI access to the | 95 | * register we are working with. It is required for NMI access to the |
96 | * CMOS/RTC registers. See include/asm-i386/mc146818rtc.h for details. | 96 | * CMOS/RTC registers. See include/asm-i386/mc146818rtc.h for details. |
97 | */ | 97 | */ |
98 | volatile unsigned long cmos_lock = 0; | 98 | volatile unsigned long cmos_lock = 0; |
99 | EXPORT_SYMBOL(cmos_lock); | 99 | EXPORT_SYMBOL(cmos_lock); |
100 | 100 | ||
101 | /* Routines for accessing the CMOS RAM/RTC. */ | 101 | /* Routines for accessing the CMOS RAM/RTC. */ |
102 | unsigned char rtc_cmos_read(unsigned char addr) | 102 | unsigned char rtc_cmos_read(unsigned char addr) |
103 | { | 103 | { |
104 | unsigned char val; | 104 | unsigned char val; |
105 | lock_cmos_prefix(addr); | 105 | lock_cmos_prefix(addr); |
106 | outb_p(addr, RTC_PORT(0)); | 106 | outb_p(addr, RTC_PORT(0)); |
107 | val = inb_p(RTC_PORT(1)); | 107 | val = inb_p(RTC_PORT(1)); |
108 | lock_cmos_suffix(addr); | 108 | lock_cmos_suffix(addr); |
109 | return val; | 109 | return val; |
110 | } | 110 | } |
111 | EXPORT_SYMBOL(rtc_cmos_read); | 111 | EXPORT_SYMBOL(rtc_cmos_read); |
112 | 112 | ||
113 | void rtc_cmos_write(unsigned char val, unsigned char addr) | 113 | void rtc_cmos_write(unsigned char val, unsigned char addr) |
114 | { | 114 | { |
115 | lock_cmos_prefix(addr); | 115 | lock_cmos_prefix(addr); |
116 | outb_p(addr, RTC_PORT(0)); | 116 | outb_p(addr, RTC_PORT(0)); |
117 | outb_p(val, RTC_PORT(1)); | 117 | outb_p(val, RTC_PORT(1)); |
118 | lock_cmos_suffix(addr); | 118 | lock_cmos_suffix(addr); |
119 | } | 119 | } |
120 | EXPORT_SYMBOL(rtc_cmos_write); | 120 | EXPORT_SYMBOL(rtc_cmos_write); |
121 | 121 | ||
122 | /* | 122 | /* |
123 | * This version of gettimeofday has microsecond resolution | 123 | * This version of gettimeofday has microsecond resolution |
124 | * and better than microsecond precision on fast x86 machines with TSC. | 124 | * and better than microsecond precision on fast x86 machines with TSC. |
125 | */ | 125 | */ |
126 | void do_gettimeofday(struct timeval *tv) | 126 | void do_gettimeofday(struct timeval *tv) |
127 | { | 127 | { |
128 | unsigned long seq; | 128 | unsigned long seq; |
129 | unsigned long usec, sec; | 129 | unsigned long usec, sec; |
130 | unsigned long max_ntp_tick; | 130 | unsigned long max_ntp_tick; |
131 | 131 | ||
132 | do { | 132 | do { |
133 | unsigned long lost; | 133 | unsigned long lost; |
134 | 134 | ||
135 | seq = read_seqbegin(&xtime_lock); | 135 | seq = read_seqbegin(&xtime_lock); |
136 | 136 | ||
137 | usec = cur_timer->get_offset(); | 137 | usec = cur_timer->get_offset(); |
138 | lost = jiffies - wall_jiffies; | 138 | lost = jiffies - wall_jiffies; |
139 | 139 | ||
140 | /* | 140 | /* |
141 | * If time_adjust is negative then NTP is slowing the clock | 141 | * If time_adjust is negative then NTP is slowing the clock |
142 | * so make sure not to go into next possible interval. | 142 | * so make sure not to go into next possible interval. |
143 | * Better to lose some accuracy than have time go backwards.. | 143 | * Better to lose some accuracy than have time go backwards.. |
144 | */ | 144 | */ |
145 | if (unlikely(time_adjust < 0)) { | 145 | if (unlikely(time_adjust < 0)) { |
146 | max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj; | 146 | max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj; |
147 | usec = min(usec, max_ntp_tick); | 147 | usec = min(usec, max_ntp_tick); |
148 | 148 | ||
149 | if (lost) | 149 | if (lost) |
150 | usec += lost * max_ntp_tick; | 150 | usec += lost * max_ntp_tick; |
151 | } | 151 | } |
152 | else if (unlikely(lost)) | 152 | else if (unlikely(lost)) |
153 | usec += lost * (USEC_PER_SEC / HZ); | 153 | usec += lost * (USEC_PER_SEC / HZ); |
154 | 154 | ||
155 | sec = xtime.tv_sec; | 155 | sec = xtime.tv_sec; |
156 | usec += (xtime.tv_nsec / 1000); | 156 | usec += (xtime.tv_nsec / 1000); |
157 | } while (read_seqretry(&xtime_lock, seq)); | 157 | } while (read_seqretry(&xtime_lock, seq)); |
158 | 158 | ||
159 | while (usec >= 1000000) { | 159 | while (usec >= 1000000) { |
160 | usec -= 1000000; | 160 | usec -= 1000000; |
161 | sec++; | 161 | sec++; |
162 | } | 162 | } |
163 | 163 | ||
164 | tv->tv_sec = sec; | 164 | tv->tv_sec = sec; |
165 | tv->tv_usec = usec; | 165 | tv->tv_usec = usec; |
166 | } | 166 | } |
167 | 167 | ||
168 | EXPORT_SYMBOL(do_gettimeofday); | 168 | EXPORT_SYMBOL(do_gettimeofday); |
169 | 169 | ||
170 | int do_settimeofday(struct timespec *tv) | 170 | int do_settimeofday(struct timespec *tv) |
171 | { | 171 | { |
172 | time_t wtm_sec, sec = tv->tv_sec; | 172 | time_t wtm_sec, sec = tv->tv_sec; |
173 | long wtm_nsec, nsec = tv->tv_nsec; | 173 | long wtm_nsec, nsec = tv->tv_nsec; |
174 | 174 | ||
175 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | 175 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) |
176 | return -EINVAL; | 176 | return -EINVAL; |
177 | 177 | ||
178 | write_seqlock_irq(&xtime_lock); | 178 | write_seqlock_irq(&xtime_lock); |
179 | /* | 179 | /* |
180 | * This is revolting. We need to set "xtime" correctly. However, the | 180 | * This is revolting. We need to set "xtime" correctly. However, the |
181 | * value in this location is the value at the most recent update of | 181 | * value in this location is the value at the most recent update of |
182 | * wall time. Discover what correction gettimeofday() would have | 182 | * wall time. Discover what correction gettimeofday() would have |
183 | * made, and then undo it! | 183 | * made, and then undo it! |
184 | */ | 184 | */ |
185 | nsec -= cur_timer->get_offset() * NSEC_PER_USEC; | 185 | nsec -= cur_timer->get_offset() * NSEC_PER_USEC; |
186 | nsec -= (jiffies - wall_jiffies) * TICK_NSEC; | 186 | nsec -= (jiffies - wall_jiffies) * TICK_NSEC; |
187 | 187 | ||
188 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); | 188 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); |
189 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); | 189 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); |
190 | 190 | ||
191 | set_normalized_timespec(&xtime, sec, nsec); | 191 | set_normalized_timespec(&xtime, sec, nsec); |
192 | set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); | 192 | set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); |
193 | 193 | ||
194 | time_adjust = 0; /* stop active adjtime() */ | 194 | time_adjust = 0; /* stop active adjtime() */ |
195 | time_status |= STA_UNSYNC; | 195 | time_status |= STA_UNSYNC; |
196 | time_maxerror = NTP_PHASE_LIMIT; | 196 | time_maxerror = NTP_PHASE_LIMIT; |
197 | time_esterror = NTP_PHASE_LIMIT; | 197 | time_esterror = NTP_PHASE_LIMIT; |
198 | write_sequnlock_irq(&xtime_lock); | 198 | write_sequnlock_irq(&xtime_lock); |
199 | clock_was_set(); | 199 | clock_was_set(); |
200 | return 0; | 200 | return 0; |
201 | } | 201 | } |
202 | 202 | ||
203 | EXPORT_SYMBOL(do_settimeofday); | 203 | EXPORT_SYMBOL(do_settimeofday); |
204 | 204 | ||
205 | static int set_rtc_mmss(unsigned long nowtime) | 205 | static int set_rtc_mmss(unsigned long nowtime) |
206 | { | 206 | { |
207 | int retval; | 207 | int retval; |
208 | 208 | ||
209 | WARN_ON(irqs_disabled()); | 209 | WARN_ON(irqs_disabled()); |
210 | 210 | ||
211 | /* gets recalled with irq locally disabled */ | 211 | /* gets recalled with irq locally disabled */ |
212 | spin_lock_irq(&rtc_lock); | 212 | spin_lock_irq(&rtc_lock); |
213 | if (efi_enabled) | 213 | if (efi_enabled) |
214 | retval = efi_set_rtc_mmss(nowtime); | 214 | retval = efi_set_rtc_mmss(nowtime); |
215 | else | 215 | else |
216 | retval = mach_set_rtc_mmss(nowtime); | 216 | retval = mach_set_rtc_mmss(nowtime); |
217 | spin_unlock_irq(&rtc_lock); | 217 | spin_unlock_irq(&rtc_lock); |
218 | 218 | ||
219 | return retval; | 219 | return retval; |
220 | } | 220 | } |
221 | 221 | ||
222 | 222 | ||
223 | int timer_ack; | 223 | int timer_ack; |
224 | 224 | ||
225 | /* monotonic_clock(): returns # of nanoseconds passed since time_init() | 225 | /* monotonic_clock(): returns # of nanoseconds passed since time_init() |
226 | * Note: This function is required to return accurate | 226 | * Note: This function is required to return accurate |
227 | * time even in the absence of multiple timer ticks. | 227 | * time even in the absence of multiple timer ticks. |
228 | */ | 228 | */ |
229 | unsigned long long monotonic_clock(void) | 229 | unsigned long long monotonic_clock(void) |
230 | { | 230 | { |
231 | return cur_timer->monotonic_clock(); | 231 | return cur_timer->monotonic_clock(); |
232 | } | 232 | } |
233 | EXPORT_SYMBOL(monotonic_clock); | 233 | EXPORT_SYMBOL(monotonic_clock); |
234 | 234 | ||
235 | #if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER) | 235 | #if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER) |
236 | unsigned long profile_pc(struct pt_regs *regs) | 236 | unsigned long profile_pc(struct pt_regs *regs) |
237 | { | 237 | { |
238 | unsigned long pc = instruction_pointer(regs); | 238 | unsigned long pc = instruction_pointer(regs); |
239 | 239 | ||
240 | if (in_lock_functions(pc)) | 240 | if (in_lock_functions(pc)) |
241 | return *(unsigned long *)(regs->ebp + 4); | 241 | return *(unsigned long *)(regs->ebp + 4); |
242 | 242 | ||
243 | return pc; | 243 | return pc; |
244 | } | 244 | } |
245 | EXPORT_SYMBOL(profile_pc); | 245 | EXPORT_SYMBOL(profile_pc); |
246 | #endif | 246 | #endif |
247 | 247 | ||
248 | /* | 248 | /* |
249 | * timer_interrupt() needs to keep up the real-time clock, | 249 | * timer_interrupt() needs to keep up the real-time clock, |
250 | * as well as call the "do_timer()" routine every clocktick | 250 | * as well as call the "do_timer()" routine every clocktick |
251 | */ | 251 | */ |
252 | static inline void do_timer_interrupt(int irq, void *dev_id, | 252 | static inline void do_timer_interrupt(int irq, void *dev_id, |
253 | struct pt_regs *regs) | 253 | struct pt_regs *regs) |
254 | { | 254 | { |
255 | #ifdef CONFIG_X86_IO_APIC | 255 | #ifdef CONFIG_X86_IO_APIC |
256 | if (timer_ack) { | 256 | if (timer_ack) { |
257 | /* | 257 | /* |
258 | * Subtle, when I/O APICs are used we have to ack timer IRQ | 258 | * Subtle, when I/O APICs are used we have to ack timer IRQ |
259 | * manually to reset the IRR bit for do_slow_gettimeoffset(). | 259 | * manually to reset the IRR bit for do_slow_gettimeoffset(). |
260 | * This will also deassert NMI lines for the watchdog if run | 260 | * This will also deassert NMI lines for the watchdog if run |
261 | * on an 82489DX-based system. | 261 | * on an 82489DX-based system. |
262 | */ | 262 | */ |
263 | spin_lock(&i8259A_lock); | 263 | spin_lock(&i8259A_lock); |
264 | outb(0x0c, PIC_MASTER_OCW3); | 264 | outb(0x0c, PIC_MASTER_OCW3); |
265 | /* Ack the IRQ; AEOI will end it automatically. */ | 265 | /* Ack the IRQ; AEOI will end it automatically. */ |
266 | inb(PIC_MASTER_POLL); | 266 | inb(PIC_MASTER_POLL); |
267 | spin_unlock(&i8259A_lock); | 267 | spin_unlock(&i8259A_lock); |
268 | } | 268 | } |
269 | #endif | 269 | #endif |
270 | 270 | ||
271 | do_timer_interrupt_hook(regs); | 271 | do_timer_interrupt_hook(regs); |
272 | 272 | ||
273 | 273 | ||
274 | if (MCA_bus) { | 274 | if (MCA_bus) { |
275 | /* The PS/2 uses level-triggered interrupts. You can't | 275 | /* The PS/2 uses level-triggered interrupts. You can't |
276 | turn them off, nor would you want to (any attempt to | 276 | turn them off, nor would you want to (any attempt to |
277 | enable edge-triggered interrupts usually gets intercepted by a | 277 | enable edge-triggered interrupts usually gets intercepted by a |
278 | special hardware circuit). Hence we have to acknowledge | 278 | special hardware circuit). Hence we have to acknowledge |
279 | the timer interrupt. Through some incredibly stupid | 279 | the timer interrupt. Through some incredibly stupid |
280 | design idea, the reset for IRQ 0 is done by setting the | 280 | design idea, the reset for IRQ 0 is done by setting the |
281 | high bit of the PPI port B (0x61). Note that some PS/2s, | 281 | high bit of the PPI port B (0x61). Note that some PS/2s, |
282 | notably the 55SX, work fine if this is removed. */ | 282 | notably the 55SX, work fine if this is removed. */ |
283 | 283 | ||
284 | irq = inb_p( 0x61 ); /* read the current state */ | 284 | irq = inb_p( 0x61 ); /* read the current state */ |
285 | outb_p( irq|0x80, 0x61 ); /* reset the IRQ */ | 285 | outb_p( irq|0x80, 0x61 ); /* reset the IRQ */ |
286 | } | 286 | } |
287 | } | 287 | } |
288 | 288 | ||
289 | /* | 289 | /* |
290 | * This is the same as the above, except we _also_ save the current | 290 | * This is the same as the above, except we _also_ save the current |
291 | * Time Stamp Counter value at the time of the timer interrupt, so that | 291 | * Time Stamp Counter value at the time of the timer interrupt, so that |
292 | * we later on can estimate the time of day more exactly. | 292 | * we later on can estimate the time of day more exactly. |
293 | */ | 293 | */ |
294 | irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 294 | irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
295 | { | 295 | { |
296 | /* | 296 | /* |
297 | * Here we are in the timer irq handler. We just have irqs locally | 297 | * Here we are in the timer irq handler. We just have irqs locally |
298 | * disabled but we don't know if the timer_bh is running on the other | 298 | * disabled but we don't know if the timer_bh is running on the other |
299 | * CPU. We need to avoid to SMP race with it. NOTE: we don' t need | 299 | * CPU. We need to avoid to SMP race with it. NOTE: we don' t need |
300 | * the irq version of write_lock because as just said we have irq | 300 | * the irq version of write_lock because as just said we have irq |
301 | * locally disabled. -arca | 301 | * locally disabled. -arca |
302 | */ | 302 | */ |
303 | write_seqlock(&xtime_lock); | 303 | write_seqlock(&xtime_lock); |
304 | 304 | ||
305 | cur_timer->mark_offset(); | 305 | cur_timer->mark_offset(); |
306 | 306 | ||
307 | do_timer_interrupt(irq, NULL, regs); | 307 | do_timer_interrupt(irq, NULL, regs); |
308 | 308 | ||
309 | write_sequnlock(&xtime_lock); | 309 | write_sequnlock(&xtime_lock); |
310 | return IRQ_HANDLED; | 310 | return IRQ_HANDLED; |
311 | } | 311 | } |
312 | 312 | ||
313 | /* not static: needed by APM */ | 313 | /* not static: needed by APM */ |
314 | unsigned long get_cmos_time(void) | 314 | unsigned long get_cmos_time(void) |
315 | { | 315 | { |
316 | unsigned long retval; | 316 | unsigned long retval; |
317 | 317 | ||
318 | spin_lock(&rtc_lock); | 318 | spin_lock(&rtc_lock); |
319 | 319 | ||
320 | if (efi_enabled) | 320 | if (efi_enabled) |
321 | retval = efi_get_time(); | 321 | retval = efi_get_time(); |
322 | else | 322 | else |
323 | retval = mach_get_cmos_time(); | 323 | retval = mach_get_cmos_time(); |
324 | 324 | ||
325 | spin_unlock(&rtc_lock); | 325 | spin_unlock(&rtc_lock); |
326 | 326 | ||
327 | return retval; | 327 | return retval; |
328 | } | 328 | } |
329 | EXPORT_SYMBOL(get_cmos_time); | 329 | EXPORT_SYMBOL(get_cmos_time); |
330 | 330 | ||
331 | static void sync_cmos_clock(unsigned long dummy); | 331 | static void sync_cmos_clock(unsigned long dummy); |
332 | 332 | ||
333 | static struct timer_list sync_cmos_timer = | 333 | static struct timer_list sync_cmos_timer = |
334 | TIMER_INITIALIZER(sync_cmos_clock, 0, 0); | 334 | TIMER_INITIALIZER(sync_cmos_clock, 0, 0); |
335 | 335 | ||
336 | static void sync_cmos_clock(unsigned long dummy) | 336 | static void sync_cmos_clock(unsigned long dummy) |
337 | { | 337 | { |
338 | struct timeval now, next; | 338 | struct timeval now, next; |
339 | int fail = 1; | 339 | int fail = 1; |
340 | 340 | ||
341 | /* | 341 | /* |
342 | * If we have an externally synchronized Linux clock, then update | 342 | * If we have an externally synchronized Linux clock, then update |
343 | * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be | 343 | * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be |
344 | * called as close as possible to 500 ms before the new second starts. | 344 | * called as close as possible to 500 ms before the new second starts. |
345 | * This code is run on a timer. If the clock is set, that timer | 345 | * This code is run on a timer. If the clock is set, that timer |
346 | * may not expire at the correct time. Thus, we adjust... | 346 | * may not expire at the correct time. Thus, we adjust... |
347 | */ | 347 | */ |
348 | if ((time_status & STA_UNSYNC) != 0) | 348 | if ((time_status & STA_UNSYNC) != 0) |
349 | /* | 349 | /* |
350 | * Not synced, exit, do not restart a timer (if one is | 350 | * Not synced, exit, do not restart a timer (if one is |
351 | * running, let it run out). | 351 | * running, let it run out). |
352 | */ | 352 | */ |
353 | return; | 353 | return; |
354 | 354 | ||
355 | do_gettimeofday(&now); | 355 | do_gettimeofday(&now); |
356 | if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 && | 356 | if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 && |
357 | now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) | 357 | now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) |
358 | fail = set_rtc_mmss(now.tv_sec); | 358 | fail = set_rtc_mmss(now.tv_sec); |
359 | 359 | ||
360 | next.tv_usec = USEC_AFTER - now.tv_usec; | 360 | next.tv_usec = USEC_AFTER - now.tv_usec; |
361 | if (next.tv_usec <= 0) | 361 | if (next.tv_usec <= 0) |
362 | next.tv_usec += USEC_PER_SEC; | 362 | next.tv_usec += USEC_PER_SEC; |
363 | 363 | ||
364 | if (!fail) | 364 | if (!fail) |
365 | next.tv_sec = 659; | 365 | next.tv_sec = 659; |
366 | else | 366 | else |
367 | next.tv_sec = 0; | 367 | next.tv_sec = 0; |
368 | 368 | ||
369 | if (next.tv_usec >= USEC_PER_SEC) { | 369 | if (next.tv_usec >= USEC_PER_SEC) { |
370 | next.tv_sec++; | 370 | next.tv_sec++; |
371 | next.tv_usec -= USEC_PER_SEC; | 371 | next.tv_usec -= USEC_PER_SEC; |
372 | } | 372 | } |
373 | mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next)); | 373 | mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next)); |
374 | } | 374 | } |
375 | 375 | ||
376 | void notify_arch_cmos_timer(void) | 376 | void notify_arch_cmos_timer(void) |
377 | { | 377 | { |
378 | mod_timer(&sync_cmos_timer, jiffies + 1); | 378 | mod_timer(&sync_cmos_timer, jiffies + 1); |
379 | } | 379 | } |
380 | 380 | ||
381 | static long clock_cmos_diff, sleep_start; | 381 | static long clock_cmos_diff, sleep_start; |
382 | 382 | ||
383 | static int timer_suspend(struct sys_device *dev, pm_message_t state) | 383 | static int timer_suspend(struct sys_device *dev, pm_message_t state) |
384 | { | 384 | { |
385 | /* | 385 | /* |
386 | * Estimate time zone so that set_time can update the clock | 386 | * Estimate time zone so that set_time can update the clock |
387 | */ | 387 | */ |
388 | clock_cmos_diff = -get_cmos_time(); | 388 | clock_cmos_diff = -get_cmos_time(); |
389 | clock_cmos_diff += get_seconds(); | 389 | clock_cmos_diff += get_seconds(); |
390 | sleep_start = get_cmos_time(); | 390 | sleep_start = get_cmos_time(); |
391 | return 0; | 391 | return 0; |
392 | } | 392 | } |
393 | 393 | ||
394 | static int timer_resume(struct sys_device *dev) | 394 | static int timer_resume(struct sys_device *dev) |
395 | { | 395 | { |
396 | unsigned long flags; | 396 | unsigned long flags; |
397 | unsigned long sec; | 397 | unsigned long sec; |
398 | unsigned long sleep_length; | 398 | unsigned long sleep_length; |
399 | 399 | ||
400 | #ifdef CONFIG_HPET_TIMER | 400 | #ifdef CONFIG_HPET_TIMER |
401 | if (is_hpet_enabled()) | 401 | if (is_hpet_enabled()) |
402 | hpet_reenable(); | 402 | hpet_reenable(); |
403 | #endif | 403 | #endif |
404 | sec = get_cmos_time() + clock_cmos_diff; | 404 | sec = get_cmos_time() + clock_cmos_diff; |
405 | sleep_length = (get_cmos_time() - sleep_start) * HZ; | 405 | sleep_length = (get_cmos_time() - sleep_start) * HZ; |
406 | write_seqlock_irqsave(&xtime_lock, flags); | 406 | write_seqlock_irqsave(&xtime_lock, flags); |
407 | xtime.tv_sec = sec; | 407 | xtime.tv_sec = sec; |
408 | xtime.tv_nsec = 0; | 408 | xtime.tv_nsec = 0; |
409 | write_sequnlock_irqrestore(&xtime_lock, flags); | 409 | write_sequnlock_irqrestore(&xtime_lock, flags); |
410 | jiffies += sleep_length; | 410 | jiffies += sleep_length; |
411 | wall_jiffies += sleep_length; | 411 | wall_jiffies += sleep_length; |
412 | return 0; | 412 | return 0; |
413 | } | 413 | } |
414 | 414 | ||
415 | static struct sysdev_class timer_sysclass = { | 415 | static struct sysdev_class timer_sysclass = { |
416 | .resume = timer_resume, | 416 | .resume = timer_resume, |
417 | .suspend = timer_suspend, | 417 | .suspend = timer_suspend, |
418 | set_kset_name("timer"), | 418 | set_kset_name("timer"), |
419 | }; | 419 | }; |
420 | 420 | ||
421 | 421 | ||
422 | /* XXX this driverfs stuff should probably go elsewhere later -john */ | 422 | /* XXX this driverfs stuff should probably go elsewhere later -john */ |
423 | static struct sys_device device_timer = { | 423 | static struct sys_device device_timer = { |
424 | .id = 0, | 424 | .id = 0, |
425 | .cls = &timer_sysclass, | 425 | .cls = &timer_sysclass, |
426 | }; | 426 | }; |
427 | 427 | ||
428 | static int time_init_device(void) | 428 | static int time_init_device(void) |
429 | { | 429 | { |
430 | int error = sysdev_class_register(&timer_sysclass); | 430 | int error = sysdev_class_register(&timer_sysclass); |
431 | if (!error) | 431 | if (!error) |
432 | error = sysdev_register(&device_timer); | 432 | error = sysdev_register(&device_timer); |
433 | return error; | 433 | return error; |
434 | } | 434 | } |
435 | 435 | ||
436 | device_initcall(time_init_device); | 436 | device_initcall(time_init_device); |
437 | 437 | ||
438 | #ifdef CONFIG_HPET_TIMER | 438 | #ifdef CONFIG_HPET_TIMER |
439 | extern void (*late_time_init)(void); | 439 | extern void (*late_time_init)(void); |
440 | /* Duplicate of time_init() below, with hpet_enable part added */ | 440 | /* Duplicate of time_init() below, with hpet_enable part added */ |
441 | static void __init hpet_time_init(void) | 441 | static void __init hpet_time_init(void) |
442 | { | 442 | { |
443 | xtime.tv_sec = get_cmos_time(); | 443 | xtime.tv_sec = get_cmos_time(); |
444 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | 444 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); |
445 | set_normalized_timespec(&wall_to_monotonic, | 445 | set_normalized_timespec(&wall_to_monotonic, |
446 | -xtime.tv_sec, -xtime.tv_nsec); | 446 | -xtime.tv_sec, -xtime.tv_nsec); |
447 | 447 | ||
448 | if ((hpet_enable() >= 0) && hpet_use_timer) { | 448 | if ((hpet_enable() >= 0) && hpet_use_timer) { |
449 | printk("Using HPET for base-timer\n"); | 449 | printk("Using HPET for base-timer\n"); |
450 | } | 450 | } |
451 | 451 | ||
452 | cur_timer = select_timer(); | 452 | cur_timer = select_timer(); |
453 | printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); | 453 | printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); |
454 | 454 | ||
455 | time_init_hook(); | 455 | time_init_hook(); |
456 | } | 456 | } |
457 | #endif | 457 | #endif |
458 | 458 | ||
459 | void __init time_init(void) | 459 | void __init time_init(void) |
460 | { | 460 | { |
461 | #ifdef CONFIG_HPET_TIMER | 461 | #ifdef CONFIG_HPET_TIMER |
462 | if (is_hpet_capable()) { | 462 | if (is_hpet_capable()) { |
463 | /* | 463 | /* |
464 | * HPET initialization needs to do memory-mapped io. So, let | 464 | * HPET initialization needs to do memory-mapped io. So, let |
465 | * us do a late initialization after mem_init(). | 465 | * us do a late initialization after mem_init(). |
466 | */ | 466 | */ |
467 | late_time_init = hpet_time_init; | 467 | late_time_init = hpet_time_init; |
468 | return; | 468 | return; |
469 | } | 469 | } |
470 | #endif | 470 | #endif |
471 | xtime.tv_sec = get_cmos_time(); | 471 | xtime.tv_sec = get_cmos_time(); |
472 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | 472 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); |
473 | set_normalized_timespec(&wall_to_monotonic, | 473 | set_normalized_timespec(&wall_to_monotonic, |
474 | -xtime.tv_sec, -xtime.tv_nsec); | 474 | -xtime.tv_sec, -xtime.tv_nsec); |
475 | 475 | ||
476 | cur_timer = select_timer(); | 476 | cur_timer = select_timer(); |
477 | printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); | 477 | printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); |
478 | 478 | ||
479 | time_init_hook(); | 479 | time_init_hook(); |
480 | } | 480 | } |
481 | 481 |
arch/i386/kernel/timers/common.c
1 | /* | 1 | /* |
2 | * Common functions used across the timers go here | 2 | * Common functions used across the timers go here |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/init.h> | 5 | #include <linux/init.h> |
6 | #include <linux/timex.h> | 6 | #include <linux/timex.h> |
7 | #include <linux/errno.h> | 7 | #include <linux/errno.h> |
8 | #include <linux/jiffies.h> | 8 | #include <linux/jiffies.h> |
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | 10 | ||
11 | #include <asm/io.h> | 11 | #include <asm/io.h> |
12 | #include <asm/timer.h> | 12 | #include <asm/timer.h> |
13 | #include <asm/hpet.h> | 13 | #include <asm/hpet.h> |
14 | 14 | ||
15 | #include "mach_timer.h" | 15 | #include "mach_timer.h" |
16 | 16 | ||
17 | /* ------ Calibrate the TSC ------- | 17 | /* ------ Calibrate the TSC ------- |
18 | * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset(). | 18 | * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset(). |
19 | * Too much 64-bit arithmetic here to do this cleanly in C, and for | 19 | * Too much 64-bit arithmetic here to do this cleanly in C, and for |
20 | * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2) | 20 | * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2) |
21 | * output busy loop as low as possible. We avoid reading the CTC registers | 21 | * output busy loop as low as possible. We avoid reading the CTC registers |
22 | * directly because of the awkward 8-bit access mechanism of the 82C54 | 22 | * directly because of the awkward 8-bit access mechanism of the 82C54 |
23 | * device. | 23 | * device. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #define CALIBRATE_TIME (5 * 1000020/HZ) | 26 | #define CALIBRATE_TIME (5 * 1000020/HZ) |
27 | 27 | ||
28 | unsigned long calibrate_tsc(void) | 28 | unsigned long calibrate_tsc(void) |
29 | { | 29 | { |
30 | mach_prepare_counter(); | 30 | mach_prepare_counter(); |
31 | 31 | ||
32 | { | 32 | { |
33 | unsigned long startlow, starthigh; | 33 | unsigned long startlow, starthigh; |
34 | unsigned long endlow, endhigh; | 34 | unsigned long endlow, endhigh; |
35 | unsigned long count; | 35 | unsigned long count; |
36 | 36 | ||
37 | rdtsc(startlow,starthigh); | 37 | rdtsc(startlow,starthigh); |
38 | mach_countup(&count); | 38 | mach_countup(&count); |
39 | rdtsc(endlow,endhigh); | 39 | rdtsc(endlow,endhigh); |
40 | 40 | ||
41 | 41 | ||
42 | /* Error: ECTCNEVERSET */ | 42 | /* Error: ECTCNEVERSET */ |
43 | if (count <= 1) | 43 | if (count <= 1) |
44 | goto bad_ctc; | 44 | goto bad_ctc; |
45 | 45 | ||
46 | /* 64-bit subtract - gcc just messes up with long longs */ | 46 | /* 64-bit subtract - gcc just messes up with long longs */ |
47 | __asm__("subl %2,%0\n\t" | 47 | __asm__("subl %2,%0\n\t" |
48 | "sbbl %3,%1" | 48 | "sbbl %3,%1" |
49 | :"=a" (endlow), "=d" (endhigh) | 49 | :"=a" (endlow), "=d" (endhigh) |
50 | :"g" (startlow), "g" (starthigh), | 50 | :"g" (startlow), "g" (starthigh), |
51 | "0" (endlow), "1" (endhigh)); | 51 | "0" (endlow), "1" (endhigh)); |
52 | 52 | ||
53 | /* Error: ECPUTOOFAST */ | 53 | /* Error: ECPUTOOFAST */ |
54 | if (endhigh) | 54 | if (endhigh) |
55 | goto bad_ctc; | 55 | goto bad_ctc; |
56 | 56 | ||
57 | /* Error: ECPUTOOSLOW */ | 57 | /* Error: ECPUTOOSLOW */ |
58 | if (endlow <= CALIBRATE_TIME) | 58 | if (endlow <= CALIBRATE_TIME) |
59 | goto bad_ctc; | 59 | goto bad_ctc; |
60 | 60 | ||
61 | __asm__("divl %2" | 61 | __asm__("divl %2" |
62 | :"=a" (endlow), "=d" (endhigh) | 62 | :"=a" (endlow), "=d" (endhigh) |
63 | :"r" (endlow), "0" (0), "1" (CALIBRATE_TIME)); | 63 | :"r" (endlow), "0" (0), "1" (CALIBRATE_TIME)); |
64 | 64 | ||
65 | return endlow; | 65 | return endlow; |
66 | } | 66 | } |
67 | 67 | ||
68 | /* | 68 | /* |
69 | * The CTC wasn't reliable: we got a hit on the very first read, | 69 | * The CTC wasn't reliable: we got a hit on the very first read, |
70 | * or the CPU was so fast/slow that the quotient wouldn't fit in | 70 | * or the CPU was so fast/slow that the quotient wouldn't fit in |
71 | * 32 bits.. | 71 | * 32 bits.. |
72 | */ | 72 | */ |
73 | bad_ctc: | 73 | bad_ctc: |
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
77 | #ifdef CONFIG_HPET_TIMER | 77 | #ifdef CONFIG_HPET_TIMER |
78 | /* ------ Calibrate the TSC using HPET ------- | 78 | /* ------ Calibrate the TSC using HPET ------- |
79 | * Return 2^32 * (1 / (TSC clocks per usec)) for getting the CPU freq. | 79 | * Return 2^32 * (1 / (TSC clocks per usec)) for getting the CPU freq. |
80 | * Second output is parameter 1 (when non NULL) | 80 | * Second output is parameter 1 (when non NULL) |
81 | * Set 2^32 * (1 / (tsc per HPET clk)) for delay_hpet(). | 81 | * Set 2^32 * (1 / (tsc per HPET clk)) for delay_hpet(). |
82 | * calibrate_tsc() calibrates the processor TSC by comparing | 82 | * calibrate_tsc() calibrates the processor TSC by comparing |
83 | * it to the HPET timer of known frequency. | 83 | * it to the HPET timer of known frequency. |
84 | * Too much 64-bit arithmetic here to do this cleanly in C | 84 | * Too much 64-bit arithmetic here to do this cleanly in C |
85 | */ | 85 | */ |
86 | #define CALIBRATE_CNT_HPET (5 * hpet_tick) | 86 | #define CALIBRATE_CNT_HPET (5 * hpet_tick) |
87 | #define CALIBRATE_TIME_HPET (5 * KERNEL_TICK_USEC) | 87 | #define CALIBRATE_TIME_HPET (5 * KERNEL_TICK_USEC) |
88 | 88 | ||
89 | unsigned long __init calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr) | 89 | unsigned long __init calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr) |
90 | { | 90 | { |
91 | unsigned long tsc_startlow, tsc_starthigh; | 91 | unsigned long tsc_startlow, tsc_starthigh; |
92 | unsigned long tsc_endlow, tsc_endhigh; | 92 | unsigned long tsc_endlow, tsc_endhigh; |
93 | unsigned long hpet_start, hpet_end; | 93 | unsigned long hpet_start, hpet_end; |
94 | unsigned long result, remain; | 94 | unsigned long result, remain; |
95 | 95 | ||
96 | hpet_start = hpet_readl(HPET_COUNTER); | 96 | hpet_start = hpet_readl(HPET_COUNTER); |
97 | rdtsc(tsc_startlow, tsc_starthigh); | 97 | rdtsc(tsc_startlow, tsc_starthigh); |
98 | do { | 98 | do { |
99 | hpet_end = hpet_readl(HPET_COUNTER); | 99 | hpet_end = hpet_readl(HPET_COUNTER); |
100 | } while ((hpet_end - hpet_start) < CALIBRATE_CNT_HPET); | 100 | } while ((hpet_end - hpet_start) < CALIBRATE_CNT_HPET); |
101 | rdtsc(tsc_endlow, tsc_endhigh); | 101 | rdtsc(tsc_endlow, tsc_endhigh); |
102 | 102 | ||
103 | /* 64-bit subtract - gcc just messes up with long longs */ | 103 | /* 64-bit subtract - gcc just messes up with long longs */ |
104 | __asm__("subl %2,%0\n\t" | 104 | __asm__("subl %2,%0\n\t" |
105 | "sbbl %3,%1" | 105 | "sbbl %3,%1" |
106 | :"=a" (tsc_endlow), "=d" (tsc_endhigh) | 106 | :"=a" (tsc_endlow), "=d" (tsc_endhigh) |
107 | :"g" (tsc_startlow), "g" (tsc_starthigh), | 107 | :"g" (tsc_startlow), "g" (tsc_starthigh), |
108 | "0" (tsc_endlow), "1" (tsc_endhigh)); | 108 | "0" (tsc_endlow), "1" (tsc_endhigh)); |
109 | 109 | ||
110 | /* Error: ECPUTOOFAST */ | 110 | /* Error: ECPUTOOFAST */ |
111 | if (tsc_endhigh) | 111 | if (tsc_endhigh) |
112 | goto bad_calibration; | 112 | goto bad_calibration; |
113 | 113 | ||
114 | /* Error: ECPUTOOSLOW */ | 114 | /* Error: ECPUTOOSLOW */ |
115 | if (tsc_endlow <= CALIBRATE_TIME_HPET) | 115 | if (tsc_endlow <= CALIBRATE_TIME_HPET) |
116 | goto bad_calibration; | 116 | goto bad_calibration; |
117 | 117 | ||
118 | ASM_DIV64_REG(result, remain, tsc_endlow, 0, CALIBRATE_TIME_HPET); | 118 | ASM_DIV64_REG(result, remain, tsc_endlow, 0, CALIBRATE_TIME_HPET); |
119 | if (remain > (tsc_endlow >> 1)) | 119 | if (remain > (tsc_endlow >> 1)) |
120 | result++; /* rounding the result */ | 120 | result++; /* rounding the result */ |
121 | 121 | ||
122 | if (tsc_hpet_quotient_ptr) { | 122 | if (tsc_hpet_quotient_ptr) { |
123 | unsigned long tsc_hpet_quotient; | 123 | unsigned long tsc_hpet_quotient; |
124 | 124 | ||
125 | ASM_DIV64_REG(tsc_hpet_quotient, remain, tsc_endlow, 0, | 125 | ASM_DIV64_REG(tsc_hpet_quotient, remain, tsc_endlow, 0, |
126 | CALIBRATE_CNT_HPET); | 126 | CALIBRATE_CNT_HPET); |
127 | if (remain > (tsc_endlow >> 1)) | 127 | if (remain > (tsc_endlow >> 1)) |
128 | tsc_hpet_quotient++; /* rounding the result */ | 128 | tsc_hpet_quotient++; /* rounding the result */ |
129 | *tsc_hpet_quotient_ptr = tsc_hpet_quotient; | 129 | *tsc_hpet_quotient_ptr = tsc_hpet_quotient; |
130 | } | 130 | } |
131 | 131 | ||
132 | return result; | 132 | return result; |
133 | bad_calibration: | 133 | bad_calibration: |
134 | /* | 134 | /* |
135 | * the CPU was so fast/slow that the quotient wouldn't fit in | 135 | * the CPU was so fast/slow that the quotient wouldn't fit in |
136 | * 32 bits.. | 136 | * 32 bits.. |
137 | */ | 137 | */ |
138 | return 0; | 138 | return 0; |
139 | } | 139 | } |
140 | #endif | 140 | #endif |
141 | 141 | ||
142 | 142 | ||
143 | unsigned long read_timer_tsc(void) | 143 | unsigned long read_timer_tsc(void) |
144 | { | 144 | { |
145 | unsigned long retval; | 145 | unsigned long retval; |
146 | rdtscl(retval); | 146 | rdtscl(retval); |
147 | return retval; | 147 | return retval; |
148 | } | 148 | } |
149 | 149 | ||
150 | 150 | ||
151 | /* calculate cpu_khz */ | 151 | /* calculate cpu_khz */ |
152 | void init_cpu_khz(void) | 152 | void init_cpu_khz(void) |
153 | { | 153 | { |
154 | if (cpu_has_tsc) { | 154 | if (cpu_has_tsc) { |
155 | unsigned long tsc_quotient = calibrate_tsc(); | 155 | unsigned long tsc_quotient = calibrate_tsc(); |
156 | if (tsc_quotient) { | 156 | if (tsc_quotient) { |
157 | /* report CPU clock rate in Hz. | 157 | /* report CPU clock rate in Hz. |
158 | * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = | 158 | * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = |
159 | * clock/second. Our precision is about 100 ppm. | 159 | * clock/second. Our precision is about 100 ppm. |
160 | */ | 160 | */ |
161 | { unsigned long eax=0, edx=1000; | 161 | { unsigned long eax=0, edx=1000; |
162 | __asm__("divl %2" | 162 | __asm__("divl %2" |
163 | :"=a" (cpu_khz), "=d" (edx) | 163 | :"=a" (cpu_khz), "=d" (edx) |
164 | :"r" (tsc_quotient), | 164 | :"r" (tsc_quotient), |
165 | "0" (eax), "1" (edx)); | 165 | "0" (eax), "1" (edx)); |
166 | printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); | 166 | printk("Detected %u.%03u MHz processor.\n", |
167 | cpu_khz / 1000, cpu_khz % 1000); | ||
167 | } | 168 | } |
168 | } | 169 | } |
169 | } | 170 | } |
170 | } | 171 | } |
171 | 172 | ||
172 | 173 |
arch/i386/kernel/timers/timer_hpet.c
1 | /* | 1 | /* |
2 | * This code largely moved from arch/i386/kernel/time.c. | 2 | * This code largely moved from arch/i386/kernel/time.c. |
3 | * See comments there for proper credits. | 3 | * See comments there for proper credits. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/spinlock.h> | 6 | #include <linux/spinlock.h> |
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/timex.h> | 8 | #include <linux/timex.h> |
9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
11 | #include <linux/jiffies.h> | 11 | #include <linux/jiffies.h> |
12 | 12 | ||
13 | #include <asm/timer.h> | 13 | #include <asm/timer.h> |
14 | #include <asm/io.h> | 14 | #include <asm/io.h> |
15 | #include <asm/processor.h> | 15 | #include <asm/processor.h> |
16 | 16 | ||
17 | #include "io_ports.h" | 17 | #include "io_ports.h" |
18 | #include "mach_timer.h" | 18 | #include "mach_timer.h" |
19 | #include <asm/hpet.h> | 19 | #include <asm/hpet.h> |
20 | 20 | ||
21 | static unsigned long hpet_usec_quotient; /* convert hpet clks to usec */ | 21 | static unsigned long hpet_usec_quotient; /* convert hpet clks to usec */ |
22 | static unsigned long tsc_hpet_quotient; /* convert tsc to hpet clks */ | 22 | static unsigned long tsc_hpet_quotient; /* convert tsc to hpet clks */ |
23 | static unsigned long hpet_last; /* hpet counter value at last tick*/ | 23 | static unsigned long hpet_last; /* hpet counter value at last tick*/ |
24 | static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */ | 24 | static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */ |
25 | static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */ | 25 | static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */ |
26 | static unsigned long long monotonic_base; | 26 | static unsigned long long monotonic_base; |
27 | static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; | 27 | static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; |
28 | 28 | ||
29 | /* convert from cycles(64bits) => nanoseconds (64bits) | 29 | /* convert from cycles(64bits) => nanoseconds (64bits) |
30 | * basic equation: | 30 | * basic equation: |
31 | * ns = cycles / (freq / ns_per_sec) | 31 | * ns = cycles / (freq / ns_per_sec) |
32 | * ns = cycles * (ns_per_sec / freq) | 32 | * ns = cycles * (ns_per_sec / freq) |
33 | * ns = cycles * (10^9 / (cpu_mhz * 10^6)) | 33 | * ns = cycles * (10^9 / (cpu_mhz * 10^6)) |
34 | * ns = cycles * (10^3 / cpu_mhz) | 34 | * ns = cycles * (10^3 / cpu_mhz) |
35 | * | 35 | * |
36 | * Then we use scaling math (suggested by george@mvista.com) to get: | 36 | * Then we use scaling math (suggested by george@mvista.com) to get: |
37 | * ns = cycles * (10^3 * SC / cpu_mhz) / SC | 37 | * ns = cycles * (10^3 * SC / cpu_mhz) / SC |
38 | * ns = cycles * cyc2ns_scale / SC | 38 | * ns = cycles * cyc2ns_scale / SC |
39 | * | 39 | * |
40 | * And since SC is a constant power of two, we can convert the div | 40 | * And since SC is a constant power of two, we can convert the div |
41 | * into a shift. | 41 | * into a shift. |
42 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" | 42 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" |
43 | */ | 43 | */ |
44 | static unsigned long cyc2ns_scale; | 44 | static unsigned long cyc2ns_scale; |
45 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ | 45 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ |
46 | 46 | ||
47 | static inline void set_cyc2ns_scale(unsigned long cpu_mhz) | 47 | static inline void set_cyc2ns_scale(unsigned long cpu_mhz) |
48 | { | 48 | { |
49 | cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz; | 49 | cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz; |
50 | } | 50 | } |
51 | 51 | ||
52 | static inline unsigned long long cycles_2_ns(unsigned long long cyc) | 52 | static inline unsigned long long cycles_2_ns(unsigned long long cyc) |
53 | { | 53 | { |
54 | return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; | 54 | return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; |
55 | } | 55 | } |
56 | 56 | ||
57 | static unsigned long long monotonic_clock_hpet(void) | 57 | static unsigned long long monotonic_clock_hpet(void) |
58 | { | 58 | { |
59 | unsigned long long last_offset, this_offset, base; | 59 | unsigned long long last_offset, this_offset, base; |
60 | unsigned seq; | 60 | unsigned seq; |
61 | 61 | ||
62 | /* atomically read monotonic base & last_offset */ | 62 | /* atomically read monotonic base & last_offset */ |
63 | do { | 63 | do { |
64 | seq = read_seqbegin(&monotonic_lock); | 64 | seq = read_seqbegin(&monotonic_lock); |
65 | last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; | 65 | last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; |
66 | base = monotonic_base; | 66 | base = monotonic_base; |
67 | } while (read_seqretry(&monotonic_lock, seq)); | 67 | } while (read_seqretry(&monotonic_lock, seq)); |
68 | 68 | ||
69 | /* Read the Time Stamp Counter */ | 69 | /* Read the Time Stamp Counter */ |
70 | rdtscll(this_offset); | 70 | rdtscll(this_offset); |
71 | 71 | ||
72 | /* return the value in ns */ | 72 | /* return the value in ns */ |
73 | return base + cycles_2_ns(this_offset - last_offset); | 73 | return base + cycles_2_ns(this_offset - last_offset); |
74 | } | 74 | } |
75 | 75 | ||
76 | static unsigned long get_offset_hpet(void) | 76 | static unsigned long get_offset_hpet(void) |
77 | { | 77 | { |
78 | register unsigned long eax, edx; | 78 | register unsigned long eax, edx; |
79 | 79 | ||
80 | eax = hpet_readl(HPET_COUNTER); | 80 | eax = hpet_readl(HPET_COUNTER); |
81 | eax -= hpet_last; /* hpet delta */ | 81 | eax -= hpet_last; /* hpet delta */ |
82 | eax = min(hpet_tick, eax); | 82 | eax = min(hpet_tick, eax); |
83 | /* | 83 | /* |
84 | * Time offset = (hpet delta) * ( usecs per HPET clock ) | 84 | * Time offset = (hpet delta) * ( usecs per HPET clock ) |
85 | * = (hpet delta) * ( usecs per tick / HPET clocks per tick) | 85 | * = (hpet delta) * ( usecs per tick / HPET clocks per tick) |
86 | * = (hpet delta) * ( hpet_usec_quotient ) / (2^32) | 86 | * = (hpet delta) * ( hpet_usec_quotient ) / (2^32) |
87 | * | 87 | * |
88 | * Where, | 88 | * Where, |
89 | * hpet_usec_quotient = (2^32 * usecs per tick)/HPET clocks per tick | 89 | * hpet_usec_quotient = (2^32 * usecs per tick)/HPET clocks per tick |
90 | * | 90 | * |
91 | * Using a mull instead of a divl saves some cycles in critical path. | 91 | * Using a mull instead of a divl saves some cycles in critical path. |
92 | */ | 92 | */ |
93 | ASM_MUL64_REG(eax, edx, hpet_usec_quotient, eax); | 93 | ASM_MUL64_REG(eax, edx, hpet_usec_quotient, eax); |
94 | 94 | ||
95 | /* our adjusted time offset in microseconds */ | 95 | /* our adjusted time offset in microseconds */ |
96 | return edx; | 96 | return edx; |
97 | } | 97 | } |
98 | 98 | ||
99 | static void mark_offset_hpet(void) | 99 | static void mark_offset_hpet(void) |
100 | { | 100 | { |
101 | unsigned long long this_offset, last_offset; | 101 | unsigned long long this_offset, last_offset; |
102 | unsigned long offset; | 102 | unsigned long offset; |
103 | 103 | ||
104 | write_seqlock(&monotonic_lock); | 104 | write_seqlock(&monotonic_lock); |
105 | last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; | 105 | last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; |
106 | rdtsc(last_tsc_low, last_tsc_high); | 106 | rdtsc(last_tsc_low, last_tsc_high); |
107 | 107 | ||
108 | if (hpet_use_timer) | 108 | if (hpet_use_timer) |
109 | offset = hpet_readl(HPET_T0_CMP) - hpet_tick; | 109 | offset = hpet_readl(HPET_T0_CMP) - hpet_tick; |
110 | else | 110 | else |
111 | offset = hpet_readl(HPET_COUNTER); | 111 | offset = hpet_readl(HPET_COUNTER); |
112 | if (unlikely(((offset - hpet_last) >= (2*hpet_tick)) && (hpet_last != 0))) { | 112 | if (unlikely(((offset - hpet_last) >= (2*hpet_tick)) && (hpet_last != 0))) { |
113 | int lost_ticks = ((offset - hpet_last) / hpet_tick) - 1; | 113 | int lost_ticks = ((offset - hpet_last) / hpet_tick) - 1; |
114 | jiffies_64 += lost_ticks; | 114 | jiffies_64 += lost_ticks; |
115 | } | 115 | } |
116 | hpet_last = offset; | 116 | hpet_last = offset; |
117 | 117 | ||
118 | /* update the monotonic base value */ | 118 | /* update the monotonic base value */ |
119 | this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; | 119 | this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; |
120 | monotonic_base += cycles_2_ns(this_offset - last_offset); | 120 | monotonic_base += cycles_2_ns(this_offset - last_offset); |
121 | write_sequnlock(&monotonic_lock); | 121 | write_sequnlock(&monotonic_lock); |
122 | } | 122 | } |
123 | 123 | ||
124 | static void delay_hpet(unsigned long loops) | 124 | static void delay_hpet(unsigned long loops) |
125 | { | 125 | { |
126 | unsigned long hpet_start, hpet_end; | 126 | unsigned long hpet_start, hpet_end; |
127 | unsigned long eax; | 127 | unsigned long eax; |
128 | 128 | ||
129 | /* loops is the number of cpu cycles. Convert it to hpet clocks */ | 129 | /* loops is the number of cpu cycles. Convert it to hpet clocks */ |
130 | ASM_MUL64_REG(eax, loops, tsc_hpet_quotient, loops); | 130 | ASM_MUL64_REG(eax, loops, tsc_hpet_quotient, loops); |
131 | 131 | ||
132 | hpet_start = hpet_readl(HPET_COUNTER); | 132 | hpet_start = hpet_readl(HPET_COUNTER); |
133 | do { | 133 | do { |
134 | rep_nop(); | 134 | rep_nop(); |
135 | hpet_end = hpet_readl(HPET_COUNTER); | 135 | hpet_end = hpet_readl(HPET_COUNTER); |
136 | } while ((hpet_end - hpet_start) < (loops)); | 136 | } while ((hpet_end - hpet_start) < (loops)); |
137 | } | 137 | } |
138 | 138 | ||
139 | static int __init init_hpet(char* override) | 139 | static int __init init_hpet(char* override) |
140 | { | 140 | { |
141 | unsigned long result, remain; | 141 | unsigned long result, remain; |
142 | 142 | ||
143 | /* check clock override */ | 143 | /* check clock override */ |
144 | if (override[0] && strncmp(override,"hpet",4)) | 144 | if (override[0] && strncmp(override,"hpet",4)) |
145 | return -ENODEV; | 145 | return -ENODEV; |
146 | 146 | ||
147 | if (!is_hpet_enabled()) | 147 | if (!is_hpet_enabled()) |
148 | return -ENODEV; | 148 | return -ENODEV; |
149 | 149 | ||
150 | printk("Using HPET for gettimeofday\n"); | 150 | printk("Using HPET for gettimeofday\n"); |
151 | if (cpu_has_tsc) { | 151 | if (cpu_has_tsc) { |
152 | unsigned long tsc_quotient = calibrate_tsc_hpet(&tsc_hpet_quotient); | 152 | unsigned long tsc_quotient = calibrate_tsc_hpet(&tsc_hpet_quotient); |
153 | if (tsc_quotient) { | 153 | if (tsc_quotient) { |
154 | /* report CPU clock rate in Hz. | 154 | /* report CPU clock rate in Hz. |
155 | * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = | 155 | * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = |
156 | * clock/second. Our precision is about 100 ppm. | 156 | * clock/second. Our precision is about 100 ppm. |
157 | */ | 157 | */ |
158 | { unsigned long eax=0, edx=1000; | 158 | { unsigned long eax=0, edx=1000; |
159 | ASM_DIV64_REG(cpu_khz, edx, tsc_quotient, | 159 | ASM_DIV64_REG(cpu_khz, edx, tsc_quotient, |
160 | eax, edx); | 160 | eax, edx); |
161 | printk("Detected %lu.%03lu MHz processor.\n", | 161 | printk("Detected %u.%03u MHz processor.\n", |
162 | cpu_khz / 1000, cpu_khz % 1000); | 162 | cpu_khz / 1000, cpu_khz % 1000); |
163 | } | 163 | } |
164 | set_cyc2ns_scale(cpu_khz/1000); | 164 | set_cyc2ns_scale(cpu_khz/1000); |
165 | } | 165 | } |
166 | } | 166 | } |
167 | 167 | ||
168 | /* | 168 | /* |
169 | * Math to calculate hpet to usec multiplier | 169 | * Math to calculate hpet to usec multiplier |
170 | * Look for the comments at get_offset_hpet() | 170 | * Look for the comments at get_offset_hpet() |
171 | */ | 171 | */ |
172 | ASM_DIV64_REG(result, remain, hpet_tick, 0, KERNEL_TICK_USEC); | 172 | ASM_DIV64_REG(result, remain, hpet_tick, 0, KERNEL_TICK_USEC); |
173 | if (remain > (hpet_tick >> 1)) | 173 | if (remain > (hpet_tick >> 1)) |
174 | result++; /* rounding the result */ | 174 | result++; /* rounding the result */ |
175 | hpet_usec_quotient = result; | 175 | hpet_usec_quotient = result; |
176 | 176 | ||
177 | return 0; | 177 | return 0; |
178 | } | 178 | } |
179 | 179 | ||
180 | /************************************************************/ | 180 | /************************************************************/ |
181 | 181 | ||
182 | /* tsc timer_opts struct */ | 182 | /* tsc timer_opts struct */ |
183 | static struct timer_opts timer_hpet = { | 183 | static struct timer_opts timer_hpet = { |
184 | .name = "hpet", | 184 | .name = "hpet", |
185 | .mark_offset = mark_offset_hpet, | 185 | .mark_offset = mark_offset_hpet, |
186 | .get_offset = get_offset_hpet, | 186 | .get_offset = get_offset_hpet, |
187 | .monotonic_clock = monotonic_clock_hpet, | 187 | .monotonic_clock = monotonic_clock_hpet, |
188 | .delay = delay_hpet, | 188 | .delay = delay_hpet, |
189 | .read_timer = read_timer_tsc, | 189 | .read_timer = read_timer_tsc, |
190 | }; | 190 | }; |
191 | 191 | ||
192 | struct init_timer_opts __initdata timer_hpet_init = { | 192 | struct init_timer_opts __initdata timer_hpet_init = { |
193 | .init = init_hpet, | 193 | .init = init_hpet, |
194 | .opts = &timer_hpet, | 194 | .opts = &timer_hpet, |
195 | }; | 195 | }; |
196 | 196 |
arch/i386/kernel/timers/timer_tsc.c
1 | /* | 1 | /* |
2 | * This code largely moved from arch/i386/kernel/time.c. | 2 | * This code largely moved from arch/i386/kernel/time.c. |
3 | * See comments there for proper credits. | 3 | * See comments there for proper credits. |
4 | * | 4 | * |
5 | * 2004-06-25 Jesper Juhl | 5 | * 2004-06-25 Jesper Juhl |
6 | * moved mark_offset_tsc below cpufreq_delayed_get to avoid gcc 3.4 | 6 | * moved mark_offset_tsc below cpufreq_delayed_get to avoid gcc 3.4 |
7 | * failing to inline. | 7 | * failing to inline. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/timex.h> | 12 | #include <linux/timex.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/cpufreq.h> | 14 | #include <linux/cpufreq.h> |
15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
16 | #include <linux/jiffies.h> | 16 | #include <linux/jiffies.h> |
17 | 17 | ||
18 | #include <asm/timer.h> | 18 | #include <asm/timer.h> |
19 | #include <asm/io.h> | 19 | #include <asm/io.h> |
20 | /* processor.h for distable_tsc flag */ | 20 | /* processor.h for distable_tsc flag */ |
21 | #include <asm/processor.h> | 21 | #include <asm/processor.h> |
22 | 22 | ||
23 | #include "io_ports.h" | 23 | #include "io_ports.h" |
24 | #include "mach_timer.h" | 24 | #include "mach_timer.h" |
25 | 25 | ||
26 | #include <asm/hpet.h> | 26 | #include <asm/hpet.h> |
27 | 27 | ||
28 | #ifdef CONFIG_HPET_TIMER | 28 | #ifdef CONFIG_HPET_TIMER |
29 | static unsigned long hpet_usec_quotient; | 29 | static unsigned long hpet_usec_quotient; |
30 | static unsigned long hpet_last; | 30 | static unsigned long hpet_last; |
31 | static struct timer_opts timer_tsc; | 31 | static struct timer_opts timer_tsc; |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | static inline void cpufreq_delayed_get(void); | 34 | static inline void cpufreq_delayed_get(void); |
35 | 35 | ||
36 | int tsc_disable __initdata = 0; | 36 | int tsc_disable __initdata = 0; |
37 | 37 | ||
38 | extern spinlock_t i8253_lock; | 38 | extern spinlock_t i8253_lock; |
39 | 39 | ||
40 | static int use_tsc; | 40 | static int use_tsc; |
41 | /* Number of usecs that the last interrupt was delayed */ | 41 | /* Number of usecs that the last interrupt was delayed */ |
42 | static int delay_at_last_interrupt; | 42 | static int delay_at_last_interrupt; |
43 | 43 | ||
44 | static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */ | 44 | static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */ |
45 | static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */ | 45 | static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */ |
46 | static unsigned long long monotonic_base; | 46 | static unsigned long long monotonic_base; |
47 | static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; | 47 | static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; |
48 | 48 | ||
49 | /* convert from cycles(64bits) => nanoseconds (64bits) | 49 | /* convert from cycles(64bits) => nanoseconds (64bits) |
50 | * basic equation: | 50 | * basic equation: |
51 | * ns = cycles / (freq / ns_per_sec) | 51 | * ns = cycles / (freq / ns_per_sec) |
52 | * ns = cycles * (ns_per_sec / freq) | 52 | * ns = cycles * (ns_per_sec / freq) |
53 | * ns = cycles * (10^9 / (cpu_mhz * 10^6)) | 53 | * ns = cycles * (10^9 / (cpu_mhz * 10^6)) |
54 | * ns = cycles * (10^3 / cpu_mhz) | 54 | * ns = cycles * (10^3 / cpu_mhz) |
55 | * | 55 | * |
56 | * Then we use scaling math (suggested by george@mvista.com) to get: | 56 | * Then we use scaling math (suggested by george@mvista.com) to get: |
57 | * ns = cycles * (10^3 * SC / cpu_mhz) / SC | 57 | * ns = cycles * (10^3 * SC / cpu_mhz) / SC |
58 | * ns = cycles * cyc2ns_scale / SC | 58 | * ns = cycles * cyc2ns_scale / SC |
59 | * | 59 | * |
60 | * And since SC is a constant power of two, we can convert the div | 60 | * And since SC is a constant power of two, we can convert the div |
61 | * into a shift. | 61 | * into a shift. |
62 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" | 62 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" |
63 | */ | 63 | */ |
64 | static unsigned long cyc2ns_scale; | 64 | static unsigned long cyc2ns_scale; |
65 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ | 65 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ |
66 | 66 | ||
67 | static inline void set_cyc2ns_scale(unsigned long cpu_mhz) | 67 | static inline void set_cyc2ns_scale(unsigned long cpu_mhz) |
68 | { | 68 | { |
69 | cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz; | 69 | cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz; |
70 | } | 70 | } |
71 | 71 | ||
72 | static inline unsigned long long cycles_2_ns(unsigned long long cyc) | 72 | static inline unsigned long long cycles_2_ns(unsigned long long cyc) |
73 | { | 73 | { |
74 | return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; | 74 | return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; |
75 | } | 75 | } |
76 | 76 | ||
77 | static int count2; /* counter for mark_offset_tsc() */ | 77 | static int count2; /* counter for mark_offset_tsc() */ |
78 | 78 | ||
79 | /* Cached *multiplier* to convert TSC counts to microseconds. | 79 | /* Cached *multiplier* to convert TSC counts to microseconds. |
80 | * (see the equation below). | 80 | * (see the equation below). |
81 | * Equal to 2^32 * (1 / (clocks per usec) ). | 81 | * Equal to 2^32 * (1 / (clocks per usec) ). |
82 | * Initialized in time_init. | 82 | * Initialized in time_init. |
83 | */ | 83 | */ |
84 | static unsigned long fast_gettimeoffset_quotient; | 84 | static unsigned long fast_gettimeoffset_quotient; |
85 | 85 | ||
86 | static unsigned long get_offset_tsc(void) | 86 | static unsigned long get_offset_tsc(void) |
87 | { | 87 | { |
88 | register unsigned long eax, edx; | 88 | register unsigned long eax, edx; |
89 | 89 | ||
90 | /* Read the Time Stamp Counter */ | 90 | /* Read the Time Stamp Counter */ |
91 | 91 | ||
92 | rdtsc(eax,edx); | 92 | rdtsc(eax,edx); |
93 | 93 | ||
94 | /* .. relative to previous jiffy (32 bits is enough) */ | 94 | /* .. relative to previous jiffy (32 bits is enough) */ |
95 | eax -= last_tsc_low; /* tsc_low delta */ | 95 | eax -= last_tsc_low; /* tsc_low delta */ |
96 | 96 | ||
97 | /* | 97 | /* |
98 | * Time offset = (tsc_low delta) * fast_gettimeoffset_quotient | 98 | * Time offset = (tsc_low delta) * fast_gettimeoffset_quotient |
99 | * = (tsc_low delta) * (usecs_per_clock) | 99 | * = (tsc_low delta) * (usecs_per_clock) |
100 | * = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy) | 100 | * = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy) |
101 | * | 101 | * |
102 | * Using a mull instead of a divl saves up to 31 clock cycles | 102 | * Using a mull instead of a divl saves up to 31 clock cycles |
103 | * in the critical path. | 103 | * in the critical path. |
104 | */ | 104 | */ |
105 | 105 | ||
106 | __asm__("mull %2" | 106 | __asm__("mull %2" |
107 | :"=a" (eax), "=d" (edx) | 107 | :"=a" (eax), "=d" (edx) |
108 | :"rm" (fast_gettimeoffset_quotient), | 108 | :"rm" (fast_gettimeoffset_quotient), |
109 | "0" (eax)); | 109 | "0" (eax)); |
110 | 110 | ||
111 | /* our adjusted time offset in microseconds */ | 111 | /* our adjusted time offset in microseconds */ |
112 | return delay_at_last_interrupt + edx; | 112 | return delay_at_last_interrupt + edx; |
113 | } | 113 | } |
114 | 114 | ||
115 | static unsigned long long monotonic_clock_tsc(void) | 115 | static unsigned long long monotonic_clock_tsc(void) |
116 | { | 116 | { |
117 | unsigned long long last_offset, this_offset, base; | 117 | unsigned long long last_offset, this_offset, base; |
118 | unsigned seq; | 118 | unsigned seq; |
119 | 119 | ||
120 | /* atomically read monotonic base & last_offset */ | 120 | /* atomically read monotonic base & last_offset */ |
121 | do { | 121 | do { |
122 | seq = read_seqbegin(&monotonic_lock); | 122 | seq = read_seqbegin(&monotonic_lock); |
123 | last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; | 123 | last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; |
124 | base = monotonic_base; | 124 | base = monotonic_base; |
125 | } while (read_seqretry(&monotonic_lock, seq)); | 125 | } while (read_seqretry(&monotonic_lock, seq)); |
126 | 126 | ||
127 | /* Read the Time Stamp Counter */ | 127 | /* Read the Time Stamp Counter */ |
128 | rdtscll(this_offset); | 128 | rdtscll(this_offset); |
129 | 129 | ||
130 | /* return the value in ns */ | 130 | /* return the value in ns */ |
131 | return base + cycles_2_ns(this_offset - last_offset); | 131 | return base + cycles_2_ns(this_offset - last_offset); |
132 | } | 132 | } |
133 | 133 | ||
134 | /* | 134 | /* |
135 | * Scheduler clock - returns current time in nanosec units. | 135 | * Scheduler clock - returns current time in nanosec units. |
136 | */ | 136 | */ |
137 | unsigned long long sched_clock(void) | 137 | unsigned long long sched_clock(void) |
138 | { | 138 | { |
139 | unsigned long long this_offset; | 139 | unsigned long long this_offset; |
140 | 140 | ||
141 | /* | 141 | /* |
142 | * In the NUMA case we dont use the TSC as they are not | 142 | * In the NUMA case we dont use the TSC as they are not |
143 | * synchronized across all CPUs. | 143 | * synchronized across all CPUs. |
144 | */ | 144 | */ |
145 | #ifndef CONFIG_NUMA | 145 | #ifndef CONFIG_NUMA |
146 | if (!use_tsc) | 146 | if (!use_tsc) |
147 | #endif | 147 | #endif |
148 | /* no locking but a rare wrong value is not a big deal */ | 148 | /* no locking but a rare wrong value is not a big deal */ |
149 | return jiffies_64 * (1000000000 / HZ); | 149 | return jiffies_64 * (1000000000 / HZ); |
150 | 150 | ||
151 | /* Read the Time Stamp Counter */ | 151 | /* Read the Time Stamp Counter */ |
152 | rdtscll(this_offset); | 152 | rdtscll(this_offset); |
153 | 153 | ||
154 | /* return the value in ns */ | 154 | /* return the value in ns */ |
155 | return cycles_2_ns(this_offset); | 155 | return cycles_2_ns(this_offset); |
156 | } | 156 | } |
157 | 157 | ||
158 | static void delay_tsc(unsigned long loops) | 158 | static void delay_tsc(unsigned long loops) |
159 | { | 159 | { |
160 | unsigned long bclock, now; | 160 | unsigned long bclock, now; |
161 | 161 | ||
162 | rdtscl(bclock); | 162 | rdtscl(bclock); |
163 | do | 163 | do |
164 | { | 164 | { |
165 | rep_nop(); | 165 | rep_nop(); |
166 | rdtscl(now); | 166 | rdtscl(now); |
167 | } while ((now-bclock) < loops); | 167 | } while ((now-bclock) < loops); |
168 | } | 168 | } |
169 | 169 | ||
170 | #ifdef CONFIG_HPET_TIMER | 170 | #ifdef CONFIG_HPET_TIMER |
171 | static void mark_offset_tsc_hpet(void) | 171 | static void mark_offset_tsc_hpet(void) |
172 | { | 172 | { |
173 | unsigned long long this_offset, last_offset; | 173 | unsigned long long this_offset, last_offset; |
174 | unsigned long offset, temp, hpet_current; | 174 | unsigned long offset, temp, hpet_current; |
175 | 175 | ||
176 | write_seqlock(&monotonic_lock); | 176 | write_seqlock(&monotonic_lock); |
177 | last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; | 177 | last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; |
178 | /* | 178 | /* |
179 | * It is important that these two operations happen almost at | 179 | * It is important that these two operations happen almost at |
180 | * the same time. We do the RDTSC stuff first, since it's | 180 | * the same time. We do the RDTSC stuff first, since it's |
181 | * faster. To avoid any inconsistencies, we need interrupts | 181 | * faster. To avoid any inconsistencies, we need interrupts |
182 | * disabled locally. | 182 | * disabled locally. |
183 | */ | 183 | */ |
184 | /* | 184 | /* |
185 | * Interrupts are just disabled locally since the timer irq | 185 | * Interrupts are just disabled locally since the timer irq |
186 | * has the SA_INTERRUPT flag set. -arca | 186 | * has the SA_INTERRUPT flag set. -arca |
187 | */ | 187 | */ |
188 | /* read Pentium cycle counter */ | 188 | /* read Pentium cycle counter */ |
189 | 189 | ||
190 | hpet_current = hpet_readl(HPET_COUNTER); | 190 | hpet_current = hpet_readl(HPET_COUNTER); |
191 | rdtsc(last_tsc_low, last_tsc_high); | 191 | rdtsc(last_tsc_low, last_tsc_high); |
192 | 192 | ||
193 | /* lost tick compensation */ | 193 | /* lost tick compensation */ |
194 | offset = hpet_readl(HPET_T0_CMP) - hpet_tick; | 194 | offset = hpet_readl(HPET_T0_CMP) - hpet_tick; |
195 | if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) { | 195 | if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) { |
196 | int lost_ticks = (offset - hpet_last) / hpet_tick; | 196 | int lost_ticks = (offset - hpet_last) / hpet_tick; |
197 | jiffies_64 += lost_ticks; | 197 | jiffies_64 += lost_ticks; |
198 | } | 198 | } |
199 | hpet_last = hpet_current; | 199 | hpet_last = hpet_current; |
200 | 200 | ||
201 | /* update the monotonic base value */ | 201 | /* update the monotonic base value */ |
202 | this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; | 202 | this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; |
203 | monotonic_base += cycles_2_ns(this_offset - last_offset); | 203 | monotonic_base += cycles_2_ns(this_offset - last_offset); |
204 | write_sequnlock(&monotonic_lock); | 204 | write_sequnlock(&monotonic_lock); |
205 | 205 | ||
206 | /* calculate delay_at_last_interrupt */ | 206 | /* calculate delay_at_last_interrupt */ |
207 | /* | 207 | /* |
208 | * Time offset = (hpet delta) * ( usecs per HPET clock ) | 208 | * Time offset = (hpet delta) * ( usecs per HPET clock ) |
209 | * = (hpet delta) * ( usecs per tick / HPET clocks per tick) | 209 | * = (hpet delta) * ( usecs per tick / HPET clocks per tick) |
210 | * = (hpet delta) * ( hpet_usec_quotient ) / (2^32) | 210 | * = (hpet delta) * ( hpet_usec_quotient ) / (2^32) |
211 | * Where, | 211 | * Where, |
212 | * hpet_usec_quotient = (2^32 * usecs per tick)/HPET clocks per tick | 212 | * hpet_usec_quotient = (2^32 * usecs per tick)/HPET clocks per tick |
213 | */ | 213 | */ |
214 | delay_at_last_interrupt = hpet_current - offset; | 214 | delay_at_last_interrupt = hpet_current - offset; |
215 | ASM_MUL64_REG(temp, delay_at_last_interrupt, | 215 | ASM_MUL64_REG(temp, delay_at_last_interrupt, |
216 | hpet_usec_quotient, delay_at_last_interrupt); | 216 | hpet_usec_quotient, delay_at_last_interrupt); |
217 | } | 217 | } |
218 | #endif | 218 | #endif |
219 | 219 | ||
220 | 220 | ||
221 | #ifdef CONFIG_CPU_FREQ | 221 | #ifdef CONFIG_CPU_FREQ |
222 | #include <linux/workqueue.h> | 222 | #include <linux/workqueue.h> |
223 | 223 | ||
224 | static unsigned int cpufreq_delayed_issched = 0; | 224 | static unsigned int cpufreq_delayed_issched = 0; |
225 | static unsigned int cpufreq_init = 0; | 225 | static unsigned int cpufreq_init = 0; |
226 | static struct work_struct cpufreq_delayed_get_work; | 226 | static struct work_struct cpufreq_delayed_get_work; |
227 | 227 | ||
228 | static void handle_cpufreq_delayed_get(void *v) | 228 | static void handle_cpufreq_delayed_get(void *v) |
229 | { | 229 | { |
230 | unsigned int cpu; | 230 | unsigned int cpu; |
231 | for_each_online_cpu(cpu) { | 231 | for_each_online_cpu(cpu) { |
232 | cpufreq_get(cpu); | 232 | cpufreq_get(cpu); |
233 | } | 233 | } |
234 | cpufreq_delayed_issched = 0; | 234 | cpufreq_delayed_issched = 0; |
235 | } | 235 | } |
236 | 236 | ||
237 | /* if we notice lost ticks, schedule a call to cpufreq_get() as it tries | 237 | /* if we notice lost ticks, schedule a call to cpufreq_get() as it tries |
238 | * to verify the CPU frequency the timing core thinks the CPU is running | 238 | * to verify the CPU frequency the timing core thinks the CPU is running |
239 | * at is still correct. | 239 | * at is still correct. |
240 | */ | 240 | */ |
241 | static inline void cpufreq_delayed_get(void) | 241 | static inline void cpufreq_delayed_get(void) |
242 | { | 242 | { |
243 | if (cpufreq_init && !cpufreq_delayed_issched) { | 243 | if (cpufreq_init && !cpufreq_delayed_issched) { |
244 | cpufreq_delayed_issched = 1; | 244 | cpufreq_delayed_issched = 1; |
245 | printk(KERN_DEBUG "Losing some ticks... checking if CPU frequency changed.\n"); | 245 | printk(KERN_DEBUG "Losing some ticks... checking if CPU frequency changed.\n"); |
246 | schedule_work(&cpufreq_delayed_get_work); | 246 | schedule_work(&cpufreq_delayed_get_work); |
247 | } | 247 | } |
248 | } | 248 | } |
249 | 249 | ||
250 | /* If the CPU frequency is scaled, TSC-based delays will need a different | 250 | /* If the CPU frequency is scaled, TSC-based delays will need a different |
251 | * loops_per_jiffy value to function properly. | 251 | * loops_per_jiffy value to function properly. |
252 | */ | 252 | */ |
253 | 253 | ||
254 | static unsigned int ref_freq = 0; | 254 | static unsigned int ref_freq = 0; |
255 | static unsigned long loops_per_jiffy_ref = 0; | 255 | static unsigned long loops_per_jiffy_ref = 0; |
256 | 256 | ||
257 | #ifndef CONFIG_SMP | 257 | #ifndef CONFIG_SMP |
258 | static unsigned long fast_gettimeoffset_ref = 0; | 258 | static unsigned long fast_gettimeoffset_ref = 0; |
259 | static unsigned long cpu_khz_ref = 0; | 259 | static unsigned int cpu_khz_ref = 0; |
260 | #endif | 260 | #endif |
261 | 261 | ||
262 | static int | 262 | static int |
263 | time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | 263 | time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, |
264 | void *data) | 264 | void *data) |
265 | { | 265 | { |
266 | struct cpufreq_freqs *freq = data; | 266 | struct cpufreq_freqs *freq = data; |
267 | 267 | ||
268 | if (val != CPUFREQ_RESUMECHANGE) | 268 | if (val != CPUFREQ_RESUMECHANGE) |
269 | write_seqlock_irq(&xtime_lock); | 269 | write_seqlock_irq(&xtime_lock); |
270 | if (!ref_freq) { | 270 | if (!ref_freq) { |
271 | ref_freq = freq->old; | 271 | ref_freq = freq->old; |
272 | loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; | 272 | loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; |
273 | #ifndef CONFIG_SMP | 273 | #ifndef CONFIG_SMP |
274 | fast_gettimeoffset_ref = fast_gettimeoffset_quotient; | 274 | fast_gettimeoffset_ref = fast_gettimeoffset_quotient; |
275 | cpu_khz_ref = cpu_khz; | 275 | cpu_khz_ref = cpu_khz; |
276 | #endif | 276 | #endif |
277 | } | 277 | } |
278 | 278 | ||
279 | if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || | 279 | if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || |
280 | (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || | 280 | (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || |
281 | (val == CPUFREQ_RESUMECHANGE)) { | 281 | (val == CPUFREQ_RESUMECHANGE)) { |
282 | if (!(freq->flags & CPUFREQ_CONST_LOOPS)) | 282 | if (!(freq->flags & CPUFREQ_CONST_LOOPS)) |
283 | cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); | 283 | cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); |
284 | #ifndef CONFIG_SMP | 284 | #ifndef CONFIG_SMP |
285 | if (cpu_khz) | 285 | if (cpu_khz) |
286 | cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); | 286 | cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); |
287 | if (use_tsc) { | 287 | if (use_tsc) { |
288 | if (!(freq->flags & CPUFREQ_CONST_LOOPS)) { | 288 | if (!(freq->flags & CPUFREQ_CONST_LOOPS)) { |
289 | fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq); | 289 | fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq); |
290 | set_cyc2ns_scale(cpu_khz/1000); | 290 | set_cyc2ns_scale(cpu_khz/1000); |
291 | } | 291 | } |
292 | } | 292 | } |
293 | #endif | 293 | #endif |
294 | } | 294 | } |
295 | 295 | ||
296 | if (val != CPUFREQ_RESUMECHANGE) | 296 | if (val != CPUFREQ_RESUMECHANGE) |
297 | write_sequnlock_irq(&xtime_lock); | 297 | write_sequnlock_irq(&xtime_lock); |
298 | 298 | ||
299 | return 0; | 299 | return 0; |
300 | } | 300 | } |
301 | 301 | ||
302 | static struct notifier_block time_cpufreq_notifier_block = { | 302 | static struct notifier_block time_cpufreq_notifier_block = { |
303 | .notifier_call = time_cpufreq_notifier | 303 | .notifier_call = time_cpufreq_notifier |
304 | }; | 304 | }; |
305 | 305 | ||
306 | 306 | ||
307 | static int __init cpufreq_tsc(void) | 307 | static int __init cpufreq_tsc(void) |
308 | { | 308 | { |
309 | int ret; | 309 | int ret; |
310 | INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); | 310 | INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); |
311 | ret = cpufreq_register_notifier(&time_cpufreq_notifier_block, | 311 | ret = cpufreq_register_notifier(&time_cpufreq_notifier_block, |
312 | CPUFREQ_TRANSITION_NOTIFIER); | 312 | CPUFREQ_TRANSITION_NOTIFIER); |
313 | if (!ret) | 313 | if (!ret) |
314 | cpufreq_init = 1; | 314 | cpufreq_init = 1; |
315 | return ret; | 315 | return ret; |
316 | } | 316 | } |
317 | core_initcall(cpufreq_tsc); | 317 | core_initcall(cpufreq_tsc); |
318 | 318 | ||
319 | #else /* CONFIG_CPU_FREQ */ | 319 | #else /* CONFIG_CPU_FREQ */ |
320 | static inline void cpufreq_delayed_get(void) { return; } | 320 | static inline void cpufreq_delayed_get(void) { return; } |
321 | #endif | 321 | #endif |
322 | 322 | ||
323 | int recalibrate_cpu_khz(void) | 323 | int recalibrate_cpu_khz(void) |
324 | { | 324 | { |
325 | #ifndef CONFIG_SMP | 325 | #ifndef CONFIG_SMP |
326 | unsigned long cpu_khz_old = cpu_khz; | 326 | unsigned int cpu_khz_old = cpu_khz; |
327 | 327 | ||
328 | if (cpu_has_tsc) { | 328 | if (cpu_has_tsc) { |
329 | init_cpu_khz(); | 329 | init_cpu_khz(); |
330 | cpu_data[0].loops_per_jiffy = | 330 | cpu_data[0].loops_per_jiffy = |
331 | cpufreq_scale(cpu_data[0].loops_per_jiffy, | 331 | cpufreq_scale(cpu_data[0].loops_per_jiffy, |
332 | cpu_khz_old, | 332 | cpu_khz_old, |
333 | cpu_khz); | 333 | cpu_khz); |
334 | return 0; | 334 | return 0; |
335 | } else | 335 | } else |
336 | return -ENODEV; | 336 | return -ENODEV; |
337 | #else | 337 | #else |
338 | return -ENODEV; | 338 | return -ENODEV; |
339 | #endif | 339 | #endif |
340 | } | 340 | } |
341 | EXPORT_SYMBOL(recalibrate_cpu_khz); | 341 | EXPORT_SYMBOL(recalibrate_cpu_khz); |
342 | 342 | ||
343 | static void mark_offset_tsc(void) | 343 | static void mark_offset_tsc(void) |
344 | { | 344 | { |
345 | unsigned long lost,delay; | 345 | unsigned long lost,delay; |
346 | unsigned long delta = last_tsc_low; | 346 | unsigned long delta = last_tsc_low; |
347 | int count; | 347 | int count; |
348 | int countmp; | 348 | int countmp; |
349 | static int count1 = 0; | 349 | static int count1 = 0; |
350 | unsigned long long this_offset, last_offset; | 350 | unsigned long long this_offset, last_offset; |
351 | static int lost_count = 0; | 351 | static int lost_count = 0; |
352 | 352 | ||
353 | write_seqlock(&monotonic_lock); | 353 | write_seqlock(&monotonic_lock); |
354 | last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; | 354 | last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; |
355 | /* | 355 | /* |
356 | * It is important that these two operations happen almost at | 356 | * It is important that these two operations happen almost at |
357 | * the same time. We do the RDTSC stuff first, since it's | 357 | * the same time. We do the RDTSC stuff first, since it's |
358 | * faster. To avoid any inconsistencies, we need interrupts | 358 | * faster. To avoid any inconsistencies, we need interrupts |
359 | * disabled locally. | 359 | * disabled locally. |
360 | */ | 360 | */ |
361 | 361 | ||
362 | /* | 362 | /* |
363 | * Interrupts are just disabled locally since the timer irq | 363 | * Interrupts are just disabled locally since the timer irq |
364 | * has the SA_INTERRUPT flag set. -arca | 364 | * has the SA_INTERRUPT flag set. -arca |
365 | */ | 365 | */ |
366 | 366 | ||
367 | /* read Pentium cycle counter */ | 367 | /* read Pentium cycle counter */ |
368 | 368 | ||
369 | rdtsc(last_tsc_low, last_tsc_high); | 369 | rdtsc(last_tsc_low, last_tsc_high); |
370 | 370 | ||
371 | spin_lock(&i8253_lock); | 371 | spin_lock(&i8253_lock); |
372 | outb_p(0x00, PIT_MODE); /* latch the count ASAP */ | 372 | outb_p(0x00, PIT_MODE); /* latch the count ASAP */ |
373 | 373 | ||
374 | count = inb_p(PIT_CH0); /* read the latched count */ | 374 | count = inb_p(PIT_CH0); /* read the latched count */ |
375 | count |= inb(PIT_CH0) << 8; | 375 | count |= inb(PIT_CH0) << 8; |
376 | 376 | ||
377 | /* | 377 | /* |
378 | * VIA686a test code... reset the latch if count > max + 1 | 378 | * VIA686a test code... reset the latch if count > max + 1 |
379 | * from timer_pit.c - cjb | 379 | * from timer_pit.c - cjb |
380 | */ | 380 | */ |
381 | if (count > LATCH) { | 381 | if (count > LATCH) { |
382 | outb_p(0x34, PIT_MODE); | 382 | outb_p(0x34, PIT_MODE); |
383 | outb_p(LATCH & 0xff, PIT_CH0); | 383 | outb_p(LATCH & 0xff, PIT_CH0); |
384 | outb(LATCH >> 8, PIT_CH0); | 384 | outb(LATCH >> 8, PIT_CH0); |
385 | count = LATCH - 1; | 385 | count = LATCH - 1; |
386 | } | 386 | } |
387 | 387 | ||
388 | spin_unlock(&i8253_lock); | 388 | spin_unlock(&i8253_lock); |
389 | 389 | ||
390 | if (pit_latch_buggy) { | 390 | if (pit_latch_buggy) { |
391 | /* get center value of last 3 time lutch */ | 391 | /* get center value of last 3 time lutch */ |
392 | if ((count2 >= count && count >= count1) | 392 | if ((count2 >= count && count >= count1) |
393 | || (count1 >= count && count >= count2)) { | 393 | || (count1 >= count && count >= count2)) { |
394 | count2 = count1; count1 = count; | 394 | count2 = count1; count1 = count; |
395 | } else if ((count1 >= count2 && count2 >= count) | 395 | } else if ((count1 >= count2 && count2 >= count) |
396 | || (count >= count2 && count2 >= count1)) { | 396 | || (count >= count2 && count2 >= count1)) { |
397 | countmp = count;count = count2; | 397 | countmp = count;count = count2; |
398 | count2 = count1;count1 = countmp; | 398 | count2 = count1;count1 = countmp; |
399 | } else { | 399 | } else { |
400 | count2 = count1; count1 = count; count = count1; | 400 | count2 = count1; count1 = count; count = count1; |
401 | } | 401 | } |
402 | } | 402 | } |
403 | 403 | ||
404 | /* lost tick compensation */ | 404 | /* lost tick compensation */ |
405 | delta = last_tsc_low - delta; | 405 | delta = last_tsc_low - delta; |
406 | { | 406 | { |
407 | register unsigned long eax, edx; | 407 | register unsigned long eax, edx; |
408 | eax = delta; | 408 | eax = delta; |
409 | __asm__("mull %2" | 409 | __asm__("mull %2" |
410 | :"=a" (eax), "=d" (edx) | 410 | :"=a" (eax), "=d" (edx) |
411 | :"rm" (fast_gettimeoffset_quotient), | 411 | :"rm" (fast_gettimeoffset_quotient), |
412 | "0" (eax)); | 412 | "0" (eax)); |
413 | delta = edx; | 413 | delta = edx; |
414 | } | 414 | } |
415 | delta += delay_at_last_interrupt; | 415 | delta += delay_at_last_interrupt; |
416 | lost = delta/(1000000/HZ); | 416 | lost = delta/(1000000/HZ); |
417 | delay = delta%(1000000/HZ); | 417 | delay = delta%(1000000/HZ); |
418 | if (lost >= 2) { | 418 | if (lost >= 2) { |
419 | jiffies_64 += lost-1; | 419 | jiffies_64 += lost-1; |
420 | 420 | ||
421 | /* sanity check to ensure we're not always losing ticks */ | 421 | /* sanity check to ensure we're not always losing ticks */ |
422 | if (lost_count++ > 100) { | 422 | if (lost_count++ > 100) { |
423 | printk(KERN_WARNING "Losing too many ticks!\n"); | 423 | printk(KERN_WARNING "Losing too many ticks!\n"); |
424 | printk(KERN_WARNING "TSC cannot be used as a timesource. \n"); | 424 | printk(KERN_WARNING "TSC cannot be used as a timesource. \n"); |
425 | printk(KERN_WARNING "Possible reasons for this are:\n"); | 425 | printk(KERN_WARNING "Possible reasons for this are:\n"); |
426 | printk(KERN_WARNING " You're running with Speedstep,\n"); | 426 | printk(KERN_WARNING " You're running with Speedstep,\n"); |
427 | printk(KERN_WARNING " You don't have DMA enabled for your hard disk (see hdparm),\n"); | 427 | printk(KERN_WARNING " You don't have DMA enabled for your hard disk (see hdparm),\n"); |
428 | printk(KERN_WARNING " Incorrect TSC synchronization on an SMP system (see dmesg).\n"); | 428 | printk(KERN_WARNING " Incorrect TSC synchronization on an SMP system (see dmesg).\n"); |
429 | printk(KERN_WARNING "Falling back to a sane timesource now.\n"); | 429 | printk(KERN_WARNING "Falling back to a sane timesource now.\n"); |
430 | 430 | ||
431 | clock_fallback(); | 431 | clock_fallback(); |
432 | } | 432 | } |
433 | /* ... but give the TSC a fair chance */ | 433 | /* ... but give the TSC a fair chance */ |
434 | if (lost_count > 25) | 434 | if (lost_count > 25) |
435 | cpufreq_delayed_get(); | 435 | cpufreq_delayed_get(); |
436 | } else | 436 | } else |
437 | lost_count = 0; | 437 | lost_count = 0; |
438 | /* update the monotonic base value */ | 438 | /* update the monotonic base value */ |
439 | this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; | 439 | this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; |
440 | monotonic_base += cycles_2_ns(this_offset - last_offset); | 440 | monotonic_base += cycles_2_ns(this_offset - last_offset); |
441 | write_sequnlock(&monotonic_lock); | 441 | write_sequnlock(&monotonic_lock); |
442 | 442 | ||
443 | /* calculate delay_at_last_interrupt */ | 443 | /* calculate delay_at_last_interrupt */ |
444 | count = ((LATCH-1) - count) * TICK_SIZE; | 444 | count = ((LATCH-1) - count) * TICK_SIZE; |
445 | delay_at_last_interrupt = (count + LATCH/2) / LATCH; | 445 | delay_at_last_interrupt = (count + LATCH/2) / LATCH; |
446 | 446 | ||
447 | /* catch corner case where tick rollover occured | 447 | /* catch corner case where tick rollover occured |
448 | * between tsc and pit reads (as noted when | 448 | * between tsc and pit reads (as noted when |
449 | * usec delta is > 90% # of usecs/tick) | 449 | * usec delta is > 90% # of usecs/tick) |
450 | */ | 450 | */ |
451 | if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ)) | 451 | if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ)) |
452 | jiffies_64++; | 452 | jiffies_64++; |
453 | } | 453 | } |
454 | 454 | ||
455 | static int __init init_tsc(char* override) | 455 | static int __init init_tsc(char* override) |
456 | { | 456 | { |
457 | 457 | ||
458 | /* check clock override */ | 458 | /* check clock override */ |
459 | if (override[0] && strncmp(override,"tsc",3)) { | 459 | if (override[0] && strncmp(override,"tsc",3)) { |
460 | #ifdef CONFIG_HPET_TIMER | 460 | #ifdef CONFIG_HPET_TIMER |
461 | if (is_hpet_enabled()) { | 461 | if (is_hpet_enabled()) { |
462 | printk(KERN_ERR "Warning: clock= override failed. Defaulting to tsc\n"); | 462 | printk(KERN_ERR "Warning: clock= override failed. Defaulting to tsc\n"); |
463 | } else | 463 | } else |
464 | #endif | 464 | #endif |
465 | { | 465 | { |
466 | return -ENODEV; | 466 | return -ENODEV; |
467 | } | 467 | } |
468 | } | 468 | } |
469 | 469 | ||
470 | /* | 470 | /* |
471 | * If we have APM enabled or the CPU clock speed is variable | 471 | * If we have APM enabled or the CPU clock speed is variable |
472 | * (CPU stops clock on HLT or slows clock to save power) | 472 | * (CPU stops clock on HLT or slows clock to save power) |
473 | * then the TSC timestamps may diverge by up to 1 jiffy from | 473 | * then the TSC timestamps may diverge by up to 1 jiffy from |
474 | * 'real time' but nothing will break. | 474 | * 'real time' but nothing will break. |
475 | * The most frequent case is that the CPU is "woken" from a halt | 475 | * The most frequent case is that the CPU is "woken" from a halt |
476 | * state by the timer interrupt itself, so we get 0 error. In the | 476 | * state by the timer interrupt itself, so we get 0 error. In the |
477 | * rare cases where a driver would "wake" the CPU and request a | 477 | * rare cases where a driver would "wake" the CPU and request a |
478 | * timestamp, the maximum error is < 1 jiffy. But timestamps are | 478 | * timestamp, the maximum error is < 1 jiffy. But timestamps are |
479 | * still perfectly ordered. | 479 | * still perfectly ordered. |
480 | * Note that the TSC counter will be reset if APM suspends | 480 | * Note that the TSC counter will be reset if APM suspends |
481 | * to disk; this won't break the kernel, though, 'cuz we're | 481 | * to disk; this won't break the kernel, though, 'cuz we're |
482 | * smart. See arch/i386/kernel/apm.c. | 482 | * smart. See arch/i386/kernel/apm.c. |
483 | */ | 483 | */ |
484 | /* | 484 | /* |
485 | * Firstly we have to do a CPU check for chips with | 485 | * Firstly we have to do a CPU check for chips with |
486 | * a potentially buggy TSC. At this point we haven't run | 486 | * a potentially buggy TSC. At this point we haven't run |
487 | * the ident/bugs checks so we must run this hook as it | 487 | * the ident/bugs checks so we must run this hook as it |
488 | * may turn off the TSC flag. | 488 | * may turn off the TSC flag. |
489 | * | 489 | * |
490 | * NOTE: this doesn't yet handle SMP 486 machines where only | 490 | * NOTE: this doesn't yet handle SMP 486 machines where only |
491 | * some CPU's have a TSC. Thats never worked and nobody has | 491 | * some CPU's have a TSC. Thats never worked and nobody has |
492 | * moaned if you have the only one in the world - you fix it! | 492 | * moaned if you have the only one in the world - you fix it! |
493 | */ | 493 | */ |
494 | 494 | ||
495 | count2 = LATCH; /* initialize counter for mark_offset_tsc() */ | 495 | count2 = LATCH; /* initialize counter for mark_offset_tsc() */ |
496 | 496 | ||
497 | if (cpu_has_tsc) { | 497 | if (cpu_has_tsc) { |
498 | unsigned long tsc_quotient; | 498 | unsigned long tsc_quotient; |
499 | #ifdef CONFIG_HPET_TIMER | 499 | #ifdef CONFIG_HPET_TIMER |
500 | if (is_hpet_enabled() && hpet_use_timer) { | 500 | if (is_hpet_enabled() && hpet_use_timer) { |
501 | unsigned long result, remain; | 501 | unsigned long result, remain; |
502 | printk("Using TSC for gettimeofday\n"); | 502 | printk("Using TSC for gettimeofday\n"); |
503 | tsc_quotient = calibrate_tsc_hpet(NULL); | 503 | tsc_quotient = calibrate_tsc_hpet(NULL); |
504 | timer_tsc.mark_offset = &mark_offset_tsc_hpet; | 504 | timer_tsc.mark_offset = &mark_offset_tsc_hpet; |
505 | /* | 505 | /* |
506 | * Math to calculate hpet to usec multiplier | 506 | * Math to calculate hpet to usec multiplier |
507 | * Look for the comments at get_offset_tsc_hpet() | 507 | * Look for the comments at get_offset_tsc_hpet() |
508 | */ | 508 | */ |
509 | ASM_DIV64_REG(result, remain, hpet_tick, | 509 | ASM_DIV64_REG(result, remain, hpet_tick, |
510 | 0, KERNEL_TICK_USEC); | 510 | 0, KERNEL_TICK_USEC); |
511 | if (remain > (hpet_tick >> 1)) | 511 | if (remain > (hpet_tick >> 1)) |
512 | result++; /* rounding the result */ | 512 | result++; /* rounding the result */ |
513 | 513 | ||
514 | hpet_usec_quotient = result; | 514 | hpet_usec_quotient = result; |
515 | } else | 515 | } else |
516 | #endif | 516 | #endif |
517 | { | 517 | { |
518 | tsc_quotient = calibrate_tsc(); | 518 | tsc_quotient = calibrate_tsc(); |
519 | } | 519 | } |
520 | 520 | ||
521 | if (tsc_quotient) { | 521 | if (tsc_quotient) { |
522 | fast_gettimeoffset_quotient = tsc_quotient; | 522 | fast_gettimeoffset_quotient = tsc_quotient; |
523 | use_tsc = 1; | 523 | use_tsc = 1; |
524 | /* | 524 | /* |
525 | * We could be more selective here I suspect | 525 | * We could be more selective here I suspect |
526 | * and just enable this for the next intel chips ? | 526 | * and just enable this for the next intel chips ? |
527 | */ | 527 | */ |
528 | /* report CPU clock rate in Hz. | 528 | /* report CPU clock rate in Hz. |
529 | * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = | 529 | * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = |
530 | * clock/second. Our precision is about 100 ppm. | 530 | * clock/second. Our precision is about 100 ppm. |
531 | */ | 531 | */ |
532 | { unsigned long eax=0, edx=1000; | 532 | { unsigned long eax=0, edx=1000; |
533 | __asm__("divl %2" | 533 | __asm__("divl %2" |
534 | :"=a" (cpu_khz), "=d" (edx) | 534 | :"=a" (cpu_khz), "=d" (edx) |
535 | :"r" (tsc_quotient), | 535 | :"r" (tsc_quotient), |
536 | "0" (eax), "1" (edx)); | 536 | "0" (eax), "1" (edx)); |
537 | printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); | 537 | printk("Detected %u.%03u MHz processor.\n", |
538 | cpu_khz / 1000, cpu_khz % 1000); | ||
538 | } | 539 | } |
539 | set_cyc2ns_scale(cpu_khz/1000); | 540 | set_cyc2ns_scale(cpu_khz/1000); |
540 | return 0; | 541 | return 0; |
541 | } | 542 | } |
542 | } | 543 | } |
543 | return -ENODEV; | 544 | return -ENODEV; |
544 | } | 545 | } |
545 | 546 | ||
546 | #ifndef CONFIG_X86_TSC | 547 | #ifndef CONFIG_X86_TSC |
547 | /* disable flag for tsc. Takes effect by clearing the TSC cpu flag | 548 | /* disable flag for tsc. Takes effect by clearing the TSC cpu flag |
548 | * in cpu/common.c */ | 549 | * in cpu/common.c */ |
549 | static int __init tsc_setup(char *str) | 550 | static int __init tsc_setup(char *str) |
550 | { | 551 | { |
551 | tsc_disable = 1; | 552 | tsc_disable = 1; |
552 | return 1; | 553 | return 1; |
553 | } | 554 | } |
554 | #else | 555 | #else |
555 | static int __init tsc_setup(char *str) | 556 | static int __init tsc_setup(char *str) |
556 | { | 557 | { |
557 | printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, " | 558 | printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, " |
558 | "cannot disable TSC.\n"); | 559 | "cannot disable TSC.\n"); |
559 | return 1; | 560 | return 1; |
560 | } | 561 | } |
561 | #endif | 562 | #endif |
562 | __setup("notsc", tsc_setup); | 563 | __setup("notsc", tsc_setup); |
563 | 564 | ||
564 | 565 | ||
565 | 566 | ||
566 | /************************************************************/ | 567 | /************************************************************/ |
567 | 568 | ||
568 | /* tsc timer_opts struct */ | 569 | /* tsc timer_opts struct */ |
569 | static struct timer_opts timer_tsc = { | 570 | static struct timer_opts timer_tsc = { |
570 | .name = "tsc", | 571 | .name = "tsc", |
571 | .mark_offset = mark_offset_tsc, | 572 | .mark_offset = mark_offset_tsc, |
572 | .get_offset = get_offset_tsc, | 573 | .get_offset = get_offset_tsc, |
573 | .monotonic_clock = monotonic_clock_tsc, | 574 | .monotonic_clock = monotonic_clock_tsc, |
574 | .delay = delay_tsc, | 575 | .delay = delay_tsc, |
575 | .read_timer = read_timer_tsc, | 576 | .read_timer = read_timer_tsc, |
576 | }; | 577 | }; |
577 | 578 | ||
578 | struct init_timer_opts __initdata timer_tsc_init = { | 579 | struct init_timer_opts __initdata timer_tsc_init = { |
579 | .init = init_tsc, | 580 | .init = init_tsc, |
580 | .opts = &timer_tsc, | 581 | .opts = &timer_tsc, |
581 | }; | 582 | }; |
582 | 583 |
include/asm-i386/timex.h
1 | /* | 1 | /* |
2 | * linux/include/asm-i386/timex.h | 2 | * linux/include/asm-i386/timex.h |
3 | * | 3 | * |
4 | * i386 architecture timex specifications | 4 | * i386 architecture timex specifications |
5 | */ | 5 | */ |
6 | #ifndef _ASMi386_TIMEX_H | 6 | #ifndef _ASMi386_TIMEX_H |
7 | #define _ASMi386_TIMEX_H | 7 | #define _ASMi386_TIMEX_H |
8 | 8 | ||
9 | #include <linux/config.h> | 9 | #include <linux/config.h> |
10 | #include <asm/processor.h> | 10 | #include <asm/processor.h> |
11 | 11 | ||
12 | #ifdef CONFIG_X86_ELAN | 12 | #ifdef CONFIG_X86_ELAN |
13 | # define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */ | 13 | # define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */ |
14 | #else | 14 | #else |
15 | # define CLOCK_TICK_RATE 1193182 /* Underlying HZ */ | 15 | # define CLOCK_TICK_RATE 1193182 /* Underlying HZ */ |
16 | #endif | 16 | #endif |
17 | 17 | ||
18 | 18 | ||
19 | /* | 19 | /* |
20 | * Standard way to access the cycle counter on i586+ CPUs. | 20 | * Standard way to access the cycle counter on i586+ CPUs. |
21 | * Currently only used on SMP. | 21 | * Currently only used on SMP. |
22 | * | 22 | * |
23 | * If you really have a SMP machine with i486 chips or older, | 23 | * If you really have a SMP machine with i486 chips or older, |
24 | * compile for that, and this will just always return zero. | 24 | * compile for that, and this will just always return zero. |
25 | * That's ok, it just means that the nicer scheduling heuristics | 25 | * That's ok, it just means that the nicer scheduling heuristics |
26 | * won't work for you. | 26 | * won't work for you. |
27 | * | 27 | * |
28 | * We only use the low 32 bits, and we'd simply better make sure | 28 | * We only use the low 32 bits, and we'd simply better make sure |
29 | * that we reschedule before that wraps. Scheduling at least every | 29 | * that we reschedule before that wraps. Scheduling at least every |
30 | * four billion cycles just basically sounds like a good idea, | 30 | * four billion cycles just basically sounds like a good idea, |
31 | * regardless of how fast the machine is. | 31 | * regardless of how fast the machine is. |
32 | */ | 32 | */ |
33 | typedef unsigned long long cycles_t; | 33 | typedef unsigned long long cycles_t; |
34 | 34 | ||
35 | static inline cycles_t get_cycles (void) | 35 | static inline cycles_t get_cycles (void) |
36 | { | 36 | { |
37 | unsigned long long ret=0; | 37 | unsigned long long ret=0; |
38 | 38 | ||
39 | #ifndef CONFIG_X86_TSC | 39 | #ifndef CONFIG_X86_TSC |
40 | if (!cpu_has_tsc) | 40 | if (!cpu_has_tsc) |
41 | return 0; | 41 | return 0; |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | #if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC) | 44 | #if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC) |
45 | rdtscll(ret); | 45 | rdtscll(ret); |
46 | #endif | 46 | #endif |
47 | return ret; | 47 | return ret; |
48 | } | 48 | } |
49 | 49 | ||
50 | extern unsigned long cpu_khz; | 50 | extern unsigned int cpu_khz; |
51 | 51 | ||
52 | extern int read_current_timer(unsigned long *timer_value); | 52 | extern int read_current_timer(unsigned long *timer_value); |
53 | #define ARCH_HAS_READ_CURRENT_TIMER 1 | 53 | #define ARCH_HAS_READ_CURRENT_TIMER 1 |
54 | 54 | ||
55 | #endif | 55 | #endif |
56 | 56 |