linux/arch/powerpc/kernel/vdso.c
<<
>>
Prefs
   1
   2/*
   3 *    Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
   4 *                       <benh@kernel.crashing.org>
   5 *
   6 *  This program is free software; you can redistribute it and/or
   7 *  modify it under the terms of the GNU General Public License
   8 *  as published by the Free Software Foundation; either version
   9 *  2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/errno.h>
  13#include <linux/sched.h>
  14#include <linux/kernel.h>
  15#include <linux/mm.h>
  16#include <linux/smp.h>
  17#include <linux/stddef.h>
  18#include <linux/unistd.h>
  19#include <linux/slab.h>
  20#include <linux/user.h>
  21#include <linux/elf.h>
  22#include <linux/security.h>
  23#include <linux/memblock.h>
  24
  25#include <asm/cpu_has_feature.h>
  26#include <asm/pgtable.h>
  27#include <asm/processor.h>
  28#include <asm/mmu.h>
  29#include <asm/mmu_context.h>
  30#include <asm/prom.h>
  31#include <asm/machdep.h>
  32#include <asm/cputable.h>
  33#include <asm/sections.h>
  34#include <asm/firmware.h>
  35#include <asm/vdso.h>
  36#include <asm/vdso_datapage.h>
  37#include <asm/setup.h>
  38
  39#undef DEBUG
  40
  41#ifdef DEBUG
  42#define DBG(fmt...) printk(fmt)
  43#else
  44#define DBG(fmt...)
  45#endif
  46
  47/* Max supported size for symbol names */
  48#define MAX_SYMNAME     64
  49
  50/* The alignment of the vDSO */
  51#define VDSO_ALIGNMENT  (1 << 16)
  52
  53static unsigned int vdso32_pages;
  54static void *vdso32_kbase;
  55static struct page **vdso32_pagelist;
  56unsigned long vdso32_sigtramp;
  57unsigned long vdso32_rt_sigtramp;
  58
  59#ifdef CONFIG_VDSO32
  60extern char vdso32_start, vdso32_end;
  61#endif
  62
  63#ifdef CONFIG_PPC64
  64extern char vdso64_start, vdso64_end;
  65static void *vdso64_kbase = &vdso64_start;
  66static unsigned int vdso64_pages;
  67static struct page **vdso64_pagelist;
  68unsigned long vdso64_rt_sigtramp;
  69#endif /* CONFIG_PPC64 */
  70
  71static int vdso_ready;
  72
  73/*
  74 * The vdso data page (aka. systemcfg for old ppc64 fans) is here.
  75 * Once the early boot kernel code no longer needs to muck around
  76 * with it, it will become dynamically allocated
  77 */
  78static union {
  79        struct vdso_data        data;
  80        u8                      page[PAGE_SIZE];
  81} vdso_data_store __page_aligned_data;
  82struct vdso_data *vdso_data = &vdso_data_store.data;
  83
  84/* Format of the patch table */
  85struct vdso_patch_def
  86{
  87        unsigned long   ftr_mask, ftr_value;
  88        const char      *gen_name;
  89        const char      *fix_name;
  90};
  91
  92/* Table of functions to patch based on the CPU type/revision
  93 *
  94 * Currently, we only change sync_dicache to do nothing on processors
  95 * with a coherent icache
  96 */
  97static struct vdso_patch_def vdso_patches[] = {
  98        {
  99                CPU_FTR_COHERENT_ICACHE, CPU_FTR_COHERENT_ICACHE,
 100                "__kernel_sync_dicache", "__kernel_sync_dicache_p5"
 101        },
 102        {
 103                CPU_FTR_USE_TB, 0,
 104                "__kernel_gettimeofday", NULL
 105        },
 106        {
 107                CPU_FTR_USE_TB, 0,
 108                "__kernel_clock_gettime", NULL
 109        },
 110        {
 111                CPU_FTR_USE_TB, 0,
 112                "__kernel_clock_getres", NULL
 113        },
 114        {
 115                CPU_FTR_USE_TB, 0,
 116                "__kernel_get_tbfreq", NULL
 117        },
 118        {
 119                CPU_FTR_USE_TB, 0,
 120                "__kernel_time", NULL
 121        },
 122};
 123
 124/*
 125 * Some infos carried around for each of them during parsing at
 126 * boot time.
 127 */
 128struct lib32_elfinfo
 129{
 130        Elf32_Ehdr      *hdr;           /* ptr to ELF */
 131        Elf32_Sym       *dynsym;        /* ptr to .dynsym section */
 132        unsigned long   dynsymsize;     /* size of .dynsym section */
 133        char            *dynstr;        /* ptr to .dynstr section */
 134        unsigned long   text;           /* offset of .text section in .so */
 135};
 136
 137struct lib64_elfinfo
 138{
 139        Elf64_Ehdr      *hdr;
 140        Elf64_Sym       *dynsym;
 141        unsigned long   dynsymsize;
 142        char            *dynstr;
 143        unsigned long   text;
 144};
 145
 146
 147/*
 148 * This is called from binfmt_elf, we create the special vma for the
 149 * vDSO and insert it into the mm struct tree
 150 */
 151int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 152{
 153        struct mm_struct *mm = current->mm;
 154        struct page **vdso_pagelist;
 155        unsigned long vdso_pages;
 156        unsigned long vdso_base;
 157        int rc;
 158
 159        if (!vdso_ready)
 160                return 0;
 161
 162#ifdef CONFIG_PPC64
 163        if (is_32bit_task()) {
 164                vdso_pagelist = vdso32_pagelist;
 165                vdso_pages = vdso32_pages;
 166                vdso_base = VDSO32_MBASE;
 167        } else {
 168                vdso_pagelist = vdso64_pagelist;
 169                vdso_pages = vdso64_pages;
 170                /*
 171                 * On 64bit we don't have a preferred map address. This
 172                 * allows get_unmapped_area to find an area near other mmaps
 173                 * and most likely share a SLB entry.
 174                 */
 175                vdso_base = 0;
 176        }
 177#else
 178        vdso_pagelist = vdso32_pagelist;
 179        vdso_pages = vdso32_pages;
 180        vdso_base = VDSO32_MBASE;
 181#endif
 182
 183        current->mm->context.vdso_base = 0;
 184
 185        /* vDSO has a problem and was disabled, just don't "enable" it for the
 186         * process
 187         */
 188        if (vdso_pages == 0)
 189                return 0;
 190        /* Add a page to the vdso size for the data page */
 191        vdso_pages ++;
 192
 193        /*
 194         * pick a base address for the vDSO in process space. We try to put it
 195         * at vdso_base which is the "natural" base for it, but we might fail
 196         * and end up putting it elsewhere.
 197         * Add enough to the size so that the result can be aligned.
 198         */
 199        if (down_write_killable(&mm->mmap_sem))
 200                return -EINTR;
 201        vdso_base = get_unmapped_area(NULL, vdso_base,
 202                                      (vdso_pages << PAGE_SHIFT) +
 203                                      ((VDSO_ALIGNMENT - 1) & PAGE_MASK),
 204                                      0, 0);
 205        if (IS_ERR_VALUE(vdso_base)) {
 206                rc = vdso_base;
 207                goto fail_mmapsem;
 208        }
 209
 210        /* Add required alignment. */
 211        vdso_base = ALIGN(vdso_base, VDSO_ALIGNMENT);
 212
 213        /*
 214         * Put vDSO base into mm struct. We need to do this before calling
 215         * install_special_mapping or the perf counter mmap tracking code
 216         * will fail to recognise it as a vDSO (since arch_vma_name fails).
 217         */
 218        current->mm->context.vdso_base = vdso_base;
 219
 220        /*
 221         * our vma flags don't have VM_WRITE so by default, the process isn't
 222         * allowed to write those pages.
 223         * gdb can break that with ptrace interface, and thus trigger COW on
 224         * those pages but it's then your responsibility to never do that on
 225         * the "data" page of the vDSO or you'll stop getting kernel updates
 226         * and your nice userland gettimeofday will be totally dead.
 227         * It's fine to use that for setting breakpoints in the vDSO code
 228         * pages though.
 229         */
 230        rc = install_special_mapping(mm, vdso_base, vdso_pages << PAGE_SHIFT,
 231                                     VM_READ|VM_EXEC|
 232                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
 233                                     vdso_pagelist);
 234        if (rc) {
 235                current->mm->context.vdso_base = 0;
 236                goto fail_mmapsem;
 237        }
 238
 239        up_write(&mm->mmap_sem);
 240        return 0;
 241
 242 fail_mmapsem:
 243        up_write(&mm->mmap_sem);
 244        return rc;
 245}
 246
 247const char *arch_vma_name(struct vm_area_struct *vma)
 248{
 249        if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base)
 250                return "[vdso]";
 251        return NULL;
 252}
 253
 254
 255
 256#ifdef CONFIG_VDSO32
 257static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname,
 258                                  unsigned long *size)
 259{
 260        Elf32_Shdr *sechdrs;
 261        unsigned int i;
 262        char *secnames;
 263
 264        /* Grab section headers and strings so we can tell who is who */
 265        sechdrs = (void *)ehdr + ehdr->e_shoff;
 266        secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset;
 267
 268        /* Find the section they want */
 269        for (i = 1; i < ehdr->e_shnum; i++) {
 270                if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
 271                        if (size)
 272                                *size = sechdrs[i].sh_size;
 273                        return (void *)ehdr + sechdrs[i].sh_offset;
 274                }
 275        }
 276        *size = 0;
 277        return NULL;
 278}
 279
 280static Elf32_Sym * __init find_symbol32(struct lib32_elfinfo *lib,
 281                                        const char *symname)
 282{
 283        unsigned int i;
 284        char name[MAX_SYMNAME], *c;
 285
 286        for (i = 0; i < (lib->dynsymsize / sizeof(Elf32_Sym)); i++) {
 287                if (lib->dynsym[i].st_name == 0)
 288                        continue;
 289                strlcpy(name, lib->dynstr + lib->dynsym[i].st_name,
 290                        MAX_SYMNAME);
 291                c = strchr(name, '@');
 292                if (c)
 293                        *c = 0;
 294                if (strcmp(symname, name) == 0)
 295                        return &lib->dynsym[i];
 296        }
 297        return NULL;
 298}
 299
 300/* Note that we assume the section is .text and the symbol is relative to
 301 * the library base
 302 */
 303static unsigned long __init find_function32(struct lib32_elfinfo *lib,
 304                                            const char *symname)
 305{
 306        Elf32_Sym *sym = find_symbol32(lib, symname);
 307
 308        if (sym == NULL) {
 309                printk(KERN_WARNING "vDSO32: function %s not found !\n",
 310                       symname);
 311                return 0;
 312        }
 313        return sym->st_value - VDSO32_LBASE;
 314}
 315
 316static int __init vdso_do_func_patch32(struct lib32_elfinfo *v32,
 317                                       struct lib64_elfinfo *v64,
 318                                       const char *orig, const char *fix)
 319{
 320        Elf32_Sym *sym32_gen, *sym32_fix;
 321
 322        sym32_gen = find_symbol32(v32, orig);
 323        if (sym32_gen == NULL) {
 324                printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", orig);
 325                return -1;
 326        }
 327        if (fix == NULL) {
 328                sym32_gen->st_name = 0;
 329                return 0;
 330        }
 331        sym32_fix = find_symbol32(v32, fix);
 332        if (sym32_fix == NULL) {
 333                printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", fix);
 334                return -1;
 335        }
 336        sym32_gen->st_value = sym32_fix->st_value;
 337        sym32_gen->st_size = sym32_fix->st_size;
 338        sym32_gen->st_info = sym32_fix->st_info;
 339        sym32_gen->st_other = sym32_fix->st_other;
 340        sym32_gen->st_shndx = sym32_fix->st_shndx;
 341
 342        return 0;
 343}
 344#else /* !CONFIG_VDSO32 */
 345static unsigned long __init find_function32(struct lib32_elfinfo *lib,
 346                                            const char *symname)
 347{
 348        return 0;
 349}
 350
 351static int __init vdso_do_func_patch32(struct lib32_elfinfo *v32,
 352                                       struct lib64_elfinfo *v64,
 353                                       const char *orig, const char *fix)
 354{
 355        return 0;
 356}
 357#endif /* CONFIG_VDSO32 */
 358
 359
 360#ifdef CONFIG_PPC64
 361
 362static void * __init find_section64(Elf64_Ehdr *ehdr, const char *secname,
 363                                  unsigned long *size)
 364{
 365        Elf64_Shdr *sechdrs;
 366        unsigned int i;
 367        char *secnames;
 368
 369        /* Grab section headers and strings so we can tell who is who */
 370        sechdrs = (void *)ehdr + ehdr->e_shoff;
 371        secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset;
 372
 373        /* Find the section they want */
 374        for (i = 1; i < ehdr->e_shnum; i++) {
 375                if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
 376                        if (size)
 377                                *size = sechdrs[i].sh_size;
 378                        return (void *)ehdr + sechdrs[i].sh_offset;
 379                }
 380        }
 381        if (size)
 382                *size = 0;
 383        return NULL;
 384}
 385
 386static Elf64_Sym * __init find_symbol64(struct lib64_elfinfo *lib,
 387                                        const char *symname)
 388{
 389        unsigned int i;
 390        char name[MAX_SYMNAME], *c;
 391
 392        for (i = 0; i < (lib->dynsymsize / sizeof(Elf64_Sym)); i++) {
 393                if (lib->dynsym[i].st_name == 0)
 394                        continue;
 395                strlcpy(name, lib->dynstr + lib->dynsym[i].st_name,
 396                        MAX_SYMNAME);
 397                c = strchr(name, '@');
 398                if (c)
 399                        *c = 0;
 400                if (strcmp(symname, name) == 0)
 401                        return &lib->dynsym[i];
 402        }
 403        return NULL;
 404}
 405
 406/* Note that we assume the section is .text and the symbol is relative to
 407 * the library base
 408 */
 409static unsigned long __init find_function64(struct lib64_elfinfo *lib,
 410                                            const char *symname)
 411{
 412        Elf64_Sym *sym = find_symbol64(lib, symname);
 413
 414        if (sym == NULL) {
 415                printk(KERN_WARNING "vDSO64: function %s not found !\n",
 416                       symname);
 417                return 0;
 418        }
 419#ifdef VDS64_HAS_DESCRIPTORS
 420        return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) -
 421                VDSO64_LBASE;
 422#else
 423        return sym->st_value - VDSO64_LBASE;
 424#endif
 425}
 426
 427static int __init vdso_do_func_patch64(struct lib32_elfinfo *v32,
 428                                       struct lib64_elfinfo *v64,
 429                                       const char *orig, const char *fix)
 430{
 431        Elf64_Sym *sym64_gen, *sym64_fix;
 432
 433        sym64_gen = find_symbol64(v64, orig);
 434        if (sym64_gen == NULL) {
 435                printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", orig);
 436                return -1;
 437        }
 438        if (fix == NULL) {
 439                sym64_gen->st_name = 0;
 440                return 0;
 441        }
 442        sym64_fix = find_symbol64(v64, fix);
 443        if (sym64_fix == NULL) {
 444                printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", fix);
 445                return -1;
 446        }
 447        sym64_gen->st_value = sym64_fix->st_value;
 448        sym64_gen->st_size = sym64_fix->st_size;
 449        sym64_gen->st_info = sym64_fix->st_info;
 450        sym64_gen->st_other = sym64_fix->st_other;
 451        sym64_gen->st_shndx = sym64_fix->st_shndx;
 452
 453        return 0;
 454}
 455
 456#endif /* CONFIG_PPC64 */
 457
 458
 459static __init int vdso_do_find_sections(struct lib32_elfinfo *v32,
 460                                        struct lib64_elfinfo *v64)
 461{
 462        void *sect;
 463
 464        /*
 465         * Locate symbol tables & text section
 466         */
 467
 468#ifdef CONFIG_VDSO32
 469        v32->dynsym = find_section32(v32->hdr, ".dynsym", &v32->dynsymsize);
 470        v32->dynstr = find_section32(v32->hdr, ".dynstr", NULL);
 471        if (v32->dynsym == NULL || v32->dynstr == NULL) {
 472                printk(KERN_ERR "vDSO32: required symbol section not found\n");
 473                return -1;
 474        }
 475        sect = find_section32(v32->hdr, ".text", NULL);
 476        if (sect == NULL) {
 477                printk(KERN_ERR "vDSO32: the .text section was not found\n");
 478                return -1;
 479        }
 480        v32->text = sect - vdso32_kbase;
 481#endif
 482
 483#ifdef CONFIG_PPC64
 484        v64->dynsym = find_section64(v64->hdr, ".dynsym", &v64->dynsymsize);
 485        v64->dynstr = find_section64(v64->hdr, ".dynstr", NULL);
 486        if (v64->dynsym == NULL || v64->dynstr == NULL) {
 487                printk(KERN_ERR "vDSO64: required symbol section not found\n");
 488                return -1;
 489        }
 490        sect = find_section64(v64->hdr, ".text", NULL);
 491        if (sect == NULL) {
 492                printk(KERN_ERR "vDSO64: the .text section was not found\n");
 493                return -1;
 494        }
 495        v64->text = sect - vdso64_kbase;
 496#endif /* CONFIG_PPC64 */
 497
 498        return 0;
 499}
 500
 501static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32,
 502                                          struct lib64_elfinfo *v64)
 503{
 504        /*
 505         * Find signal trampolines
 506         */
 507
 508#ifdef CONFIG_PPC64
 509        vdso64_rt_sigtramp = find_function64(v64, "__kernel_sigtramp_rt64");
 510#endif
 511        vdso32_sigtramp    = find_function32(v32, "__kernel_sigtramp32");
 512        vdso32_rt_sigtramp = find_function32(v32, "__kernel_sigtramp_rt32");
 513}
 514
 515static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32,
 516                                       struct lib64_elfinfo *v64)
 517{
 518#ifdef CONFIG_VDSO32
 519        Elf32_Sym *sym32;
 520#endif
 521#ifdef CONFIG_PPC64
 522        Elf64_Sym *sym64;
 523
 524        sym64 = find_symbol64(v64, "__kernel_datapage_offset");
 525        if (sym64 == NULL) {
 526                printk(KERN_ERR "vDSO64: Can't find symbol "
 527                       "__kernel_datapage_offset !\n");
 528                return -1;
 529        }
 530        *((int *)(vdso64_kbase + sym64->st_value - VDSO64_LBASE)) =
 531                (vdso64_pages << PAGE_SHIFT) -
 532                (sym64->st_value - VDSO64_LBASE);
 533#endif /* CONFIG_PPC64 */
 534
 535#ifdef CONFIG_VDSO32
 536        sym32 = find_symbol32(v32, "__kernel_datapage_offset");
 537        if (sym32 == NULL) {
 538                printk(KERN_ERR "vDSO32: Can't find symbol "
 539                       "__kernel_datapage_offset !\n");
 540                return -1;
 541        }
 542        *((int *)(vdso32_kbase + (sym32->st_value - VDSO32_LBASE))) =
 543                (vdso32_pages << PAGE_SHIFT) -
 544                (sym32->st_value - VDSO32_LBASE);
 545#endif
 546
 547        return 0;
 548}
 549
 550
 551static __init int vdso_fixup_features(struct lib32_elfinfo *v32,
 552                                      struct lib64_elfinfo *v64)
 553{
 554        unsigned long size;
 555        void *start;
 556
 557#ifdef CONFIG_PPC64
 558        start = find_section64(v64->hdr, "__ftr_fixup", &size);
 559        if (start)
 560                do_feature_fixups(cur_cpu_spec->cpu_features,
 561                                  start, start + size);
 562
 563        start = find_section64(v64->hdr, "__mmu_ftr_fixup", &size);
 564        if (start)
 565                do_feature_fixups(cur_cpu_spec->mmu_features,
 566                                  start, start + size);
 567
 568        start = find_section64(v64->hdr, "__fw_ftr_fixup", &size);
 569        if (start)
 570                do_feature_fixups(powerpc_firmware_features,
 571                                  start, start + size);
 572
 573        start = find_section64(v64->hdr, "__lwsync_fixup", &size);
 574        if (start)
 575                do_lwsync_fixups(cur_cpu_spec->cpu_features,
 576                                 start, start + size);
 577#endif /* CONFIG_PPC64 */
 578
 579#ifdef CONFIG_VDSO32
 580        start = find_section32(v32->hdr, "__ftr_fixup", &size);
 581        if (start)
 582                do_feature_fixups(cur_cpu_spec->cpu_features,
 583                                  start, start + size);
 584
 585        start = find_section32(v32->hdr, "__mmu_ftr_fixup", &size);
 586        if (start)
 587                do_feature_fixups(cur_cpu_spec->mmu_features,
 588                                  start, start + size);
 589
 590#ifdef CONFIG_PPC64
 591        start = find_section32(v32->hdr, "__fw_ftr_fixup", &size);
 592        if (start)
 593                do_feature_fixups(powerpc_firmware_features,
 594                                  start, start + size);
 595#endif /* CONFIG_PPC64 */
 596
 597        start = find_section32(v32->hdr, "__lwsync_fixup", &size);
 598        if (start)
 599                do_lwsync_fixups(cur_cpu_spec->cpu_features,
 600                                 start, start + size);
 601#endif
 602
 603        return 0;
 604}
 605
 606static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32,
 607                                       struct lib64_elfinfo *v64)
 608{
 609        int i;
 610
 611        for (i = 0; i < ARRAY_SIZE(vdso_patches); i++) {
 612                struct vdso_patch_def *patch = &vdso_patches[i];
 613                int match = (cur_cpu_spec->cpu_features & patch->ftr_mask)
 614                        == patch->ftr_value;
 615                if (!match)
 616                        continue;
 617
 618                DBG("replacing %s with %s...\n", patch->gen_name,
 619                    patch->fix_name ? "NONE" : patch->fix_name);
 620
 621                /*
 622                 * Patch the 32 bits and 64 bits symbols. Note that we do not
 623                 * patch the "." symbol on 64 bits.
 624                 * It would be easy to do, but doesn't seem to be necessary,
 625                 * patching the OPD symbol is enough.
 626                 */
 627                vdso_do_func_patch32(v32, v64, patch->gen_name,
 628                                     patch->fix_name);
 629#ifdef CONFIG_PPC64
 630                vdso_do_func_patch64(v32, v64, patch->gen_name,
 631                                     patch->fix_name);
 632#endif /* CONFIG_PPC64 */
 633        }
 634
 635        return 0;
 636}
 637
 638
 639static __init int vdso_setup(void)
 640{
 641        struct lib32_elfinfo    v32;
 642        struct lib64_elfinfo    v64;
 643
 644        v32.hdr = vdso32_kbase;
 645#ifdef CONFIG_PPC64
 646        v64.hdr = vdso64_kbase;
 647#endif
 648        if (vdso_do_find_sections(&v32, &v64))
 649                return -1;
 650
 651        if (vdso_fixup_datapage(&v32, &v64))
 652                return -1;
 653
 654        if (vdso_fixup_features(&v32, &v64))
 655                return -1;
 656
 657        if (vdso_fixup_alt_funcs(&v32, &v64))
 658                return -1;
 659
 660        vdso_setup_trampolines(&v32, &v64);
 661
 662        return 0;
 663}
 664
 665/*
 666 * Called from setup_arch to initialize the bitmap of available
 667 * syscalls in the systemcfg page
 668 */
 669static void __init vdso_setup_syscall_map(void)
 670{
 671        unsigned int i;
 672        extern unsigned long *sys_call_table;
 673        extern unsigned long sys_ni_syscall;
 674
 675
 676        for (i = 0; i < NR_syscalls; i++) {
 677#ifdef CONFIG_PPC64
 678                if (sys_call_table[i*2] != sys_ni_syscall)
 679                        vdso_data->syscall_map_64[i >> 5] |=
 680                                0x80000000UL >> (i & 0x1f);
 681                if (sys_call_table[i*2+1] != sys_ni_syscall)
 682                        vdso_data->syscall_map_32[i >> 5] |=
 683                                0x80000000UL >> (i & 0x1f);
 684#else /* CONFIG_PPC64 */
 685                if (sys_call_table[i] != sys_ni_syscall)
 686                        vdso_data->syscall_map_32[i >> 5] |=
 687                                0x80000000UL >> (i & 0x1f);
 688#endif /* CONFIG_PPC64 */
 689        }
 690}
 691
 692#ifdef CONFIG_PPC64
 693int vdso_getcpu_init(void)
 694{
 695        unsigned long cpu, node, val;
 696
 697        /*
 698         * SPRG_VDSO contains the CPU in the bottom 16 bits and the NUMA node
 699         * in the next 16 bits.  The VDSO uses this to implement getcpu().
 700         */
 701        cpu = get_cpu();
 702        WARN_ON_ONCE(cpu > 0xffff);
 703
 704        node = cpu_to_node(cpu);
 705        WARN_ON_ONCE(node > 0xffff);
 706
 707        val = (cpu & 0xfff) | ((node & 0xffff) << 16);
 708        mtspr(SPRN_SPRG_VDSO_WRITE, val);
 709        get_paca()->sprg_vdso = val;
 710
 711        put_cpu();
 712
 713        return 0;
 714}
 715/* We need to call this before SMP init */
 716early_initcall(vdso_getcpu_init);
 717#endif
 718
 719static int __init vdso_init(void)
 720{
 721        int i;
 722
 723#ifdef CONFIG_PPC64
 724        /*
 725         * Fill up the "systemcfg" stuff for backward compatibility
 726         */
 727        strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
 728        vdso_data->version.major = SYSTEMCFG_MAJOR;
 729        vdso_data->version.minor = SYSTEMCFG_MINOR;
 730        vdso_data->processor = mfspr(SPRN_PVR);
 731        /*
 732         * Fake the old platform number for pSeries and add
 733         * in LPAR bit if necessary
 734         */
 735        vdso_data->platform = 0x100;
 736        if (firmware_has_feature(FW_FEATURE_LPAR))
 737                vdso_data->platform |= 1;
 738        vdso_data->physicalMemorySize = memblock_phys_mem_size();
 739        vdso_data->dcache_size = ppc64_caches.l1d.size;
 740        vdso_data->dcache_line_size = ppc64_caches.l1d.line_size;
 741        vdso_data->icache_size = ppc64_caches.l1i.size;
 742        vdso_data->icache_line_size = ppc64_caches.l1i.line_size;
 743        vdso_data->dcache_block_size = ppc64_caches.l1d.block_size;
 744        vdso_data->icache_block_size = ppc64_caches.l1i.block_size;
 745        vdso_data->dcache_log_block_size = ppc64_caches.l1d.log_block_size;
 746        vdso_data->icache_log_block_size = ppc64_caches.l1i.log_block_size;
 747
 748        /*
 749         * Calculate the size of the 64 bits vDSO
 750         */
 751        vdso64_pages = (&vdso64_end - &vdso64_start) >> PAGE_SHIFT;
 752        DBG("vdso64_kbase: %p, 0x%x pages\n", vdso64_kbase, vdso64_pages);
 753#else
 754        vdso_data->dcache_block_size = L1_CACHE_BYTES;
 755        vdso_data->dcache_log_block_size = L1_CACHE_SHIFT;
 756        vdso_data->icache_block_size = L1_CACHE_BYTES;
 757        vdso_data->icache_log_block_size = L1_CACHE_SHIFT;
 758#endif /* CONFIG_PPC64 */
 759
 760
 761#ifdef CONFIG_VDSO32
 762        vdso32_kbase = &vdso32_start;
 763
 764        /*
 765         * Calculate the size of the 32 bits vDSO
 766         */
 767        vdso32_pages = (&vdso32_end - &vdso32_start) >> PAGE_SHIFT;
 768        DBG("vdso32_kbase: %p, 0x%x pages\n", vdso32_kbase, vdso32_pages);
 769#endif
 770
 771
 772        /*
 773         * Setup the syscall map in the vDOS
 774         */
 775        vdso_setup_syscall_map();
 776
 777        /*
 778         * Initialize the vDSO images in memory, that is do necessary
 779         * fixups of vDSO symbols, locate trampolines, etc...
 780         */
 781        if (vdso_setup()) {
 782                printk(KERN_ERR "vDSO setup failure, not enabled !\n");
 783                vdso32_pages = 0;
 784#ifdef CONFIG_PPC64
 785                vdso64_pages = 0;
 786#endif
 787                return 0;
 788        }
 789
 790#ifdef CONFIG_VDSO32
 791        /* Make sure pages are in the correct state */
 792        vdso32_pagelist = kzalloc(sizeof(struct page *) * (vdso32_pages + 2),
 793                                  GFP_KERNEL);
 794        BUG_ON(vdso32_pagelist == NULL);
 795        for (i = 0; i < vdso32_pages; i++) {
 796                struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE);
 797                ClearPageReserved(pg);
 798                get_page(pg);
 799                vdso32_pagelist[i] = pg;
 800        }
 801        vdso32_pagelist[i++] = virt_to_page(vdso_data);
 802        vdso32_pagelist[i] = NULL;
 803#endif
 804
 805#ifdef CONFIG_PPC64
 806        vdso64_pagelist = kzalloc(sizeof(struct page *) * (vdso64_pages + 2),
 807                                  GFP_KERNEL);
 808        BUG_ON(vdso64_pagelist == NULL);
 809        for (i = 0; i < vdso64_pages; i++) {
 810                struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE);
 811                ClearPageReserved(pg);
 812                get_page(pg);
 813                vdso64_pagelist[i] = pg;
 814        }
 815        vdso64_pagelist[i++] = virt_to_page(vdso_data);
 816        vdso64_pagelist[i] = NULL;
 817#endif /* CONFIG_PPC64 */
 818
 819        get_page(virt_to_page(vdso_data));
 820
 821        smp_wmb();
 822        vdso_ready = 1;
 823
 824        return 0;
 825}
 826arch_initcall(vdso_init);
 827