Blame view

arch/x86/vdso/vdso32-setup.c 6.44 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
   * (C) Copyright 2002 Linus Torvalds
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
3
4
   * Portions based on the vdso-randomization code from exec-shield:
   * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
12
13
14
15
   *
   * This file contains the needed initializations to support sysenter.
   */
  
  #include <linux/init.h>
  #include <linux/smp.h>
  #include <linux/thread_info.h>
  #include <linux/sched.h>
  #include <linux/gfp.h>
  #include <linux/string.h>
  #include <linux/elf.h>
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
16
  #include <linux/mm.h>
4e950f6f0   Alexey Dobriyan   Remove fs.h from ...
17
  #include <linux/err.h>
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
18
  #include <linux/module.h>
4e40112c4   Stefani Seibold   x86, vdso32: hand...
19
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
  
  #include <asm/cpufeature.h>
  #include <asm/msr.h>
  #include <asm/pgtable.h>
  #include <asm/unistd.h>
d4f7a2c18   Jeremy Fitzhardinge   [PATCH] i386: Rel...
25
  #include <asm/elf.h>
1dbf527c5   Jeremy Fitzhardinge   [PATCH] i386: Mak...
26
  #include <asm/tlbflush.h>
6c3652efc   Roland McGrath   x86 vDSO: i386 vd...
27
  #include <asm/vdso.h>
af65d6484   Roland McGrath   x86 vDSO: consoli...
28
  #include <asm/proto.h>
7a59ed415   Stefani Seibold   x86, vdso: Add 32...
29
30
31
  #include <asm/fixmap.h>
  #include <asm/hpet.h>
  #include <asm/vvar.h>
1dbf527c5   Jeremy Fitzhardinge   [PATCH] i386: Mak...
32

1dbf527c5   Jeremy Fitzhardinge   [PATCH] i386: Mak...
33
  #ifdef CONFIG_COMPAT_VDSO
b0b49f267   Andy Lutomirski   x86, vdso: Remove...
34
  #define VDSO_DEFAULT	0
1dbf527c5   Jeremy Fitzhardinge   [PATCH] i386: Mak...
35
  #else
b0b49f267   Andy Lutomirski   x86, vdso: Remove...
36
  #define VDSO_DEFAULT	1
1dbf527c5   Jeremy Fitzhardinge   [PATCH] i386: Mak...
37
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

af65d6484   Roland McGrath   x86 vDSO: consoli...
39
40
41
  #ifdef CONFIG_X86_64
  #define vdso_enabled			sysctl_vsyscall32
  #define arch_setup_additional_pages	syscall32_setup_pages
fa81511bb   Linus Torvalds   x86-64, modify_ld...
42
  extern int sysctl_ldt16;
af65d6484   Roland McGrath   x86 vDSO: consoli...
43
44
45
  #endif
  
  /*
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
46
47
48
   * Should the kernel map a VDSO page into processes and pass its
   * address down to glibc upon exec()?
   */
1dbf527c5   Jeremy Fitzhardinge   [PATCH] i386: Mak...
49
  unsigned int __read_mostly vdso_enabled = VDSO_DEFAULT;
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
50

e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
51
52
53
  static int __init vdso_setup(char *s)
  {
  	vdso_enabled = simple_strtoul(s, NULL, 0);
b0b49f267   Andy Lutomirski   x86, vdso: Remove...
54
55
56
  	if (vdso_enabled > 1)
  		pr_warn("vdso32 values other than 0 and 1 are no longer allowed; vdso disabled
  ");
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
57
58
  	return 1;
  }
af65d6484   Roland McGrath   x86 vDSO: consoli...
59
60
61
62
63
64
  /*
   * For consistency, the argument vdso32=[012] affects the 32-bit vDSO
   * behavior on both 64-bit and 32-bit kernels.
   * On 32-bit kernels, vdso=[012] means the same thing.
   */
  __setup("vdso32=", vdso_setup);
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
65

af65d6484   Roland McGrath   x86 vDSO: consoli...
66
67
68
69
70
  #ifdef CONFIG_X86_32
  __setup_param("vdso=", vdso32_setup, vdso_setup, 0);
  
  EXPORT_SYMBOL_GPL(vdso_enabled);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71

4e40112c4   Stefani Seibold   x86, vdso32: hand...
72
  static struct page **vdso32_pages;
b67e612ce   Andy Lutomirski   x86: Load the 32-...
73
  static unsigned vdso32_size;
af65d6484   Roland McGrath   x86 vDSO: consoli...
74
75
  
  #ifdef CONFIG_X86_64
b6ad92d4f   Jeremy Fitzhardinge   x86_64: vdso32 cl...
76
  #define	vdso32_sysenter()	(boot_cpu_has(X86_FEATURE_SYSENTER32))
6a52e4b1c   Jeremy Fitzhardinge   x86_64: further c...
77
  #define	vdso32_syscall()	(boot_cpu_has(X86_FEATURE_SYSCALL32))
af65d6484   Roland McGrath   x86 vDSO: consoli...
78
79
80
81
  
  /* May not be __init: called during resume */
  void syscall32_cpu_init(void)
  {
af65d6484   Roland McGrath   x86 vDSO: consoli...
82
83
  	/* Load these always in case some future AMD CPU supports
  	   SYSENTER from compat mode too. */
715c85b1f   H. Peter Anvin   x86, cpu: Rename ...
84
85
86
  	wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
  	wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
  	wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target);
af65d6484   Roland McGrath   x86 vDSO: consoli...
87
88
89
  
  	wrmsrl(MSR_CSTAR, ia32_cstar_target);
  }
