aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhu Guihua <zhugh.fnst@cn.fujitsu.com>2015-07-03 05:37:19 -0400
committerIngo Molnar <mingo@kernel.org>2015-07-06 09:00:34 -0400
commit20d5e4a9cd453991e2590a4c25230a99b42dee0c (patch)
tree2471151b639d5de698f1d3d9a36fb49a9b07189a
parent1db875631f8d5bbf497f67e47f254eece888d51d (diff)
x86/espfix: Init espfix on the boot CPU side
As we alloc pages with GFP_KERNEL in init_espfix_ap() which is called before we enable local irqs, so the lockdep sub-system would (correctly) trigger a warning about the potentially blocking API. So we allocate them on the boot CPU side when the secondary CPU is brought up by the boot CPU, and hand them over to the secondary CPU. And we use alloc_pages_node() with the secondary CPU's node, to make sure the espfix stack is NUMA-local to the CPU that is going to use it. Signed-off-by: Zhu Guihua <zhugh.fnst@cn.fujitsu.com> Cc: <bp@alien8.de> Cc: <luto@amacapital.net> Cc: <luto@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/c97add2670e9abebb90095369f0cfc172373ac94.1435824469.git.zhugh.fnst@cn.fujitsu.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/kernel/espfix_64.c21
-rw-r--r--arch/x86/kernel/smpboot.c14
2 files changed, 20 insertions, 15 deletions
diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c
index 1fb0e0003c94..ce95676abd60 100644
--- a/arch/x86/kernel/espfix_64.c
+++ b/arch/x86/kernel/espfix_64.c
@@ -141,12 +141,12 @@ void init_espfix_ap(int cpu)
141 pud_t pud, *pud_p; 141 pud_t pud, *pud_p;
142 pmd_t pmd, *pmd_p; 142 pmd_t pmd, *pmd_p;
143 pte_t pte, *pte_p; 143 pte_t pte, *pte_p;
144 int n; 144 int n, node;
145 void *stack_page; 145 void *stack_page;
146 pteval_t ptemask; 146 pteval_t ptemask;
147 147
148 /* We only have to do this once... */ 148 /* We only have to do this once... */
149 if (likely(this_cpu_read(espfix_stack))) 149 if (likely(per_cpu(espfix_stack, cpu)))
150 return; /* Already initialized */ 150 return; /* Already initialized */
151 151
152 addr = espfix_base_addr(cpu); 152 addr = espfix_base_addr(cpu);
@@ -164,12 +164,15 @@ void init_espfix_ap(int cpu)
164 if (stack_page) 164 if (stack_page)
165 goto unlock_done; 165 goto unlock_done;
166 166
167 node = cpu_to_node(cpu);
167 ptemask = __supported_pte_mask; 168 ptemask = __supported_pte_mask;
168 169
169 pud_p = &espfix_pud_page[pud_index(addr)]; 170 pud_p = &espfix_pud_page[pud_index(addr)];
170 pud = *pud_p; 171 pud = *pud_p;
171 if (!pud_present(pud)) { 172 if (!pud_present(pud)) {
172 pmd_p = (pmd_t *)__get_free_page(PGALLOC_GFP); 173 struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0);
174
175 pmd_p = (pmd_t *)page_address(page);
173 pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask)); 176 pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask));
174 paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT); 177 paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT);
175 for (n = 0; n < ESPFIX_PUD_CLONES; n++) 178 for (n = 0; n < ESPFIX_PUD_CLONES; n++)
@@ -179,7 +182,9 @@ void init_espfix_ap(int cpu)
179 pmd_p = pmd_offset(&pud, addr); 182 pmd_p = pmd_offset(&pud, addr);
180 pmd = *pmd_p; 183 pmd = *pmd_p;
181 if (!pmd_present(pmd)) { 184 if (!pmd_present(pmd)) {
182 pte_p = (pte_t *)__get_free_page(PGALLOC_GFP); 185 struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0);
186
187 pte_p = (pte_t *)page_address(page);
183 pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask)); 188 pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask));
184 paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT); 189 paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT);
185 for (n = 0; n < ESPFIX_PMD_CLONES; n++) 190 for (n = 0; n < ESPFIX_PMD_CLONES; n++)
@@ -187,7 +192,7 @@ void init_espfix_ap(int cpu)
187 } 192 }
188 193
189 pte_p = pte_offset_kernel(&pmd, addr); 194 pte_p = pte_offset_kernel(&pmd, addr);
190 stack_page = (void *)__get_free_page(GFP_KERNEL); 195 stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0));
191 pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask)); 196 pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask));
192 for (n = 0; n < ESPFIX_PTE_CLONES; n++) 197 for (n = 0; n < ESPFIX_PTE_CLONES; n++)
193 set_pte(&pte_p[n*PTE_STRIDE], pte); 198 set_pte(&pte_p[n*PTE_STRIDE], pte);
@@ -198,7 +203,7 @@ void init_espfix_ap(int cpu)
198unlock_done: 203unlock_done:
199 mutex_unlock(&espfix_init_mutex); 204 mutex_unlock(&espfix_init_mutex);
200done: 205done:
201 this_cpu_write(espfix_stack, addr); 206 per_cpu(espfix_stack, cpu) = addr;
202 this_cpu_write(espfix_waddr, (unsigned long)stack_page 207 per_cpu(espfix_waddr, cpu) = (unsigned long)stack_page
203 + (addr & ~PAGE_MASK)); 208 + (addr & ~PAGE_MASK);
204} 209}
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 6f5abac6c28b..0bd8c1d507b3 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -239,13 +239,6 @@ static void notrace start_secondary(void *unused)
239 check_tsc_sync_target(); 239 check_tsc_sync_target();
240 240
241 /* 241 /*
242 * Enable the espfix hack for this CPU
243 */
244#ifdef CONFIG_X86_ESPFIX64
245 init_espfix_ap(smp_processor_id());
246#endif
247
248 /*
249 * We need to hold vector_lock so there the set of online cpus 242 * We need to hold vector_lock so there the set of online cpus
250 * does not change while we are assigning vectors to cpus. Holding 243 * does not change while we are assigning vectors to cpus. Holding
251 * this lock ensures we don't half assign or remove an irq from a cpu. 244 * this lock ensures we don't half assign or remove an irq from a cpu.
@@ -854,6 +847,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
854 initial_code = (unsigned long)start_secondary; 847 initial_code = (unsigned long)start_secondary;
855 stack_start = idle->thread.sp; 848 stack_start = idle->thread.sp;
856 849
850 /*
851 * Enable the espfix hack for this CPU
852 */
853#ifdef CONFIG_X86_ESPFIX64
854 init_espfix_ap(cpu);
855#endif
856
857 /* So we see what's up */ 857 /* So we see what's up */
858 announce_cpu(cpu, apicid); 858 announce_cpu(cpu, apicid);
859 859