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