af65d6484   Roland McGrath   x86 vDSO: consoli...
90
91
92
  #else  /* CONFIG_X86_32 */
  
  #define vdso32_sysenter()	(boot_cpu_has(X86_FEATURE_SEP))
6a52e4b1c   Jeremy Fitzhardinge   x86_64: further c...
93
  #define vdso32_syscall()	(0)
af65d6484   Roland McGrath   x86 vDSO: consoli...
94

6fe940d6c   Li Shaohua   [PATCH] sep initi...
95
  void enable_sep_cpu(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
  {
  	int cpu = get_cpu();
  	struct tss_struct *tss = &per_cpu(init_tss, cpu);
6fe940d6c   Li Shaohua   [PATCH] sep initi...
99
100
101
102
  	if (!boot_cpu_has(X86_FEATURE_SEP)) {
  		put_cpu();
  		return;
  	}
a75c54f93   Rusty Russell   [PATCH] i386: i38...
103
  	tss->x86_tss.ss1 = __KERNEL_CS;
faca62273   H. Peter Anvin   x86: use generic ...
104
  	tss->x86_tss.sp1 = sizeof(struct tss_struct) + (unsigned long) tss;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  	wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
faca62273   H. Peter Anvin   x86: use generic ...
106
  	wrmsr(MSR_IA32_SYSENTER_ESP, tss->x86_tss.sp1, 0);
0aa97fb22   Roland McGrath   x86 vDSO: ia32_sy...
107
  	wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) ia32_sysenter_target, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
  	put_cpu();	
  }
af65d6484   Roland McGrath   x86 vDSO: consoli...
110
  #endif	/* CONFIG_X86_64 */
