aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Ebbert <76306.1226@compuserve.com>2006-02-05 02:28:03 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-05 14:06:53 -0500
commitfe38d8553ccb5237bf0eddda9e94fbca7288551c (patch)
tree4ebdcf473fcf7e429536e86346c258514671f044
parent170aa3d02614ae621d54af10555e2f48977ae8de (diff)
[PATCH] i386 cpu hotplug: don't access freed memory
i386 CPU init code accesses freed init memory when booting a newly-started processor after CPU hotplug. The cpu_devs array is searched to find the vendor and it contains pointers to freed data. Fix that by: 1. Zeroing entries for freed vendor data after bootup. 2. Changing Transmeta, NSC and UMC to all __init[data]. 3. Printing a warning (once only) and setting this_cpu to a safe default when the vendor is not found. This does not change behavior for AMD systems. They were broken already but no error was reported. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/i386/kernel/cpu/amd.c8
-rw-r--r--arch/i386/kernel/cpu/centaur.c8
-rw-r--r--arch/i386/kernel/cpu/common.c11
-rw-r--r--arch/i386/kernel/cpu/cyrix.c18
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c1
-rw-r--r--arch/i386/kernel/cpu/nexgen.c8
-rw-r--r--arch/i386/kernel/cpu/rise.c8
-rw-r--r--arch/i386/kernel/cpu/transmeta.c10
-rw-r--r--arch/i386/kernel/cpu/umc.c8
9 files changed, 77 insertions, 3 deletions
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 333578a4e91a..0810f81f2a05 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -282,3 +282,11 @@ int __init amd_init_cpu(void)
282} 282}
283 283
284//early_arch_initcall(amd_init_cpu); 284//early_arch_initcall(amd_init_cpu);
285
286static int __init amd_exit_cpu(void)
287{
288 cpu_devs[X86_VENDOR_AMD] = NULL;
289 return 0;
290}
291
292late_initcall(amd_exit_cpu);
diff --git a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c
index 0dd92a23d622..f52669ecb93f 100644
--- a/arch/i386/kernel/cpu/centaur.c
+++ b/arch/i386/kernel/cpu/centaur.c
@@ -470,3 +470,11 @@ int __init centaur_init_cpu(void)
470} 470}
471 471
472//early_arch_initcall(centaur_init_cpu); 472//early_arch_initcall(centaur_init_cpu);
473
474static int __init centaur_exit_cpu(void)
475{
476 cpu_devs[X86_VENDOR_CENTAUR] = NULL;
477 return 0;
478}
479
480late_initcall(centaur_exit_cpu);
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 15aee26ec2b6..7eb9213734a3 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -44,6 +44,7 @@ static void default_init(struct cpuinfo_x86 * c)
44 44
45static struct cpu_dev default_cpu = { 45static struct cpu_dev default_cpu = {
46 .c_init = default_init, 46 .c_init = default_init,
47 .c_vendor = "Unknown",
47}; 48};
48static struct cpu_dev * this_cpu = &default_cpu; 49static struct cpu_dev * this_cpu = &default_cpu;
49 50
@@ -150,6 +151,7 @@ static void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
150{ 151{
151 char *v = c->x86_vendor_id; 152 char *v = c->x86_vendor_id;
152 int i; 153 int i;
154 static int printed;
153 155
154 for (i = 0; i < X86_VENDOR_NUM; i++) { 156 for (i = 0; i < X86_VENDOR_NUM; i++) {
155 if (cpu_devs[i]) { 157 if (cpu_devs[i]) {
@@ -159,10 +161,17 @@ static void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
159 c->x86_vendor = i; 161 c->x86_vendor = i;
160 if (!early) 162 if (!early)
161 this_cpu = cpu_devs[i]; 163 this_cpu = cpu_devs[i];
162 break; 164 return;
163 } 165 }
164 } 166 }
165 } 167 }
168 if (!printed) {
169 printed++;
170 printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
171 printk(KERN_ERR "CPU: Your system may be unstable.\n");
172 }
173 c->x86_vendor = X86_VENDOR_UNKNOWN;
174 this_cpu = &default_cpu;
166} 175}
167 176
168 177
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index 75015975d038..00f2e058797c 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -345,7 +345,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
345/* 345/*
346 * Handle National Semiconductor branded processors 346 * Handle National Semiconductor branded processors
347 */ 347 */
348static void __devinit init_nsc(struct cpuinfo_x86 *c) 348static void __init init_nsc(struct cpuinfo_x86 *c)
349{ 349{
350 /* There may be GX1 processors in the wild that are branded 350 /* There may be GX1 processors in the wild that are branded
351 * NSC and not Cyrix. 351 * NSC and not Cyrix.
@@ -444,6 +444,14 @@ int __init cyrix_init_cpu(void)
444 444
445//early_arch_initcall(cyrix_init_cpu); 445//early_arch_initcall(cyrix_init_cpu);
446 446
447static int __init cyrix_exit_cpu(void)
448{
449 cpu_devs[X86_VENDOR_CYRIX] = NULL;
450 return 0;
451}
452
453late_initcall(cyrix_exit_cpu);
454
447static struct cpu_dev nsc_cpu_dev __initdata = { 455static struct cpu_dev nsc_cpu_dev __initdata = {
448 .c_vendor = "NSC", 456 .c_vendor = "NSC",
449 .c_ident = { "Geode by NSC" }, 457 .c_ident = { "Geode by NSC" },
@@ -458,3 +466,11 @@ int __init nsc_init_cpu(void)
458} 466}
459 467
460//early_arch_initcall(nsc_init_cpu); 468//early_arch_initcall(nsc_init_cpu);
469
470static int __init nsc_exit_cpu(void)
471{
472 cpu_devs[X86_VENDOR_NSC] = NULL;
473 return 0;
474}
475
476late_initcall(nsc_exit_cpu);
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index af591c73345f..ffe58cee0c48 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -152,6 +152,7 @@ static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_le
152 return 0; 152 return 0;
153} 153}
154 154
155/* will only be called once; __init is safe here */
155static int __init find_num_cache_leaves(void) 156static int __init find_num_cache_leaves(void)
156{ 157{
157 unsigned int eax, ebx, ecx, edx; 158 unsigned int eax, ebx, ecx, edx;
diff --git a/arch/i386/kernel/cpu/nexgen.c b/arch/i386/kernel/cpu/nexgen.c
index 30898a260a5c..ad87fa58058d 100644
--- a/arch/i386/kernel/cpu/nexgen.c
+++ b/arch/i386/kernel/cpu/nexgen.c
@@ -61,3 +61,11 @@ int __init nexgen_init_cpu(void)
61} 61}
62 62
63//early_arch_initcall(nexgen_init_cpu); 63//early_arch_initcall(nexgen_init_cpu);
64
65static int __init nexgen_exit_cpu(void)
66{
67 cpu_devs[X86_VENDOR_NEXGEN] = NULL;
68 return 0;
69}
70
71late_initcall(nexgen_exit_cpu);
diff --git a/arch/i386/kernel/cpu/rise.c b/arch/i386/kernel/cpu/rise.c
index 8602425628ca..d08d5a2811c8 100644
--- a/arch/i386/kernel/cpu/rise.c
+++ b/arch/i386/kernel/cpu/rise.c
@@ -51,3 +51,11 @@ int __init rise_init_cpu(void)
51} 51}
52 52
53//early_arch_initcall(rise_init_cpu); 53//early_arch_initcall(rise_init_cpu);
54
55static int __init rise_exit_cpu(void)
56{
57 cpu_devs[X86_VENDOR_RISE] = NULL;
58 return 0;
59}
60
61late_initcall(rise_exit_cpu);
diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c
index fc426380366b..bdbeb77f4e22 100644
--- a/arch/i386/kernel/cpu/transmeta.c
+++ b/arch/i386/kernel/cpu/transmeta.c
@@ -84,7 +84,7 @@ static void __init init_transmeta(struct cpuinfo_x86 *c)
84#endif 84#endif
85} 85}
86 86
87static void transmeta_identify(struct cpuinfo_x86 * c) 87static void __init transmeta_identify(struct cpuinfo_x86 * c)
88{ 88{
89 u32 xlvl; 89 u32 xlvl;
90 generic_identify(c); 90 generic_identify(c);
@@ -111,3 +111,11 @@ int __init transmeta_init_cpu(void)
111} 111}
112 112
113//early_arch_initcall(transmeta_init_cpu); 113//early_arch_initcall(transmeta_init_cpu);
114
115static int __init transmeta_exit_cpu(void)
116{
117 cpu_devs[X86_VENDOR_TRANSMETA] = NULL;
118 return 0;
119}
120
121late_initcall(transmeta_exit_cpu);
diff --git a/arch/i386/kernel/cpu/umc.c b/arch/i386/kernel/cpu/umc.c
index 264fcad559d5..2cd988f6dc55 100644
--- a/arch/i386/kernel/cpu/umc.c
+++ b/arch/i386/kernel/cpu/umc.c
@@ -31,3 +31,11 @@ int __init umc_init_cpu(void)
31} 31}
32 32
33//early_arch_initcall(umc_init_cpu); 33//early_arch_initcall(umc_init_cpu);
34
35static int __init umc_exit_cpu(void)
36{
37 cpu_devs[X86_VENDOR_UMC] = NULL;
38 return 0;
39}
40
41late_initcall(umc_exit_cpu);