diff options
author | Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | 2008-02-15 06:00:23 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-17 11:40:47 -0400 |
commit | 03ae5768b6110ebaa97dc3e7abf1c3d8bec5f874 (patch) | |
tree | e9dffa8c5eccd43ea8284d7e2e48b782166bbcac /arch/x86/kernel/cpu | |
parent | bc7c314d7048017caa0725b41cc577cccf4fc53b (diff) |
x86: use ELF section to list CPU vendor specific code
Replace the hardcoded list of initialization functions for each CPU
vendor by a list in an ELF section, which is read at initialization in
arch/x86/kernel/cpu/cpu.c to fill the cpu_devs[] array. The ELF
section, named .x86cpuvendor.init, is reclaimed after boot, and
contains entries of type "struct cpu_vendor_dev" which associates a
vendor number with a pointer to a "struct cpu_dev" structure.
This first modification allows to remove all the VENDOR_init_cpu()
functions.
This patch also removes the hardcoded calls to early_init_amd() and
early_init_intel(). Instead, we add a "c_early_init" member to the
cpu_dev structure, which is then called if not NULL by the generic CPU
initialization code. Unfortunately, in early_cpu_detect(), this_cpu is
not yet set, so we have to use the cpu_devs[] array directly.
This patch is part of the Linux Tiny project, and is needed for
further patch that will allow to disable compilation of unused CPU
support code.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r-- | arch/x86/kernel/cpu/amd.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/centaur.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 33 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/cpu.h | 26 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/cyrix.c | 13 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/transmeta.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/umc.c | 7 |
8 files changed, 36 insertions, 69 deletions
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 693e353999cd..cab4e562b5cb 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -63,7 +63,7 @@ static __cpuinit int amd_apic_timer_broken(void) | |||
63 | 63 | ||
64 | int force_mwait __cpuinitdata; | 64 | int force_mwait __cpuinitdata; |
65 | 65 | ||
66 | void __cpuinit early_init_amd(struct cpuinfo_x86 *c) | 66 | static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) |
67 | { | 67 | { |
68 | if (cpuid_eax(0x80000000) >= 0x80000007) { | 68 | if (cpuid_eax(0x80000000) >= 0x80000007) { |
69 | c->x86_power = cpuid_edx(0x80000007); | 69 | c->x86_power = cpuid_edx(0x80000007); |
@@ -336,6 +336,7 @@ static struct cpu_dev amd_cpu_dev __cpuinitdata = { | |||
336 | } | 336 | } |
337 | }, | 337 | }, |
338 | }, | 338 | }, |
339 | .c_early_init = early_init_amd, | ||
339 | .c_init = init_amd, | 340 | .c_init = init_amd, |
340 | .c_size_cache = amd_size_cache, | 341 | .c_size_cache = amd_size_cache, |
341 | }; | 342 | }; |
@@ -345,3 +346,5 @@ int __init amd_init_cpu(void) | |||
345 | cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev; | 346 | cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev; |
346 | return 0; | 347 | return 0; |
347 | } | 348 | } |
349 | |||
350 | cpu_vendor_dev_register(X86_VENDOR_AMD, &amd_cpu_dev); | ||
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index 9681fa15ddf0..194ec8311c3b 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c | |||
@@ -464,8 +464,4 @@ static struct cpu_dev centaur_cpu_dev __cpuinitdata = { | |||
464 | .c_size_cache = centaur_size_cache, | 464 | .c_size_cache = centaur_size_cache, |
465 | }; | 465 | }; |
466 | 466 | ||
467 | int __init centaur_init_cpu(void) | 467 | cpu_vendor_dev_register(X86_VENDOR_CENTAUR, ¢aur_cpu_dev); |
468 | { | ||
469 | cpu_devs[X86_VENDOR_CENTAUR] = ¢aur_cpu_dev; | ||
470 | return 0; | ||
471 | } | ||
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index a38aafaefc23..0fd6be154d5d 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -328,14 +328,9 @@ static void __init early_cpu_detect(void) | |||
328 | 328 | ||
329 | get_cpu_vendor(c, 1); | 329 | get_cpu_vendor(c, 1); |
330 | 330 | ||
331 | switch (c->x86_vendor) { | 331 | if (c->x86_vendor != X86_VENDOR_UNKNOWN && |
332 | case X86_VENDOR_AMD: | 332 | cpu_devs[c->x86_vendor]->c_early_init) |
333 | early_init_amd(c); | 333 | cpu_devs[c->x86_vendor]->c_early_init(c); |
334 | break; | ||
335 | case X86_VENDOR_INTEL: | ||
336 | early_init_intel(c); | ||
337 | break; | ||
338 | } | ||
339 | 334 | ||
340 | early_get_cap(c); | 335 | early_get_cap(c); |
341 | } | 336 | } |
@@ -616,23 +611,15 @@ __setup("clearcpuid=", setup_disablecpuid); | |||
616 | 611 | ||
617 | cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; | 612 | cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; |
618 | 613 | ||
619 | /* This is hacky. :) | ||
620 | * We're emulating future behavior. | ||
621 | * In the future, the cpu-specific init functions will be called implicitly | ||
622 | * via the magic of initcalls. | ||
623 | * They will insert themselves into the cpu_devs structure. | ||
624 | * Then, when cpu_init() is called, we can just iterate over that array. | ||
625 | */ | ||
626 | void __init early_cpu_init(void) | 614 | void __init early_cpu_init(void) |
627 | { | 615 | { |
628 | intel_cpu_init(); | 616 | struct cpu_vendor_dev *cvdev; |
629 | cyrix_init_cpu(); | 617 | |
630 | nsc_init_cpu(); | 618 | for (cvdev = __x86cpuvendor_start ; |
631 | amd_init_cpu(); | 619 | cvdev < __x86cpuvendor_end ; |
632 | centaur_init_cpu(); | 620 | cvdev++) |
633 | transmeta_init_cpu(); | 621 | cpu_devs[cvdev->vendor] = cvdev->cpu_dev; |
634 | nexgen_init_cpu(); | 622 | |
635 | umc_init_cpu(); | ||
636 | early_cpu_detect(); | 623 | early_cpu_detect(); |
637 | } | 624 | } |
638 | 625 | ||
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h index e0b38c33d842..783691b2a738 100644 --- a/arch/x86/kernel/cpu/cpu.h +++ b/arch/x86/kernel/cpu/cpu.h | |||
@@ -14,6 +14,7 @@ struct cpu_dev { | |||
14 | 14 | ||
15 | struct cpu_model_info c_models[4]; | 15 | struct cpu_model_info c_models[4]; |
16 | 16 | ||
17 | void (*c_early_init)(struct cpuinfo_x86 *c); | ||
17 | void (*c_init)(struct cpuinfo_x86 * c); | 18 | void (*c_init)(struct cpuinfo_x86 * c); |
18 | void (*c_identify)(struct cpuinfo_x86 * c); | 19 | void (*c_identify)(struct cpuinfo_x86 * c); |
19 | unsigned int (*c_size_cache)(struct cpuinfo_x86 * c, unsigned int size); | 20 | unsigned int (*c_size_cache)(struct cpuinfo_x86 * c, unsigned int size); |
@@ -21,18 +22,17 @@ struct cpu_dev { | |||
21 | 22 | ||
22 | extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM]; | 23 | extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM]; |
23 | 24 | ||
25 | struct cpu_vendor_dev { | ||
26 | int vendor; | ||
27 | struct cpu_dev *cpu_dev; | ||
28 | }; | ||
29 | |||
30 | #define cpu_vendor_dev_register(cpu_vendor_id, cpu_dev) \ | ||
31 | static struct cpu_vendor_dev __cpu_vendor_dev_##cpu_vendor_id __used \ | ||
32 | __attribute__((__section__(".x86cpuvendor.init"))) = \ | ||
33 | { cpu_vendor_id, cpu_dev } | ||
34 | |||
35 | extern struct cpu_vendor_dev __x86cpuvendor_start[], __x86cpuvendor_end[]; | ||
36 | |||
24 | extern int get_model_name(struct cpuinfo_x86 *c); | 37 | extern int get_model_name(struct cpuinfo_x86 *c); |
25 | extern void display_cacheinfo(struct cpuinfo_x86 *c); | 38 | extern void display_cacheinfo(struct cpuinfo_x86 *c); |
26 | |||
27 | extern void early_init_intel(struct cpuinfo_x86 *c); | ||
28 | extern void early_init_amd(struct cpuinfo_x86 *c); | ||
29 | |||
30 | /* Specific CPU type init functions */ | ||
31 | int intel_cpu_init(void); | ||
32 | int amd_init_cpu(void); | ||
33 | int cyrix_init_cpu(void); | ||
34 | int nsc_init_cpu(void); | ||
35 | int centaur_init_cpu(void); | ||
36 | int transmeta_init_cpu(void); | ||
37 | int nexgen_init_cpu(void); | ||
38 | int umc_init_cpu(void); | ||
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 7139b0262703..9c4ee98f2cb8 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c | |||
@@ -439,11 +439,7 @@ static struct cpu_dev cyrix_cpu_dev __cpuinitdata = { | |||
439 | .c_identify = cyrix_identify, | 439 | .c_identify = cyrix_identify, |
440 | }; | 440 | }; |
441 | 441 | ||
442 | int __init cyrix_init_cpu(void) | 442 | cpu_vendor_dev_register(X86_VENDOR_CYRIX, &cyrix_cpu_dev); |
443 | { | ||
444 | cpu_devs[X86_VENDOR_CYRIX] = &cyrix_cpu_dev; | ||
445 | return 0; | ||
446 | } | ||
447 | 443 | ||
448 | static struct cpu_dev nsc_cpu_dev __cpuinitdata = { | 444 | static struct cpu_dev nsc_cpu_dev __cpuinitdata = { |
449 | .c_vendor = "NSC", | 445 | .c_vendor = "NSC", |
@@ -451,9 +447,4 @@ static struct cpu_dev nsc_cpu_dev __cpuinitdata = { | |||
451 | .c_init = init_nsc, | 447 | .c_init = init_nsc, |
452 | }; | 448 | }; |
453 | 449 | ||
454 | int __init nsc_init_cpu(void) | 450 | cpu_vendor_dev_register(X86_VENDOR_NSC, &nsc_cpu_dev); |
455 | { | ||
456 | cpu_devs[X86_VENDOR_NSC] = &nsc_cpu_dev; | ||
457 | return 0; | ||
458 | } | ||
459 | |||
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index fae31ce747bd..34468b2e2507 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -30,7 +30,7 @@ | |||
30 | struct movsl_mask movsl_mask __read_mostly; | 30 | struct movsl_mask movsl_mask __read_mostly; |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | void __cpuinit early_init_intel(struct cpuinfo_x86 *c) | 33 | static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) |
34 | { | 34 | { |
35 | /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */ | 35 | /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */ |
36 | if (c->x86 == 15 && c->x86_cache_alignment == 64) | 36 | if (c->x86 == 15 && c->x86_cache_alignment == 64) |
@@ -290,15 +290,12 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = { | |||
290 | } | 290 | } |
291 | }, | 291 | }, |
292 | }, | 292 | }, |
293 | .c_early_init = early_init_intel, | ||
293 | .c_init = init_intel, | 294 | .c_init = init_intel, |
294 | .c_size_cache = intel_size_cache, | 295 | .c_size_cache = intel_size_cache, |
295 | }; | 296 | }; |
296 | 297 | ||
297 | __init int intel_cpu_init(void) | 298 | cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev); |
298 | { | ||
299 | cpu_devs[X86_VENDOR_INTEL] = &intel_cpu_dev; | ||
300 | return 0; | ||
301 | } | ||
302 | 299 | ||
303 | #ifndef CONFIG_X86_CMPXCHG | 300 | #ifndef CONFIG_X86_CMPXCHG |
304 | unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new) | 301 | unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new) |
diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index e8b422c1c512..c2d168e992f4 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c | |||
@@ -102,8 +102,4 @@ static struct cpu_dev transmeta_cpu_dev __cpuinitdata = { | |||
102 | .c_identify = transmeta_identify, | 102 | .c_identify = transmeta_identify, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | int __init transmeta_init_cpu(void) | 105 | cpu_vendor_dev_register(X86_VENDOR_TRANSMETA, &transmeta_cpu_dev); |
106 | { | ||
107 | cpu_devs[X86_VENDOR_TRANSMETA] = &transmeta_cpu_dev; | ||
108 | return 0; | ||
109 | } | ||
diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c index a7a4e75bdcd7..b1acf08245fb 100644 --- a/arch/x86/kernel/cpu/umc.c +++ b/arch/x86/kernel/cpu/umc.c | |||
@@ -19,8 +19,5 @@ static struct cpu_dev umc_cpu_dev __cpuinitdata = { | |||
19 | }, | 19 | }, |
20 | }; | 20 | }; |
21 | 21 | ||
22 | int __init umc_init_cpu(void) | 22 | cpu_vendor_dev_register(X86_VENDOR_UMC, &umc_cpu_dev); |
23 | { | 23 | |
24 | cpu_devs[X86_VENDOR_UMC] = &umc_cpu_dev; | ||
25 | return 0; | ||
26 | } | ||