a6c4e076e   Jeremy Fitzhardinge   [PATCH] i386: cle...
111
  int __init sysenter_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  {
b67e612ce   Andy Lutomirski   x86: Load the 32-...
113
114
  	char *vdso32_start, *vdso32_end;
  	int npages, i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115

b67e612ce   Andy Lutomirski   x86: Load the 32-...
116
  #ifdef CONFIG_COMPAT
6a52e4b1c   Jeremy Fitzhardinge   x86_64: further c...
117
  	if (vdso32_syscall()) {
b67e612ce   Andy Lutomirski   x86: Load the 32-...
118
119
120
121
122
123
124
125
126
  		vdso32_start = vdso32_syscall_start;
  		vdso32_end = vdso32_syscall_end;
  		vdso32_pages = vdso32_syscall_pages;
  	} else
  #endif
  	if (vdso32_sysenter()) {
  		vdso32_start = vdso32_sysenter_start;
  		vdso32_end = vdso32_sysenter_end;
  		vdso32_pages = vdso32_sysenter_pages;
6a52e4b1c   Jeremy Fitzhardinge   x86_64: further c...
127
  	} else {
b67e612ce   Andy Lutomirski   x86: Load the 32-...
128
129
130
  		vdso32_start = vdso32_int80_start;
  		vdso32_end = vdso32_int80_end;
  		vdso32_pages = vdso32_int80_pages;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  	}
b67e612ce   Andy Lutomirski   x86: Load the 32-...
132
133
134
135
  	npages = ((vdso32_end - vdso32_start) + PAGE_SIZE - 1) / PAGE_SIZE;
  	vdso32_size = npages << PAGE_SHIFT;
  	for (i = 0; i < npages; i++)
  		vdso32_pages[i] = virt_to_page(vdso32_start + i*PAGE_SIZE);
4e40112c4   Stefani Seibold   x86, vdso32: hand...
136

b67e612ce   Andy Lutomirski   x86: Load the 32-...
137
  	patch_vdso32(vdso32_start, vdso32_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
  	return 0;
  }
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
141

e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
142
  /* Setup a VMA at program startup for the vsyscall page */
fc5243d98   Martin Schwidefsky   [S390] arch_setup...
143
  int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
144
  {
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
145
146
  	struct mm_struct *mm = current->mm;
  	unsigned long addr;
752783c05   Zachary Amsden   [PATCH] i386: In ...
147
  	int ret = 0;
7a59ed415   Stefani Seibold   x86, vdso: Add 32...
148
  	struct vm_area_struct *vma;
368b69a5b   Andy Lutomirski   x86, vdso: Fix an...
149
  	static struct page *no_pages[] = {NULL};
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
150

1a21d4e09   H. J. Lu   x32: Add x32 VDSO...
151
  #ifdef CONFIG_X86_X32_ABI
1a21d4e09   H. J. Lu   x32: Add x32 VDSO...
152
  	if (test_thread_flag(TIF_X32))
22e842d4d   H. Peter Anvin   x32: Fix coding s...
153
  		return x32_setup_additional_pages(bprm, uses_interp);
1a21d4e09   H. J. Lu   x32: Add x32 VDSO...
154
  #endif
b0b49f267   Andy Lutomirski   x86, vdso: Remove...
155
  	if (vdso_enabled != 1)  /* Other values all mean "disabled" */
5de253cc5   Roland McGrath   x86 vDSO: don't m...
156
  		return 0;
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
157
  	down_write(&mm->mmap_sem);
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
158

645a387ec   Stefani Seibold   x86, vdso: Fix si...
159
  	addr = get_unmapped_area(NULL, 0, vdso32_size + VDSO_OFFSET(VDSO_PREV_PAGES), 0, 0);
b0b49f267   Andy Lutomirski   x86, vdso: Remove...
160
161
162
  	if (IS_ERR_VALUE(addr)) {
  		ret = addr;
  		goto up_fail;
af65d6484   Roland McGrath   x86 vDSO: consoli...
163
  	}
1dbf527c5   Jeremy Fitzhardinge   [PATCH] i386: Mak...
164

645a387ec   Stefani Seibold   x86, vdso: Fix si...
165
  	addr += VDSO_OFFSET(VDSO_PREV_PAGES);
f7b6eb3fa   Peter Zijlstra   x86: Set context....
166
  	current->mm->context.vdso = (void *)addr;
b0b49f267   Andy Lutomirski   x86, vdso: Remove...
167
168
169
  	/*
  	 * MAYWRITE to allow gdb to COW and set breakpoints
  	 */
7a59ed415   Stefani Seibold   x86, vdso: Add 32...
170
171
  	ret = install_special_mapping(mm,
  			addr,
b67e612ce   Andy Lutomirski   x86: Load the 32-...
172
  			vdso32_size,
7a59ed415   Stefani Seibold   x86, vdso: Add 32...
173
174
175
  			VM_READ|VM_EXEC|
  			VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
  			vdso32_pages);
b0b49f267   Andy Lutomirski   x86, vdso: Remove...
176
177
178
  
  	if (ret)
  		goto up_fail;
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
179

7a59ed415   Stefani Seibold   x86, vdso: Add 32...
180
181
182
183
  	vma = _install_special_mapping(mm,
  			addr -  VDSO_OFFSET(VDSO_PREV_PAGES),
  			VDSO_OFFSET(VDSO_PREV_PAGES),
  			VM_READ,
368b69a5b   Andy Lutomirski   x86, vdso: Fix an...
184
  			no_pages);
7a59ed415   Stefani Seibold   x86, vdso: Add 32...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  
  	if (IS_ERR(vma)) {
  		ret = PTR_ERR(vma);
  		goto up_fail;
  	}
  
  	ret = remap_pfn_range(vma,
  		addr - VDSO_OFFSET(VDSO_VVAR_PAGE),
  		__pa_symbol(&__vvar_page) >> PAGE_SHIFT,
  		PAGE_SIZE,
  		PAGE_READONLY);
  
  	if (ret)
  		goto up_fail;
  
  #ifdef CONFIG_HPET_TIMER
  	if (hpet_address) {
  		ret = io_remap_pfn_range(vma,
  			addr - VDSO_OFFSET(VDSO_HPET_PAGE),
  			hpet_address >> PAGE_SHIFT,
  			PAGE_SIZE,
  			pgprot_noncached(PAGE_READONLY));
  
  		if (ret)
  			goto up_fail;
  	}
  #endif
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
212
  	current_thread_info()->sysenter_return =
6c3652efc   Roland McGrath   x86 vDSO: i386 vd...
213
  		VDSO32_SYMBOL(addr, SYSENTER_RETURN);
1dbf527c5   Jeremy Fitzhardinge   [PATCH] i386: Mak...
214
215
  
    up_fail:
f7b6eb3fa   Peter Zijlstra   x86: Set context....
216
217
  	if (ret)
  		current->mm->context.vdso = NULL;
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
218
  	up_write(&mm->mmap_sem);
1dbf527c5   Jeremy Fitzhardinge   [PATCH] i386: Mak...
219

e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
220
  	return ret;
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
221
  }
af65d6484   Roland McGrath   x86 vDSO: consoli...
222
  #ifdef CONFIG_X86_64
d7a0380dc   Jiri Slaby   x86-64, mm: Initi...
223
  subsys_initcall(sysenter_setup);
af65d6484   Roland McGrath   x86 vDSO: consoli...
224

a97f52e67   Roland McGrath   x86: compat_binfm...
225
226
227
  #ifdef CONFIG_SYSCTL
  /* Register vsyscall32 into the ABI table */
  #include <linux/sysctl.h>
f07d91ede   Joe Perches   x86/vdso: Convert...
228
  static struct ctl_table abi_table2[] = {
a97f52e67   Roland McGrath   x86: compat_binfm...
229
230
231
232
233
234
235
  	{
  		.procname	= "vsyscall32",
  		.data		= &sysctl_vsyscall32,
  		.maxlen		= sizeof(int),
  		.mode		= 0644,
  		.proc_handler	= proc_dointvec
  	},
fa81511bb   Linus Torvalds   x86-64, modify_ld...
236
237
238
239
240
241
242
  	{
  		.procname	= "ldt16",
  		.data		= &sysctl_ldt16,
  		.maxlen		= sizeof(int),
  		.mode		= 0644,
  		.proc_handler	= proc_dointvec
  	},
a97f52e67   Roland McGrath   x86: compat_binfm...
243
244
  	{}
  };
f07d91ede   Joe Perches   x86/vdso: Convert...
245
  static struct ctl_table abi_root_table2[] = {
a97f52e67   Roland McGrath   x86: compat_binfm...
246
  	{
a97f52e67   Roland McGrath   x86: compat_binfm...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  		.procname = "abi",
  		.mode = 0555,
  		.child = abi_table2
  	},
  	{}
  };
  
  static __init int ia32_binfmt_init(void)
  {
  	register_sysctl_table(abi_root_table2);
  	return 0;
  }
  __initcall(ia32_binfmt_init);
  #endif
af65d6484   Roland McGrath   x86 vDSO: consoli...
261
  #else  /* CONFIG_X86_32 */
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
262
263
264
265
266
267
  const char *arch_vma_name(struct vm_area_struct *vma)
  {
  	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
  		return "[vdso]";
  	return NULL;
  }
31db58b3a   Stephen Wilson   mm: arch: make ge...
268
  struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
269
270
271
  {
  	return NULL;
  }
83b964bbf   Stephen Wilson   mm: arch: make in...
272
  int in_gate_area(struct mm_struct *mm, unsigned long addr)
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
273
  {
b0b49f267   Andy Lutomirski   x86, vdso: Remove...
274
  	return 0;
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
275
  }
cae5d3903   Stephen Wilson   mm: arch: rename ...
276
  int in_gate_area_no_mm(unsigned long addr)
e6e5494cb   Ingo Molnar   [PATCH] vdso: ran...
277
278
279
  {
  	return 0;
  }
af65d6484   Roland McGrath   x86 vDSO: consoli...
280
281
  
  #endif	/* CONFIG_X86_64 */