12 #include <linux/errno.h>
13 #include <linux/sched.h>
14 #include <linux/kernel.h>
17 #include <linux/stddef.h>
19 #include <linux/slab.h>
21 #include <linux/elf.h>
26 #include <asm/pgtable.h>
27 #include <asm/processor.h>
29 #include <asm/mmu_context.h>
31 #include <asm/machdep.h>
32 #include <asm/cputable.h>
33 #include <asm/sections.h>
36 #include <asm/vdso_datapage.h>
43 #define DBG(fmt...) printk(fmt)
49 #define MAX_SYMNAME 64
52 #define VDSO_ALIGNMENT (1 << 16)
56 static unsigned int vdso32_pages;
57 static struct page **vdso32_pagelist;
62 extern char vdso64_start, vdso64_end;
63 static void *vdso64_kbase = &vdso64_start;
64 static unsigned int vdso64_pages;
65 static struct page **vdso64_pagelist;
66 unsigned long vdso64_rt_sigtramp;
69 static int vdso_ready;
98 "__kernel_sync_dicache",
"__kernel_sync_dicache_p5"
102 "__kernel_gettimeofday",
NULL
106 "__kernel_clock_gettime",
NULL
110 "__kernel_clock_getres",
NULL
114 "__kernel_get_tbfreq",
NULL
142 static void dump_one_vdso_page(
struct page *
pg,
struct page *upg)
147 if (upg && !IS_ERR(upg) ) {
161 printk(
"vDSO32 @ %016lx:\n", (
unsigned long)vdso32_kbase);
162 for (i=0; i<vdso32_pages; i++) {
168 dump_one_vdso_page(pg, upg);
172 printk(
"vDSO64 @ %016lx:\n", (
unsigned long)vdso64_kbase);
173 for (i=0; i<vdso64_pages; i++) {
179 dump_one_vdso_page(pg, upg);
192 struct page **vdso_pagelist;
194 unsigned long vdso_base;
202 vdso_pagelist = vdso32_pagelist;
203 vdso_pages = vdso32_pages;
204 vdso_base = VDSO32_MBASE;
206 vdso_pagelist = vdso64_pagelist;
207 vdso_pages = vdso64_pages;
216 vdso_pagelist = vdso32_pagelist;
217 vdso_pages = vdso32_pages;
218 vdso_base = VDSO32_MBASE;
221 current->mm->context.vdso_base = 0;
255 current->mm->context.vdso_base = vdso_base;
269 VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
272 current->mm->context.vdso_base = 0;
301 sechdrs = (
void *)ehdr + ehdr->
e_shoff;
305 for (i = 1; i < ehdr->
e_shnum; i++) {
306 if (
strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
330 if (
strcmp(symname, name) == 0)
342 Elf32_Sym *sym = find_symbol32(lib, symname);
354 const char *orig,
const char *fix)
358 sym32_gen = find_symbol32(v32, orig);
359 if (sym32_gen ==
NULL) {
367 sym32_fix = find_symbol32(v32, fix);
368 if (sym32_fix ==
NULL) {
392 sechdrs = (
void *)ehdr + ehdr->
e_shoff;
396 for (i = 1; i < ehdr->
e_shnum; i++) {
397 if (
strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
422 if (
strcmp(symname, name) == 0)
434 Elf64_Sym *sym = find_symbol64(lib, symname);
441 #ifdef VDS64_HAS_DESCRIPTORS
451 const char *orig,
const char *fix)
455 sym64_gen = find_symbol64(v64, orig);
456 if (sym64_gen ==
NULL) {
464 sym64_fix = find_symbol64(v64, fix);
465 if (sym64_fix ==
NULL) {
496 sect = find_section32(v32->
hdr,
".text",
NULL);
501 v32->
text = sect - vdso32_kbase;
510 sect = find_section64(v64->
hdr,
".text",
NULL);
515 v64->
text = sect - vdso64_kbase;
529 vdso64_rt_sigtramp = find_function64(v64,
"__kernel_sigtramp_rt64");
542 sym64 = find_symbol64(v64,
"__kernel_datapage_offset");
545 "__kernel_datapage_offset !\n");
553 sym32 = find_symbol32(v32,
"__kernel_datapage_offset");
556 "__kernel_datapage_offset !\n");
571 unsigned long size32;
575 unsigned long size64;
577 start64 = find_section64(v64->
hdr,
"__ftr_fixup", &size64);
580 start64, start64 + size64);
582 start64 = find_section64(v64->
hdr,
"__mmu_ftr_fixup", &size64);
585 start64, start64 + size64);
587 start64 = find_section64(v64->
hdr,
"__fw_ftr_fixup", &size64);
590 start64, start64 + size64);
592 start64 = find_section64(v64->
hdr,
"__lwsync_fixup", &size64);
595 start64, start64 + size64);
598 start32 = find_section32(v32->
hdr,
"__ftr_fixup", &size32);
601 start32, start32 + size32);
603 start32 = find_section32(v32->
hdr,
"__mmu_ftr_fixup", &size32);
606 start32, start32 + size32);
609 start32 = find_section32(v32->
hdr,
"__fw_ftr_fixup", &size32);
612 start32, start32 + size32);
615 start32 = find_section32(v32->
hdr,
"__lwsync_fixup", &size32);
618 start32, start32 + size32);
628 for (i = 0; i <
ARRAY_SIZE(vdso_patches); i++) {
644 vdso_do_func_patch32(v32, v64, patch->
gen_name,
647 vdso_do_func_patch64(v32, v64, patch->
gen_name,
656 static __init int vdso_setup(
void)
661 v32.
hdr = vdso32_kbase;
663 v64.
hdr = vdso64_kbase;
665 if (vdso_do_find_sections(&v32, &v64))
668 if (vdso_fixup_datapage(&v32, &v64))
671 if (vdso_fixup_features(&v32, &v64))
674 if (vdso_fixup_alt_funcs(&v32, &v64))
677 vdso_setup_trampolines(&v32, &v64);
686 static void __init vdso_setup_syscall_map(
void)
695 if (sys_call_table[i*2] != sys_ni_syscall)
696 vdso_data->syscall_map_64[i >> 5] |=
697 0x80000000
UL >> (i & 0x1f);
698 if (sys_call_table[i*2+1] != sys_ni_syscall)
699 vdso_data->syscall_map_32[i >> 5] |=
700 0x80000000
UL >> (i & 0x1f);
702 if (sys_call_table[i] != sys_ni_syscall)
703 vdso_data->syscall_map_32[i >> 5] |=
704 0x80000000
UL >> (i & 0x1f);
724 val = (cpu & 0xfff) | ((node & 0xffff) << 16);
725 mtspr(SPRN_SPRG3, val);
726 get_paca()->sprg3 =
val;
736 static int __init vdso_init(
void)
744 strcpy((
char *)vdso_data->eye_catcher,
"SYSTEMCFG:PPC64");
745 vdso_data->version.major = SYSTEMCFG_MAJOR;
746 vdso_data->version.minor = SYSTEMCFG_MINOR;
752 vdso_data->platform = 0x100;
753 if (firmware_has_feature(FW_FEATURE_LPAR))
754 vdso_data->platform |= 1;
764 vdso_data->dcache_log_block_size =
ppc64_caches.log_dline_size;
765 vdso_data->icache_log_block_size =
ppc64_caches.log_iline_size;
770 vdso64_pages = (&vdso64_end - &vdso64_start) >>
PAGE_SHIFT;
771 DBG(
"vdso64_kbase: %p, 0x%x pages\n", vdso64_kbase, vdso64_pages);
784 DBG(
"vdso32_kbase: %p, 0x%x pages\n", vdso32_kbase, vdso32_pages);
790 vdso_setup_syscall_map();
806 vdso32_pagelist = kzalloc(
sizeof(
struct page *) * (vdso32_pages + 2),
809 for (i = 0; i < vdso32_pages; i++) {
811 ClearPageReserved(pg);
813 vdso32_pagelist[
i] =
pg;
816 vdso32_pagelist[
i] =
NULL;
819 vdso64_pagelist = kzalloc(
sizeof(
struct page *) * (vdso64_pages + 2),
822 for (i = 0; i < vdso64_pages; i++) {
824 ClearPageReserved(pg);
826 vdso64_pagelist[
i] =
pg;
829 vdso64_pagelist[
i] =
NULL;