.. | .. |
---|
32 | 32 | |
---|
33 | 33 | extern char vdso_start[], vdso_end[]; |
---|
34 | 34 | |
---|
35 | | -/* Total number of pages needed for the data and text portions of the VDSO. */ |
---|
| 35 | +/* |
---|
| 36 | + * Total number of pages needed for the data, private and text |
---|
| 37 | + * portions of the VDSO. |
---|
| 38 | + */ |
---|
36 | 39 | unsigned int vdso_total_pages __ro_after_init; |
---|
37 | 40 | |
---|
38 | 41 | /* |
---|
.. | .. |
---|
53 | 56 | unsigned long new_size = new_vma->vm_end - new_vma->vm_start; |
---|
54 | 57 | unsigned long vdso_size; |
---|
55 | 58 | |
---|
56 | | - /* without VVAR page */ |
---|
57 | | - vdso_size = (vdso_total_pages - 1) << PAGE_SHIFT; |
---|
| 59 | + /* without VVAR and VPRIV pages */ |
---|
| 60 | + vdso_size = (vdso_total_pages - 2) << PAGE_SHIFT; |
---|
58 | 61 | |
---|
59 | 62 | if (vdso_size != new_size) |
---|
60 | 63 | return -EINVAL; |
---|
.. | .. |
---|
180 | 183 | /* If the virtual counter is absent or non-functional we don't |
---|
181 | 184 | * want programs to incur the slight additional overhead of |
---|
182 | 185 | * dispatching through the VDSO only to fall back to syscalls. |
---|
| 186 | + * However, if clocksources supporting generic MMIO access can |
---|
| 187 | + * be reached via the vDSO, keep this fast path enabled. |
---|
183 | 188 | */ |
---|
184 | | - if (!cntvct_ok) { |
---|
| 189 | + if (!cntvct_ok && !IS_ENABLED(CONFIG_GENERIC_CLOCKSOURCE_VDSO)) { |
---|
185 | 190 | vdso_nullpatch_one(&einfo, "__vdso_gettimeofday"); |
---|
186 | 191 | vdso_nullpatch_one(&einfo, "__vdso_clock_gettime"); |
---|
187 | 192 | vdso_nullpatch_one(&einfo, "__vdso_clock_gettime64"); |
---|
.. | .. |
---|
219 | 224 | |
---|
220 | 225 | vdso_text_mapping.pages = vdso_text_pagelist; |
---|
221 | 226 | |
---|
222 | | - vdso_total_pages = 1; /* for the data/vvar page */ |
---|
| 227 | + vdso_total_pages = 2; /* for the data/vvar and vpriv pages */ |
---|
223 | 228 | vdso_total_pages += text_pages; |
---|
224 | 229 | |
---|
225 | 230 | cntvct_ok = cntvct_functional(); |
---|
226 | 231 | |
---|
227 | 232 | patch_vdso(vdso_start); |
---|
| 233 | +#ifdef CONFIG_GENERIC_CLOCKSOURCE_VDSO |
---|
| 234 | + vdso_data->cs_type_seq = CLOCKSOURCE_VDSO_NONE << 16 | 1; |
---|
| 235 | +#endif |
---|
228 | 236 | |
---|
229 | 237 | return 0; |
---|
230 | 238 | } |
---|
231 | 239 | arch_initcall(vdso_init); |
---|
| 240 | + |
---|
| 241 | +static int install_vpriv(struct mm_struct *mm, unsigned long addr) |
---|
| 242 | +{ |
---|
| 243 | + return mmap_region(NULL, addr, PAGE_SIZE, |
---|
| 244 | + VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE, |
---|
| 245 | + 0, NULL) != addr ? -EINVAL : 0; |
---|
| 246 | +} |
---|
232 | 247 | |
---|
233 | 248 | static int install_vvar(struct mm_struct *mm, unsigned long addr) |
---|
234 | 249 | { |
---|
.. | .. |
---|
237 | 252 | vma = _install_special_mapping(mm, addr, PAGE_SIZE, |
---|
238 | 253 | VM_READ | VM_MAYREAD, |
---|
239 | 254 | &vdso_data_mapping); |
---|
| 255 | + if (IS_ERR(vma)) |
---|
| 256 | + return PTR_ERR(vma); |
---|
240 | 257 | |
---|
241 | | - return PTR_ERR_OR_ZERO(vma); |
---|
| 258 | + if (cache_is_vivt()) |
---|
| 259 | + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
---|
| 260 | + |
---|
| 261 | + return vma->vm_start != addr ? -EINVAL : 0; |
---|
242 | 262 | } |
---|
243 | 263 | |
---|
244 | 264 | /* assumes mmap_lock is write-locked */ |
---|
.. | .. |
---|
252 | 272 | if (vdso_text_pagelist == NULL) |
---|
253 | 273 | return; |
---|
254 | 274 | |
---|
255 | | - if (install_vvar(mm, addr)) |
---|
| 275 | + if (install_vpriv(mm, addr)) { |
---|
| 276 | + pr_err("cannot map VPRIV at expected address!\n"); |
---|
256 | 277 | return; |
---|
| 278 | + } |
---|
257 | 279 | |
---|
258 | | - /* Account for vvar page. */ |
---|
| 280 | + /* Account for the private storage. */ |
---|
259 | 281 | addr += PAGE_SIZE; |
---|
260 | | - len = (vdso_total_pages - 1) << PAGE_SHIFT; |
---|
| 282 | + if (install_vvar(mm, addr)) { |
---|
| 283 | + WARN(1, "cannot map VVAR at expected address!\n"); |
---|
| 284 | + return; |
---|
| 285 | + } |
---|
| 286 | + |
---|
| 287 | + /* Account for vvar and vpriv pages. */ |
---|
| 288 | + addr += PAGE_SIZE; |
---|
| 289 | + len = (vdso_total_pages - 2) << PAGE_SHIFT; |
---|
261 | 290 | |
---|
262 | 291 | vma = _install_special_mapping(mm, addr, len, |
---|
263 | 292 | VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, |
---|
264 | 293 | &vdso_text_mapping); |
---|
265 | 294 | |
---|
266 | | - if (!IS_ERR(vma)) |
---|
| 295 | + if (IS_ERR(vma) || vma->vm_start != addr) |
---|
| 296 | + WARN(1, "cannot map VDSO at expected address!\n"); |
---|
| 297 | + else |
---|
267 | 298 | mm->context.vdso = addr; |
---|
268 | 299 | } |
---|
269 | 300 | |
---|