aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-03-24 13:50:09 -0400
committerTejun Heo <tj@kernel.org>2011-03-24 13:50:09 -0400
commit0415b00d175e0d8945e6785aad21b5f157976ce0 (patch)
treecf6f9286a47a22bf57766a3f17eaf4190bc9c242
parent6c5103890057b1bb781b26b7aae38d33e4c517d8 (diff)
percpu: Always align percpu output section to PAGE_SIZE
Percpu allocator honors alignment request upto PAGE_SIZE and both the percpu addresses in the percpu address space and the translated kernel addresses should be aligned accordingly. The calculation of the former depends on the alignment of percpu output section in the kernel image. The linker script macros PERCPU_VADDR() and PERCPU() are used to define this output section and the latter takes @align parameter. Several architectures are using @align smaller than PAGE_SIZE breaking percpu memory alignment. This patch removes @align parameter from PERCPU(), renames it to PERCPU_SECTION() and makes it always align to PAGE_SIZE. While at it, add PCPU_SETUP_BUG_ON() checks such that alignment problems are reliably detected and remove percpu alignment comment recently added in workqueue.c as the condition would trigger BUG way before reaching there. For um, this patch raises the alignment of percpu area. As the area is in .init, there shouldn't be any noticeable difference. This problem was discovered by David Howells while debugging boot failure on mn10300. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Mike Frysinger <vapier@gentoo.org> Cc: uclinux-dist-devel@blackfin.uclinux.org Cc: David Howells <dhowells@redhat.com> Cc: Jeff Dike <jdike@addtoit.com> Cc: user-mode-linux-devel@lists.sourceforge.net
-rw-r--r--arch/alpha/kernel/vmlinux.lds.S2
-rw-r--r--arch/arm/kernel/vmlinux.lds.S2
-rw-r--r--arch/blackfin/kernel/vmlinux.lds.S2
-rw-r--r--arch/cris/kernel/vmlinux.lds.S2
-rw-r--r--arch/frv/kernel/vmlinux.lds.S2
-rw-r--r--arch/m32r/kernel/vmlinux.lds.S2
-rw-r--r--arch/mips/kernel/vmlinux.lds.S2
-rw-r--r--arch/mn10300/kernel/vmlinux.lds.S2
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S2
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S2
-rw-r--r--arch/s390/kernel/vmlinux.lds.S2
-rw-r--r--arch/sh/kernel/vmlinux.lds.S2
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S2
-rw-r--r--arch/tile/kernel/vmlinux.lds.S2
-rw-r--r--arch/um/include/asm/common.lds.S2
-rw-r--r--arch/x86/kernel/vmlinux.lds.S2
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S2
-rw-r--r--include/asm-generic/vmlinux.lds.h17
-rw-r--r--kernel/workqueue.c4
-rw-r--r--mm/percpu.c2
20 files changed, 28 insertions, 29 deletions
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index 433be2a24f31..8d57948c0aef 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -39,7 +39,7 @@ SECTIONS
39 __init_begin = ALIGN(PAGE_SIZE); 39 __init_begin = ALIGN(PAGE_SIZE);
40 INIT_TEXT_SECTION(PAGE_SIZE) 40 INIT_TEXT_SECTION(PAGE_SIZE)
41 INIT_DATA_SECTION(16) 41 INIT_DATA_SECTION(16)
42 PERCPU(L1_CACHE_BYTES, PAGE_SIZE) 42 PERCPU_SECTION(L1_CACHE_BYTES)
43 /* Align to THREAD_SIZE rather than PAGE_SIZE here so any padding page 43 /* Align to THREAD_SIZE rather than PAGE_SIZE here so any padding page
44 needed for the THREAD_SIZE aligned init_task gets freed after init */ 44 needed for the THREAD_SIZE aligned init_task gets freed after init */
45 . = ALIGN(THREAD_SIZE); 45 . = ALIGN(THREAD_SIZE);
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index b4348e62ef06..e5287f21badc 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -82,7 +82,7 @@ SECTIONS
82#endif 82#endif
83 } 83 }
84 84
85 PERCPU(32, PAGE_SIZE) 85 PERCPU_SECTION(32)
86 86
87#ifndef CONFIG_XIP_KERNEL 87#ifndef CONFIG_XIP_KERNEL
88 . = ALIGN(PAGE_SIZE); 88 . = ALIGN(PAGE_SIZE);
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 854fa49f1c3e..8d85c8c6f857 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -136,7 +136,7 @@ SECTIONS
136 136
137 . = ALIGN(16); 137 . = ALIGN(16);
138 INIT_DATA_SECTION(16) 138 INIT_DATA_SECTION(16)
139 PERCPU(32, PAGE_SIZE) 139 PERCPU_SECTION(32)
140 140
141 .exit.data : 141 .exit.data :
142 { 142 {
diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S
index 728bbd9e7d4c..a6990cb0f098 100644
--- a/arch/cris/kernel/vmlinux.lds.S
+++ b/arch/cris/kernel/vmlinux.lds.S
@@ -102,7 +102,7 @@ SECTIONS
102#endif 102#endif
103 __vmlinux_end = .; /* Last address of the physical file. */ 103 __vmlinux_end = .; /* Last address of the physical file. */
104#ifdef CONFIG_ETRAX_ARCH_V32 104#ifdef CONFIG_ETRAX_ARCH_V32
105 PERCPU(32, PAGE_SIZE) 105 PERCPU_SECTION(32)
106 106
107 .init.ramfs : { 107 .init.ramfs : {
108 INIT_RAM_FS 108 INIT_RAM_FS
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index 0daae8af5787..7e958d829ec9 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -37,7 +37,7 @@ SECTIONS
37 _einittext = .; 37 _einittext = .;
38 38
39 INIT_DATA_SECTION(8) 39 INIT_DATA_SECTION(8)
40 PERCPU(L1_CACHE_BYTES, 4096) 40 PERCPU_SECTION(L1_CACHE_BYTES)
41 41
42 . = ALIGN(PAGE_SIZE); 42 . = ALIGN(PAGE_SIZE);
43 __init_end = .; 43 __init_end = .;
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
index c194d64cdbb9..2e7ccf7299a0 100644
--- a/arch/m32r/kernel/vmlinux.lds.S
+++ b/arch/m32r/kernel/vmlinux.lds.S
@@ -53,7 +53,7 @@ SECTIONS
53 __init_begin = .; 53 __init_begin = .;
54 INIT_TEXT_SECTION(PAGE_SIZE) 54 INIT_TEXT_SECTION(PAGE_SIZE)
55 INIT_DATA_SECTION(16) 55 INIT_DATA_SECTION(16)
56 PERCPU(32, PAGE_SIZE) 56 PERCPU_SECTION(32)
57 . = ALIGN(PAGE_SIZE); 57 . = ALIGN(PAGE_SIZE);
58 __init_end = .; 58 __init_end = .;
59 /* freed after init ends here */ 59 /* freed after init ends here */
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 832afbb87588..8616709452b1 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -115,7 +115,7 @@ SECTIONS
115 EXIT_DATA 115 EXIT_DATA
116 } 116 }
117 117
118 PERCPU(1 << CONFIG_MIPS_L1_CACHE_SHIFT, PAGE_SIZE) 118 PERCPU_SECTION(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
119 . = ALIGN(PAGE_SIZE); 119 . = ALIGN(PAGE_SIZE);
120 __init_end = .; 120 __init_end = .;
121 /* freed after init ends here */ 121 /* freed after init ends here */
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 968bcd2cb022..6f702a6ab395 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -70,7 +70,7 @@ SECTIONS
70 .exit.text : { EXIT_TEXT; } 70 .exit.text : { EXIT_TEXT; }
71 .exit.data : { EXIT_DATA; } 71 .exit.data : { EXIT_DATA; }
72 72
73 PERCPU(32, PAGE_SIZE) 73 PERCPU_SECTION(32)
74 . = ALIGN(PAGE_SIZE); 74 . = ALIGN(PAGE_SIZE);
75 __init_end = .; 75 __init_end = .;
76 /* freed after init ends here */ 76 /* freed after init ends here */
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 8f1e4efd143e..85b86617fe0b 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -145,7 +145,7 @@ SECTIONS
145 EXIT_DATA 145 EXIT_DATA
146 } 146 }
147 147
148 PERCPU(L1_CACHE_BYTES, PAGE_SIZE) 148 PERCPU_SECTION(L1_CACHE_BYTES)
149 . = ALIGN(PAGE_SIZE); 149 . = ALIGN(PAGE_SIZE);
150 __init_end = .; 150 __init_end = .;
151 /* freed after init ends here */ 151 /* freed after init ends here */
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index b9150f07d266..920276c0f6a1 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -160,7 +160,7 @@ SECTIONS
160 INIT_RAM_FS 160 INIT_RAM_FS
161 } 161 }
162 162
163 PERCPU(L1_CACHE_BYTES, PAGE_SIZE) 163 PERCPU_SECTION(L1_CACHE_BYTES)
164 164
165 . = ALIGN(8); 165 . = ALIGN(8);
166 .machine.desc : AT(ADDR(.machine.desc) - LOAD_OFFSET) { 166 .machine.desc : AT(ADDR(.machine.desc) - LOAD_OFFSET) {
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 1bc18cdb525b..56fe6bc81fee 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -77,7 +77,7 @@ SECTIONS
77 . = ALIGN(PAGE_SIZE); 77 . = ALIGN(PAGE_SIZE);
78 INIT_DATA_SECTION(0x100) 78 INIT_DATA_SECTION(0x100)
79 79
80 PERCPU(0x100, PAGE_SIZE) 80 PERCPU_SECTION(0x100)
81 . = ALIGN(PAGE_SIZE); 81 . = ALIGN(PAGE_SIZE);
82 __init_end = .; /* freed after init ends here */ 82 __init_end = .; /* freed after init ends here */
83 83
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index af4d46187a79..731c10ce67b5 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -66,7 +66,7 @@ SECTIONS
66 __machvec_end = .; 66 __machvec_end = .;
67 } 67 }
68 68
69 PERCPU(L1_CACHE_BYTES, PAGE_SIZE) 69 PERCPU_SECTION(L1_CACHE_BYTES)
70 70
71 /* 71 /*
72 * .exit.text is discarded at runtime, not link time, to deal with 72 * .exit.text is discarded at runtime, not link time, to deal with
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 92b557afe535..c0220759003e 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -108,7 +108,7 @@ SECTIONS
108 __sun4v_2insn_patch_end = .; 108 __sun4v_2insn_patch_end = .;
109 } 109 }
110 110
111 PERCPU(SMP_CACHE_BYTES, PAGE_SIZE) 111 PERCPU_SECTION(SMP_CACHE_BYTES)
112 112
113 . = ALIGN(PAGE_SIZE); 113 . = ALIGN(PAGE_SIZE);
114 __init_end = .; 114 __init_end = .;
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index 38f64fafdc10..631f10de12fe 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -60,7 +60,7 @@ SECTIONS
60 . = ALIGN(PAGE_SIZE); 60 . = ALIGN(PAGE_SIZE);
61 VMLINUX_SYMBOL(_sinitdata) = .; 61 VMLINUX_SYMBOL(_sinitdata) = .;
62 INIT_DATA_SECTION(16) :data =0 62 INIT_DATA_SECTION(16) :data =0
63 PERCPU(L2_CACHE_BYTES, PAGE_SIZE) 63 PERCPU_SECTION(L2_CACHE_BYTES)
64 . = ALIGN(PAGE_SIZE); 64 . = ALIGN(PAGE_SIZE);
65 VMLINUX_SYMBOL(_einitdata) = .; 65 VMLINUX_SYMBOL(_einitdata) = .;
66 66
diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S
index 34bede8aad4a..4938de5512d2 100644
--- a/arch/um/include/asm/common.lds.S
+++ b/arch/um/include/asm/common.lds.S
@@ -42,7 +42,7 @@
42 INIT_SETUP(0) 42 INIT_SETUP(0)
43 } 43 }
44 44
45 PERCPU(32, 32) 45 PERCPU_SECTION(32)
46 46
47 .initcall.init : { 47 .initcall.init : {
48 INIT_CALLS 48 INIT_CALLS
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 624a2016198e..3e9fb5d54f96 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -319,7 +319,7 @@ SECTIONS
319 } 319 }
320 320
321#if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP) 321#if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
322 PERCPU(INTERNODE_CACHE_BYTES, PAGE_SIZE) 322 PERCPU_SECTION(INTERNODE_CACHE_BYTES)
323#endif 323#endif
324 324
325 . = ALIGN(PAGE_SIZE); 325 . = ALIGN(PAGE_SIZE);
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index a2820065927e..88ecea3facb4 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -155,7 +155,7 @@ SECTIONS
155 INIT_RAM_FS 155 INIT_RAM_FS
156 } 156 }
157 157
158 PERCPU(XCHAL_ICACHE_LINESIZE, PAGE_SIZE) 158 PERCPU_SECTION(XCHAL_ICACHE_LINESIZE)
159 159
160 /* We need this dummy segment here */ 160 /* We need this dummy segment here */
161 161
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 32c45e5fe0ab..f301cea5ca2d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -15,7 +15,7 @@
15 * HEAD_TEXT_SECTION 15 * HEAD_TEXT_SECTION
16 * INIT_TEXT_SECTION(PAGE_SIZE) 16 * INIT_TEXT_SECTION(PAGE_SIZE)
17 * INIT_DATA_SECTION(...) 17 * INIT_DATA_SECTION(...)
18 * PERCPU(CACHELINE_SIZE, PAGE_SIZE) 18 * PERCPU_SECTION(CACHELINE_SIZE)
19 * __init_end = .; 19 * __init_end = .;
20 * 20 *
21 * _stext = .; 21 * _stext = .;
@@ -709,7 +709,7 @@
709 * 709 *
710 * Note that this macros defines __per_cpu_load as an absolute symbol. 710 * Note that this macros defines __per_cpu_load as an absolute symbol.
711 * If there is no need to put the percpu section at a predetermined 711 * If there is no need to put the percpu section at a predetermined
712 * address, use PERCPU(). 712 * address, use PERCPU_SECTION.
713 */ 713 */
714#define PERCPU_VADDR(cacheline, vaddr, phdr) \ 714#define PERCPU_VADDR(cacheline, vaddr, phdr) \
715 VMLINUX_SYMBOL(__per_cpu_load) = .; \ 715 VMLINUX_SYMBOL(__per_cpu_load) = .; \
@@ -729,20 +729,19 @@
729 . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data..percpu); 729 . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data..percpu);
730 730
731/** 731/**
732 * PERCPU - define output section for percpu area, simple version 732 * PERCPU_SECTION - define output section for percpu area, simple version
733 * @cacheline: cacheline size 733 * @cacheline: cacheline size
734 * @align: required alignment
735 * 734 *
736 * Align to @align and outputs output section for percpu area. This macro 735 * Align to PAGE_SIZE and outputs output section for percpu area. This
737 * doesn't manipulate @vaddr or @phdr and __per_cpu_load and 736 * macro doesn't manipulate @vaddr or @phdr and __per_cpu_load and
738 * __per_cpu_start will be identical. 737 * __per_cpu_start will be identical.
739 * 738 *
740 * This macro is equivalent to ALIGN(@align); PERCPU_VADDR(@cacheline,,) 739 * This macro is equivalent to ALIGN(PAGE_SIZE); PERCPU_VADDR(@cacheline,,)
741 * except that __per_cpu_load is defined as a relative symbol against 740 * except that __per_cpu_load is defined as a relative symbol against
742 * .data..percpu which is required for relocatable x86_32 configuration. 741 * .data..percpu which is required for relocatable x86_32 configuration.
743 */ 742 */
744#define PERCPU(cacheline, align) \ 743#define PERCPU_SECTION(cacheline) \
745 . = ALIGN(align); \ 744 . = ALIGN(PAGE_SIZE); \
746 .data..percpu : AT(ADDR(.data..percpu) - LOAD_OFFSET) { \ 745 .data..percpu : AT(ADDR(.data..percpu) - LOAD_OFFSET) { \
747 VMLINUX_SYMBOL(__per_cpu_load) = .; \ 746 VMLINUX_SYMBOL(__per_cpu_load) = .; \
748 VMLINUX_SYMBOL(__per_cpu_start) = .; \ 747 VMLINUX_SYMBOL(__per_cpu_start) = .; \
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 04ef830690ec..d30a502e8c6d 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2860,9 +2860,7 @@ static int alloc_cwqs(struct workqueue_struct *wq)
2860 } 2860 }
2861 } 2861 }
2862 2862
2863 /* just in case, make sure it's actually aligned 2863 /* just in case, make sure it's actually aligned */
2864 * - this is affected by PERCPU() alignment in vmlinux.lds.S
2865 */
2866 BUG_ON(!IS_ALIGNED(wq->cpu_wq.v, align)); 2864 BUG_ON(!IS_ALIGNED(wq->cpu_wq.v, align));
2867 return wq->cpu_wq.v ? 0 : -ENOMEM; 2865 return wq->cpu_wq.v ? 0 : -ENOMEM;
2868} 2866}
diff --git a/mm/percpu.c b/mm/percpu.c
index 3f930018aa60..c5feb79f5995 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1216,8 +1216,10 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
1216 PCPU_SETUP_BUG_ON(ai->nr_groups <= 0); 1216 PCPU_SETUP_BUG_ON(ai->nr_groups <= 0);
1217#ifdef CONFIG_SMP 1217#ifdef CONFIG_SMP
1218 PCPU_SETUP_BUG_ON(!ai->static_size); 1218 PCPU_SETUP_BUG_ON(!ai->static_size);
1219 PCPU_SETUP_BUG_ON((unsigned long)__per_cpu_start & ~PAGE_MASK);
1219#endif 1220#endif
1220 PCPU_SETUP_BUG_ON(!base_addr); 1221 PCPU_SETUP_BUG_ON(!base_addr);
1222 PCPU_SETUP_BUG_ON((unsigned long)base_addr & ~PAGE_MASK);
1221 PCPU_SETUP_BUG_ON(ai->unit_size < size_sum); 1223 PCPU_SETUP_BUG_ON(ai->unit_size < size_sum);
1222 PCPU_SETUP_BUG_ON(ai->unit_size & ~PAGE_MASK); 1224 PCPU_SETUP_BUG_ON(ai->unit_size & ~PAGE_MASK);
1223 PCPU_SETUP_BUG_ON(ai->unit_size < PCPU_MIN_UNIT_SIZE); 1225 PCPU_SETUP_BUG_ON(ai->unit_size < PCPU_MIN_UNIT_SIZE);