Commit 71fff5e6ca1b738ac4742580e4c0ff79d906f6c8
Committed by
Thomas Gleixner
1 parent
dbeb2be21d
Exists in
master
and in
7 other branches
x86: convert cpu_to_apicid to be a per cpu variable
This patch converts the x86_cpu_to_apicid array to be a per cpu variable. This saves sizeof(apicid) * NR unused cpus. Access is mostly from startup and CPU HOTPLUG functions. MP_processor_info() is one of the functions that require access to the x86_cpu_to_apicid array before the per_cpu data area is setup. For this case, a pointer to the __initdata array is initialized in setup_arch() and removed in smp_prepare_cpus() after the per_cpu data area is initialized. A second change is included to change the initial array value of ARCH i386 from 0xff to BAD_APICID to be consistent with ARCH x86_64. Signed-off-by: Mike Travis <travis@sgi.com> Cc: Andi Kleen <ak@suse.de> Cc: Christoph Lameter <clameter@sgi.com> Cc: "Siddha, Suresh B" <suresh.b.siddha@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Showing 12 changed files with 80 additions and 22 deletions Side-by-side Diff
- arch/x86/kernel/acpi/boot.c
- arch/x86/kernel/genapic_64.c
- arch/x86/kernel/genapic_flat_64.c
- arch/x86/kernel/mpparse_64.c
- arch/x86/kernel/setup_64.c
- arch/x86/kernel/smp_32.c
- arch/x86/kernel/smpboot_32.c
- arch/x86/kernel/smpboot_64.c
- arch/x86/mm/numa_64.c
- include/asm-x86/ipi.h
- include/asm-x86/smp_32.h
- include/asm-x86/smp_64.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/genapic_64.c
... | ... | @@ -24,10 +24,19 @@ |
24 | 24 | #include <acpi/acpi_bus.h> |
25 | 25 | #endif |
26 | 26 | |
27 | -/* which logical CPU number maps to which CPU (physical APIC ID) */ | |
28 | -u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly | |
27 | +/* | |
28 | + * which logical CPU number maps to which CPU (physical APIC ID) | |
29 | + * | |
30 | + * The following static array is used during kernel startup | |
31 | + * and the x86_cpu_to_apicid_ptr contains the address of the | |
32 | + * array during this time. Is it zeroed when the per_cpu | |
33 | + * data area is removed. | |
34 | + */ | |
35 | +u8 x86_cpu_to_apicid_init[NR_CPUS] __initdata | |
29 | 36 | = { [0 ... NR_CPUS-1] = BAD_APICID }; |
30 | -EXPORT_SYMBOL(x86_cpu_to_apicid); | |
37 | +void *x86_cpu_to_apicid_ptr; | |
38 | +DEFINE_PER_CPU(u8, x86_cpu_to_apicid) = BAD_APICID; | |
39 | +EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid); | |
31 | 40 | |
32 | 41 | struct genapic __read_mostly *genapic = &apic_flat; |
33 | 42 |
arch/x86/kernel/genapic_flat_64.c
arch/x86/kernel/mpparse_64.c
... | ... | @@ -86,7 +86,7 @@ |
86 | 86 | return sum & 0xFF; |
87 | 87 | } |
88 | 88 | |
89 | -static void __cpuinit MP_processor_info (struct mpc_config_processor *m) | |
89 | +static void __cpuinit MP_processor_info(struct mpc_config_processor *m) | |
90 | 90 | { |
91 | 91 | int cpu; |
92 | 92 | cpumask_t tmp_map; |
... | ... | @@ -123,7 +123,18 @@ |
123 | 123 | cpu = 0; |
124 | 124 | } |
125 | 125 | bios_cpu_apicid[cpu] = m->mpc_apicid; |
126 | - x86_cpu_to_apicid[cpu] = m->mpc_apicid; | |
126 | + /* | |
127 | + * We get called early in the the start_kernel initialization | |
128 | + * process when the per_cpu data area is not yet setup, so we | |
129 | + * use a static array that is removed after the per_cpu data | |
130 | + * area is created. | |
131 | + */ | |
132 | + if (x86_cpu_to_apicid_ptr) { | |
133 | + u8 *x86_cpu_to_apicid = (u8 *)x86_cpu_to_apicid_ptr; | |
134 | + x86_cpu_to_apicid[cpu] = m->mpc_apicid; | |
135 | + } else { | |
136 | + per_cpu(x86_cpu_to_apicid, cpu) = m->mpc_apicid; | |
137 | + } | |
127 | 138 | |
128 | 139 | cpu_set(cpu, cpu_possible_map); |
129 | 140 | cpu_set(cpu, cpu_present_map); |
arch/x86/kernel/setup_64.c
... | ... | @@ -271,6 +271,11 @@ |
271 | 271 | |
272 | 272 | dmi_scan_machine(); |
273 | 273 | |
274 | +#ifdef CONFIG_SMP | |
275 | + /* setup to use the static apicid table during kernel startup */ | |
276 | + x86_cpu_to_apicid_ptr = (void *)&x86_cpu_to_apicid_init; | |
277 | +#endif | |
278 | + | |
274 | 279 | #ifdef CONFIG_ACPI |
275 | 280 | /* |
276 | 281 | * Initialize the ACPI boot-time table parser (gets the RSDP and SDT). |
arch/x86/kernel/smp_32.c
arch/x86/kernel/smpboot_32.c
... | ... | @@ -92,9 +92,17 @@ |
92 | 92 | struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; |
93 | 93 | EXPORT_SYMBOL(cpu_data); |
94 | 94 | |
95 | -u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly = | |
96 | - { [0 ... NR_CPUS-1] = 0xff }; | |
97 | -EXPORT_SYMBOL(x86_cpu_to_apicid); | |
95 | +/* | |
96 | + * The following static array is used during kernel startup | |
97 | + * and the x86_cpu_to_apicid_ptr contains the address of the | |
98 | + * array during this time. Is it zeroed when the per_cpu | |
99 | + * data area is removed. | |
100 | + */ | |
101 | +u8 x86_cpu_to_apicid_init[NR_CPUS] __initdata = | |
102 | + { [0 ... NR_CPUS-1] = BAD_APICID }; | |
103 | +void *x86_cpu_to_apicid_ptr; | |
104 | +DEFINE_PER_CPU(u8, x86_cpu_to_apicid) = BAD_APICID; | |
105 | +EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid); | |
98 | 106 | |
99 | 107 | u8 apicid_2_node[MAX_APICID]; |
100 | 108 | |
... | ... | @@ -804,7 +812,7 @@ |
804 | 812 | |
805 | 813 | irq_ctx_init(cpu); |
806 | 814 | |
807 | - x86_cpu_to_apicid[cpu] = apicid; | |
815 | + per_cpu(x86_cpu_to_apicid, cpu) = apicid; | |
808 | 816 | /* |
809 | 817 | * This grunge runs the startup process for |
810 | 818 | * the targeted processor. |
... | ... | @@ -866,7 +874,7 @@ |
866 | 874 | cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */ |
867 | 875 | cpucount--; |
868 | 876 | } else { |
869 | - x86_cpu_to_apicid[cpu] = apicid; | |
877 | + per_cpu(x86_cpu_to_apicid, cpu) = apicid; | |
870 | 878 | cpu_set(cpu, cpu_present_map); |
871 | 879 | } |
872 | 880 | |
... | ... | @@ -915,7 +923,7 @@ |
915 | 923 | struct warm_boot_cpu_info info; |
916 | 924 | int apicid, ret; |
917 | 925 | |
918 | - apicid = x86_cpu_to_apicid[cpu]; | |
926 | + apicid = per_cpu(x86_cpu_to_apicid, cpu); | |
919 | 927 | if (apicid == BAD_APICID) { |
920 | 928 | ret = -ENODEV; |
921 | 929 | goto exit; |
... | ... | @@ -965,7 +973,7 @@ |
965 | 973 | |
966 | 974 | boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); |
967 | 975 | boot_cpu_logical_apicid = logical_smp_processor_id(); |
968 | - x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; | |
976 | + per_cpu(x86_cpu_to_apicid, 0) = boot_cpu_physical_apicid; | |
969 | 977 | |
970 | 978 | current_thread_info()->cpu = 0; |
971 | 979 |
arch/x86/kernel/smpboot_64.c
... | ... | @@ -694,7 +694,7 @@ |
694 | 694 | clear_node_cpumask(cpu); /* was set by numa_add_cpu */ |
695 | 695 | cpu_clear(cpu, cpu_present_map); |
696 | 696 | cpu_clear(cpu, cpu_possible_map); |
697 | - x86_cpu_to_apicid[cpu] = BAD_APICID; | |
697 | + per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID; | |
698 | 698 | return -EIO; |
699 | 699 | } |
700 | 700 | |
... | ... | @@ -841,6 +841,26 @@ |
841 | 841 | } |
842 | 842 | |
843 | 843 | /* |
844 | + * Copy apicid's found by MP_processor_info from initial array to the per cpu | |
845 | + * data area. The x86_cpu_to_apicid_init array is then expendable and the | |
846 | + * x86_cpu_to_apicid_ptr is zeroed indicating that the static array is no | |
847 | + * longer available. | |
848 | + */ | |
849 | +void __init smp_set_apicids(void) | |
850 | +{ | |
851 | + int cpu; | |
852 | + | |
853 | + for_each_cpu_mask(cpu, cpu_possible_map) { | |
854 | + if (per_cpu_offset(cpu)) | |
855 | + per_cpu(x86_cpu_to_apicid, cpu) = | |
856 | + x86_cpu_to_apicid_init[cpu]; | |
857 | + } | |
858 | + | |
859 | + /* indicate the static array will be going away soon */ | |
860 | + x86_cpu_to_apicid_ptr = NULL; | |
861 | +} | |
862 | + | |
863 | +/* | |
844 | 864 | * Prepare for SMP bootup. The MP table or ACPI has been read |
845 | 865 | * earlier. Just do some sanity checking here and enable APIC mode. |
846 | 866 | */ |
... | ... | @@ -849,6 +869,7 @@ |
849 | 869 | nmi_watchdog_default(); |
850 | 870 | current_cpu_data = boot_cpu_data; |
851 | 871 | current_thread_info()->cpu = 0; /* needed? */ |
872 | + smp_set_apicids(); | |
852 | 873 | set_cpu_sibling_map(0); |
853 | 874 | |
854 | 875 | if (smp_sanity_check(max_cpus) < 0) { |
arch/x86/mm/numa_64.c
include/asm-x86/ipi.h
... | ... | @@ -119,7 +119,7 @@ |
119 | 119 | */ |
120 | 120 | local_irq_save(flags); |
121 | 121 | for_each_cpu_mask(query_cpu, mask) { |
122 | - __send_IPI_dest_field(x86_cpu_to_apicid[query_cpu], | |
122 | + __send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, query_cpu), | |
123 | 123 | vector, APIC_DEST_PHYSICAL); |
124 | 124 | } |
125 | 125 | local_irq_restore(flags); |
include/asm-x86/smp_32.h
... | ... | @@ -39,9 +39,11 @@ |
39 | 39 | extern void unlock_ipi_call_lock(void); |
40 | 40 | |
41 | 41 | #define MAX_APICID 256 |
42 | -extern u8 x86_cpu_to_apicid[]; | |
42 | +extern u8 __initdata x86_cpu_to_apicid_init[]; | |
43 | +extern void *x86_cpu_to_apicid_ptr; | |
44 | +DECLARE_PER_CPU(u8, x86_cpu_to_apicid); | |
43 | 45 | |
44 | -#define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu] | |
46 | +#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) | |
45 | 47 | |
46 | 48 | extern void set_cpu_sibling_map(int cpu); |
47 | 49 |
include/asm-x86/smp_64.h
... | ... | @@ -86,7 +86,9 @@ |
86 | 86 | * Some lowlevel functions might want to know about |
87 | 87 | * the real APIC ID <-> CPU # mapping. |
88 | 88 | */ |
89 | -extern u8 x86_cpu_to_apicid[NR_CPUS]; /* physical ID */ | |
89 | +extern u8 __initdata x86_cpu_to_apicid_init[]; | |
90 | +extern void *x86_cpu_to_apicid_ptr; | |
91 | +DECLARE_PER_CPU(u8, x86_cpu_to_apicid); /* physical ID */ | |
90 | 92 | extern u8 bios_cpu_apicid[]; |
91 | 93 | |
92 | 94 | static inline int cpu_present_to_apicid(int mps_cpu) |
... | ... | @@ -117,7 +119,7 @@ |
117 | 119 | } |
118 | 120 | |
119 | 121 | #ifdef CONFIG_SMP |
120 | -#define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu] | |
122 | +#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) | |
121 | 123 | #else |
122 | 124 | #define cpu_physical_id(cpu) boot_cpu_id |
123 | 125 | #endif /* !CONFIG_SMP */ |