aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-05-29 23:51:37 -0400
committerPaul Mackerras <paulus@samba.org>2006-06-09 07:20:57 -0400
commita5bba930d802009c259e56c8d53086d96f63813b (patch)
tree8dd60002042bc0795b3d0544fcae7f5082405b16
parent98a90c02792f22afd8161f96fc9b9f0f0eb0880e (diff)
[PATCH] powerpc vdso updates
This patch cleans up some locking & error handling in the ppc vdso and moves the vdso base pointer from the thread struct to the mm context where it more logically belongs. It brings the powerpc implementation closer to Ingo's new x86 one and also adds an arch_vma_name() function allowing to print [vsdo] in /proc/<pid>/maps if Ingo's x86 vdso patch is also applied. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/signal_32.c8
-rw-r--r--arch/powerpc/kernel/signal_64.c4
-rw-r--r--arch/powerpc/kernel/vdso.c57
-rw-r--r--include/asm-powerpc/elf.h2
-rw-r--r--include/asm-powerpc/mmu.h1
-rw-r--r--include/asm-powerpc/page.h3
-rw-r--r--include/asm-powerpc/processor.h1
7 files changed, 47 insertions, 29 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 01e3c08cb550..22f078984845 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -757,10 +757,10 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
757 757
758 /* Save user registers on the stack */ 758 /* Save user registers on the stack */
759 frame = &rt_sf->uc.uc_mcontext; 759 frame = &rt_sf->uc.uc_mcontext;
760 if (vdso32_rt_sigtramp && current->thread.vdso_base) { 760 if (vdso32_rt_sigtramp && current->mm->context.vdso_base) {
761 if (save_user_regs(regs, frame, 0)) 761 if (save_user_regs(regs, frame, 0))
762 goto badframe; 762 goto badframe;
763 regs->link = current->thread.vdso_base + vdso32_rt_sigtramp; 763 regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp;
764 } else { 764 } else {
765 if (save_user_regs(regs, frame, __NR_rt_sigreturn)) 765 if (save_user_regs(regs, frame, __NR_rt_sigreturn))
766 goto badframe; 766 goto badframe;
@@ -1029,10 +1029,10 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
1029 || __put_user(sig, &sc->signal)) 1029 || __put_user(sig, &sc->signal))
1030 goto badframe; 1030 goto badframe;
1031 1031
1032 if (vdso32_sigtramp && current->thread.vdso_base) { 1032 if (vdso32_sigtramp && current->mm->context.vdso_base) {
1033 if (save_user_regs(regs, &frame->mctx, 0)) 1033 if (save_user_regs(regs, &frame->mctx, 0))
1034 goto badframe; 1034 goto badframe;
1035 regs->link = current->thread.vdso_base + vdso32_sigtramp; 1035 regs->link = current->mm->context.vdso_base + vdso32_sigtramp;
1036 } else { 1036 } else {
1037 if (save_user_regs(regs, &frame->mctx, __NR_sigreturn)) 1037 if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
1038 goto badframe; 1038 goto badframe;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 27f65b95184d..23ba69c26913 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -394,8 +394,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
394 current->thread.fpscr.val = 0; 394 current->thread.fpscr.val = 0;
395 395
396 /* Set up to return from userspace. */ 396 /* Set up to return from userspace. */
397 if (vdso64_rt_sigtramp && current->thread.vdso_base) { 397 if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
398 regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; 398 regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp;
399 } else { 399 } else {
400 err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); 400 err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
401 if (err) 401 if (err)
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 573afb68d69e..bc3e15be3087 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -223,6 +223,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
223 struct vm_area_struct *vma; 223 struct vm_area_struct *vma;
224 unsigned long vdso_pages; 224 unsigned long vdso_pages;
225 unsigned long vdso_base; 225 unsigned long vdso_base;
226 int rc;
226 227
227#ifdef CONFIG_PPC64 228#ifdef CONFIG_PPC64
228 if (test_thread_flag(TIF_32BIT)) { 229 if (test_thread_flag(TIF_32BIT)) {
@@ -237,20 +238,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
237 vdso_base = VDSO32_MBASE; 238 vdso_base = VDSO32_MBASE;
238#endif 239#endif
239 240
240 current->thread.vdso_base = 0; 241 current->mm->context.vdso_base = 0;
241 242
242 /* vDSO has a problem and was disabled, just don't "enable" it for the 243 /* vDSO has a problem and was disabled, just don't "enable" it for the
243 * process 244 * process
244 */ 245 */
245 if (vdso_pages == 0) 246 if (vdso_pages == 0)
246 return 0; 247 return 0;
247
248 vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
249 if (vma == NULL)
250 return -ENOMEM;
251
252 memset(vma, 0, sizeof(*vma));
253
254 /* Add a page to the vdso size for the data page */ 248 /* Add a page to the vdso size for the data page */
255 vdso_pages ++; 249 vdso_pages ++;
256 250
@@ -259,17 +253,23 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
259 * at vdso_base which is the "natural" base for it, but we might fail 253 * at vdso_base which is the "natural" base for it, but we might fail
260 * and end up putting it elsewhere. 254 * and end up putting it elsewhere.
261 */ 255 */
256 down_write(&mm->mmap_sem);
262 vdso_base = get_unmapped_area(NULL, vdso_base, 257 vdso_base = get_unmapped_area(NULL, vdso_base,
263 vdso_pages << PAGE_SHIFT, 0, 0); 258 vdso_pages << PAGE_SHIFT, 0, 0);
264 if (vdso_base & ~PAGE_MASK) { 259 if (IS_ERR_VALUE(vdso_base)) {
265 kmem_cache_free(vm_area_cachep, vma); 260 rc = vdso_base;
266 return (int)vdso_base; 261 goto fail_mmapsem;
267 } 262 }
268 263
269 current->thread.vdso_base = vdso_base;
270 264
265 /* Allocate a VMA structure and fill it up */
266 vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
267 if (vma == NULL) {
268 rc = -ENOMEM;
269 goto fail_mmapsem;
270 }
271 vma->vm_mm = mm; 271 vma->vm_mm = mm;
272 vma->vm_start = current->thread.vdso_base; 272 vma->vm_start = vdso_base;
273 vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT); 273 vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT);
274 274
275 /* 275 /*
@@ -282,23 +282,38 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
282 * It's fine to use that for setting breakpoints in the vDSO code 282 * It's fine to use that for setting breakpoints in the vDSO code
283 * pages though 283 * pages though
284 */ 284 */
285 vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; 285 vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC;
286 vma->vm_flags |= mm->def_flags; 286 vma->vm_flags |= mm->def_flags;
287 vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; 287 vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
288 vma->vm_ops = &vdso_vmops; 288 vma->vm_ops = &vdso_vmops;
289 289
290 down_write(&mm->mmap_sem); 290 /* Insert new VMA */
291 if (insert_vm_struct(mm, vma)) { 291 rc = insert_vm_struct(mm, vma);
292 up_write(&mm->mmap_sem); 292 if (rc)
293 kmem_cache_free(vm_area_cachep, vma); 293 goto fail_vma;
294 return -ENOMEM; 294
295 } 295 /* Put vDSO base into mm struct and account for memory usage */
296 current->mm->context.vdso_base = vdso_base;
296 mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; 297 mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
297 up_write(&mm->mmap_sem); 298 up_write(&mm->mmap_sem);
298
299 return 0; 299 return 0;
300
301 fail_vma:
302 kmem_cache_free(vm_area_cachep, vma);
303 fail_mmapsem:
304 up_write(&mm->mmap_sem);
305 return rc;
306}
307
308const char *arch_vma_name(struct vm_area_struct *vma)
309{
310 if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base)
311 return "[vdso]";
312 return NULL;
300} 313}
301 314
315
316
302static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname, 317static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname,
303 unsigned long *size) 318 unsigned long *size)
304{ 319{
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index 94d228f9c6ac..319655ce66c0 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -294,7 +294,7 @@ do { \
294 NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \ 294 NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
295 NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \ 295 NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
296 NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \ 296 NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
297 VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base) \ 297 VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base) \
298} while (0) 298} while (0)
299 299
300/* PowerPC64 relocations defined by the ABIs */ 300/* PowerPC64 relocations defined by the ABIs */
diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h
index 31f721994bd8..96e47d1ce979 100644
--- a/include/asm-powerpc/mmu.h
+++ b/include/asm-powerpc/mmu.h
@@ -360,6 +360,7 @@ typedef struct {
360#ifdef CONFIG_HUGETLB_PAGE 360#ifdef CONFIG_HUGETLB_PAGE
361 u16 low_htlb_areas, high_htlb_areas; 361 u16 low_htlb_areas, high_htlb_areas;
362#endif 362#endif
363 unsigned long vdso_base;
363} mm_context_t; 364} mm_context_t;
364 365
365 366
diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h
index ae610b620487..a315d0c0d96a 100644
--- a/include/asm-powerpc/page.h
+++ b/include/asm-powerpc/page.h
@@ -192,6 +192,9 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr,
192 struct page *p); 192 struct page *p);
193extern int page_is_ram(unsigned long pfn); 193extern int page_is_ram(unsigned long pfn);
194 194
195struct vm_area_struct;
196extern const char *arch_vma_name(struct vm_area_struct *vma);
197
195#include <asm-generic/memory_model.h> 198#include <asm-generic/memory_model.h>
196#endif /* __ASSEMBLY__ */ 199#endif /* __ASSEMBLY__ */
197 200
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index 93f83efeb310..d5c7ef1cca26 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -153,7 +153,6 @@ struct thread_struct {
153 unsigned long start_tb; /* Start purr when proc switched in */ 153 unsigned long start_tb; /* Start purr when proc switched in */
154 unsigned long accum_tb; /* Total accumilated purr for process */ 154 unsigned long accum_tb; /* Total accumilated purr for process */
155#endif 155#endif
156 unsigned long vdso_base; /* base of the vDSO library */
157 unsigned long dabr; /* Data address breakpoint register */ 156 unsigned long dabr; /* Data address breakpoint register */
158#ifdef CONFIG_ALTIVEC 157#ifdef CONFIG_ALTIVEC
159 /* Complete AltiVec register set */ 158 /* Complete AltiVec register set */