2 * (C) Copyright 2002 Linus Torvalds
3 * Portions based on the vdso-randomization code from exec-shield:
4 * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar
6 * This file contains the needed initializations to support sysenter.
9 #include <linux/init.h>
10 #include <linux/smp.h>
11 #include <linux/thread_info.h>
12 #include <linux/sched.h>
13 #include <linux/gfp.h>
14 #include <linux/string.h>
15 #include <linux/elf.h>
17 #include <linux/err.h>
18 #include <linux/module.h>
20 #include <asm/cpufeature.h>
22 #include <asm/pgtable.h>
23 #include <asm/unistd.h>
25 #include <asm/tlbflush.h>
27 #include <asm/proto.h>
29 #ifdef CONFIG_COMPAT_VDSO
30 #define VDSO_DEFAULT 0
32 #define VDSO_DEFAULT 1
36 #define vdso_enabled sysctl_vsyscall32
37 #define arch_setup_additional_pages syscall32_setup_pages
41 * Should the kernel map a VDSO page into processes and pass its
42 * address down to glibc upon exec()?
44 unsigned int __read_mostly vdso_enabled
= VDSO_DEFAULT
;
46 static int __init
vdso_setup(char *s
)
48 vdso_enabled
= simple_strtoul(s
, NULL
, 0);
51 pr_warn("vdso32 values other than 0 and 1 are no longer allowed; vdso disabled\n");
57 * For consistency, the argument vdso32=[012] affects the 32-bit vDSO
58 * behavior on both 64-bit and 32-bit kernels.
59 * On 32-bit kernels, vdso=[012] means the same thing.
61 __setup("vdso32=", vdso_setup
);
64 __setup_param("vdso=", vdso32_setup
, vdso_setup
, 0);
66 EXPORT_SYMBOL_GPL(vdso_enabled
);
69 static struct page
*vdso32_pages
[1];
73 #define vdso32_sysenter() (boot_cpu_has(X86_FEATURE_SYSENTER32))
74 #define vdso32_syscall() (boot_cpu_has(X86_FEATURE_SYSCALL32))
76 /* May not be __init: called during resume */
77 void syscall32_cpu_init(void)
79 /* Load these always in case some future AMD CPU supports
80 SYSENTER from compat mode too. */
81 wrmsrl_safe(MSR_IA32_SYSENTER_CS
, (u64
)__KERNEL_CS
);
82 wrmsrl_safe(MSR_IA32_SYSENTER_ESP
, 0ULL);
83 wrmsrl_safe(MSR_IA32_SYSENTER_EIP
, (u64
)ia32_sysenter_target
);
85 wrmsrl(MSR_CSTAR
, ia32_cstar_target
);
88 #else /* CONFIG_X86_32 */
90 #define vdso32_sysenter() (boot_cpu_has(X86_FEATURE_SEP))
91 #define vdso32_syscall() (0)
93 void enable_sep_cpu(void)
96 struct tss_struct
*tss
= &per_cpu(init_tss
, cpu
);
98 if (!boot_cpu_has(X86_FEATURE_SEP
)) {
103 tss
->x86_tss
.ss1
= __KERNEL_CS
;
104 tss
->x86_tss
.sp1
= sizeof(struct tss_struct
) + (unsigned long) tss
;
105 wrmsr(MSR_IA32_SYSENTER_CS
, __KERNEL_CS
, 0);
106 wrmsr(MSR_IA32_SYSENTER_ESP
, tss
->x86_tss
.sp1
, 0);
107 wrmsr(MSR_IA32_SYSENTER_EIP
, (unsigned long) ia32_sysenter_target
, 0);
111 #endif /* CONFIG_X86_64 */
113 int __init
sysenter_setup(void)
115 void *syscall_page
= (void *)get_zeroed_page(GFP_ATOMIC
);
116 const void *vsyscall
;
119 vdso32_pages
[0] = virt_to_page(syscall_page
);
121 if (vdso32_syscall()) {
122 vsyscall
= &vdso32_syscall_start
;
123 vsyscall_len
= &vdso32_syscall_end
- &vdso32_syscall_start
;
124 } else if (vdso32_sysenter()){
125 vsyscall
= &vdso32_sysenter_start
;
126 vsyscall_len
= &vdso32_sysenter_end
- &vdso32_sysenter_start
;
128 vsyscall
= &vdso32_int80_start
;
129 vsyscall_len
= &vdso32_int80_end
- &vdso32_int80_start
;
132 memcpy(syscall_page
, vsyscall
, vsyscall_len
);
137 /* Setup a VMA at program startup for the vsyscall page */
138 int arch_setup_additional_pages(struct linux_binprm
*bprm
, int uses_interp
)
140 struct mm_struct
*mm
= current
->mm
;
144 #ifdef CONFIG_X86_X32_ABI
145 if (test_thread_flag(TIF_X32
))
146 return x32_setup_additional_pages(bprm
, uses_interp
);
149 if (vdso_enabled
!= 1) /* Other values all mean "disabled" */
152 down_write(&mm
->mmap_sem
);
154 addr
= get_unmapped_area(NULL
, 0, PAGE_SIZE
, 0, 0);
155 if (IS_ERR_VALUE(addr
)) {
160 current
->mm
->context
.vdso
= (void *)addr
;
163 * MAYWRITE to allow gdb to COW and set breakpoints
165 ret
= install_special_mapping(mm
, addr
, PAGE_SIZE
,
167 VM_MAYREAD
|VM_MAYWRITE
|VM_MAYEXEC
,
173 current_thread_info()->sysenter_return
=
174 VDSO32_SYMBOL(addr
, SYSENTER_RETURN
);
178 current
->mm
->context
.vdso
= NULL
;
180 up_write(&mm
->mmap_sem
);
187 subsys_initcall(sysenter_setup
);
190 /* Register vsyscall32 into the ABI table */
191 #include <linux/sysctl.h>
193 static struct ctl_table abi_table2
[] = {
195 .procname
= "vsyscall32",
196 .data
= &sysctl_vsyscall32
,
197 .maxlen
= sizeof(int),
199 .proc_handler
= proc_dointvec
204 static struct ctl_table abi_root_table2
[] = {
213 static __init
int ia32_binfmt_init(void)
215 register_sysctl_table(abi_root_table2
);
218 __initcall(ia32_binfmt_init
);
221 #else /* CONFIG_X86_32 */
223 const char *arch_vma_name(struct vm_area_struct
*vma
)
225 if (vma
->vm_mm
&& vma
->vm_start
== (long)vma
->vm_mm
->context
.vdso
)
230 struct vm_area_struct
*get_gate_vma(struct mm_struct
*mm
)
235 int in_gate_area(struct mm_struct
*mm
, unsigned long addr
)
240 int in_gate_area_no_mm(unsigned long addr
)
245 #endif /* CONFIG_X86_64 */