[POWERPC] Fix vDSO page count calculation

The recent vDSO consolidation patches broke powerpc due to a mistake
in the definition of MAXPAGES constants. This fixes it by moving to
a dynamically allocated array of pages instead as I don't like much
hard coded size limits. Also move the vdso initialisation to an initcall
since it doesn't really need to be done -that- early.

Applogies for not catching the breakage earlier, Roland _did_ CC me on
his patches a while ago, I got busy with other things and forgot to test
them.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Benjamin Herrenschmidt 2007-02-12 13:31:08 +11:00 committed by Paul Mackerras
parent a334bdbdda
commit 7ac9a13717
3 changed files with 23 additions and 19 deletions

View File

@ -49,24 +49,23 @@
/* Max supported size for symbol names */ /* Max supported size for symbol names */
#define MAX_SYMNAME 64 #define MAX_SYMNAME 64
#define VDSO32_MAXPAGES (((0x3000 + PAGE_MASK) >> PAGE_SHIFT) + 2)
#define VDSO64_MAXPAGES (((0x3000 + PAGE_MASK) >> PAGE_SHIFT) + 2)
extern char vdso32_start, vdso32_end; extern char vdso32_start, vdso32_end;
static void *vdso32_kbase = &vdso32_start; static void *vdso32_kbase = &vdso32_start;
unsigned int vdso32_pages; static unsigned int vdso32_pages;
static struct page *vdso32_pagelist[VDSO32_MAXPAGES]; static struct page **vdso32_pagelist;
unsigned long vdso32_sigtramp; unsigned long vdso32_sigtramp;
unsigned long vdso32_rt_sigtramp; unsigned long vdso32_rt_sigtramp;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
extern char vdso64_start, vdso64_end; extern char vdso64_start, vdso64_end;
static void *vdso64_kbase = &vdso64_start; static void *vdso64_kbase = &vdso64_start;
unsigned int vdso64_pages; static unsigned int vdso64_pages;
static struct page *vdso64_pagelist[VDSO64_MAXPAGES]; static struct page **vdso64_pagelist;
unsigned long vdso64_rt_sigtramp; unsigned long vdso64_rt_sigtramp;
#endif /* CONFIG_PPC64 */ #endif /* CONFIG_PPC64 */
static int vdso_ready;
/* /*
* The vdso data page (aka. systemcfg for old ppc64 fans) is here. * The vdso data page (aka. systemcfg for old ppc64 fans) is here.
* Once the early boot kernel code no longer needs to muck around * Once the early boot kernel code no longer needs to muck around
@ -182,6 +181,9 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
unsigned long vdso_base; unsigned long vdso_base;
int rc; int rc;
if (!vdso_ready)
return 0;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
if (test_thread_flag(TIF_32BIT)) { if (test_thread_flag(TIF_32BIT)) {
vdso_pagelist = vdso32_pagelist; vdso_pagelist = vdso32_pagelist;
@ -661,7 +663,7 @@ static void __init vdso_setup_syscall_map(void)
} }
void __init vdso_init(void) static int __init vdso_init(void)
{ {
int i; int i;
@ -716,11 +718,13 @@ void __init vdso_init(void)
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
vdso64_pages = 0; vdso64_pages = 0;
#endif #endif
return; return 0;
} }
/* Make sure pages are in the correct state */ /* Make sure pages are in the correct state */
BUG_ON(vdso32_pages + 2 > VDSO32_MAXPAGES); vdso32_pagelist = kzalloc(sizeof(struct page *) * (vdso32_pages + 2),
GFP_KERNEL);
BUG_ON(vdso32_pagelist == NULL);
for (i = 0; i < vdso32_pages; i++) { for (i = 0; i < vdso32_pages; i++) {
struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE); struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE);
ClearPageReserved(pg); ClearPageReserved(pg);
@ -731,7 +735,9 @@ void __init vdso_init(void)
vdso32_pagelist[i] = NULL; vdso32_pagelist[i] = NULL;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
BUG_ON(vdso64_pages + 2 > VDSO64_MAXPAGES); vdso64_pagelist = kzalloc(sizeof(struct page *) * (vdso64_pages + 2),
GFP_KERNEL);
BUG_ON(vdso64_pagelist == NULL);
for (i = 0; i < vdso64_pages; i++) { for (i = 0; i < vdso64_pages; i++) {
struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE); struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE);
ClearPageReserved(pg); ClearPageReserved(pg);
@ -743,7 +749,13 @@ void __init vdso_init(void)
#endif /* CONFIG_PPC64 */ #endif /* CONFIG_PPC64 */
get_page(virt_to_page(vdso_data)); get_page(virt_to_page(vdso_data));
smp_wmb();
vdso_ready = 1;
return 0;
} }
arch_initcall(vdso_init);
int in_gate_area_no_task(unsigned long addr) int in_gate_area_no_task(unsigned long addr)
{ {

View File

@ -384,9 +384,6 @@ void __init mem_init(void)
initsize >> 10); initsize >> 10);
mem_init_done = 1; mem_init_done = 1;
/* Initialize the vDSO */
vdso_init();
} }
/* /*

View File

@ -18,16 +18,11 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
extern unsigned int vdso64_pages;
extern unsigned int vdso32_pages;
/* Offsets relative to thread->vdso_base */ /* Offsets relative to thread->vdso_base */
extern unsigned long vdso64_rt_sigtramp; extern unsigned long vdso64_rt_sigtramp;
extern unsigned long vdso32_sigtramp; extern unsigned long vdso32_sigtramp;
extern unsigned long vdso32_rt_sigtramp; extern unsigned long vdso32_rt_sigtramp;
extern void vdso_init(void);
#else /* __ASSEMBLY__ */ #else /* __ASSEMBLY__ */
#ifdef __VDSO64__ #ifdef __VDSO64__